VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/drawprim.c@ 48611

最後變更 在這個檔案從48611是 48345,由 vboxsync 提交於 12 年 前

header fixes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 29.6 KB
 
1/*
2 * WINED3D draw functions
3 *
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2006, 2008 Henri Verbeet
9 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * Copyright 2009 Henri Verbeet for CodeWeavers
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27/*
28 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
29 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
30 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
31 * a choice of LGPL license versions is made available with the language indicating
32 * that LGPLv2 or any later version may be used, or where a choice of which version
33 * of the LGPL is applied is otherwise unspecified.
34 */
35
36#include "config.h"
37#include "wine/port.h"
38
39#include "wined3d_private.h"
40
41WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
42WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
43
44#include <stdio.h>
45#include <math.h>
46
47#ifdef DEBUG_misha
48#include "../VBox/VBoxDbgGl.h"
49#endif
50
51#ifdef VBOX_WITH_WINE_FIXES
52# define ceilf ceil
53#endif
54
55/* Context activation is done by the caller. */
56static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size,
57 const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count)
58{
59 if (idx_size)
60 {
61 GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
62 if (instance_count)
63 {
64 if (!gl_info->supported[ARB_DRAW_INSTANCED])
65 {
66 FIXME("Instanced drawing not supported.\n");
67 }
68 else
69 {
70 if (start_instance)
71 FIXME("Start instance (%u) not supported.\n", start_instance);
72 GL_EXTCALL(glDrawElementsInstancedBaseVertex(primitive_type, count, idxtype,
73 (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_index));
74 checkGLcall("glDrawElementsInstancedBaseVertex");
75 }
76 }
77 else if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
78 {
79 GL_EXTCALL(glDrawElementsBaseVertex(primitive_type, count, idxtype,
80 (const char *)idx_data + (idx_size * start_idx), base_vertex_index));
81 checkGLcall("glDrawElementsBaseVertex");
82 }
83 else
84 {
85 gl_info->gl_ops.gl.p_glDrawElements(primitive_type, count,
86 idxtype, (const char *)idx_data + (idx_size * start_idx));
87 checkGLcall("glDrawElements");
88 }
89 }
90 else
91 {
92 gl_info->gl_ops.gl.p_glDrawArrays(primitive_type, start_idx, count);
93 checkGLcall("glDrawArrays");
94 }
95}
96
97/*
98 * Actually draw using the supplied information.
99 * Slower GL version which extracts info about each vertex in turn
100 */
101
102/* Context activation is done by the caller. */
103static void drawStridedSlow(const struct wined3d_device *device, const struct wined3d_context *context,
104 const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType,
105 const void *idxData, UINT idxSize, UINT startIdx)
106{
107 unsigned int textureNo = 0;
108 const WORD *pIdxBufS = NULL;
109 const DWORD *pIdxBufL = NULL;
110 UINT vx_index;
111 const struct wined3d_state *state = &device->stateBlock->state;
112 LONG SkipnStrides = startIdx;
113 BOOL pixelShader = use_ps(state);
114 BOOL specular_fog = FALSE;
115 const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
116 const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
117 const struct wined3d_gl_info *gl_info = context->gl_info;
118 const struct wined3d_d3d_info *d3d_info = context->d3d_info;
119 UINT texture_stages = d3d_info->limits.ffp_blend_stages;
120 const struct wined3d_stream_info_element *element;
121 UINT num_untracked_materials;
122 DWORD tex_mask = 0;
123
124 TRACE_(d3d_perf)("Using slow vertex array code\n");
125
126 /* Variable Initialization */
127 if (idxSize)
128 {
129 /* Immediate mode drawing can't make use of indices in a vbo - get the
130 * data from the index buffer. If the index buffer has no vbo (not
131 * supported or other reason), or with user pointer drawing idxData
132 * will be non-NULL. */
133 if (!idxData)
134 idxData = buffer_get_sysmem(state->index_buffer, gl_info);
135
136 if (idxSize == 2) pIdxBufS = idxData;
137 else pIdxBufL = idxData;
138 } else if (idxData) {
139 ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
140 return;
141 }
142
143 /* Start drawing in GL */
144 gl_info->gl_ops.gl.p_glBegin(glPrimType);
145
146 if (si->use_map & (1 << WINED3D_FFP_POSITION))
147 {
148 element = &si->elements[WINED3D_FFP_POSITION];
149 position = element->data.addr;
150 }
151
152 if (si->use_map & (1 << WINED3D_FFP_NORMAL))
153 {
154 element = &si->elements[WINED3D_FFP_NORMAL];
155 normal = element->data.addr;
156 }
157 else
158 {
159 gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0);
160 }
161
162 num_untracked_materials = context->num_untracked_materials;
163 if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
164 {
165 element = &si->elements[WINED3D_FFP_DIFFUSE];
166 diffuse = element->data.addr;
167
168 if (num_untracked_materials && element->format->id != WINED3DFMT_B8G8R8A8_UNORM)
169 FIXME("Implement diffuse color tracking from %s\n", debug_d3dformat(element->format->id));
170 }
171 else
172 {
173 gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
174 }
175
176 if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
177 {
178 element = &si->elements[WINED3D_FFP_SPECULAR];
179 specular = element->data.addr;
180
181 /* special case where the fog density is stored in the specular alpha channel */
182 if (state->render_states[WINED3D_RS_FOGENABLE]
183 && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE
184 || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT)
185 && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
186 {
187 if (gl_info->supported[EXT_FOG_COORD])
188 {
189 if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM) specular_fog = TRUE;
190 else FIXME("Implement fog coordinates from %s\n", debug_d3dformat(element->format->id));
191 }
192 else
193 {
194 static BOOL warned;
195
196 if (!warned)
197 {
198 /* TODO: Use the fog table code from old ddraw */
199 FIXME("Implement fog for transformed vertices in software\n");
200 warned = TRUE;
201 }
202 }
203 }
204 }
205 else if (gl_info->supported[EXT_SECONDARY_COLOR])
206 {
207 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
208 }
209
210 for (textureNo = 0; textureNo < texture_stages; ++textureNo)
211 {
212 int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
213 DWORD texture_idx = device->texUnitMap[textureNo];
214
215 if (!gl_info->supported[ARB_MULTITEXTURE] && textureNo > 0)
216 {
217 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
218 continue;
219 }
220
221 if (!pixelShader && !state->textures[textureNo]) continue;
222
223 if (texture_idx == WINED3D_UNMAPPED_STAGE) continue;
224
225 if (coordIdx > 7)
226 {
227 TRACE("tex: %d - Skip tex coords, as being system generated\n", textureNo);
228 continue;
229 }
230 else if (coordIdx < 0)
231 {
232 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
233 continue;
234 }
235
236 if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))
237 {
238 element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
239 texCoords[coordIdx] = element->data.addr;
240 tex_mask |= (1 << textureNo);
241 }
242 else
243 {
244 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
245 if (gl_info->supported[ARB_MULTITEXTURE])
246 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
247 else
248 gl_info->gl_ops.gl.p_glTexCoord4f(0, 0, 0, 1);
249 }
250 }
251
252 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
253 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
254 */
255
256 /* For each primitive */
257 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
258 UINT texture, tmp_tex_mask;
259 /* Blending data and Point sizes are not supported by this function. They are not supported by the fixed
260 * function pipeline at all. A Fixme for them is printed after decoding the vertex declaration
261 */
262
263 /* For indexed data, we need to go a few more strides in */
264 if (idxData)
265 {
266 /* Indexed so work out the number of strides to skip */
267 if (idxSize == 2)
268 SkipnStrides = pIdxBufS[startIdx + vx_index] + state->base_vertex_index;
269 else
270 SkipnStrides = pIdxBufL[startIdx + vx_index] + state->base_vertex_index;
271 }
272
273 tmp_tex_mask = tex_mask;
274 for (texture = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture)
275 {
276 int coord_idx;
277 const void *ptr;
278 DWORD texture_idx;
279
280 if (!(tmp_tex_mask & 1)) continue;
281
282 coord_idx = state->texture_states[texture][WINED3D_TSS_TEXCOORD_INDEX];
283 ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
284
285 texture_idx = device->texUnitMap[texture];
286 multi_texcoord_funcs[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
287 GL_TEXTURE0_ARB + texture_idx, ptr);
288 }
289
290 /* Diffuse -------------------------------- */
291 if (diffuse) {
292 const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride;
293
294 diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptrToCoords);
295 if (num_untracked_materials)
296 {
297 DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0];
298 unsigned char i;
299 float color[4];
300
301 color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0f;
302 color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0f;
303 color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0f;
304 color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0f;
305
306 for (i = 0; i < num_untracked_materials; ++i)
307 {
308 gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], color);
309 }
310 }
311 }
312
313 /* Specular ------------------------------- */
314 if (specular) {
315 const void *ptrToCoords = specular + SkipnStrides * si->elements[WINED3D_FFP_SPECULAR].stride;
316
317 specular_funcs[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptrToCoords);
318
319 if (specular_fog)
320 {
321 DWORD specularColor = *(const DWORD *)ptrToCoords;
322 GL_EXTCALL(glFogCoordfEXT((float) (specularColor >> 24)));
323 }
324 }
325
326 /* Normal -------------------------------- */
327 if (normal)
328 {
329 const void *ptrToCoords = normal + SkipnStrides * si->elements[WINED3D_FFP_NORMAL].stride;
330 normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
331 }
332
333 /* Position -------------------------------- */
334 if (position) {
335 const void *ptrToCoords = position + SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride;
336 position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
337 }
338
339 /* For non indexed mode, step onto next parts */
340 if (!idxData) ++SkipnStrides;
341 }
342
343 gl_info->gl_ops.gl.p_glEnd();
344 checkGLcall("glEnd and previous calls");
345}
346
347/* Context activation is done by the caller. */
348static inline void send_attribute(const struct wined3d_gl_info *gl_info,
349 enum wined3d_format_id format, const UINT index, const void *ptr)
350{
351 switch(format)
352 {
353 case WINED3DFMT_R32_FLOAT:
354 GL_EXTCALL(glVertexAttrib1fvARB(index, ptr));
355 break;
356 case WINED3DFMT_R32G32_FLOAT:
357 GL_EXTCALL(glVertexAttrib2fvARB(index, ptr));
358 break;
359 case WINED3DFMT_R32G32B32_FLOAT:
360 GL_EXTCALL(glVertexAttrib3fvARB(index, ptr));
361 break;
362 case WINED3DFMT_R32G32B32A32_FLOAT:
363 GL_EXTCALL(glVertexAttrib4fvARB(index, ptr));
364 break;
365
366 case WINED3DFMT_R8G8B8A8_UINT:
367 GL_EXTCALL(glVertexAttrib4ubvARB(index, ptr));
368 break;
369 case WINED3DFMT_B8G8R8A8_UNORM:
370 if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
371 {
372 const DWORD *src = ptr;
373 DWORD c = *src & 0xff00ff00;
374 c |= (*src & 0xff0000) >> 16;
375 c |= (*src & 0xff) << 16;
376 GL_EXTCALL(glVertexAttrib4NubvARB(index, (GLubyte *)&c));
377 break;
378 }
379 /* else fallthrough */
380 case WINED3DFMT_R8G8B8A8_UNORM:
381 GL_EXTCALL(glVertexAttrib4NubvARB(index, ptr));
382 break;
383
384 case WINED3DFMT_R16G16_SINT:
385 GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
386 break;
387 case WINED3DFMT_R16G16B16A16_SINT:
388 GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
389 break;
390
391 case WINED3DFMT_R16G16_SNORM:
392 {
393 GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
394 GL_EXTCALL(glVertexAttrib4NsvARB(index, s));
395 break;
396 }
397 case WINED3DFMT_R16G16_UNORM:
398 {
399 GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
400 GL_EXTCALL(glVertexAttrib4NusvARB(index, s));
401 break;
402 }
403 case WINED3DFMT_R16G16B16A16_SNORM:
404 GL_EXTCALL(glVertexAttrib4NsvARB(index, ptr));
405 break;
406 case WINED3DFMT_R16G16B16A16_UNORM:
407 GL_EXTCALL(glVertexAttrib4NusvARB(index, ptr));
408 break;
409
410 case WINED3DFMT_R10G10B10A2_UINT:
411 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
412 /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */
413 break;
414 case WINED3DFMT_R10G10B10A2_SNORM:
415 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
416 /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */
417 break;
418
419 case WINED3DFMT_R16G16_FLOAT:
420 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
421 * byte float according to the IEEE standard
422 */
423 if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
424 {
425 /* Not supported by GL_ARB_half_float_vertex */
426 GL_EXTCALL(glVertexAttrib2hvNV(index, ptr));
427 }
428 else
429 {
430 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
431 float y = float_16_to_32(((const unsigned short *)ptr) + 1);
432 GL_EXTCALL(glVertexAttrib2fARB(index, x, y));
433 }
434 break;
435 case WINED3DFMT_R16G16B16A16_FLOAT:
436 if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
437 {
438 /* Not supported by GL_ARB_half_float_vertex */
439 GL_EXTCALL(glVertexAttrib4hvNV(index, ptr));
440 }
441 else
442 {
443 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
444 float y = float_16_to_32(((const unsigned short *)ptr) + 1);
445 float z = float_16_to_32(((const unsigned short *)ptr) + 2);
446 float w = float_16_to_32(((const unsigned short *)ptr) + 3);
447 GL_EXTCALL(glVertexAttrib4fARB(index, x, y, z, w));
448 }
449 break;
450
451 default:
452 ERR("Unexpected attribute format: %s\n", debug_d3dformat(format));
453 break;
454 }
455}
456
457/* Context activation is done by the caller. */
458static void drawStridedSlowVs(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
459 const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
460 const void *idxData, UINT idxSize, UINT startIdx)
461{
462 LONG SkipnStrides = startIdx + state->load_base_vertex_index;
463 const DWORD *pIdxBufL = NULL;
464 const WORD *pIdxBufS = NULL;
465 UINT vx_index;
466 int i;
467 const BYTE *ptr;
468
469 if (idxSize)
470 {
471 /* Immediate mode drawing can't make use of indices in a vbo - get the
472 * data from the index buffer. If the index buffer has no vbo (not
473 * supported or other reason), or with user pointer drawing idxData
474 * will be non-NULL. */
475 if (!idxData)
476 idxData = buffer_get_sysmem(state->index_buffer, gl_info);
477
478 if (idxSize == 2) pIdxBufS = idxData;
479 else pIdxBufL = idxData;
480 } else if (idxData) {
481 ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
482 return;
483 }
484
485 /* Start drawing in GL */
486 gl_info->gl_ops.gl.p_glBegin(glPrimitiveType);
487
488 for (vx_index = 0; vx_index < numberOfVertices; ++vx_index)
489 {
490 if (idxData)
491 {
492 /* Indexed so work out the number of strides to skip */
493 if (idxSize == 2)
494 SkipnStrides = pIdxBufS[startIdx + vx_index] + state->load_base_vertex_index;
495 else
496 SkipnStrides = pIdxBufL[startIdx + vx_index] + state->load_base_vertex_index;
497 }
498
499 for (i = MAX_ATTRIBS - 1; i >= 0; i--)
500 {
501 if (!(si->use_map & (1 << i))) continue;
502
503 ptr = si->elements[i].data.addr + si->elements[i].stride * SkipnStrides;
504
505 send_attribute(gl_info, si->elements[i].format->id, i, ptr);
506 }
507 SkipnStrides++;
508 }
509
510 gl_info->gl_ops.gl.p_glEnd();
511}
512
513/* Context activation is done by the caller. */
514static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
515 const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
516 const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count)
517{
518 int numInstancedAttribs = 0, j;
519 UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */];
520 GLenum idxtype = idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
521 UINT i;
522
523 if (!idxSize)
524 {
525 /* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
526 * We don't support this for now
527 *
528 * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
529 * But the StreamSourceFreq value has a different meaning in that situation.
530 */
531 FIXME("Non-indexed instanced drawing is not supported\n");
532 return;
533 }
534
535 for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i)
536 {
537 if (!(si->use_map & (1 << i))) continue;
538
539 if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
540 {
541 instancedData[numInstancedAttribs] = i;
542 numInstancedAttribs++;
543 }
544 }
545
546 for (i = 0; i < instance_count; ++i)
547 {
548 /* Specify the instanced attributes using immediate mode calls */
549 for(j = 0; j < numInstancedAttribs; j++) {
550 const BYTE *ptr = si->elements[instancedData[j]].data.addr
551 + si->elements[instancedData[j]].stride * i;
552 if (si->elements[instancedData[j]].data.buffer_object)
553 {
554 struct wined3d_buffer *vb = state->streams[si->elements[instancedData[j]].stream_idx].buffer;
555 ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info);
556 }
557
558 send_attribute(gl_info, si->elements[instancedData[j]].format->id, instancedData[j], ptr);
559 }
560
561 if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
562 {
563 GL_EXTCALL(glDrawElementsBaseVertex(glPrimitiveType, numberOfVertices, idxtype,
564 (const char *)idxData+(idxSize * startIdx), base_vertex_index));
565 checkGLcall("glDrawElementsBaseVertex");
566 }
567 else
568 {
569 gl_info->gl_ops.gl.p_glDrawElements(glPrimitiveType, numberOfVertices, idxtype,
570 (const char *)idxData + (idxSize * startIdx));
571 checkGLcall("glDrawElements");
572 }
573 }
574}
575
576static void remove_vbos(const struct wined3d_gl_info *gl_info,
577 const struct wined3d_state *state, struct wined3d_stream_info *s)
578{
579 unsigned int i;
580
581 for (i = 0; i < (sizeof(s->elements) / sizeof(*s->elements)); ++i)
582 {
583 struct wined3d_stream_info_element *e;
584
585 if (!(s->use_map & (1 << i))) continue;
586
587 e = &s->elements[i];
588 if (e->data.buffer_object)
589 {
590 struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
591 e->data.buffer_object = 0;
592 e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
593 }
594 }
595}
596
597/* Routine common to the draw primitive and draw indexed primitive routines */
598void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
599 UINT start_instance, UINT instance_count, BOOL indexed)
600{
601 const struct wined3d_state *state = &device->stateBlock->state;
602 const struct wined3d_stream_info *stream_info;
603 struct wined3d_event_query *ib_query = NULL;
604 struct wined3d_stream_info si_emulated;
605 const struct wined3d_gl_info *gl_info;
606 struct wined3d_context *context;
607 BOOL emulation = FALSE;
608 const void *idx_data = NULL;
609 UINT idx_size = 0;
610 unsigned int i;
611
612 if (!index_count) return;
613
614 if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
615 {
616 /* Invalidate the back buffer memory so LockRect will read it the next time */
617 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
618 {
619 struct wined3d_surface *target = device->fb.render_targets[i];
620 if (target)
621 {
622 surface_load_location(target, target->draw_binding, NULL);
623 surface_modify_location(target, target->draw_binding, TRUE);
624 }
625 }
626 }
627
628 /* Signals other modules that a drawing is in progress and the stateblock finalized */
629 device->isInDraw = TRUE;
630
631 context = context_acquire(device, device->fb.render_targets[0]);
632 if (!context->valid)
633 {
634 context_release(context);
635 WARN("Invalid context, skipping draw.\n");
636 return;
637 }
638 gl_info = context->gl_info;
639
640 if (device->fb.depth_stencil)
641 {
642 /* Note that this depends on the context_acquire() call above to set
643 * context->render_offscreen properly. We don't currently take the
644 * Z-compare function into account, but we could skip loading the
645 * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note
646 * that we never copy the stencil data.*/
647 DWORD location = context->render_offscreen ? device->fb.depth_stencil->draw_binding : SFLAG_INDRAWABLE;
648 if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE])
649 {
650 struct wined3d_surface *ds = device->fb.depth_stencil;
651 RECT current_rect, draw_rect, r;
652
653 if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
654 device_switch_onscreen_ds(device, context, ds);
655
656 if (ds->flags & location)
657 SetRect(&current_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
658 else
659 SetRectEmpty(&current_rect);
660
661 wined3d_get_draw_rect(state, &draw_rect);
662
663 IntersectRect(&r, &draw_rect, &current_rect);
664 if (!EqualRect(&r, &draw_rect))
665 surface_load_ds_location(ds, context, location);
666 }
667 }
668
669 if (!context_apply_draw_state(context, device))
670 {
671 context_release(context);
672 WARN("Unable to apply draw state, skipping draw.\n");
673 return;
674 }
675
676#ifdef DEBUG_misha
677 DBGL_CHECK_DRAWPRIM(context->gl_info, device);
678#endif
679
680 if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE])
681 {
682 struct wined3d_surface *ds = device->fb.depth_stencil;
683 DWORD location = context->render_offscreen ? ds->draw_binding : SFLAG_INDRAWABLE;
684
685 surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy);
686 }
687
688 if ((!gl_info->supported[WINED3D_GL_VERSION_2_0]
689 || !gl_info->supported[NV_POINT_SPRITE])
690 && context->render_offscreen
691 && state->render_states[WINED3D_RS_POINTSPRITEENABLE]
692 && state->gl_primitive_type == GL_POINTS)
693 {
694 FIXME("Point sprite coordinate origin switching not supported.\n");
695 }
696
697 stream_info = &device->stream_info;
698 if (device->instance_count)
699 instance_count = device->instance_count;
700
701 if (indexed)
702 {
703 struct wined3d_buffer *index_buffer = state->index_buffer;
704 if (!index_buffer->buffer_object || !stream_info->all_vbo)
705 idx_data = index_buffer->resource.allocatedMemory;
706 else
707 {
708 ib_query = index_buffer->query;
709 idx_data = NULL;
710 }
711
712 if (state->index_format == WINED3DFMT_R16_UINT)
713 idx_size = 2;
714 else
715 idx_size = 4;
716 }
717
718 if (!use_vs(state))
719 {
720 if (!stream_info->position_transformed && context->num_untracked_materials
721 && state->render_states[WINED3D_RS_LIGHTING])
722 {
723 static BOOL warned;
724
725 if (!warned++)
726 FIXME("Using software emulation because not all material properties could be tracked.\n");
727 else
728 WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n");
729 emulation = TRUE;
730 }
731 else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE])
732 {
733 static BOOL warned;
734
735 /* Either write a pipeline replacement shader or convert the
736 * specular alpha from unsigned byte to a float in the vertex
737 * buffer. */
738 if (!warned++)
739 FIXME("Using software emulation because manual fog coordinates are provided.\n");
740 else
741 WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n");
742 emulation = TRUE;
743 }
744
745 if (emulation)
746 {
747 si_emulated = device->stream_info;
748 remove_vbos(gl_info, state, &si_emulated);
749 stream_info = &si_emulated;
750 }
751 }
752
753 if (device->useDrawStridedSlow || emulation)
754 {
755 /* Immediate mode drawing. */
756 if (use_vs(state))
757 {
758 static BOOL warned;
759
760 if (!warned++)
761 FIXME("Using immediate mode with vertex shaders for half float emulation.\n");
762 else
763 WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n");
764
765 drawStridedSlowVs(gl_info, state, stream_info, index_count,
766 state->gl_primitive_type, idx_data, idx_size, start_idx);
767 }
768 else
769 {
770 drawStridedSlow(device, context, stream_info, index_count,
771 state->gl_primitive_type, idx_data, idx_size, start_idx);
772 }
773 }
774 else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count)
775 {
776 /* Instancing emulation by mixing immediate mode and arrays. */
777 drawStridedInstanced(gl_info, state, stream_info, index_count, state->gl_primitive_type,
778 idx_data, idx_size, start_idx, state->base_vertex_index, instance_count);
779 }
780 else
781 {
782 drawStridedFast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data,
783 start_idx, state->base_vertex_index, start_instance, instance_count);
784 }
785
786 if (ib_query)
787 wined3d_event_query_issue(ib_query, device);
788 for (i = 0; i < device->num_buffer_queries; ++i)
789 {
790 wined3d_event_query_issue(device->buffer_queries[i], device);
791 }
792
793 if (wined3d_settings.strict_draw_ordering)
794 gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
795
796 context_release(context);
797
798 TRACE("Done all gl drawing\n");
799
800 /* Control goes back to the device, stateblock values may change again */
801 device->isInDraw = FALSE;
802}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette