ReactOS 0.4.15-dev-7961-gdcf9eb0
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{
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
56static 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
79invalidate_all:
80 buffer->modified_areas = 1;
81 buffer->maps[0].offset = 0;
82 buffer->maps[0].size = buffer->resource.size;
83}
84
85static 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;
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
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
263fail:
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;
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",
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
489static 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
510static 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
606}
607
610{
611 switch (location)
612 {
614 if (buffer->resource.heap_memory)
615 return TRUE;
616
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
773static 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);
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
868drop_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);
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. */
1022 {
1023 dirty_offset = 0;
1024 dirty_size = 0;
1025 }
1026
1028 || (!(flags & WINED3D_MAP_WRITE) && (buffer->locations & WINED3D_LOCATION_SYSMEM))
1030 {
1031 if (!(buffer->locations & WINED3D_LOCATION_SYSMEM))
1032 {
1036 }
1037
1040 }
1041 else
1042 {
1043 const struct wined3d_gl_info *gl_info;
1044
1046 gl_info = context->gl_info;
1047
1050 else
1052
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)
1071 flags &= ~WINED3D_MAP_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
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
1195void 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
1283static HRESULT buffer_resource_sub_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx,
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
1301static 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{
1322};
1323
1325 unsigned int bind_flags)
1326{
1327 if (bind_flags == WINED3D_BIND_INDEX_BUFFER)
1329
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);
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}
static int state
Definition: maze.c:121
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
void wined3d_cs_destroy_object(struct wined3d_cs *cs, void(*callback)(void *object), void *object)
Definition: cs.c:1885
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static unsigned int fixup_transformed_pos(struct wined3d_vec4 *p)
Definition: buffer.c:510
#define WINED3D_BUFFER_FIXUP_D3DCOLOR
Definition: buffer.c:327
static void wined3d_buffer_destroy_object(void *object)
Definition: buffer.c:773
static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const struct wined3d_gl_info *gl_info)
Definition: buffer.c:815
DWORD wined3d_buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_bo_address *data, DWORD locations)
Definition: buffer.c:713
static void wined3d_buffer_evict_sysmem(struct wined3d_buffer *buffer)
Definition: buffer.c:43
static BOOL buffer_is_fully_dirty(const struct wined3d_buffer *buffer)
Definition: buffer.c:95
static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, DWORD location)
Definition: buffer.c:608
BYTE * wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:706
static void buffer_clear_dirty_areas(struct wined3d_buffer *This)
Definition: buffer.c:85
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 buffer_resource_preload(struct wined3d_resource *resource)
Definition: buffer.c:1248
static BOOL buffer_is_dirty(const struct wined3d_buffer *buffer)
Definition: buffer.c:90
#define VB_RESETFULLCONVS
Definition: buffer.c:41
void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *context, const struct wined3d_state *state)
Definition: buffer.c:887
static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UINT size, BYTE **data, DWORD flags)
Definition: buffer.c:1002
static void wined3d_buffer_drop_bo(struct wined3d_buffer *buffer)
Definition: buffer.c:767
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
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
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
static BOOL buffer_create_buffer_object(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:197
static unsigned int fixup_d3dcolor(DWORD *dst_color)
Definition: buffer.c:489
static ULONG buffer_resource_decref(struct wined3d_resource *resource)
Definition: buffer.c:1243
#define VB_MAXFULLCONVERSIONS
Definition: buffer.c:40
static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
Definition: buffer.c:1301
#define WINED3D_BUFFER_PIN_SYSMEM
Definition: buffer.c:34
void *CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
Definition: buffer.c:807
#define WINED3D_BUFFER_DISCARD
Definition: buffer.c:35
static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:142
ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer)
Definition: buffer.c:525
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
ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
Definition: buffer.c:791
static void wined3d_buffer_unmap(struct wined3d_buffer *buffer)
Definition: buffer.c:1132
#define WINED3D_BUFFER_APPLESYNC
Definition: buffer.c:36
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 const struct wined3d_resource_ops buffer_resource_ops
Definition: buffer.c:1313
#define VB_RESETDECLCHANGE
Definition: buffer.c:39
#define WINED3D_BUFFER_FIXUP_XYZRHW
Definition: buffer.c:328
#define WINED3D_BUFFER_HASDESC
Definition: buffer.c:32
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
static void buffer_bind(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:136
struct wined3d_resource *CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer)
Definition: buffer.c:995
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 void wined3d_buffer_invalidate_range(struct wined3d_buffer *buffer, DWORD location, unsigned int offset, unsigned int size)
Definition: buffer.c:113
static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, unsigned int offset, unsigned int size)
Definition: buffer.c:56
static void wined3d_buffer_validate_location(struct wined3d_buffer *buffer, DWORD location)
Definition: buffer.c:101
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
static ULONG buffer_resource_incref(struct wined3d_resource *resource)
Definition: buffer.c:1238
static void buffer_mark_used(struct wined3d_buffer *buffer)
Definition: buffer.c:881
BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, struct wined3d_context *context, DWORD location)
Definition: buffer.c:641
static void buffer_unload(struct wined3d_resource *resource)
Definition: buffer.c:738
#define VB_MAXDECLCHANGES
Definition: buffer.c:38
static void buffer_conversion_upload(struct wined3d_buffer *buffer, struct wined3d_context *context)
Definition: buffer.c:552
#define WINED3D_BUFFER_USE_BO
Definition: buffer.c:33
void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD location)
Definition: buffer.c:130
static GLenum buffer_type_hint_from_bind_flags(const struct wined3d_gl_info *gl_info, unsigned int bind_flags)
Definition: buffer.c:1324
void context_bind_bo(struct wined3d_context *context, GLenum binding, GLuint name)
Definition: context.c:2724
struct wined3d_context * context_acquire(const struct wined3d_device *device, struct wined3d_texture *texture, unsigned int sub_resource_idx)
Definition: context.c:4242
void context_end_transform_feedback(struct wined3d_context *context)
Definition: context.c:4127
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
void context_release(struct wined3d_context *context)
Definition: context.c:1571
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
void device_invalidate_state(const struct wined3d_device *device, DWORD state)
Definition: device.c:5263
void wined3d_fence_destroy(struct wined3d_fence *fence)
Definition: query.c:286
enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence, const struct wined3d_device *device)
Definition: query.c:169
HRESULT wined3d_fence_create(struct wined3d_device *device, struct wined3d_fence **fence)
Definition: query.c:303
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
void wined3d_resource_free_sysmem(struct wined3d_resource *resource)
Definition: resource.c:504
GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
Definition: resource.c:515
BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource)
Definition: resource.c:487
void resource_cleanup(struct wined3d_resource *resource)
Definition: resource.c:237
void resource_unload(struct wined3d_resource *resource)
Definition: resource.c:257
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
const char * debug_d3dformat(enum wined3d_format_id format_id)
Definition: utils.c:3980
const char * debug_d3dusage(DWORD usage)
Definition: utils.c:4217
BOOL wined3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
Definition: utils.c:6526
unsigned int idx
Definition: utils.c:41
const char * debug_glerror(GLenum error)
Definition: utils.c:4796
const char * wined3d_debug_location(DWORD location)
Definition: utils.c:6396
#define CDECL
Definition: compat.h:29
r parent
Definition: btrfs.c:3010
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define GL_TRUE
Definition: gl.h:174
GLuint start
Definition: gl.h:1545
unsigned int GLenum
Definition: gl.h:150
unsigned int GLbitfield
Definition: gl.h:152
#define GL_NO_ERROR
Definition: gl.h:693
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define GL_FALSE
Definition: gl.h:173
GLsizeiptr size
Definition: glext.h:5919
#define GL_BUFFER_SERIALIZED_MODIFY_APPLE
Definition: glext.h:4547
#define GL_UNIFORM_BUFFER
Definition: glext.h:1846
GLenum src
Definition: glext.h:6340
GLsizei const GLint * locations
Definition: glext.h:10542
GLuint buffer
Definition: glext.h:5915
#define GL_ARRAY_BUFFER
Definition: glext.h:336
#define GL_TEXTURE_BUFFER
Definition: glext.h:748
GLenum GLint * range
Definition: glext.h:7539
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
#define GL_TRANSFORM_FEEDBACK_BUFFER
Definition: glext.h:557
GLfloat GLfloat p
Definition: glext.h:8902
#define GL_READ_WRITE
Definition: glext.h:343
#define GL_BUFFER_FLUSHING_UNMAP_APPLE
Definition: glext.h:4548
#define GL_STATIC_DRAW
Definition: glext.h:350
#define GL_ELEMENT_ARRAY_BUFFER
Definition: glext.h:337
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
#define GL_STREAM_DRAW_ARB
Definition: glext.h:1506
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
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
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
#define FAILED(hr)
Definition: intsafe.h:51
#define buffer_init
Definition: intsym.h:261
#define location(file, line)
Definition: kmtest.h:18
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const WCHAR desc[]
Definition: protectdata.c:36
int vertex_count
Definition: d3drm.c:3367
static UINT format_id
Definition: clipboard.c:1343
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
long LONG
Definition: pedump.c:60
static void * heap_calloc(SIZE_T count, SIZE_T size)
Definition: heap.h:49
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: palette.c:468
Definition: http.c:7252
Definition: devices.h:37
struct wined3d_resource resource
const struct wined3d_gl_info * gl_info
unsigned int sub_resource_idx
BOOL supported[WINED3D_GL_EXT_COUNT]
struct opengl_funcs gl_ops
const struct wined3d_format * format
struct wined3d_bo_address data
struct wined3d_stream_info_element elements[MAX_ATTRIBS]
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
int ret
@ WINED3D_MULTISAMPLE_NONE
Definition: wined3d.h:554
#define WINED3D_OK
Definition: wined3d.h:37
#define WINED3D_BIND_VERTEX_BUFFER
Definition: wined3d.h:890
#define WINED3D_RESOURCE_ACCESS_GPU
Definition: wined3d.h:55
@ WINED3D_RTYPE_BUFFER
Definition: wined3d.h:698
#define WINED3D_BIND_UNORDERED_ACCESS
Definition: wined3d.h:897
#define WINED3DERR_NOTAVAILABLE
Definition: wined3d.h:46
#define WINED3D_BIND_SHADER_RESOURCE
Definition: wined3d.h:893
wined3d_format_id
Definition: wined3d.h:106
@ WINED3DFMT_B8G8R8A8_UNORM
Definition: wined3d.h:223
@ WINED3DFMT_UNKNOWN
Definition: wined3d.h:107
@ WINED3DFMT_R32G32B32A32_FLOAT
Definition: wined3d.h:136
#define WINED3D_MAP_DISCARD
Definition: wined3d.h:935
#define WINED3D_MAP_WRITE
Definition: wined3d.h:938
#define WINED3D_MAP_NOOVERWRITE
Definition: wined3d.h:934
#define WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
Definition: wined3d.h:1011
#define WINED3DUSAGE_DYNAMIC
Definition: wined3d.h:907
#define WINED3DUSAGE_STATICDECL
Definition: wined3d.h:920
#define WINED3D_BIND_CONSTANT_BUFFER
Definition: wined3d.h:892
#define WINED3D_BIND_STREAM_OUTPUT
Definition: wined3d.h:894
#define WINED3D_BIND_INDEX_BUFFER
Definition: wined3d.h:891
@ ARB_TEXTURE_BUFFER_OBJECT
Definition: wined3d_gl.h:108
@ APPLE_FLUSH_BUFFER_RANGE
Definition: wined3d_gl.h:42
@ ARB_VERTEX_BUFFER_OBJECT
Definition: wined3d_gl.h:138
@ ARB_VERTEX_ARRAY_BGRA
Definition: wined3d_gl.h:136
@ ARB_MAP_BUFFER_RANGE
Definition: wined3d_gl.h:83
#define WINED3D_CONSTANT_BUFFER_ALIGNMENT
#define STATE_CONSTANT_BUFFER(a)
@ WINED3D_FFP_TEXCOORD4
@ WINED3D_FFP_TEXCOORD3
@ WINED3D_FFP_SPECULAR
@ WINED3D_FFP_TEXCOORD7
@ WINED3D_FFP_TEXCOORD1
@ WINED3D_FFP_POSITION
@ WINED3D_FFP_NORMAL
@ WINED3D_FFP_TEXCOORD5
@ WINED3D_FFP_BLENDWEIGHT
@ WINED3D_FFP_TEXCOORD2
@ WINED3D_FFP_DIFFUSE
@ WINED3D_FFP_TEXCOORD6
@ WINED3D_FFP_BLENDINDICES
@ WINED3D_FFP_TEXCOORD0
#define WINED3D_LOCATION_SYSMEM
#define STATE_STREAM_OUTPUT
static BOOL use_vs(const struct wined3d_state *state)
#define WINED3D_LOCATION_BUFFER
#define GL_EXTCALL(f)
#define RESOURCE_ALIGNMENT
static BOOL wined3d_resource_access_is_managed(unsigned int access)
#define STATE_STREAMSRC
wined3d_buffer_conversion_type
@ CONV_NONE
@ CONV_POSITIONT
@ CONV_D3DCOLOR
@ WINED3D_SHADER_TYPE_HULL
@ WINED3D_SHADER_TYPE_PIXEL
@ WINED3D_SHADER_TYPE_GEOMETRY
@ WINED3D_SHADER_TYPE_DOMAIN
@ WINED3D_SHADER_TYPE_COMPUTE
@ WINED3D_SHADER_TYPE_VERTEX
#define WINED3D_LOCATION_DISCARDED
wined3d_fence_result
@ WINED3D_FENCE_WRONG_THREAD
@ WINED3D_FENCE_OK
@ WINED3D_FENCE_NOT_STARTED
#define STATE_INDEXBUFFER
static void wined3d_resource_wait_idle(struct wined3d_resource *resource)
#define checkGLcall(A)
static struct wined3d_buffer * buffer_from_resource(struct wined3d_resource *resource)
unsigned char BYTE
Definition: xxhash.c:193