ReactOS  0.4.14-dev-115-g4576127
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  {
619  ERR("Failed to allocate system memory.\n");
620  return FALSE;
621  }
622  return TRUE;
623 
625  if (buffer->buffer_object)
626  return TRUE;
627 
628  if (!(buffer->flags & WINED3D_BUFFER_USE_BO))
629  {
630  WARN("Trying to create BO for buffer %p with no WINED3D_BUFFER_USE_BO.\n", buffer);
631  return FALSE;
632  }
634 
635  default:
636  ERR("Invalid location %s.\n", wined3d_debug_location(location));
637  return FALSE;
638  }
639 }
640 
643 {
644  const struct wined3d_gl_info *gl_info = context->gl_info;
645 
646  TRACE("buffer %p, context %p, location %s.\n",
648 
649  if (buffer->locations & location)
650  {
651  TRACE("Location (%#x) is already up to date.\n", location);
652  return TRUE;
653  }
654 
655  if (!buffer->locations)
656  {
657  ERR("Buffer %p does not have any up to date location.\n", buffer);
660  }
661 
662  TRACE("Current buffer location %s.\n", wined3d_debug_location(buffer->locations));
663 
665  return FALSE;
666 
667  if (buffer->locations & WINED3D_LOCATION_DISCARDED)
668  {
669  TRACE("Buffer previously discarded, nothing to do.\n");
672  return TRUE;
673  }
674 
675  switch (location)
676  {
679  GL_EXTCALL(glGetBufferSubData(buffer->buffer_type_hint, 0, buffer->resource.size,
680  buffer->resource.heap_memory));
681  checkGLcall("buffer download");
682  break;
683 
685  if (!buffer->conversion_map)
686  wined3d_buffer_upload_ranges(buffer, context, buffer->resource.heap_memory,
687  0, buffer->modified_areas, buffer->maps);
688  else
690  break;
691 
692  default:
693  ERR("Invalid location %s.\n", wined3d_debug_location(location));
694  return FALSE;
695  }
696 
698  if (buffer->resource.heap_memory && location == WINED3D_LOCATION_BUFFER
699  && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
701 
702  return TRUE;
703 }
704 
705 /* Context activation is done by the caller. */
707 {
710  return buffer->resource.heap_memory;
711 }
712 
715 {
716  TRACE("buffer %p, data %p, locations %s.\n",
718 
720  {
721  data->buffer_object = buffer->buffer_object;
722  data->addr = NULL;
724  }
726  {
727  data->buffer_object = 0;
728  data->addr = buffer->resource.heap_memory;
730  }
731 
732  ERR("Unexpected locations %s.\n", wined3d_debug_location(locations));
733  data->buffer_object = 0;
734  data->addr = NULL;
735  return 0;
736 }
737 
739 {
741 
742  TRACE("buffer %p.\n", buffer);
743 
744  if (buffer->buffer_object)
745  {
746  struct wined3d_context *context;
747 
748  context = context_acquire(resource->device, NULL, 0);
749 
754 
756 
757  heap_free(buffer->conversion_map);
758  buffer->conversion_map = NULL;
759  buffer->stride = 0;
760  buffer->conversion_stride = 0;
761  buffer->flags &= ~WINED3D_BUFFER_HASDESC;
762  }
763 
765 }
766 
768 {
769  buffer->flags &= ~WINED3D_BUFFER_USE_BO;
770  buffer_unload(&buffer->resource);
771 }
772 
773 static void wined3d_buffer_destroy_object(void *object)
774 {
775  struct wined3d_buffer *buffer = object;
776  struct wined3d_context *context;
777 
778  if (buffer->buffer_object)
779  {
780  context = context_acquire(buffer->resource.device, NULL, 0);
783 
784  heap_free(buffer->conversion_map);
785  }
786 
787  heap_free(buffer->maps);
788  heap_free(buffer);
789 }
790 
792 {
793  ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
794 
795  TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
796 
797  if (!refcount)
798  {
799  buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
800  resource_cleanup(&buffer->resource);
802  }
803 
804  return refcount;
805 }
806 
808 {
809  TRACE("buffer %p.\n", buffer);
810 
811  return buffer->resource.parent;
812 }
813 
814 /* The caller provides a context and binds the buffer */
816 {
818  HRESULT hr;
819 
820  /* No fencing needs to be done if the app promises not to overwrite
821  * existing data. */
823  return;
824 
826  {
827  GL_EXTCALL(glBufferData(buffer->buffer_type_hint, buffer->resource.size, NULL, buffer->buffer_object_usage));
828  checkGLcall("glBufferData");
829  return;
830  }
831 
832  if (!buffer->fence)
833  {
834  TRACE("Creating fence for buffer %p.\n", buffer);
835 
836  if (FAILED(hr = wined3d_fence_create(buffer->resource.device, &buffer->fence)))
837  {
839  FIXME("Fences not supported, dropping async buffer locks.\n");
840  else
841  ERR("Failed to create fence, hr %#x.\n", hr);
842  goto drop_fence;
843  }
844 
845  /* Since we don't know about old draws a glFinish is needed once */
846  gl_info->gl_ops.gl.p_glFinish();
847  return;
848  }
849 
850  TRACE("Synchronizing buffer %p.\n", buffer);
851  ret = wined3d_fence_wait(buffer->fence, buffer->resource.device);
852  switch (ret)
853  {
855  case WINED3D_FENCE_OK:
856  /* All done */
857  return;
858 
860  WARN("Cannot synchronize buffer lock due to a thread conflict.\n");
861  goto drop_fence;
862 
863  default:
864  ERR("wined3d_fence_wait() returned %u, dropping async buffer locks.\n", ret);
865  goto drop_fence;
866  }
867 
868 drop_fence:
869  if (buffer->fence)
870  {
872  buffer->fence = NULL;
873  }
874 
875  gl_info->gl_ops.gl.p_glFinish();
876  GL_EXTCALL(glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
877  checkGLcall("glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
878  buffer->flags &= ~WINED3D_BUFFER_APPLESYNC;
879 }
880 
882 {
883  buffer->flags &= ~WINED3D_BUFFER_DISCARD;
884 }
885 
886 /* Context activation is done by the caller. */
888  const struct wined3d_state *state)
889 {
890  const struct wined3d_gl_info *gl_info = context->gl_info;
891  BOOL decl_changed = FALSE;
892 
893  TRACE("buffer %p.\n", buffer);
894 
895  if (buffer->resource.map_count)
896  {
897  WARN("Buffer is mapped, skipping preload.\n");
898  return;
899  }
900 
902 
903  /* TODO: Make converting independent from VBOs */
904  if (!(buffer->flags & WINED3D_BUFFER_USE_BO))
905  {
906  /* Not doing any conversion */
907  return;
908  }
909 
911  {
912  ERR("Failed to prepare buffer location.\n");
913  return;
914  }
915 
916  /* Reading the declaration makes only sense if we have valid state information
917  * (i.e., if this function is called during draws). */
918  if (state)
919  {
920  DWORD fixup_flags = 0;
921 
922  if (!use_vs(state))
923  {
924  if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && !context->d3d_info->ffp_generic_attributes)
925  fixup_flags |= WINED3D_BUFFER_FIXUP_D3DCOLOR;
926  if (!context->d3d_info->xyzrhw)
927  fixup_flags |= WINED3D_BUFFER_FIXUP_XYZRHW;
928  }
929 
930  decl_changed = buffer_find_decl(buffer, &context->stream_info, state, fixup_flags);
931  buffer->flags |= WINED3D_BUFFER_HASDESC;
932  }
933 
934  if (!decl_changed && !(buffer->flags & WINED3D_BUFFER_HASDESC && buffer_is_dirty(buffer)))
935  {
936  ++buffer->draw_count;
937  if (buffer->draw_count > VB_RESETDECLCHANGE)
938  buffer->decl_change_count = 0;
939  if (buffer->draw_count > VB_RESETFULLCONVS)
940  buffer->full_conversion_count = 0;
941  return;
942  }
943 
944  /* If applications change the declaration over and over, reconverting all the time is a huge
945  * performance hit. So count the declaration changes and release the VBO if there are too many
946  * of them (and thus stop converting)
947  */
948  if (decl_changed)
949  {
950  ++buffer->decl_change_count;
951  buffer->draw_count = 0;
952 
953  if (buffer->decl_change_count > VB_MAXDECLCHANGES
954  || (buffer->conversion_map && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)))
955  {
956  FIXME("Too many declaration changes or converting dynamic buffer, stopping converting.\n");
958  return;
959  }
960 
961  /* The declaration changed, reload the whole buffer. */
962  WARN("Reloading buffer because of a vertex declaration change.\n");
964  }
965  else
966  {
967  /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that
968  * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
969  * decl changes and reset the decl change count after a specific number of them
970  */
971  if (buffer->conversion_map && buffer_is_fully_dirty(buffer))
972  {
973  ++buffer->full_conversion_count;
974  if (buffer->full_conversion_count > VB_MAXFULLCONVERSIONS)
975  {
976  FIXME("Too many full buffer conversions, stopping converting.\n");
978  return;
979  }
980  }
981  else
982  {
983  ++buffer->draw_count;
984  if (buffer->draw_count > VB_RESETDECLCHANGE)
985  buffer->decl_change_count = 0;
986  if (buffer->draw_count > VB_RESETFULLCONVS)
987  buffer->full_conversion_count = 0;
988  }
989  }
990 
992  ERR("Failed to load buffer location.\n");
993 }
994 
996 {
997  TRACE("buffer %p.\n", buffer);
998 
999  return &buffer->resource;
1000 }
1001 
1003 {
1004  struct wined3d_device *device = buffer->resource.device;
1005  struct wined3d_context *context;
1006  LONG count;
1007  BYTE *base;
1008 
1009  TRACE("buffer %p, offset %u, size %u, data %p, flags %#x.\n", buffer, offset, size, data, flags);
1010 
1011  count = ++buffer->resource.map_count;
1012 
1013  if (buffer->buffer_object)
1014  {
1015  unsigned int dirty_offset = offset, dirty_size = size;
1016 
1017  /* DISCARD invalidates the entire buffer, regardless of the specified
1018  * offset and size. Some applications also depend on the entire buffer
1019  * being uploaded in that case. Two such applications are Port Royale
1020  * and Darkstar One. */
1021  if (flags & WINED3D_MAP_DISCARD)
1022  {
1023  dirty_offset = 0;
1024  dirty_size = 0;
1025  }
1026 
1028  || (!(flags & WINED3D_MAP_WRITE) && (buffer->locations & WINED3D_LOCATION_SYSMEM))
1029  || buffer->flags & WINED3D_BUFFER_PIN_SYSMEM)
1030  {
1031  if (!(buffer->locations & WINED3D_LOCATION_SYSMEM))
1032  {
1036  }
1037 
1038  if (flags & WINED3D_MAP_WRITE)
1040  }
1041  else
1042  {
1043  const struct wined3d_gl_info *gl_info;
1044 
1046  gl_info = context->gl_info;
1047 
1048  if (flags & WINED3D_MAP_DISCARD)
1050  else
1052 
1053  if (flags & WINED3D_MAP_WRITE)
1054  buffer_invalidate_bo_range(buffer, dirty_offset, dirty_size);
1055 
1056  if ((flags & WINED3D_MAP_DISCARD) && buffer->resource.heap_memory)
1058 
1059  if (count == 1)
1060  {
1062 
1063  /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001
1064  * multitexture fill rate test seems to depend on this. When
1065  * we map a buffer with GL_MAP_INVALIDATE_BUFFER_BIT, the
1066  * driver is free to discard the previous contents of the
1067  * buffer. The r600g driver only does this when the buffer is
1068  * currently in use, while the proprietary NVIDIA driver
1069  * appears to do this unconditionally. */
1070  if (buffer->flags & WINED3D_BUFFER_DISCARD)
1072 
1073  if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
1074  {
1076  buffer->map_ptr = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint,
1077  0, buffer->resource.size, mapflags));
1078  checkGLcall("glMapBufferRange");
1079  }
1080  else
1081  {
1082  if (buffer->flags & WINED3D_BUFFER_APPLESYNC)
1083  buffer_sync_apple(buffer, flags, gl_info);
1084  buffer->map_ptr = GL_EXTCALL(glMapBuffer(buffer->buffer_type_hint,
1085  GL_READ_WRITE));
1086  checkGLcall("glMapBuffer");
1087  }
1088 
1089  if (((DWORD_PTR)buffer->map_ptr) & (RESOURCE_ALIGNMENT - 1))
1090  {
1091  WARN("Pointer %p is not %u byte aligned.\n", buffer->map_ptr, RESOURCE_ALIGNMENT);
1092 
1093  GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint));
1094  checkGLcall("glUnmapBuffer");
1095  buffer->map_ptr = NULL;
1096 
1097  if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)
1098  {
1099  /* The extra copy is more expensive than not using VBOs at
1100  * all on the Nvidia Linux driver, which is the only driver
1101  * that returns unaligned pointers.
1102  */
1103  TRACE("Dynamic buffer, dropping VBO.\n");
1105  }
1106  else
1107  {
1108  TRACE("Falling back to doublebuffered operation.\n");
1111  }
1112  TRACE("New pointer is %p.\n", buffer->resource.heap_memory);
1113  }
1114  }
1115 
1117  }
1118 
1119  if (flags & WINED3D_MAP_DISCARD)
1120  buffer->flags |= WINED3D_BUFFER_DISCARD;
1121  }
1122 
1123  base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory;
1124  *data = base + offset;
1125 
1126  TRACE("Returning memory at %p (base %p, offset %u).\n", *data, base, offset);
1127  /* TODO: check Flags compatibility with buffer->currentDesc.Usage (see MSDN) */
1128 
1129  return WINED3D_OK;
1130 }
1131 
1133 {
1134  ULONG i;
1135 
1136  TRACE("buffer %p.\n", buffer);
1137 
1138  /* In the case that the number of Unmap calls > the
1139  * number of Map calls, d3d returns always D3D_OK.
1140  * This is also needed to prevent Map from returning garbage on
1141  * the next call (this will happen if the lock_count is < 0). */
1142  if (!buffer->resource.map_count)
1143  {
1144  WARN("Unmap called without a previous map call.\n");
1145  return;
1146  }
1147 
1148  if (--buffer->resource.map_count)
1149  {
1150  /* Delay loading the buffer until everything is unlocked */
1151  TRACE("Ignoring unmap.\n");
1152  return;
1153  }
1154 
1155  if (buffer->map_ptr)
1156  {
1157  struct wined3d_device *device = buffer->resource.device;
1158  const struct wined3d_gl_info *gl_info;
1159  struct wined3d_context *context;
1160 
1162  gl_info = context->gl_info;
1163 
1165 
1166  if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
1167  {
1168  for (i = 0; i < buffer->modified_areas; ++i)
1169  {
1170  GL_EXTCALL(glFlushMappedBufferRange(buffer->buffer_type_hint,
1171  buffer->maps[i].offset, buffer->maps[i].size));
1172  checkGLcall("glFlushMappedBufferRange");
1173  }
1174  }
1175  else if (buffer->flags & WINED3D_BUFFER_APPLESYNC)
1176  {
1177  for (i = 0; i < buffer->modified_areas; ++i)
1178  {
1179  GL_EXTCALL(glFlushMappedBufferRangeAPPLE(buffer->buffer_type_hint,
1180  buffer->maps[i].offset, buffer->maps[i].size));
1181  checkGLcall("glFlushMappedBufferRangeAPPLE");
1182  }
1183  }
1184 
1185  GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint));
1187  gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
1189 
1191  buffer->map_ptr = NULL;
1192  }
1193 }
1194 
1195 void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_offset,
1196  struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size)
1197 {
1198  struct wined3d_bo_address dst, src;
1199  struct wined3d_context *context;
1200  DWORD dst_location;
1201 
1202  buffer_mark_used(dst_buffer);
1203  buffer_mark_used(src_buffer);
1204 
1205  dst_location = wined3d_buffer_get_memory(dst_buffer, &dst, dst_buffer->locations);
1206  dst.addr += dst_offset;
1207 
1208  wined3d_buffer_get_memory(src_buffer, &src, src_buffer->locations);
1209  src.addr += src_offset;
1210 
1211  context = context_acquire(dst_buffer->resource.device, NULL, 0);
1213  &src, src_buffer->buffer_type_hint, size);
1215 
1216  wined3d_buffer_invalidate_range(dst_buffer, ~dst_location, dst_offset, size);
1217 }
1218 
1220  const struct wined3d_box *box, const void *data)
1221 {
1222  struct wined3d_map_range range;
1223 
1224  if (box)
1225  {
1226  range.offset = box->left;
1227  range.size = box->right - box->left;
1228  }
1229  else
1230  {
1231  range.offset = 0;
1232  range.size = buffer->resource.size;
1233  }
1234 
1236 }
1237 
1239 {
1241 }
1242 
1244 {
1246 }
1247 
1249 {
1250  struct wined3d_context *context;
1251 
1252  context = context_acquire(resource->device, NULL, 0);
1255 }
1256 
1258  struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
1259 {
1261  UINT offset, size;
1262 
1263  if (sub_resource_idx)
1264  {
1265  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1266  return E_INVALIDARG;
1267  }
1268 
1269  if (box)
1270  {
1271  offset = box->left;
1272  size = box->right - box->left;
1273  }
1274  else
1275  {
1276  offset = size = 0;
1277  }
1278 
1279  map_desc->row_pitch = map_desc->slice_pitch = buffer->desc.byte_width;
1280  return wined3d_buffer_map(buffer, offset, size, (BYTE **)&map_desc->data, flags);
1281 }
1282 
1283 static HRESULT buffer_resource_sub_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx,
1284  struct wined3d_map_info *info, DWORD flags)
1285 {
1287 
1288  if (sub_resource_idx)
1289  {
1290  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1291  return E_INVALIDARG;
1292  }
1293 
1294  info->row_pitch = buffer->desc.byte_width;
1295  info->slice_pitch = buffer->desc.byte_width;
1296  info->size = buffer->resource.size;
1297 
1298  return WINED3D_OK;
1299 }
1300 
1301 static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
1302 {
1303  if (sub_resource_idx)
1304  {
1305  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
1306  return E_INVALIDARG;
1307  }
1308 
1310  return WINED3D_OK;
1311 }
1312 
1314 {
1318  buffer_unload,
1322 };
1323 
1325  unsigned int bind_flags)
1326 {
1327  if (bind_flags == WINED3D_BIND_INDEX_BUFFER)
1328  return GL_ELEMENT_ARRAY_BUFFER;
1329 
1331  && gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
1332  return GL_TEXTURE_BUFFER;
1333 
1334  if (bind_flags & WINED3D_BIND_CONSTANT_BUFFER)
1335  return GL_UNIFORM_BUFFER;
1336 
1337  if (bind_flags & WINED3D_BIND_STREAM_OUTPUT)
1339 
1341  FIXME("Unhandled bind flags %#x.\n", bind_flags);
1342 
1343  return GL_ARRAY_BUFFER;
1344 }
1345 
1347  UINT size, DWORD usage, enum wined3d_format_id format_id, unsigned int access, unsigned int bind_flags,
1348  const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops)
1349 {
1350  const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1351  const struct wined3d_format *format = wined3d_get_format(gl_info, format_id, usage);
1352  BOOL dynamic_buffer_ok;
1353  HRESULT hr;
1354 
1355  if (!size)
1356  {
1357  WARN("Size 0 requested, returning E_INVALIDARG.\n");
1358  return E_INVALIDARG;
1359  }
1360 
1362  {
1363  WARN("Size %#x is not suitably aligned for constant buffers.\n", size);
1364  return E_INVALIDARG;
1365  }
1366 
1367  if (data && !data->data)
1368  {
1369  WARN("Invalid sub-resource data specified.\n");
1370  return E_INVALIDARG;
1371  }
1372 
1374  0, usage, access, size, 1, 1, size, parent, parent_ops, &buffer_resource_ops)))
1375  {
1376  WARN("Failed to initialize resource, hr %#x.\n", hr);
1377  return hr;
1378  }
1379  buffer->buffer_type_hint = buffer_type_hint_from_bind_flags(gl_info, bind_flags);
1380  buffer->bind_flags = bind_flags;
1381  buffer->locations = WINED3D_LOCATION_SYSMEM;
1382 
1383  TRACE("buffer %p, size %#x, usage %#x, format %s, memory @ %p.\n",
1384  buffer, buffer->resource.size, buffer->resource.usage,
1385  debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory);
1386 
1387  if (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
1389  {
1390  /* SWvp and managed buffers always return the same pointer in buffer
1391  * maps and retain data in DISCARD maps. Keep a system memory copy of
1392  * the buffer to provide the same behavior to the application. */
1393  TRACE("Using doublebuffer mode.\n");
1395  }
1396 
1397  /* Observations show that draw_primitive_immediate_mode() is faster on
1398  * dynamic vertex buffers than converting + draw_primitive_arrays().
1399  * (Half-Life 2 and others.) */
1400  dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE];
1401 
1402  if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
1403  {
1404  TRACE("Not creating a BO because GL_ARB_vertex_buffer is not supported.\n");
1405  }
1406  else if (!(access & WINED3D_RESOURCE_ACCESS_GPU))
1407  {
1408  TRACE("Not creating a BO because the buffer is not GPU accessible.\n");
1409  }
1410  else if (!dynamic_buffer_ok && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
1411  {
1412  TRACE("Not creating a BO because the buffer has dynamic usage and no GL support.\n");
1413  }
1414  else
1415  {
1416  buffer->flags |= WINED3D_BUFFER_USE_BO;
1417  }
1418 
1419  if (!(buffer->maps = heap_alloc(sizeof(*buffer->maps))))
1420  {
1421  ERR("Out of memory.\n");
1422  buffer_unload(&buffer->resource);
1423  resource_cleanup(&buffer->resource);
1424  wined3d_resource_wait_idle(&buffer->resource);
1425  return E_OUTOFMEMORY;
1426  }
1427  buffer->maps_size = 1;
1428 
1429  if (data)
1431  0, NULL, data->data, data->row_pitch, data->slice_pitch);
1432 
1433  return WINED3D_OK;
1434 }
1435 
1437  const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
1438  struct wined3d_buffer **buffer)
1439 {
1440  struct wined3d_buffer *object;
1441  HRESULT hr;
1442 
1443  TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1444  device, desc, data, parent, parent_ops, buffer);
1445 
1446  if (!(object = heap_alloc_zero(sizeof(*object))))
1447  return E_OUTOFMEMORY;
1448 
1449  if (FAILED(hr = buffer_init(object, device, desc->byte_width, desc->usage, WINED3DFMT_UNKNOWN,
1450  desc->access, desc->bind_flags, data, parent, parent_ops)))
1451  {
1452  WARN("Failed to initialize buffer, hr %#x.\n", hr);
1453  heap_free(object);
1454  return hr;
1455  }
1456  object->desc = *desc;
1457 
1458  TRACE("Created buffer %p.\n", object);
1459 
1460  *buffer = object;
1461 
1462  return WINED3D_OK;
1463 }
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
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)
Definition: device.c:4281
#define WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
Definition: wined3d.h:1011
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:815
#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:706
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:1283
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:890
BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, struct wined3d_context *context, DWORD location)
Definition: buffer.c:641
#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:1346
#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:907
static void buffer_mark_used(struct wined3d_buffer *buffer)
Definition: buffer.c:881
#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:3831
#define WINED3D_BIND_UNORDERED_ACCESS
Definition: wined3d.h:897
#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:1885
void resource_unload(struct wined3d_resource *resource)
Definition: resource.c:257
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:713
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:1238
static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
Definition: buffer.c:1301
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:893
static void wined3d_buffer_unmap(struct wined3d_buffer *buffer)
Definition: buffer.c:1132
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:891
static GLenum buffer_type_hint_from_bind_flags(const struct wined3d_gl_info *gl_info, unsigned int bind_flags)
Definition: buffer.c:1324
void *CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
Definition: buffer.c:807
const char * wined3d_debug_location(DWORD location)
Definition: utils.c:6396
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:920
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:515
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
#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:1571
void wined3d_buffer_upload_data(struct wined3d_buffer *buffer, struct wined3d_context *context, const struct wined3d_box *box, const void *data)
Definition: buffer.c:1219
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:4796
#define GL_UNIFORM_BUFFER
Definition: glext.h:1846
#define STATE_STREAMSRC
#define GL_EXTCALL(f)
#define WINED3D_MAP_DISCARD
Definition: wined3d.h:935
#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:892
r parent
Definition: btrfs.c:2897
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:487
ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
Definition: buffer.c:791
BOOL wined3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
Definition: utils.c:6526
#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:767
#define InterlockedDecrement
Definition: armddk.h:52
#define WINED3D_MAP_WRITE
Definition: wined3d.h:938
#define WINED3D_LOCATION_SYSMEM
static const struct wined3d_resource_ops buffer_resource_ops
Definition: buffer.c:1313
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:4127
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:1002
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:934
#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:4242
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:995
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:2846
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:1248
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:5263
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:1436
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 GLbitfield
Definition: gl.h:152
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:887
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:1257
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:2724
#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:4217
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:773
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:1195
const char * debug_d3dformat(enum wined3d_format_id format_id)
Definition: utils.c:3980
void resource_cleanup(struct wined3d_resource *resource)
Definition: resource.c:237
#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:1243
#define VB_MAXDECLCHANGES
Definition: buffer.c:38
static void buffer_unload(struct wined3d_resource *resource)
Definition: buffer.c:738
Definition: palette.c:467
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define WINED3D_BIND_STREAM_OUTPUT
Definition: wined3d.h:894
void wined3d_resource_free_sysmem(struct wined3d_resource *resource)
Definition: resource.c:504