ReactOS  0.4.13-dev-563-g0561610
buffer.c
Go to the documentation of this file.
1 /*
2  * Copyright 2002-2005 Jason Edmeades
3  * Copyright 2002-2005 Raphael Junqueira
4  * Copyright 2004 Christian Costa
5  * Copyright 2005 Oliver Stieber
6  * Copyright 2007-2011, 2013-2014 Stefan Dösinger for CodeWeavers
7  * Copyright 2009-2010 Henri Verbeet for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  */
24 
25 #include "config.h"
26 #include "wine/port.h"
27 
28 #include "wined3d_private.h"
29 
31 
32 #define WINED3D_BUFFER_HASDESC 0x01 /* A vertex description has been found. */
33 #define WINED3D_BUFFER_USE_BO 0x02 /* Use a buffer object for this buffer. */
34 #define WINED3D_BUFFER_PIN_SYSMEM 0x04 /* Keep a system memory copy for this buffer. */
35 #define WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */
36 #define WINED3D_BUFFER_APPLESYNC 0x10 /* Using sync as in GL_APPLE_flush_buffer_range. */
37 
38 #define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */
39 #define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */
40 #define VB_MAXFULLCONVERSIONS 5 /* Number of full conversions before we stop converting */
41 #define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */
42 
44 {
45  if (buffer->flags & WINED3D_BUFFER_PIN_SYSMEM)
46  {
47  TRACE("Not evicting system memory for buffer %p.\n", buffer);
48  return;
49  }
50 
51  TRACE("Evicting system memory for buffer %p.\n", buffer);
54 }
55 
56 static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, unsigned int offset, unsigned int size)
57 {
58  if (!offset && (!size || size == buffer->resource.size))
59  goto invalidate_all;
60 
61  if (offset > buffer->resource.size || size > buffer->resource.size - offset)
62  {
63  WARN("Invalid range specified, invalidating entire buffer.\n");
64  goto invalidate_all;
65  }
66 
67  if (!wined3d_array_reserve((void **)&buffer->maps, &buffer->maps_size,
68  buffer->modified_areas + 1, sizeof(*buffer->maps)))
69  {
70  ERR("Failed to allocate maps array, invalidating entire buffer.\n");
71  goto invalidate_all;
72  }
73 
74  buffer->maps[buffer->modified_areas].offset = offset;
75  buffer->maps[buffer->modified_areas].size = size;
76  ++buffer->modified_areas;
77  return;
78 
79 invalidate_all:
80  buffer->modified_areas = 1;
81  buffer->maps[0].offset = 0;
82  buffer->maps[0].size = buffer->resource.size;
83 }
84 
85 static inline void buffer_clear_dirty_areas(struct wined3d_buffer *This)
86 {
87  This->modified_areas = 0;
88 }
89 
91 {
92  return !!buffer->modified_areas;
93 }
94 
96 {
97  return buffer->modified_areas == 1
98  && !buffer->maps->offset && buffer->maps->size == buffer->resource.size;
99 }
100 
102 {
103  TRACE("buffer %p, location %s.\n", buffer, wined3d_debug_location(location));
104 
107 
108  buffer->locations |= location;
109 
110  TRACE("New locations flags are %s.\n", wined3d_debug_location(buffer->locations));
111 }
112 
114  unsigned int offset, unsigned int size)
115 {
116  TRACE("buffer %p, location %s, offset %u, size %u.\n",
118 
121 
122  buffer->locations &= ~location;
123 
124  TRACE("New locations flags are %s.\n", wined3d_debug_location(buffer->locations));
125 
126  if (!buffer->locations)
127  ERR("Buffer %p does not have any up to date location.\n", buffer);
128 }
129 
131 {
133 }
134 
135 /* Context activation is done by the caller. */
137 {
138  context_bind_bo(context, buffer->buffer_type_hint, buffer->buffer_object);
139 }
140 
141 /* Context activation is done by the caller. */
143 {
144  const struct wined3d_gl_info *gl_info = context->gl_info;
145  struct wined3d_resource *resource = &buffer->resource;
146 
147  if (!buffer->buffer_object)
148  return;
149 
150  /* The stream source state handler might have read the memory of the
151  * vertex buffer already and got the memory in the vbo which is not
152  * valid any longer. Dirtify the stream source to force a reload. This
153  * happens only once per changed vertexbuffer and should occur rather
154  * rarely. */
155  if (resource->bind_count)
156  {
157  if (buffer->bind_flags & WINED3D_BIND_VERTEX_BUFFER)
159  if (buffer->bind_flags & WINED3D_BIND_INDEX_BUFFER)
161  if (buffer->bind_flags & WINED3D_BIND_CONSTANT_BUFFER)
162  {
169  }
170  if (buffer->bind_flags & WINED3D_BIND_STREAM_OUTPUT)
171  {
173  if (context->transform_feedback_active)
174  {
175  /* We have to make sure that transform feedback is not active
176  * when deleting a potentially bound transform feedback buffer.
177  * This may happen when the device is being destroyed. */
178  WARN("Deleting buffer object for buffer %p, disabling transform feedback.\n", buffer);
180  }
181  }
182  }
183 
184  GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object));
185  checkGLcall("glDeleteBuffers");
186  buffer->buffer_object = 0;
187 
188  if (buffer->fence)
189  {
191  buffer->fence = NULL;
192  }
193  buffer->flags &= ~WINED3D_BUFFER_APPLESYNC;
194 }
195 
196 /* Context activation is done by the caller. */
198 {
199  const struct wined3d_gl_info *gl_info = context->gl_info;
200  GLenum gl_usage = GL_STATIC_DRAW;
201  GLenum error;
202 
203  TRACE("Creating an OpenGL buffer object for wined3d_buffer %p with usage %s.\n",
204  buffer, debug_d3dusage(buffer->resource.usage));
205 
206  /* Make sure that the gl error is cleared. Do not use checkGLcall
207  * here because checkGLcall just prints a fixme and continues. However,
208  * if an error during VBO creation occurs we can fall back to non-VBO operation
209  * with full functionality(but performance loss).
210  */
211  while (gl_info->gl_ops.gl.p_glGetError() != GL_NO_ERROR);
212 
213  /* Basically the FVF parameter passed to CreateVertexBuffer is no good.
214  * The vertex declaration from the device determines how the data in the
215  * buffer is interpreted. This means that on each draw call the buffer has
216  * to be verified to check if the rhw and color values are in the correct
217  * format. */
218 
219  GL_EXTCALL(glGenBuffers(1, &buffer->buffer_object));
220  error = gl_info->gl_ops.gl.p_glGetError();
221  if (!buffer->buffer_object || error != GL_NO_ERROR)
222  {
223  ERR("Failed to create a BO with error %s (%#x).\n", debug_glerror(error), error);
224  goto fail;
225  }
226 
228  error = gl_info->gl_ops.gl.p_glGetError();
229  if (error != GL_NO_ERROR)
230  {
231  ERR("Failed to bind the BO with error %s (%#x).\n", debug_glerror(error), error);
232  goto fail;
233  }
234 
235  if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)
236  {
237  TRACE("Buffer has WINED3DUSAGE_DYNAMIC set.\n");
238  gl_usage = GL_STREAM_DRAW_ARB;
239 
240  if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
241  {
242  GL_EXTCALL(glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE));
243  GL_EXTCALL(glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
244  checkGLcall("glBufferParameteriAPPLE");
246  }
247  /* No setup is needed here for GL_ARB_map_buffer_range. */
248  }
249 
250  GL_EXTCALL(glBufferData(buffer->buffer_type_hint, buffer->resource.size, NULL, gl_usage));
251  error = gl_info->gl_ops.gl.p_glGetError();
252  if (error != GL_NO_ERROR)
253  {
254  ERR("glBufferData failed with error %s (%#x).\n", debug_glerror(error), error);
255  goto fail;
256  }
257 
258  buffer->buffer_object_usage = gl_usage;
260 
261  return TRUE;
262 
263 fail:
264  /* Clean up all BO init, but continue because we can work without a BO :-) */
265  ERR("Failed to create a buffer object. Continuing, but performance issues may occur.\n");
266  buffer->flags &= ~WINED3D_BUFFER_USE_BO;
269  return FALSE;
270 }
271 
273  const enum wined3d_buffer_conversion_type conversion_type,
274  const struct wined3d_stream_info_element *attrib, DWORD *stride_this_run)
275 {
276  const struct wined3d_format *format = attrib->format;
277  BOOL ret = FALSE;
278  unsigned int i;
279  DWORD_PTR data;
280 
281  /* Check for some valid situations which cause us pain. One is if the buffer is used for
282  * constant attributes(stride = 0), the other one is if the buffer is used on two streams
283  * with different strides. In the 2nd case we might have to drop conversion entirely,
284  * it is possible that the same bytes are once read as FLOAT2 and once as UBYTE4N.
285  */
286  if (!attrib->stride)
287  {
288  FIXME("%s used with stride 0, let's hope we get the vertex stride from somewhere else.\n",
289  debug_d3dformat(format->id));
290  }
291  else if (attrib->stride != *stride_this_run && *stride_this_run)
292  {
293  FIXME("Got two concurrent strides, %d and %d.\n", attrib->stride, *stride_this_run);
294  }
295  else
296  {
297  *stride_this_run = attrib->stride;
298  if (buffer->stride != *stride_this_run)
299  {
300  /* We rely that this happens only on the first converted attribute that is found,
301  * if at all. See above check
302  */
303  TRACE("Reconverting because converted attributes occur, and the stride changed.\n");
304  buffer->stride = *stride_this_run;
305  heap_free(buffer->conversion_map);
306  buffer->conversion_map = heap_calloc(buffer->stride, sizeof(*buffer->conversion_map));
307  ret = TRUE;
308  }
309  }
310 
311  data = ((DWORD_PTR)attrib->data.addr) % buffer->stride;
312  for (i = 0; i < format->attribute_size; ++i)
313  {
314  DWORD_PTR idx = (data + i) % buffer->stride;
315  if (buffer->conversion_map[idx] != conversion_type)
316  {
317  TRACE("Byte %lu in vertex changed:\n", idx);
318  TRACE(" It was type %#x, is %#x now.\n", buffer->conversion_map[idx], conversion_type);
319  ret = TRUE;
320  buffer->conversion_map[idx] = conversion_type;
321  }
322  }
323 
324  return ret;
325 }
326 
327 #define WINED3D_BUFFER_FIXUP_D3DCOLOR 0x01
328 #define WINED3D_BUFFER_FIXUP_XYZRHW 0x02
329 
331  const struct wined3d_state *state, UINT attrib_idx, DWORD fixup_flags, DWORD *stride_this_run)
332 {
333  const struct wined3d_stream_info_element *attrib = &si->elements[attrib_idx];
335  BOOL ret = FALSE;
336 
337  /* Ignore attributes that do not have our vbo. After that check we can be sure that the attribute is
338  * there, on nonexistent attribs the vbo is 0.
339  */
340  if (!(si->use_map & (1u << attrib_idx))
341  || state->streams[attrib->stream_idx].buffer != This)
342  return FALSE;
343 
344  format = attrib->format->id;
345  /* Look for newly appeared conversion */
347  {
348  ret = buffer_process_converted_attribute(This, CONV_D3DCOLOR, attrib, stride_this_run);
349  }
350  else if (fixup_flags & WINED3D_BUFFER_FIXUP_XYZRHW && si->position_transformed)
351  {
353  {
354  FIXME("Unexpected format %s for transformed position.\n", debug_d3dformat(format));
355  return FALSE;
356  }
357 
358  ret = buffer_process_converted_attribute(This, CONV_POSITIONT, attrib, stride_this_run);
359  }
360  else if (This->conversion_map)
361  {
362  ret = buffer_process_converted_attribute(This, CONV_NONE, attrib, stride_this_run);
363  }
364 
365  return ret;
366 }
367 
369  const struct wined3d_state *state, DWORD fixup_flags)
370 {
371  UINT stride_this_run = 0;
372  BOOL ret = FALSE;
373 
374  /* In d3d7 the vertex buffer declaration NEVER changes because it is stored in the d3d7 vertex buffer.
375  * Once we have our declaration there is no need to look it up again. Index buffers also never need
376  * conversion, so once the (empty) conversion structure is created don't bother checking again
377  */
378  if (This->flags & WINED3D_BUFFER_HASDESC)
379  {
380  if(This->resource.usage & WINED3DUSAGE_STATICDECL) return FALSE;
381  }
382 
383  if (!fixup_flags)
384  {
385  TRACE("No fixup required.\n");
386  if(This->conversion_map)
387  {
388  heap_free(This->conversion_map);
389  This->conversion_map = NULL;
390  This->stride = 0;
391  return TRUE;
392  }
393 
394  return FALSE;
395  }
396 
397  TRACE("Finding vertex buffer conversion information\n");
398  /* Certain declaration types need some fixups before we can pass them to
399  * opengl. This means D3DCOLOR attributes with fixed function vertex
400  * processing, FLOAT4 POSITIONT with fixed function, and FLOAT16 if
401  * GL_ARB_half_float_vertex is not supported.
402  *
403  * Note for d3d8 and d3d9:
404  * The vertex buffer FVF doesn't help with finding them, we have to use
405  * the decoded vertex declaration and pick the things that concern the
406  * current buffer. A problem with this is that this can change between
407  * draws, so we have to validate the information and reprocess the buffer
408  * if it changes, and avoid false positives for performance reasons.
409  * WineD3D doesn't even know the vertex buffer any more, it is managed
410  * by the client libraries and passed to SetStreamSource and ProcessVertices
411  * as needed.
412  *
413  * We have to distinguish between vertex shaders and fixed function to
414  * pick the way we access the strided vertex information.
415  *
416  * This code sets up a per-byte array with the size of the detected
417  * stride of the arrays in the buffer. For each byte we have a field
418  * that marks the conversion needed on this byte. For example, the
419  * following declaration with fixed function vertex processing:
420  *
421  * POSITIONT, FLOAT4
422  * NORMAL, FLOAT3
423  * DIFFUSE, FLOAT16_4
424  * SPECULAR, D3DCOLOR
425  *
426  * Will result in
427  * { POSITIONT }{ NORMAL }{ DIFFUSE }{SPECULAR }
428  * [P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][0][0][0][0][0][0][0][0][0][0][0][0][F][F][F][F][F][F][F][F][C][C][C][C]
429  *
430  * Where in this example map P means 4 component position conversion, 0
431  * means no conversion, F means FLOAT16_2 conversion and C means D3DCOLOR
432  * conversion (red / blue swizzle).
433  *
434  * If we're doing conversion and the stride changes we have to reconvert
435  * the whole buffer. Note that we do not mind if the semantic changes,
436  * we only care for the conversion type. So if the NORMAL is replaced
437  * with a TEXCOORD, nothing has to be done, or if the DIFFUSE is replaced
438  * with a D3DCOLOR BLENDWEIGHT we can happily dismiss the change. Some
439  * conversion types depend on the semantic as well, for example a FLOAT4
440  * texcoord needs no conversion while a FLOAT4 positiont needs one
441  */
442 
444  fixup_flags, &stride_this_run) || ret;
445  fixup_flags &= ~WINED3D_BUFFER_FIXUP_XYZRHW;
446 
448  fixup_flags, &stride_this_run) || ret;
450  fixup_flags, &stride_this_run) || ret;
452  fixup_flags, &stride_this_run) || ret;
454  fixup_flags, &stride_this_run) || ret;
456  fixup_flags, &stride_this_run) || ret;
458  fixup_flags, &stride_this_run) || ret;
460  fixup_flags, &stride_this_run) || ret;
462  fixup_flags, &stride_this_run) || ret;
464  fixup_flags, &stride_this_run) || ret;
466  fixup_flags, &stride_this_run) || ret;
468  fixup_flags, &stride_this_run) || ret;
470  fixup_flags, &stride_this_run) || ret;
472  fixup_flags, &stride_this_run) || ret;
473 
474  if (!stride_this_run && This->conversion_map)
475  {
476  /* Sanity test */
477  if (!ret)
478  ERR("no converted attributes found, old conversion map exists, and no declaration change?\n");
479  heap_free(This->conversion_map);
480  This->conversion_map = NULL;
481  This->stride = 0;
482  }
483 
484  if (ret) TRACE("Conversion information changed\n");
485 
486  return ret;
487 }
488 
489 static inline unsigned int fixup_d3dcolor(DWORD *dst_color)
490 {
491  DWORD src_color = *dst_color;
492 
493  /* Color conversion like in draw_primitive_immediate_mode(). Watch out for
494  * endianness. If we want this to work on big-endian machines as well we
495  * have to consider more things.
496  *
497  * 0xff000000: Alpha mask
498  * 0x00ff0000: Blue mask
499  * 0x0000ff00: Green mask
500  * 0x000000ff: Red mask
501  */
502  *dst_color = 0;
503  *dst_color |= (src_color & 0xff00ff00u); /* Alpha Green */
504  *dst_color |= (src_color & 0x00ff0000u) >> 16; /* Red */
505  *dst_color |= (src_color & 0x000000ffu) << 16; /* Blue */
506 
507  return sizeof(*dst_color);
508 }
509 
510 static inline unsigned int fixup_transformed_pos(struct wined3d_vec4 *p)
511 {
512  /* rhw conversion like in position_float4(). */
513  if (p->w != 1.0f && p->w != 0.0f)
514  {
515  float w = 1.0f / p->w;
516  p->x *= w;
517  p->y *= w;
518  p->z *= w;
519  p->w = w;
520  }
521 
522  return sizeof(*p);
523 }
524 
526 {
527  ULONG refcount = InterlockedIncrement(&buffer->resource.ref);
528 
529  TRACE("%p increasing refcount to %u.\n", buffer, refcount);
530 
531  return refcount;
532 }
533 
534 /* Context activation is done by the caller. */
536  const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
537 {
538  const struct wined3d_gl_info *gl_info = context->gl_info;
539  const struct wined3d_map_range *range;
540 
542 
543  while (range_count--)
544  {
545  range = &ranges[range_count];
546  GL_EXTCALL(glBufferSubData(buffer->buffer_type_hint,
547  range->offset, range->size, (BYTE *)data + range->offset - data_offset));
548  }
549  checkGLcall("glBufferSubData");
550 }
551 
553 {
554  unsigned int i, j, range_idx, start, end, vertex_count;
555  BYTE *data;
556 
558  {
559  ERR("Failed to load system memory.\n");
560  return;
561  }
563 
564  /* Now for each vertex in the buffer that needs conversion. */
565  vertex_count = buffer->resource.size / buffer->stride;
566 
567  if (!(data = heap_alloc(buffer->resource.size)))
568  {
569  ERR("Out of memory.\n");
570  return;
571  }
572 
573  for (range_idx = 0; range_idx < buffer->modified_areas; ++range_idx)
574  {
575  start = buffer->maps[range_idx].offset;
576  end = start + buffer->maps[range_idx].size;
577 
578  memcpy(data + start, (BYTE *)buffer->resource.heap_memory + start, end - start);
579  for (i = start / buffer->stride; i < min((end / buffer->stride) + 1, vertex_count); ++i)
580  {
581  for (j = 0; j < buffer->stride;)
582  {
583  switch (buffer->conversion_map[j])
584  {
585  case CONV_NONE:
586  /* Done already */
587  j += sizeof(DWORD);
588  break;
589  case CONV_D3DCOLOR:
590  j += fixup_d3dcolor((DWORD *) (data + i * buffer->stride + j));
591  break;
592  case CONV_POSITIONT:
593  j += fixup_transformed_pos((struct wined3d_vec4 *) (data + i * buffer->stride + j));
594  break;
595  default:
596  FIXME("Unimplemented conversion %d in shifted conversion.\n", buffer->conversion_map[j]);
597  ++j;
598  }
599  }
600  }
601  }
602 
603  wined3d_buffer_upload_ranges(buffer, context, data, 0, buffer->modified_areas, buffer->maps);
604 
605  heap_free(data);
606 }
607 
610 {
611  switch (location)
612  {
614  if (buffer->resource.heap_memory)
615  return TRUE;
616 
617  if (!wined3d_resource_allocate_sysmem(&buffer->resource))
618  return FALSE;
619  return TRUE;
620 
622  if (buffer->buffer_object)
623  return TRUE;
624 
625  if (!(buffer->flags & WINED3D_BUFFER_USE_BO))
626  {
627  WARN("Trying to create BO for buffer %p with no WINED3D_BUFFER_USE_BO.\n", buffer);
628  return FALSE;
629  }
631 
632  default:
633  ERR("Invalid location %s.\n", wined3d_debug_location(location));
634  return FALSE;
635  }
636 }
637 
640 {
641  const struct wined3d_gl_info *gl_info = context->gl_info;
642 
643  TRACE("buffer %p, context %p, location %s.\n",
645 
646  if (buffer->locations & location)
647  {
648  TRACE("Location (%#x) is already up to date.\n", location);
649  return TRUE;
650  }
651 
652  if (!buffer->locations)
653  {
654  ERR("Buffer %p does not have any up to date location.\n", buffer);
657  }
658 
659  TRACE("Current buffer location %s.\n", wined3d_debug_location(buffer->locations));
660 
662  return FALSE;
663 
664  if (buffer->locations & WINED3D_LOCATION_DISCARDED)
665  {
666  TRACE("Buffer previously discarded, nothing to do.\n");
669  return TRUE;
670  }
671 
672  switch (location)
673  {
676  GL_EXTCALL(glGetBufferSubData(buffer->buffer_type_hint, 0, buffer->resource.size,
677  buffer->resource.heap_memory));
678  checkGLcall("buffer download");
679  break;
680 
682  if (!buffer->conversion_map)
683  wined3d_buffer_upload_ranges(buffer, context, buffer->resource.heap_memory,
684  0, buffer->modified_areas, buffer->maps);
685  else
687  break;
688 
689  default:
690  ERR("Invalid location %s.\n", wined3d_debug_location(location));
691  return FALSE;
692  }
693 
695  if (buffer->resource.heap_memory && location == WINED3D_LOCATION_BUFFER
696  && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
698 
699  return TRUE;
700 }
701 
702 /* Context activation is done by the caller. */
704 {
707  return buffer->resource.heap_memory;
708 }
709 
712 {
713  TRACE("buffer %p, data %p, locations %s.\n",
715 
717  {
718  data->buffer_object = buffer->buffer_object;
719  data->addr = NULL;
721  }
723  {
724  data->buffer_object = 0;
725  data->addr = buffer->resource.heap_memory;
727  }
728 
729  ERR("Unexpected locations %s.\n", wined3d_debug_location(locations));
730  data->buffer_object = 0;
731  data->addr = NULL;
732  return 0;
733 }
734 
736 {
738 
739  TRACE("buffer %p.\n", buffer);
740 
741  if (buffer->buffer_object)
742  {
743  struct wined3d_context *context;
744 
745  context = context_acquire(resource->device, NULL, 0);
746 
751 
753 
754  heap_free(buffer->conversion_map);
755  buffer->conversion_map = NULL;
756  buffer->stride = 0;
757  buffer->conversion_stride = 0;
758  buffer->flags &= ~WINED3D_BUFFER_HASDESC;
759  }
760 
762 }
763 
765 {
766  buffer->flags &= ~WINED3D_BUFFER_USE_BO;
767  buffer_unload(&buffer->resource);
768 }
769 
770 static void wined3d_buffer_destroy_object(void *object)
771 {
772  struct wined3d_buffer *buffer = object;
773  struct wined3d_context *context;
774 
775  if (buffer->buffer_object)
776  {
777  context = context_acquire(buffer->resource.device, NULL, 0);
780 
781  heap_free(buffer->conversion_map);
782  }
783 
784  heap_free(buffer->maps);
785  heap_free(buffer);
786 }
787 
789 {
790  ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
791 
792  TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
793 
794  if (!refcount)
795  {
796  buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
797  resource_cleanup(&buffer->resource);
799  }
800 
801  return refcount;
802 }
803 
805 {
806  TRACE("buffer %p.\n", buffer);
807 
808  return buffer->resource.parent;
809 }
810 
811 /* The caller provides a context and binds the buffer */
813 {
815  HRESULT hr;
816 
817  /* No fencing needs to be done if the app promises not to overwrite
818  * existing data. */
820  return;
821 
823  {
824  GL_EXTCALL(glBufferData(buffer->buffer_type_hint, buffer->resource.size, NULL, buffer->buffer_object_usage));
825  checkGLcall("glBufferData");
826  return;
827  }
828 
829  if (!buffer->fence)
830  {
831  TRACE("Creating fence for buffer %p.\n", buffer);
832 
833  if (FAILED(hr = wined3d_fence_create(buffer->resource.device, &buffer->fence)))
834  {
836  FIXME("Fences not supported, dropping async buffer locks.\n");
837  else
838  ERR("Failed to create fence, hr %#x.\n", hr);
839  goto drop_fence;
840  }
841 
842  /* Since we don't know about old draws a glFinish is needed once */
843  gl_info->gl_ops.gl.p_glFinish();
844  return;
845  }
846 
847  TRACE("Synchronizing buffer %p.\n", buffer);
848  ret = wined3d_fence_wait(buffer->fence, buffer->resource.device);
849  switch (ret)
850  {
852  case WINED3D_FENCE_OK:
853  /* All done */
854  return;
855 
857  WARN("Cannot synchronize buffer lock due to a thread conflict.\n");
858  goto drop_fence;
859 
860  default:
861  ERR("wined3d_fence_wait() returned %u, dropping async buffer locks.\n", ret);
862  goto drop_fence;
863  }
864 
865 drop_fence:
866  if (buffer->fence)
867  {
869  buffer->fence = NULL;
870  }
871 
872  gl_info->gl_ops.gl.p_glFinish();
873  GL_EXTCALL(glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
874  checkGLcall("glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
875  buffer->flags &= ~WINED3D_BUFFER_APPLESYNC;
876 }
877 
879 {
880  buffer->flags &= ~WINED3D_BUFFER_DISCARD;
881 }
882 
883 /* Context activation is done by the caller. */
885  const struct wined3d_state *state)
886 {
887  const struct wined3d_gl_info *gl_info = context->gl_info;
888  BOOL decl_changed = FALSE;
889 
890  TRACE("buffer %p.\n", buffer);
891 
892  if (buffer->resource.map_count)
893  {
894  WARN("Buffer is mapped, skipping preload.\n");
895  return;
896  }
897 
899 
900  /* TODO: Make converting independent from VBOs */
901  if (!(buffer->flags & WINED3D_BUFFER_USE_BO))
902  {
903  /* Not doing any conversion */
904  return;
905  }
906 
908  {
909  ERR("Failed to prepare buffer location.\n");
910  return;
911  }
912 
913  /* Reading the declaration makes only sense if we have valid state information
914  * (i.e., if this function is called during draws). */
915  if (state)
916  {
917  DWORD fixup_flags = 0;
918 
919  if (!use_vs(state))
920  {
921  if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && !context->d3d_info->ffp_generic_attributes)
922  fixup_flags |= WINED3D_BUFFER_FIXUP_D3DCOLOR;
923  if (!context->d3d_info->xyzrhw)
924  fixup_flags |= WINED3D_BUFFER_FIXUP_XYZRHW;
925  }
926 
927  decl_changed = buffer_find_decl(buffer, &context->stream_info, state, fixup_flags);
928  buffer->flags |= WINED3D_BUFFER_HASDESC;
929  }
930 
931  if (!decl_changed && !(buffer->flags & WINED3D_BUFFER_HASDESC && buffer_is_dirty(buffer)))
932  {
933  ++buffer->draw_count;
934  if (buffer->draw_count > VB_RESETDECLCHANGE)
935  buffer->decl_change_count = 0;
936  if (buffer->draw_count > VB_RESETFULLCONVS)
937  buffer->full_conversion_count = 0;
938  return;
939  }
940 
941  /* If applications change the declaration over and over, reconverting all the time is a huge
942  * performance hit. So count the declaration changes and release the VBO if there are too many
943  * of them (and thus stop converting)
944  */
945  if (decl_changed)
946  {
947  ++buffer->decl_change_count;
948  buffer->draw_count = 0;
949 
950  if (buffer->decl_change_count > VB_MAXDECLCHANGES
951  || (buffer->conversion_map && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)))
952  {
953  FIXME("Too many declaration changes or converting dynamic buffer, stopping converting.\n");
955  return;
956  }
957 
958  /* The declaration changed, reload the whole buffer. */
959  WARN("Reloading buffer because of a vertex declaration change.\n");
961  }
962  else
963  {
964  /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that
965  * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
966  * decl changes and reset the decl change count after a specific number of them
967  */
968  if (buffer->conversion_map && buffer_is_fully_dirty(buffer))
969  {
970  ++buffer->full_conversion_count;
971  if (buffer->full_conversion_count > VB_MAXFULLCONVERSIONS)
972  {
973  FIXME("Too many full buffer conversions, stopping converting.\n");
975  return;
976  }
977  }
978  else
979  {
980  ++buffer->draw_count;
981  if (buffer->draw_count > VB_RESETDECLCHANGE)
982  buffer->decl_change_count = 0;
983  if (buffer->draw_count > VB_RESETFULLCONVS)
984  buffer->full_conversion_count = 0;
985  }
986  }
987 
989  ERR("Failed to load buffer location.\n");
990 }
991 
993 {
994  TRACE("buffer %p.\n", buffer);
995 
996  return &buffer->resource;
997 }
998 
1000 {
1001  struct wined3d_device *device = buffer->resource.device;
1002  struct wined3d_context *context;
1003  LONG count;
1004  BYTE *base;
1005 
1006  TRACE("buffer %p, offset %u, size %u, data %p, flags %#x.\n", buffer, offset, size, data, flags);
1007 
1008  count = ++buffer->resource.map_count;
1009 
1010  if (buffer->buffer_object)
1011  {
1012  unsigned int dirty_offset = offset, dirty_size = size;
1013 
1014  /* DISCARD invalidates the entire buffer, regardless of the specified
1015  * offset and size. Some applications also depend on the entire buffer
1016  * being uploaded in that case. Two such applications are Port Royale
1017  * and Darkstar One. */
1018  if (flags & WINED3D_MAP_DISCARD)
1019  {
1020  dirty_offset = 0;
1021  dirty_size = 0;
1022  }
1023 
1025  || (!(flags & WINED3D_MAP_WRITE) && (buffer->locations & WINED3D_LOCATION_SYSMEM))
1026  || buffer->flags & WINED3D_BUFFER_PIN_SYSMEM)
1027  {
1028  if (!(buffer->locations & WINED3D_LOCATION_SYSMEM))
1029  {
1033  }
1034 
1035  if (flags & WINED3D_MAP_WRITE)
1037  }
1038  else
1039  {
1040  const struct wined3d_gl_info *gl_info;
1041 
1043  gl_info = context->gl_info;
1044 
1045  if (flags & WINED3D_MAP_DISCARD)
1047  else
1049 
1050  if (flags & WINED3D_MAP_WRITE)
1051  buffer_invalidate_bo_range(buffer, dirty_offset, dirty_size);
1052 
1053  if ((flags & WINED3D_MAP_DISCARD) && buffer->resource.heap_memory)
1055 
1056  if (count == 1)
1057  {
1059 
1060  /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001
1061  * multitexture fill rate test seems to depend on this. When
1062  * we map a buffer with GL_MAP_INVALIDATE_BUFFER_BIT, the
1063  * driver is free to discard the previous contents of the
1064  * buffer. The r600g driver only does this when the buffer is
1065  * currently in use, while the proprietary NVIDIA driver
1066  * appears to do this unconditionally. */
1067  if (buffer->flags & WINED3D_BUFFER_DISCARD)
1069 
1070  if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
1071  {
1073  buffer->map_ptr = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint,
1074  0, buffer->resource.size, mapflags));
1075  checkGLcall("glMapBufferRange");
1076  }
1077  else
1078  {
1079  if (buffer->flags & WINED3D_BUFFER_APPLESYNC)
1080  buffer_sync_apple(buffer, flags, gl_info);
1081  buffer->map_ptr = GL_EXTCALL(glMapBuffer(buffer->buffer_type_hint,
1082  GL_READ_WRITE));
1083  checkGLcall("glMapBuffer");
1084  }
1085 
1086  if (((DWORD_PTR)buffer->map_ptr) & (RESOURCE_ALIGNMENT - 1))
1087  {
1088  WARN("Pointer %p is not %u byte aligned.\n", buffer->map_ptr, RESOURCE_ALIGNMENT);
1089 
1090  GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint));
1091  checkGLcall("glUnmapBuffer");
1092  buffer->map_ptr = NULL;
1093 
1094  if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)
1095  {
1096  /* The extra copy is more expensive than not using VBOs at
1097  * all on the Nvidia Linux driver, which is the only driver
1098  * that returns unaligned pointers.
1099  */
1100  TRACE("Dynamic buffer, dropping VBO.\n");
1102  }
1103  else
1104  {
1105  TRACE("Falling back to doublebuffered operation.\n");
1108  }
1109  TRACE("New pointer is %p.\n", buffer->resource.heap_memory);
1110  }
1111  }
1112 
1114  }
1115 
1116  if (flags & WINED3D_MAP_DISCARD)
1117  buffer->flags |= WINED3D_BUFFER_DISCARD;
1118  }
1119 
1120  base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory;
1121  *data = base + offset;
1122 
1123  TRACE("Returning memory at %p (base %p, offset %u).\n", *data, base, offset);
1124  /* TODO: check Flags compatibility with buffer->currentDesc.Usage (see MSDN) */
1125 
1126  return WINED3D_OK;
1127 }
1128 
1130 {
1131  ULONG i;
1132 
1133  TRACE("buffer %p.\n", buffer);
1134 
1135  /* In the case that the number of Unmap calls > the
1136  * number of Map calls, d3d returns always D3D_OK.
1137  * This is also needed to prevent Map from returning garbage on
1138  * the next call (this will happen if the lock_count is < 0). */
1139  if (!buffer->resource.map_count)
1140  {
1141  WARN("Unmap called without a previous map call.\n");
1142  return;
1143  }
1144 
1145  if (--buffer->resource.map_count)
1146  {
1147  /* Delay loading the buffer until everything is unlocked */
1148  TRACE("Ignoring unmap.\n");
1149  return;
1150  }
1151 
1152  if (buffer->map_ptr)
1153  {
1154  struct wined3d_device *device = buffer->resource.device;
1155  const struct wined3d_gl_info *gl_info;
1156  struct wined3d_context *context;
1157 
1159  gl_info = context->gl_info;
1160 
1162 
1163  if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
1164  {
1165  for (i = 0; i < buffer->modified_areas; ++i)
1166  {
1167  GL_EXTCALL(glFlushMappedBufferRange(buffer->buffer_type_hint,
1168  buffer->maps[i].offset, buffer->maps[i].size));
1169  checkGLcall("glFlushMappedBufferRange");
1170  }
1171  }
1172  else if (buffer->flags & WINED3D_BUFFER_APPLESYNC)
1173  {
1174  for (i = 0; i < buffer->modified_areas; ++i)
1175  {
1176  GL_EXTCALL(glFlushMappedBufferRangeAPPLE(buffer->buffer_type_hint,
1177  buffer->maps[i].offset, buffer->maps[i].size));
1178  checkGLcall("glFlushMappedBufferRangeAPPLE");
1179  }
1180  }
1181 
1182  GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint));
1184 
1186  buffer->map_ptr = NULL;
1187  }
1188 }
1189 
1190 void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_offset,
1191  struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size)
1192 {
1193  struct wined3d_bo_address dst, src;
1194  struct wined3d_context *context;
1195  DWORD dst_location;
1196 
1197  buffer_mark_used(dst_buffer);
1198  buffer_mark_used(src_buffer);
1199 
1200  dst_location = wined3d_buffer_get_memory(dst_buffer, &dst, dst_buffer->locations);
1201  dst.addr += dst_offset;
1202 
1203  wined3d_buffer_get_memory(src_buffer, &src, src_buffer->locations);
1204  src.addr += src_offset;
1205 
1206  context = context_acquire(dst_buffer->resource.device, NULL, 0);
1208  &src, src_buffer->buffer_type_hint, size);
1210 
1211  wined3d_buffer_invalidate_range(dst_buffer, ~dst_location, dst_offset, size);
1212 }
1213 
1215  const struct wined3d_box *box, const void *data)
1216 {
1217  struct wined3d_map_range range;
1218 
1219  if (box)
1220  {
1221  range.offset = box->left;
1222  range.size = box->right - box->left;
1223  }
1224  else
1225  {
1226  range.offset = 0;
1227  range.size = buffer->resource.size;
1228  }
1229 
1231 }
1232 
1234 {
1236 }
1237 
1239 {
1241 }
1242 
1244 {
1245  struct wined3d_context *context;
1246 
1247  context = context_acquire(resource->device, NULL, 0);
1250 }
1251 
1253  struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
1254 {
1256  UINT offset, size;
1257 
1258  if (sub_resource_idx)
1259  {
1260  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1261  return E_INVALIDARG;
1262  }
1263 
1264  if (box)
1265  {
1266  offset = box->left;
1267  size = box->right - box->left;
1268  }
1269  else
1270  {
1271  offset = size = 0;
1272  }
1273 
1274  map_desc->row_pitch = map_desc->slice_pitch = buffer->desc.byte_width;
1275  return wined3d_buffer_map(buffer, offset, size, (BYTE **)&map_desc->data, flags);
1276 }
1277 
1278 static HRESULT buffer_resource_sub_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx,
1279  struct wined3d_map_info *info, DWORD flags)
1280 {
1282 
1283  if (sub_resource_idx)
1284  {
1285  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1286  return E_INVALIDARG;
1287  }
1288 
1289  info->row_pitch = buffer->desc.byte_width;
1290  info->slice_pitch = buffer->desc.byte_width;
1291  info->size = buffer->resource.size;
1292 
1293  return WINED3D_OK;
1294 }
1295 
1296 static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
1297 {
1298  if (sub_resource_idx)
1299  {
1300  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1301  return E_INVALIDARG;
1302  }
1303 
1305  return WINED3D_OK;
1306 }
1307 
1309 {
1313  buffer_unload,
1317 };
1318 
1320  unsigned int bind_flags)
1321 {
1322  if (bind_flags == WINED3D_BIND_INDEX_BUFFER)
1323  return GL_ELEMENT_ARRAY_BUFFER;
1324 
1326  && gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
1327  return GL_TEXTURE_BUFFER;
1328 
1329  if (bind_flags & WINED3D_BIND_CONSTANT_BUFFER)
1330  return GL_UNIFORM_BUFFER;
1331 
1332  if (bind_flags & WINED3D_BIND_STREAM_OUTPUT)
1334 
1336  FIXME("Unhandled bind flags %#x.\n", bind_flags);
1337 
1338  return GL_ARRAY_BUFFER;
1339 }
1340 
1342  UINT size, DWORD usage, enum wined3d_format_id format_id, unsigned int access, unsigned int bind_flags,
1343  const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops)
1344 {
1345  const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1346  const struct wined3d_format *format = wined3d_get_format(gl_info, format_id, usage);
1347  BOOL dynamic_buffer_ok;
1348  HRESULT hr;
1349 
1350  if (!size)
1351  {
1352  WARN("Size 0 requested, returning E_INVALIDARG.\n");
1353  return E_INVALIDARG;
1354  }
1355 
1357  {
1358  WARN("Size %#x is not suitably aligned for constant buffers.\n", size);
1359  return E_INVALIDARG;
1360  }
1361 
1362  if (data && !data->data)
1363  {
1364  WARN("Invalid sub-resource data specified.\n");
1365  return E_INVALIDARG;
1366  }
1367 
1369  0, usage, access, size, 1, 1, size, parent, parent_ops, &buffer_resource_ops)))
1370  {
1371  WARN("Failed to initialize resource, hr %#x.\n", hr);
1372  return hr;
1373  }
1374  buffer->buffer_type_hint = buffer_type_hint_from_bind_flags(gl_info, bind_flags);
1375  buffer->bind_flags = bind_flags;
1376  buffer->locations = WINED3D_LOCATION_SYSMEM;
1377 
1378  if (!wined3d_resource_allocate_sysmem(&buffer->resource))
1379  return E_OUTOFMEMORY;
1380 
1381  TRACE("buffer %p, size %#x, usage %#x, format %s, memory @ %p.\n",
1382  buffer, buffer->resource.size, buffer->resource.usage,
1383  debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory);
1384 
1385  if (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
1387  {
1388  /* SWvp and managed buffers always return the same pointer in buffer
1389  * maps and retain data in DISCARD maps. Keep a system memory copy of
1390  * the buffer to provide the same behavior to the application. */
1391  TRACE("Using doublebuffer mode.\n");
1393  }
1394 
1395  /* Observations show that draw_primitive_immediate_mode() is faster on
1396  * dynamic vertex buffers than converting + draw_primitive_arrays().
1397  * (Half-Life 2 and others.) */
1398  dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE];
1399 
1400  if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
1401  {
1402  TRACE("Not creating a BO because GL_ARB_vertex_buffer is not supported.\n");
1403  }
1404  else if (!(access & WINED3D_RESOURCE_ACCESS_GPU))
1405  {
1406  TRACE("Not creating a BO because the buffer is not GPU accessible.\n");
1407  }
1408  else if (!dynamic_buffer_ok && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
1409  {
1410  TRACE("Not creating a BO because the buffer has dynamic usage and no GL support.\n");
1411  }
1412  else
1413  {
1414  buffer->flags |= WINED3D_BUFFER_USE_BO;
1415  }
1416 
1417  if (!(buffer->maps = heap_alloc(sizeof(*buffer->maps))))
1418  {
1419  ERR("Out of memory.\n");
1420  buffer_unload(&buffer->resource);
1421  resource_cleanup(&buffer->resource);
1422  wined3d_resource_wait_idle(&buffer->resource);
1423  return E_OUTOFMEMORY;
1424  }
1425  buffer->maps_size = 1;
1426 
1427  if (data)
1429  0, NULL, data->data, data->row_pitch, data->slice_pitch, 0);
1430 
1431  return WINED3D_OK;
1432 }
1433 
1435  const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
1436  struct wined3d_buffer **buffer)
1437 {
1438  struct wined3d_buffer *object;
1439  HRESULT hr;
1440 
1441  TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1442  device, desc, data, parent, parent_ops, buffer);
1443 
1444  if (!(object = heap_alloc_zero(sizeof(*object))))
1445  return E_OUTOFMEMORY;
1446 
1447  if (FAILED(hr = buffer_init(object, device, desc->byte_width, desc->usage, WINED3DFMT_UNKNOWN,
1448  desc->access, desc->bind_flags, data, parent, parent_ops)))
1449  {
1450  WARN("Failed to initialize buffer, hr %#x.\n", hr);
1451  heap_free(object);
1452  return hr;
1453  }
1454  object->desc = *desc;
1455 
1456  TRACE("Created buffer %p.\n", object);
1457 
1458  *buffer = object;
1459 
1460  return WINED3D_OK;
1461 }
HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, enum wined3d_resource_type type, const struct wined3d_format *format, enum wined3d_multisample_type multisample_type, unsigned int multisample_quality, unsigned int usage, unsigned int access, unsigned int width, unsigned int height, unsigned int depth, unsigned int size, void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops)
Definition: resource.c:59
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
Definition: wined3d.h:1013
static BOOL buffer_process_converted_attribute(struct wined3d_buffer *buffer, const enum wined3d_buffer_conversion_type conversion_type, const struct wined3d_stream_info_element *attrib, DWORD *stride_this_run)
Definition: buffer.c:272
static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const struct wined3d_gl_info *gl_info)
Definition: buffer.c:812
#define WINED3D_BUFFER_PIN_SYSMEM
Definition: buffer.c:34
static void buffer_bind(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:136
#define TRUE
Definition: types.h:120
#define VB_RESETDECLCHANGE
Definition: buffer.c:39
BYTE * wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:703
static void wined3d_buffer_validate_location(struct wined3d_buffer *buffer, DWORD location)
Definition: buffer.c:101
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
#define GL_TRANSFORM_FEEDBACK_BUFFER
Definition: glext.h:557
struct opengl_funcs gl_ops
static HRESULT buffer_resource_sub_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_info *info, DWORD flags)
Definition: buffer.c:1278
static void buffer_conversion_upload(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:552
#define DWORD_PTR
Definition: treelist.c:76
HRESULT wined3d_fence_create(struct wined3d_device *device, struct wined3d_fence **fence)
Definition: query.c:303
HRESULT hr
Definition: shlfolder.c:183
#define error(str)
Definition: mkdosfs.c:1605
#define WINED3D_BIND_VERTEX_BUFFER
Definition: wined3d.h:899
BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, struct wined3d_context *context, DWORD location)
Definition: buffer.c:638
#define WINED3D_BUFFER_APPLESYNC
Definition: buffer.c:36
#define RESOURCE_ALIGNMENT
Definition: http.c:6587
static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, UINT size, DWORD usage, enum wined3d_format_id format_id, unsigned int access, unsigned int bind_flags, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops)
Definition: buffer.c:1341
#define GL_TEXTURE_BUFFER
Definition: glext.h:748
#define GL_FALSE
Definition: gl.h:173
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define WINED3DUSAGE_DYNAMIC
Definition: wined3d.h:916
static void buffer_mark_used(struct wined3d_buffer *buffer)
Definition: buffer.c:878
#define WARN(fmt,...)
Definition: debug.h:111
#define WINED3D_BUFFER_FIXUP_D3DCOLOR
Definition: buffer.c:327
static BOOL buffer_create_buffer_object(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:197
GLintptr offset
Definition: glext.h:5920
static void wined3d_buffer_invalidate_range(struct wined3d_buffer *buffer, DWORD location, unsigned int offset, unsigned int size)
Definition: buffer.c:113
#define STATE_STREAM_OUTPUT
const struct wined3d_format * wined3d_get_format(const struct wined3d_gl_info *gl_info, enum wined3d_format_id format_id, unsigned int resource_usage)
Definition: utils.c:3773
#define WINED3D_BIND_UNORDERED_ACCESS
Definition: wined3d.h:906
#define GL_NO_ERROR
Definition: gl.h:693
#define STATE_INDEXBUFFER
#define WINED3D_LOCATION_BUFFER
GLuint buffer
Definition: glext.h:5915
GLuint GLuint end
Definition: gl.h:1545
void wined3d_cs_destroy_object(struct wined3d_cs *cs, void(*callback)(void *object), void *object)
Definition: cs.c:1907
void resource_unload(struct wined3d_resource *resource)
Definition: resource.c:247
int vertex_count
Definition: d3drm.c:2807
void wined3d_fence_destroy(struct wined3d_fence *fence)
Definition: query.c:286
static void * heap_calloc(SIZE_T count, SIZE_T size)
Definition: heap.h:49
#define WINED3D_BUFFER_HASDESC
Definition: buffer.c:32
#define GL_READ_WRITE
Definition: glext.h:343
#define DWORD
Definition: nt_native.h:44
#define GL_BUFFER_SERIALIZED_MODIFY_APPLE
Definition: glext.h:4547
DWORD wined3d_buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_bo_address *data, DWORD locations)
Definition: buffer.c:710
struct wined3d_resource resource
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
static ULONG buffer_resource_incref(struct wined3d_resource *resource)
Definition: buffer.c:1233
static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
Definition: buffer.c:1296
static void wined3d_resource_wait_idle(struct wined3d_resource *resource)
ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer)
Definition: buffer.c:525
#define WINED3D_BUFFER_DISCARD
Definition: buffer.c:35
struct wined3d_bo_address data
#define WINED3D_BIND_SHADER_RESOURCE
Definition: wined3d.h:902
static void wined3d_buffer_unmap(struct wined3d_buffer *buffer)
Definition: buffer.c:1129
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct wined3d_stream_info_element elements[MAX_ATTRIBS]
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define WINED3D_BIND_INDEX_BUFFER
Definition: wined3d.h:900
static GLenum buffer_type_hint_from_bind_flags(const struct wined3d_gl_info *gl_info, unsigned int bind_flags)
Definition: buffer.c:1319
void *CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
Definition: buffer.c:804
const char * wined3d_debug_location(DWORD location)
Definition: utils.c:6306
unsigned int BOOL
Definition: ntddk_ex.h:94
wined3d_buffer_conversion_type
GLuint base
Definition: 3dtext.c:35
long LONG
Definition: pedump.c:60
Definition: devices.h:37
static BOOL wined3d_resource_access_is_managed(unsigned int access)
#define FIXME(fmt,...)
Definition: debug.h:110
BOOL supported[WINED3D_GL_EXT_COUNT]
unsigned int idx
Definition: utils.c:41
#define WINED3DUSAGE_STATICDECL
Definition: wined3d.h:929
static unsigned int fixup_transformed_pos(struct wined3d_vec4 *p)
Definition: buffer.c:510
#define E_INVALIDARG
Definition: ddrawi.h:101
GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
Definition: resource.c:508
const struct builtin_class_descr * desc
Definition: regcontrol.c:48
smooth NULL
Definition: ftsmooth.c:416
static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, DWORD location)
Definition: buffer.c:608
unsigned int GLbitfield
Definition: gl.h:152
#define GL_BUFFER_FLUSHING_UNMAP_APPLE
Definition: glext.h:4548
static void buffer_clear_dirty_areas(struct wined3d_buffer *This)
Definition: buffer.c:85
static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct wined3d_stream_info *si, const struct wined3d_state *state, UINT attrib_idx, DWORD fixup_flags, DWORD *stride_this_run)
Definition: buffer.c:330
void context_release(struct wined3d_context *context)
Definition: context.c:1559
void wined3d_buffer_upload_data(struct wined3d_buffer *buffer, struct wined3d_context *context, const struct wined3d_box *box, const void *data)
Definition: buffer.c:1214
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
const char * debug_glerror(GLenum error)
Definition: utils.c:4737
#define GL_UNIFORM_BUFFER
Definition: glext.h:1846
#define STATE_STREAMSRC
#define GL_EXTCALL(f)
#define WINED3D_MAP_DISCARD
Definition: wined3d.h:944
#define TRACE(s)
Definition: solgame.cpp:4
void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD location)
Definition: buffer.c:130
GLsizeiptr size
Definition: glext.h:5919
#define WINED3D_BIND_CONSTANT_BUFFER
Definition: wined3d.h:901
r parent
Definition: btrfs.c:2708
if(!(yy_init))
Definition: macro.lex.yy.c:714
LONG HRESULT
Definition: typedefs.h:77
BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource)
Definition: resource.c:477
ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
Definition: buffer.c:788
BOOL wined3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
Definition: utils.c:6436
#define WINED3D_OK
Definition: wined3d.h:37
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WINED3D_BUFFER_FIXUP_XYZRHW
Definition: buffer.c:328
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
#define VB_MAXFULLCONVERSIONS
Definition: buffer.c:40
int ret
static BOOL buffer_is_dirty(const struct wined3d_buffer *buffer)
Definition: buffer.c:90
static void wined3d_buffer_drop_bo(struct wined3d_buffer *buffer)
Definition: buffer.c:764
#define InterlockedDecrement
Definition: armddk.h:52
#define WINED3D_MAP_WRITE
Definition: wined3d.h:947
#define WINED3D_LOCATION_SYSMEM
static const struct wined3d_resource_ops buffer_resource_ops
Definition: buffer.c:1308
static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, unsigned int offset, unsigned int size)
Definition: buffer.c:56
void context_end_transform_feedback(struct wined3d_context *context)
Definition: context.c:4103
static int state
Definition: maze.c:121
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
GLsizei const GLint * locations
Definition: glext.h:10542
static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UINT size, BYTE **data, DWORD flags)
Definition: buffer.c:999
GLenum src
Definition: glext.h:6340
static struct wined3d_buffer * buffer_from_resource(struct wined3d_resource *resource)
unsigned int GLenum
Definition: gl.h:150
uint32_t DWORD_PTR
Definition: typedefs.h:63
static unsigned int fixup_d3dcolor(DWORD *dst_color)
Definition: buffer.c:489
#define WINED3D_RESOURCE_ACCESS_GPU
Definition: wined3d.h:55
#define WINED3D_MAP_NOOVERWRITE
Definition: wined3d.h:943
#define location(file, line)
Definition: kmtest.h:18
GLenum GLint * range
Definition: glext.h:7539
wined3d_format_id
Definition: wined3d.h:105
#define ERR(fmt,...)
Definition: debug.h:109
struct wined3d_context * context_acquire(const struct wined3d_device *device, struct wined3d_texture *texture, unsigned int sub_resource_idx)
Definition: context.c:4218
static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:142
static BOOL buffer_find_decl(struct wined3d_buffer *This, const struct wined3d_stream_info *si, const struct wined3d_state *state, DWORD fixup_flags)
Definition: buffer.c:368
#define InterlockedIncrement
Definition: armddk.h:53
#define CDECL
Definition: compat.h:21
struct wined3d_resource *CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer)
Definition: buffer.c:992
const struct wined3d_format * format
void context_copy_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *dst, GLenum dst_binding, const struct wined3d_bo_address *src, GLenum src_binding, size_t size)
Definition: context.c:2613
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint start
Definition: gl.h:1545
static void buffer_resource_preload(struct wined3d_resource *resource)
Definition: buffer.c:1243
wined3d_fence_result
#define GL_TRUE
Definition: gl.h:174
GLenum GLenum dst
Definition: glext.h:6340
#define checkGLcall(A)
#define WINED3DERR_NOTAVAILABLE
Definition: wined3d.h:46
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define GL_ARRAY_BUFFER
Definition: glext.h:336
#define VB_RESETFULLCONVS
Definition: buffer.c:41
void device_invalidate_state(const struct wined3d_device *device, DWORD state)
Definition: device.c:5293
HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
Definition: buffer.c:1434
void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, unsigned int depth_pitch, unsigned int flags)
Definition: device.c:4321
enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence, const struct wined3d_device *device)
Definition: query.c:169
#define WINED3D_CONSTANT_BUFFER_ALIGNMENT
unsigned int ULONG
Definition: retypes.h:1
static BOOL buffer_is_fully_dirty(const struct wined3d_buffer *buffer)
Definition: buffer.c:95
unsigned int sub_resource_idx
void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *context, const struct wined3d_state *state)
Definition: buffer.c:884
static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
Definition: buffer.c:1252
static UINT format_id
Definition: clipboard.c:1343
const struct wined3d_gl_info * gl_info
void context_bind_bo(struct wined3d_context *context, GLenum binding, GLuint name)
Definition: context.c:2493
#define WINED3D_LOCATION_DISCARDED
static void wined3d_buffer_evict_sysmem(struct wined3d_buffer *buffer)
Definition: buffer.c:43
GLfloat GLfloat p
Definition: glext.h:8902
#define WINED3D_BUFFER_USE_BO
Definition: buffer.c:33
static BOOL use_vs(const struct wined3d_state *state)
const char * debug_d3dusage(DWORD usage)
Definition: utils.c:4159
WINE_DEFAULT_DEBUG_CHANNEL(d3d8)
static void wined3d_buffer_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context, const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
Definition: buffer.c:535
static void wined3d_buffer_destroy_object(void *object)
Definition: buffer.c:770
void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size)
Definition: buffer.c:1190
const char * debug_d3dformat(enum wined3d_format_id format_id)
Definition: utils.c:3922
void resource_cleanup(struct wined3d_resource *resource)
Definition: resource.c:227
#define STATE_CONSTANT_BUFFER(a)
#define GL_STREAM_DRAW_ARB
Definition: glext.h:1506
#define GL_ELEMENT_ARRAY_BUFFER
Definition: glext.h:337
#define GL_STATIC_DRAW
Definition: glext.h:350
void * object
Definition: jmemsys.h:48
static ULONG buffer_resource_decref(struct wined3d_resource *resource)
Definition: buffer.c:1238
#define VB_MAXDECLCHANGES
Definition: buffer.c:38
static void buffer_unload(struct wined3d_resource *resource)
Definition: buffer.c:735
Definition: palette.c:467
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define WINED3D_BIND_STREAM_OUTPUT
Definition: wined3d.h:903
void wined3d_resource_free_sysmem(struct wined3d_resource *resource)
Definition: resource.c:497