2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
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.
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.
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
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
34 extern IWineD3DVertexShaderImpl* VertexShaders[64];
35 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
36 extern IWineD3DPixelShaderImpl* PixelShaders[64];
38 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
41 /* Issues the glBegin call for gl given the primitive type and count */
42 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
46 DWORD NumVertexes = NumPrimitives;
48 switch (PrimitiveType) {
51 *primType = GL_POINTS;
52 NumVertexes = NumPrimitives;
58 NumVertexes = NumPrimitives * 2;
62 TRACE("LINE_STRIP\n");
63 *primType = GL_LINE_STRIP;
64 NumVertexes = NumPrimitives + 1;
67 case D3DPT_TRIANGLELIST:
69 *primType = GL_TRIANGLES;
70 NumVertexes = NumPrimitives * 3;
73 case D3DPT_TRIANGLESTRIP:
74 TRACE("TRIANGLE_STRIP\n");
75 *primType = GL_TRIANGLE_STRIP;
76 NumVertexes = NumPrimitives + 2;
79 case D3DPT_TRIANGLEFAN:
80 TRACE("TRIANGLE_FAN\n");
81 *primType = GL_TRIANGLE_FAN;
82 NumVertexes = NumPrimitives + 2;
86 FIXME("Unhandled primitive\n");
87 *primType = GL_POINTS;
93 /* Ensure the appropriate material states are set up - only change
94 state if really required */
95 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
97 BOOL requires_material_reset = FALSE;
98 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
100 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
101 /* If we have not set up the material color tracking, do it now as required */
102 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
103 checkGLcall("glDisable GL_COLOR_MATERIAL");
104 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
105 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
106 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
107 glEnable(GL_COLOR_MATERIAL);
108 checkGLcall("glEnable GL_COLOR_MATERIAL");
109 This->tracking_color = IS_TRACKING;
110 requires_material_reset = TRUE; /* Restore material settings as will be used */
112 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
113 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
114 /* If we are tracking the current color but one isn't supplied, don't! */
115 glDisable(GL_COLOR_MATERIAL);
116 checkGLcall("glDisable GL_COLOR_MATERIAL");
117 This->tracking_color = NEEDS_TRACKING;
118 requires_material_reset = TRUE; /* Restore material settings as will be used */
120 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
121 /* No need to reset material colors since no change to gl_color_material */
122 requires_material_reset = FALSE;
124 } else if (This->tracking_color == NEEDS_DISABLE) {
125 glDisable(GL_COLOR_MATERIAL);
126 checkGLcall("glDisable GL_COLOR_MATERIAL");
127 This->tracking_color = DISABLED_TRACKING;
128 requires_material_reset = TRUE; /* Restore material settings as will be used */
131 /* Reset the material colors which may have been tracking the color*/
132 if (requires_material_reset) {
133 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
134 checkGLcall("glMaterialfv");
135 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
136 checkGLcall("glMaterialfv");
137 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
138 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
139 checkGLcall("glMaterialfv");
141 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
142 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
143 checkGLcall("glMaterialfv");
145 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
146 checkGLcall("glMaterialfv");
151 static GLfloat invymat[16] = {
152 1.0f, 0.0f, 0.0f, 0.0f,
153 0.0f, -1.0f, 0.0f, 0.0f,
154 0.0f, 0.0f, 1.0f, 0.0f,
155 0.0f, 0.0f, 0.0f, 1.0f};
157 void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
158 /* If the last draw was transformed as well, no need to reapply all the matrixes */
159 if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
161 double X, Y, height, width, minZ, maxZ;
162 This->last_was_rhw = TRUE;
163 This->viewport_changed = FALSE;
165 /* Transformed already into viewport coordinates, so we do not need transform
166 matrices. Reset all matrices to identity and leave the default matrix in world
168 glMatrixMode(GL_MODELVIEW);
169 checkGLcall("glMatrixMode(GL_MODELVIEW)");
171 checkGLcall("glLoadIdentity");
173 glMatrixMode(GL_PROJECTION);
174 checkGLcall("glMatrixMode(GL_PROJECTION)");
176 checkGLcall("glLoadIdentity");
178 /* Set up the viewport to be full viewport */
179 X = This->stateBlock->viewport.X;
180 Y = This->stateBlock->viewport.Y;
181 height = This->stateBlock->viewport.Height;
182 width = This->stateBlock->viewport.Width;
183 minZ = This->stateBlock->viewport.MinZ;
184 maxZ = This->stateBlock->viewport.MaxZ;
185 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
186 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
187 checkGLcall("glOrtho");
189 /* Window Coord 0 is the middle of the first pixel, so translate by half
190 a pixel (See comment above glTranslate below) */
191 glTranslatef(0.375, 0.375, 0);
192 checkGLcall("glTranslatef(0.375, 0.375, 0)");
193 if (This->renderUpsideDown) {
194 glMultMatrixf(invymat);
195 checkGLcall("glMultMatrixf(invymat)");
198 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
199 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
200 if(GL_SUPPORT(EXT_FOG_COORD)) {
201 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
202 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
203 glFogi(GL_FOG_MODE, GL_LINEAR);
204 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
205 /* The dx fog range in this case is fixed to 0 - 255,
206 * but in GL it still depends on the fog start and end (according to the ext)
207 * Use this to turn around the fog as it's needed. That prevents some
208 * calculations during drawing :-)
210 glFogf(GL_FOG_START, (float) 0xff);
211 checkGLcall("glFogfv GL_FOG_END");
212 glFogf(GL_FOG_END, 0.0);
213 checkGLcall("glFogfv GL_FOG_START");
215 /* Disable GL fog, handle this in software in drawStridedSlow */
217 checkGLcall("glDisable(GL_FOG)");
222 /* Setup views - Transformed & lit if RHW, else untransformed.
223 Only unlit if Normals are supplied
224 Returns: Whether to restore lighting afterwards */
225 static void primitiveInitState(
226 IWineD3DDevice *iface,
227 WineDirect3DVertexStridedData* strided,
229 BOOL* lighting_changed,
230 BOOL* lighting_original) {
232 BOOL fixed_vtx_transformed =
233 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
234 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
235 strided->u.s.position_transformed;
238 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
239 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
243 *lighting_changed = FALSE;
245 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
246 set by the appropriate render state. Note Vertex Shader output is already lit */
247 if (fixed_vtx_lit || useVS) {
248 *lighting_changed = TRUE;
249 *lighting_original = glIsEnabled(GL_LIGHTING);
250 glDisable(GL_LIGHTING);
251 checkGLcall("glDisable(GL_LIGHTING);");
252 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
255 if (!useVS && fixed_vtx_transformed) {
256 d3ddevice_set_ortho(This);
260 /* Untransformed, so relies on the view and projection matrices */
262 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
263 /* Only reapply when have to */
264 This->modelview_valid = TRUE;
265 glMatrixMode(GL_MODELVIEW);
266 checkGLcall("glMatrixMode");
268 /* In the general case, the view matrix is the identity matrix */
269 if (This->view_ident) {
270 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
271 checkGLcall("glLoadMatrixf");
273 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
274 checkGLcall("glLoadMatrixf");
275 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
276 checkGLcall("glMultMatrixf");
280 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
281 /* Only reapply when have to */
282 This->proj_valid = TRUE;
283 glMatrixMode(GL_PROJECTION);
284 checkGLcall("glMatrixMode");
286 /* The rule is that the window coordinate 0 does not correspond to the
287 beginning of the first pixel, but the center of the first pixel.
288 As a consequence if you want to correctly draw one line exactly from
289 the left to the right end of the viewport (with all matrices set to
290 be identity), the x coords of both ends of the line would be not
291 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
295 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
296 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
298 if (This->renderUpsideDown) {
299 glMultMatrixf(invymat);
300 checkGLcall("glMultMatrixf(invymat)");
302 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
303 checkGLcall("glLoadMatrixf");
306 /* Vertex Shader output is already transformed, so set up identity matrices */
307 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
308 come along this needs to take into account whether s/w ones were
311 glMatrixMode(GL_MODELVIEW);
312 checkGLcall("glMatrixMode");
314 glMatrixMode(GL_PROJECTION);
315 checkGLcall("glMatrixMode");
317 /* Window Coord 0 is the middle of the first pixel, so translate by half
318 a pixel (See comment above glTranslate above) */
319 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
320 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
321 if (This->renderUpsideDown) {
322 glMultMatrixf(invymat);
323 checkGLcall("glMultMatrixf(invymat)");
325 This->modelview_valid = FALSE;
326 This->proj_valid = FALSE;
328 This->last_was_rhw = FALSE;
330 /* Restore fogging */
331 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
332 if(GL_SUPPORT(EXT_FOG_COORD)) {
333 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
334 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
335 /* Reapply the fog range */
336 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
337 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
338 /* Restore the fog mode */
339 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
341 /* Enable GL_FOG again because we disabled it above */
343 checkGLcall("glEnable(GL_FOG)");
349 static BOOL fixed_get_input(
350 BYTE usage, BYTE usage_idx,
351 unsigned int* regnum) {
355 /* Those positions must have the order in the
356 * named part of the strided data */
358 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
360 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
362 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
364 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
366 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
368 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
370 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
372 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < D3DDP_MAXTEXCOORD)
373 *regnum = 7 + usage_idx;
374 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
375 *regnum = 7 + D3DDP_MAXTEXCOORD;
376 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
377 *regnum = 8 + D3DDP_MAXTEXCOORD;
378 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
379 *regnum = 9 + D3DDP_MAXTEXCOORD;
380 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
381 *regnum = 10 + D3DDP_MAXTEXCOORD;
382 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
383 *regnum = 11 + D3DDP_MAXTEXCOORD;
384 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
385 *regnum = 12 + D3DDP_MAXTEXCOORD;
386 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
387 *regnum = 13 + D3DDP_MAXTEXCOORD;
388 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
389 *regnum = 14 + D3DDP_MAXTEXCOORD;
392 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
393 debug_d3ddeclusage(usage), usage_idx);
399 void primitiveDeclarationConvertToStridedData(
400 IWineD3DDevice *iface,
401 BOOL useVertexShaderFunction,
402 WineDirect3DVertexStridedData *strided,
403 LONG BaseVertexIndex,
406 /* We need to deal with frequency data!*/
409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
410 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
412 WINED3DVERTEXELEMENT *element;
416 /* Locate the vertex declaration */
417 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
418 TRACE("Using vertex declaration from shader\n");
419 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
421 TRACE("Using vertex declaration\n");
422 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
425 /* Translate the declaration into strided data */
426 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
431 element = vertexDeclaration->pDeclarationWine + i;
432 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
433 if (This->stateBlock->streamIsUP) {
434 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
436 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
437 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
439 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
440 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
441 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
443 if( streamVBO != 0) *fixup = TRUE;
444 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
447 stride = This->stateBlock->streamStride[element->Stream];
448 data += (BaseVertexIndex * stride);
449 data += element->Offset;
452 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
454 if (useVertexShaderFunction)
455 stride_used = vshader_get_input(This->stateBlock->vertexShader,
456 element->Usage, element->UsageIndex, &idx);
458 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
461 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
462 "stream=%u, offset=%u, stride=%lu, VBO=%u]\n",
463 useVertexShaderFunction? "shader": "fixed function", idx,
464 debug_d3ddeclusage(element->Usage), element->UsageIndex,
465 element->Stream, element->Offset, stride, streamVBO);
467 strided->u.input[idx].lpData = data;
468 strided->u.input[idx].dwType = element->Type;
469 strided->u.input[idx].dwStride = stride;
470 strided->u.input[idx].VBO = streamVBO;
471 if (!useVertexShaderFunction) {
472 if (element->Usage == D3DDECLUSAGE_POSITION)
473 strided->u.s.position_transformed = FALSE;
474 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
475 strided->u.s.position_transformed = TRUE;
481 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
485 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
486 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
488 /* Either 3 or 4 floats depending on the FVF */
489 /* FIXME: Can blending data be in a different stream to the position data?
490 and if so using the fixed pipeline how do we handle it */
491 if (thisFVF & D3DFVF_POSITION_MASK) {
492 strided->u.s.position.lpData = data;
493 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
494 strided->u.s.position.dwStride = stride;
495 strided->u.s.position.VBO = streamVBO;
496 data += 3 * sizeof(float);
497 if (thisFVF & D3DFVF_XYZRHW) {
498 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
499 strided->u.s.position_transformed = TRUE;
500 data += sizeof(float);
502 strided->u.s.position_transformed = FALSE;
505 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
506 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
507 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
508 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
510 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
511 TRACE("Setting blend Weights to %p\n", data);
512 strided->u.s.blendWeights.lpData = data;
513 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
514 strided->u.s.blendWeights.dwStride = stride;
515 strided->u.s.blendWeights.VBO = streamVBO;
516 data += numBlends * sizeof(FLOAT);
518 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
519 strided->u.s.blendMatrixIndices.lpData = data;
520 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
521 strided->u.s.blendMatrixIndices.dwStride= stride;
522 strided->u.s.blendMatrixIndices.VBO = streamVBO;
523 data += sizeof(DWORD);
527 /* Normal is always 3 floats */
528 if (thisFVF & D3DFVF_NORMAL) {
529 strided->u.s.normal.lpData = data;
530 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
531 strided->u.s.normal.dwStride = stride;
532 strided->u.s.normal.VBO = streamVBO;
533 data += 3 * sizeof(FLOAT);
536 /* Pointsize is a single float */
537 if (thisFVF & D3DFVF_PSIZE) {
538 strided->u.s.pSize.lpData = data;
539 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
540 strided->u.s.pSize.dwStride = stride;
541 strided->u.s.pSize.VBO = streamVBO;
542 data += sizeof(FLOAT);
545 /* Diffuse is 4 unsigned bytes */
546 if (thisFVF & D3DFVF_DIFFUSE) {
547 strided->u.s.diffuse.lpData = data;
548 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
549 strided->u.s.diffuse.dwStride = stride;
550 strided->u.s.diffuse.VBO = streamVBO;
551 data += sizeof(DWORD);
554 /* Specular is 4 unsigned bytes */
555 if (thisFVF & D3DFVF_SPECULAR) {
556 strided->u.s.specular.lpData = data;
557 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
558 strided->u.s.specular.dwStride = stride;
559 strided->u.s.specular.VBO = streamVBO;
560 data += sizeof(DWORD);
564 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
565 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
567 /* numTextures indicates the number of texture coordinates supplied */
568 /* However, the first set may not be for stage 0 texture - it all */
569 /* depends on D3DTSS_TEXCOORDINDEX. */
570 /* The number of bytes for each coordinate set is based off */
571 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
573 /* So, for each supplied texture extract the coords */
574 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
576 strided->u.s.texCoords[textureNo].lpData = data;
577 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
578 strided->u.s.texCoords[textureNo].dwStride = stride;
579 strided->u.s.texCoords[textureNo].VBO = streamVBO;
580 numCoords[textureNo] = coordIdxInfo & 0x03;
583 data += sizeof(float);
584 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
585 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
586 data += sizeof(float);
587 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
588 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
589 data += sizeof(float);
590 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
591 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
592 data += sizeof(float);
596 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
600 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
602 short LoopThroughTo = 0;
606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
608 /* OK, Now to setup the data locations
609 For the non-created vertex shaders, the VertexShader var holds the real
610 FVF and only stream 0 matters
611 For the created vertex shaders, there is an FVF per stream */
612 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
613 LoopThroughTo = MAX_STREAMS;
618 /* Work through stream by stream */
619 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
620 DWORD stride = This->stateBlock->streamStride[nStream];
624 /* Skip empty streams */
625 if (This->stateBlock->streamSource[nStream] == NULL) continue;
627 /* Retrieve appropriate FVF */
628 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
629 thisFVF = This->stateBlock->fvf;
630 /* Handle memory passed directly as well as vertex buffers */
631 if (This->stateBlock->streamIsUP) {
633 data = (BYTE *)This->stateBlock->streamSource[nStream];
635 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
636 /* GetMemory binds the VBO */
637 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
639 if(streamVBO != 0 ) *fixup = TRUE;
643 #if 0 /* TODO: Vertex shader support */
644 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
645 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
648 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
649 if (thisFVF == 0) continue;
651 /* Now convert the stream into pointers */
653 /* Shuffle to the beginning of the vertexes to render and index from there */
654 data = data + (BaseVertexIndex * stride);
656 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
660 #if 0 /* TODO: Software Shaders */
661 /* Draw a single vertex using this information */
662 static void draw_vertex(IWineD3DDevice *iface, /* interface */
663 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
664 BOOL isNormal, float nx, float ny, float nz, /* normal */
665 BOOL isDiffuse, float *dRGBA, /* 1st colors */
666 BOOL isSpecular, float *sRGB, /* 2ndry colors */
667 BOOL isPtSize, float ptSize, /* pointSize */
668 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
670 unsigned int textureNo;
672 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
674 /* Diffuse -------------------------------- */
677 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
680 /* Specular Colour ------------------------------------------*/
682 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
683 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
684 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
686 VTRACE(("Specular color extensions not supplied\n"));
690 /* Normal -------------------------------- */
692 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
693 glNormal3f(nx, ny, nz);
696 /* Point Size ----------------------------------------------*/
699 /* no such functionality in the fixed function GL pipeline */
700 FIXME("Cannot change ptSize here in openGl\n");
703 /* Texture coords --------------------------- */
704 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
706 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
707 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
711 /* Query tex coords */
712 if (This->stateBlock->textures[textureNo] != NULL) {
714 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
715 if (coordIdx >= MAX_TEXTURES) {
716 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
718 } else if (numcoords[coordIdx] == 0) {
719 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
723 /* Initialize vars */
729 switch (numcoords[coordIdx]) {
730 case 4: q = texcoords[coordIdx].w; /* drop through */
731 case 3: r = texcoords[coordIdx].z; /* drop through */
732 case 2: t = texcoords[coordIdx].y; /* drop through */
733 case 1: s = texcoords[coordIdx].x;
736 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
738 VTRACE(("tex:%d, s=%f\n", textureNo, s));
739 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
740 GLMULTITEXCOORD1F(textureNo, s);
746 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
747 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
748 GLMULTITEXCOORD2F(textureNo, s, t);
754 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
755 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
756 GLMULTITEXCOORD3F(textureNo, s, t, r);
758 glTexCoord3f(s, t, r);
762 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
763 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
764 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
766 glTexCoord4f(s, t, r, q);
770 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
774 } /* End of textures */
776 /* Position -------------------------------- */
778 if (1.0f == rhw || rhw < 0.00001f) {
779 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
782 /* Cannot optimize by dividing through by rhw as rhw is required
783 later for perspective in the GL pipeline for vertex shaders */
784 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
785 glVertex4f(x,y,z,rhw);
789 #endif /* TODO: Software shaders */
791 static void loadNumberedArrays(
792 IWineD3DDevice *iface,
793 IWineD3DVertexShader *shader,
794 WineDirect3DVertexStridedData *strided) {
796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
800 for (i = 0; i < MAX_ATTRIBS; i++) {
802 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
805 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
807 if(curVBO != strided->u.input[i].VBO) {
808 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
809 checkGLcall("glBindBufferARB");
810 curVBO = strided->u.input[i].VBO;
812 GL_EXTCALL(glVertexAttribPointerARB(i,
813 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
814 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
815 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
816 strided->u.input[i].dwStride,
817 strided->u.input[i].lpData));
818 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
822 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
823 unsigned int textureNo = 0;
824 unsigned int texture_idx = 0;
825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
828 TRACE("Using fast vertex array code\n");
829 /* Blend Data ---------------------------------------------- */
830 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
831 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
834 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
837 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
838 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
841 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
842 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
843 /* FIXME("TODO\n");*/
844 /* Note dwType == float3 or float4 == 2 or 3 */
847 /* with this on, the normals appear to be being modified,
848 but the vertices aren't being translated as they should be
849 Maybe the world matrix aren't being setup properly? */
850 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
854 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
855 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
856 sd->u.s.blendWeights.dwStride,
857 sd->u.s.blendWeights.lpData));
859 if(curVBO != sd->u.s.blendWeights.VBO) {
860 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
861 checkGLcall("glBindBufferARB");
862 curVBO = sd->u.s.blendWeights.VBO;
865 GL_EXTCALL(glWeightPointerARB)(
866 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
867 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
868 sd->u.s.blendWeights.dwStride,
869 sd->u.s.blendWeights.lpData);
871 checkGLcall("glWeightPointerARB");
873 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
874 static BOOL showfixme = TRUE;
876 FIXME("blendMatrixIndices support\n");
881 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
882 /* FIXME("TODO\n");*/
885 GL_EXTCALL(glVertexWeightPointerEXT)(
886 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
887 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
888 sd->u.s.blendWeights.dwStride,
889 sd->u.s.blendWeights.lpData);
890 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
891 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
892 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
896 /* TODO: support blends in fixupVertices */
897 FIXME("unsupported blending in openGl\n");
900 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
901 #if 0 /* TODO: Vertex blending */
902 glDisable(GL_VERTEX_BLEND_ARB);
904 TRACE("ARB_VERTEX_BLEND\n");
905 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
906 TRACE(" EXT_VERTEX_WEIGHTING\n");
907 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
908 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
913 #if 0 /* FOG ----------------------------------------------*/
914 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
916 if (GL_SUPPORT(EXT_FOG_COORD) {
917 glEnableClientState(GL_FOG_COORDINATE_EXT);
918 (GL_EXTCALL)(FogCoordPointerEXT)(
919 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
920 sd->u.s.fog.dwStride,
923 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
924 /* FIXME: fixme once */
925 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
928 if (GL_SUPPRT(EXT_FOR_COORD) {
929 /* make sure fog is disabled */
930 glDisableClientState(GL_FOG_COORDINATE_EXT);
935 #if 0 /* tangents ----------------------------------------------*/
936 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
937 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
939 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
940 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
941 glEnable(GL_TANGENT_ARRAY_EXT);
942 (GL_EXTCALL)(TangentPointerEXT)(
943 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
944 sd->u.s.tangent.dwStride,
945 sd->u.s.tangent.lpData);
947 glDisable(GL_TANGENT_ARRAY_EXT);
949 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
950 glEnable(GL_BINORMAL_ARRAY_EXT);
951 (GL_EXTCALL)(BinormalPointerEXT)(
952 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
953 sd->u.s.binormal.dwStride,
954 sd->u.s.binormal.lpData);
956 glDisable(GL_BINORMAL_ARRAY_EXT);
960 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
961 /* FIXME: fixme once */
962 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
965 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
966 /* make sure fog is disabled */
967 glDisable(GL_TANGENT_ARRAY_EXT);
968 glDisable(GL_BINORMAL_ARRAY_EXT);
973 /* Point Size ----------------------------------------------*/
974 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
976 /* no such functionality in the fixed function GL pipeline */
977 TRACE("Cannot change ptSize here in openGl\n");
978 /* TODO: Implement this function in using shaders if they are available */
982 /* Vertex Pointers -----------------------------------------*/
983 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
984 /* Note dwType == float3 or float4 == 2 or 3 */
985 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
986 sd->u.s.position.dwStride,
987 sd->u.s.position.dwType + 1,
988 sd->u.s.position.lpData));
990 if(curVBO != sd->u.s.position.VBO) {
991 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
992 checkGLcall("glBindBufferARB");
993 curVBO = sd->u.s.position.VBO;
996 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
997 handling for rhw mode should not impact screen position whereas in GL it does.
998 This may result in very slightly distored textures in rhw mode, but
999 a very minimal different. There's always the other option of
1000 fixing the view matrix to prevent w from having any effect
1002 This only applies to user pointer sources, in VBOs the vertices are fixed up
1004 if(sd->u.s.position.VBO == 0) {
1005 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1006 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1007 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1010 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1011 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1012 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1014 checkGLcall("glVertexPointer(...)");
1015 glEnableClientState(GL_VERTEX_ARRAY);
1016 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1019 glDisableClientState(GL_VERTEX_ARRAY);
1020 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1023 /* Normals -------------------------------------------------*/
1024 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1025 /* Note dwType == float3 or float4 == 2 or 3 */
1026 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1027 sd->u.s.normal.dwStride,
1028 sd->u.s.normal.lpData));
1029 if(curVBO != sd->u.s.normal.VBO) {
1030 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1031 checkGLcall("glBindBufferARB");
1032 curVBO = sd->u.s.normal.VBO;
1035 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1036 sd->u.s.normal.dwStride,
1037 sd->u.s.normal.lpData);
1038 checkGLcall("glNormalPointer(...)");
1039 glEnableClientState(GL_NORMAL_ARRAY);
1040 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1043 glDisableClientState(GL_NORMAL_ARRAY);
1044 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1045 glNormal3f(0, 0, 1);
1046 checkGLcall("glNormal3f(0, 0, 1)");
1049 /* Diffuse Colour --------------------------------------------*/
1050 /* WARNING: Data here MUST be in RGBA format, so cannot */
1051 /* go directly into fast mode from app pgm, because */
1052 /* directx requires data in BGRA format. */
1053 /* currently fixupVertices swizels the format, but this isn't */
1054 /* very practical when using VBOS */
1055 /* NOTE: Unless we write a vertex shader to swizel the colour */
1056 /* , or the user doesn't care and wants the speed advantage */
1058 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1059 /* Note dwType == float3 or float4 == 2 or 3 */
1060 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1061 sd->u.s.diffuse.dwStride,
1062 sd->u.s.diffuse.lpData));
1064 if(curVBO != sd->u.s.diffuse.VBO) {
1065 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1066 checkGLcall("glBindBufferARB");
1067 curVBO = sd->u.s.diffuse.VBO;
1069 glColorPointer(4, GL_UNSIGNED_BYTE,
1070 sd->u.s.diffuse.dwStride,
1071 sd->u.s.diffuse.lpData);
1072 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1073 glEnableClientState(GL_COLOR_ARRAY);
1074 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1077 glDisableClientState(GL_COLOR_ARRAY);
1078 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1079 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1080 checkGLcall("glColor4f(1, 1, 1, 1)");
1083 /* Specular Colour ------------------------------------------*/
1084 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1085 TRACE("setting specular colour\n");
1086 /* Note dwType == float3 or float4 == 2 or 3 */
1087 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1088 sd->u.s.specular.dwStride,
1089 sd->u.s.specular.lpData));
1090 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1091 if(curVBO != sd->u.s.specular.VBO) {
1092 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1093 checkGLcall("glBindBufferARB");
1094 curVBO = sd->u.s.specular.VBO;
1096 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1097 sd->u.s.specular.dwStride,
1098 sd->u.s.specular.lpData);
1099 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1100 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1101 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1104 /* Missing specular color is not critical, no warnings */
1105 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1109 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1111 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1112 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1113 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1114 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1117 /* Missing specular color is not critical, no warnings */
1118 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1122 /* Texture coords -------------------------------------------*/
1124 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1125 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1126 /* Abort if we don't support the extension. */
1127 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1128 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1132 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1133 /* Select the correct texture stage */
1134 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1137 if (This->stateBlock->textures[textureNo] != NULL) {
1138 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1139 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1141 if (coordIdx >= MAX_TEXTURES) {
1142 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1143 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1144 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1146 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1147 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1148 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1149 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1152 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1153 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1154 checkGLcall("glBindBufferARB");
1155 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1157 /* The coords to supply depend completely on the fvf / vertex shader */
1159 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1160 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1161 sd->u.s.texCoords[coordIdx].dwStride,
1162 sd->u.s.texCoords[coordIdx].lpData);
1163 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1165 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1166 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1167 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1169 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1171 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1172 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1173 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1174 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1175 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1180 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1181 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1184 if (idxData != NULL /* This crashes sometimes!*/) {
1185 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1186 idxData = idxData == (void *)-1 ? NULL : idxData;
1189 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1190 glEnableClientState(GL_INDEX_ARRAY);
1192 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1193 (const char *)idxData+(idxSize * startIdx));
1194 #else /* using drawRangeElements may be faster */
1196 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1197 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1198 (const char *)idxData+(idxSize * startIdx));
1200 checkGLcall("glDrawRangeElements");
1204 /* Note first is now zero as we shuffled along earlier */
1205 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1206 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1207 checkGLcall("glDrawArrays");
1215 * Actually draw using the supplied information.
1216 * Slower GL version which extracts info about each vertex in turn
1219 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1220 UINT NumVertexes, GLenum glPrimType,
1221 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1223 unsigned int textureNo = 0;
1224 unsigned int texture_idx = 0;
1225 const short *pIdxBufS = NULL;
1226 const long *pIdxBufL = NULL;
1227 LONG SkipnStrides = 0;
1229 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1230 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1231 float rhw = 0.0f; /* rhw */
1232 float ptSize = 0.0f; /* Point size */
1233 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1234 DWORD specularColor = 0; /* Specular Color */
1235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1237 TRACE("Using slow vertex array code\n");
1239 /* Variable Initialization */
1240 if (idxData != NULL) {
1241 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1242 else pIdxBufL = (const long *) idxData;
1245 /* Start drawing in GL */
1246 VTRACE(("glBegin(%x)\n", glPrimType));
1247 glBegin(glPrimType);
1249 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1250 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1253 /* For each primitive */
1254 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1256 /* Initialize diffuse color */
1257 diffuseColor = 0xFFFFFFFF;
1259 /* For indexed data, we need to go a few more strides in */
1260 if (idxData != NULL) {
1262 /* Indexed so work out the number of strides to skip */
1264 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1265 SkipnStrides = pIdxBufS[startIdx + vx_index];
1267 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1268 SkipnStrides = pIdxBufL[startIdx + vx_index];
1272 /* Position Information ------------------ */
1273 if (sd->u.s.position.lpData != NULL) {
1275 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1280 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1282 /* RHW follows, only if transformed, ie 4 floats were provided */
1283 if (sd->u.s.position_transformed) {
1284 rhw = ptrToCoords[3];
1285 VTRACE(("rhw=%f\n", rhw));
1289 /* Blending data -------------------------- */
1290 if (sd->u.s.blendWeights.lpData != NULL) {
1291 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1292 FIXME("Blending not supported yet\n");
1294 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1295 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1299 /* Vertex Normal Data (untransformed only)- */
1300 if (sd->u.s.normal.lpData != NULL) {
1302 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1303 nx = ptrToCoords[0];
1304 ny = ptrToCoords[1];
1305 nz = ptrToCoords[2];
1306 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1309 /* Point Size ----------------------------- */
1310 if (sd->u.s.pSize.lpData != NULL) {
1312 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1313 ptSize = ptrToCoords[0];
1314 VTRACE(("ptSize=%f\n", ptSize));
1315 FIXME("No support for ptSize yet\n");
1318 /* Diffuse -------------------------------- */
1319 if (sd->u.s.diffuse.lpData != NULL) {
1321 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1322 diffuseColor = ptrToCoords[0];
1323 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1326 /* Specular -------------------------------- */
1327 if (sd->u.s.specular.lpData != NULL) {
1329 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1330 specularColor = ptrToCoords[0];
1331 VTRACE(("specularColor=%lx\n", specularColor));
1334 /* Texture coords --------------------------- */
1335 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1337 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1338 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1342 /* Query tex coords */
1343 if (This->stateBlock->textures[textureNo] != NULL) {
1345 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1346 float *ptrToCoords = NULL;
1347 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1350 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1352 } else if (coordIdx < 0) {
1353 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1357 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1358 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1359 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1363 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1365 /* The coords to supply depend completely on the fvf / vertex shader */
1366 switch (coordsToUse) {
1367 case 4: q = ptrToCoords[3]; /* drop through */
1368 case 3: r = ptrToCoords[2]; /* drop through */
1369 case 2: t = ptrToCoords[1]; /* drop through */
1370 case 1: s = ptrToCoords[0];
1373 /* Projected is more 'fun' - Move the last coord to the 'q'
1374 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1375 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1376 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1378 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1379 switch (coordsToUse) {
1380 case 0: /* Drop Through */
1382 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1394 case 4: /* Nop here */
1397 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1398 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1403 switch (coordsToUse) { /* Supply the provided texture coords */
1404 case D3DTTFF_COUNT1:
1405 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1406 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1407 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1412 case D3DTTFF_COUNT2:
1413 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1414 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1415 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1420 case D3DTTFF_COUNT3:
1421 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1422 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1423 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1425 glTexCoord3f(s, t, r);
1428 case D3DTTFF_COUNT4:
1429 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1430 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1431 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1433 glTexCoord4f(s, t, r, q);
1437 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1441 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1442 } /* End of textures */
1444 /* Diffuse -------------------------------- */
1445 if (sd->u.s.diffuse.lpData != NULL) {
1446 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1447 D3DCOLOR_B_G(diffuseColor),
1448 D3DCOLOR_B_B(diffuseColor),
1449 D3DCOLOR_B_A(diffuseColor));
1450 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1451 D3DCOLOR_B_R(diffuseColor),
1452 D3DCOLOR_B_G(diffuseColor),
1453 D3DCOLOR_B_B(diffuseColor),
1454 D3DCOLOR_B_A(diffuseColor)));
1456 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1459 /* Specular ------------------------------- */
1460 if (sd->u.s.specular.lpData != NULL) {
1461 /* special case where the fog density is stored in the diffuse alpha channel */
1462 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1463 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
1464 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1465 if(GL_SUPPORT(EXT_FOG_COORD)) {
1466 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1468 static BOOL warned = FALSE;
1470 /* TODO: Use the fog table code from old ddraw */
1471 FIXME("Implement fog for transformed vertices in software\n");
1477 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1478 D3DCOLOR_B_R(specularColor),
1479 D3DCOLOR_B_G(specularColor),
1480 D3DCOLOR_B_B(specularColor)));
1481 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1482 GL_EXTCALL(glSecondaryColor3ubEXT)(
1483 D3DCOLOR_B_R(specularColor),
1484 D3DCOLOR_B_G(specularColor),
1485 D3DCOLOR_B_B(specularColor));
1487 /* Do not worry if specular colour missing and disable request */
1488 VTRACE(("Specular color extensions not supplied\n"));
1491 if (vx_index == 0) {
1492 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1493 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1495 /* Do not worry if specular colour missing and disable request */
1496 VTRACE(("Specular color extensions not supplied\n"));
1501 /* Normal -------------------------------- */
1502 if (sd->u.s.normal.lpData != NULL) {
1503 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1504 glNormal3f(nx, ny, nz);
1506 if (vx_index == 0) glNormal3f(0, 0, 1);
1509 /* Position -------------------------------- */
1510 if (sd->u.s.position.lpData != NULL) {
1511 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1512 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1513 glVertex3f(x, y, z);
1515 GLfloat w = 1.0 / rhw;
1516 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1517 glVertex4f(x*w, y*w, z*w, w);
1521 /* For non indexed mode, step onto next parts */
1522 if (idxData == NULL) {
1528 checkGLcall("glEnd and previous calls");
1531 #if 0 /* TODO: Software/Hardware vertex blending support */
1533 * Draw with emulated vertex shaders
1534 * Note: strided data is uninitialized, as we need to pass the vertex
1535 * shader directly as ordering irs yet
1537 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1538 int PrimitiveType, ULONG NumPrimitives,
1539 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1541 unsigned int textureNo = 0;
1542 GLenum glPrimType = GL_POINTS;
1543 int NumVertexes = NumPrimitives;
1544 const short *pIdxBufS = NULL;
1545 const long *pIdxBufL = NULL;
1546 LONG SkipnStrides = 0;
1548 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1549 float rhw = 0.0f; /* rhw */
1550 float ptSize = 0.0f; /* Point size */
1551 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1552 int numcoords[8]; /* Number of coords */
1553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1555 IDirect3DVertexShaderImpl* vertexShader = NULL;
1557 TRACE("Using slow software vertex shader code\n");
1559 /* Variable Initialization */
1560 if (idxData != NULL) {
1561 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1562 else pIdxBufL = (const long *) idxData;
1565 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1566 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1568 /* Retrieve the VS information */
1569 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1571 /* Start drawing in GL */
1572 VTRACE(("glBegin(%x)\n", glPrimType));
1573 glBegin(glPrimType);
1575 /* For each primitive */
1576 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1578 /* For indexed data, we need to go a few more strides in */
1579 if (idxData != NULL) {
1581 /* Indexed so work out the number of strides to skip */
1583 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1584 SkipnStrides = pIdxBufS[startIdx+vx_index];
1586 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1587 SkipnStrides = pIdxBufL[startIdx+vx_index];
1591 /* Fill the vertex shader input */
1592 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1594 /* Initialize the output fields to the same defaults as it would normally have */
1595 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1596 vertexShader->output.oD[0].x = 1.0;
1597 vertexShader->output.oD[0].y = 1.0;
1598 vertexShader->output.oD[0].z = 1.0;
1599 vertexShader->output.oD[0].w = 1.0;
1601 /* Now execute the vertex shader */
1602 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1605 TRACE_VECTOR(vertexShader->output.oPos);
1606 TRACE_VECTOR(vertexShader->output.oD[0]);
1607 TRACE_VECTOR(vertexShader->output.oD[1]);
1608 TRACE_VECTOR(vertexShader->output.oT[0]);
1609 TRACE_VECTOR(vertexShader->output.oT[1]);
1610 TRACE_VECTOR(vertexShader->input.V[0]);
1611 TRACE_VECTOR(vertexShader->data->C[0]);
1612 TRACE_VECTOR(vertexShader->data->C[1]);
1613 TRACE_VECTOR(vertexShader->data->C[2]);
1614 TRACE_VECTOR(vertexShader->data->C[3]);
1615 TRACE_VECTOR(vertexShader->data->C[4]);
1616 TRACE_VECTOR(vertexShader->data->C[5]);
1617 TRACE_VECTOR(vertexShader->data->C[6]);
1618 TRACE_VECTOR(vertexShader->data->C[7]);
1621 /* Extract out the output */
1622 /* FIXME: Fog coords? */
1623 x = vertexShader->output.oPos.x;
1624 y = vertexShader->output.oPos.y;
1625 z = vertexShader->output.oPos.z;
1626 rhw = vertexShader->output.oPos.w;
1627 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1629 /** Update textures coords using vertexShader->output.oT[0->7] */
1630 memset(texcoords, 0x00, sizeof(texcoords));
1631 memset(numcoords, 0x00, sizeof(numcoords));
1632 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1633 if (This->stateBlock->textures[textureNo] != NULL) {
1634 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1635 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1636 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1637 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1638 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1639 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1641 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1642 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1643 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1644 default: numcoords[textureNo] = 4;
1648 numcoords[textureNo] = 0;
1652 /* Draw using this information */
1655 TRUE, 0.0f, 0.0f, 1.0f,
1656 TRUE, (float*) &vertexShader->output.oD[0],
1657 TRUE, (float*) &vertexShader->output.oD[1],
1658 FALSE, ptSize, /* FIXME: Change back when supported */
1659 texcoords, numcoords);
1661 /* For non indexed mode, step onto next parts */
1662 if (idxData == NULL) {
1666 } /* for each vertex */
1669 checkGLcall("glEnd and previous calls");
1674 inline static void drawPrimitiveDrawStrided(
1675 IWineD3DDevice *iface,
1676 BOOL useVertexShaderFunction,
1677 BOOL usePixelShaderFunction,
1678 WineDirect3DVertexStridedData *dataLocations,
1679 UINT numberOfvertices,
1680 UINT numberOfIndicies,
1682 const void *idxData,
1688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1689 BOOL useDrawStridedSlow;
1691 int startStride = idxData == NULL ? 0 :
1692 idxData == (void *) -1 ? 0 :
1693 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1694 int endStride = startStride;
1695 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1696 startStride, endStride, numberOfIndicies, numberOfvertices);
1698 /* Generate some fixme's if unsupported functionality is being used */
1699 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1700 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1701 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1702 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1704 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1705 FIXME("Tweening is only valid with vertex shaders\n");
1707 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1708 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1710 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1711 FIXME("Extended attributes are only valid with vertex shaders\n");
1713 #undef BUFFER_OR_DATA
1715 /* Fixed pipeline, no fixups required - load arrays */
1716 if (!useVertexShaderFunction &&
1717 ((dataLocations->u.s.pSize.lpData == NULL &&
1718 dataLocations->u.s.diffuse.lpData == NULL &&
1719 dataLocations->u.s.specular.lpData == NULL) ||
1722 /* Load the vertex data using named arrays */
1723 TRACE("(%p) Loading vertex data\n", This);
1724 loadVertexData(iface, dataLocations);
1725 useDrawStridedSlow = FALSE;
1727 /* Shader pipeline - load attribute arrays */
1728 } else if(useVertexShaderFunction) {
1730 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1731 useDrawStridedSlow = FALSE;
1733 /* Draw vertex by vertex */
1735 TRACE("Not loading vertex data\n");
1736 useDrawStridedSlow = TRUE;
1739 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1740 * Otherwise set 0, which restores fixed function */
1741 if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1742 (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1743 set_glsl_shader_program(iface);
1745 This->stateBlock->shaderPrgId = 0;
1747 /* If GLSL is used now, or might have been used before, (re)set the program */
1748 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
1749 wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1751 if (This->stateBlock->shaderPrgId)
1752 TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
1753 GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
1754 checkGLcall("glUseProgramObjectARB");
1757 if (useVertexShaderFunction) {
1759 TRACE("Using vertex shader\n");
1761 if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1762 /* Bind the vertex program */
1763 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1764 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1765 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1767 /* Enable OpenGL vertex programs */
1768 glEnable(GL_VERTEX_PROGRAM_ARB);
1769 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1770 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1771 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1775 if (usePixelShaderFunction) {
1777 TRACE("Using pixel shader\n");
1779 if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1780 /* Bind the fragment program */
1781 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1782 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1783 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1785 /* Enable OpenGL fragment programs */
1786 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1787 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1788 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1789 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1793 /* Load any global constants/uniforms that may have been set by the application */
1794 if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
1795 shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1796 else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
1797 shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1799 /* Draw vertex-by-vertex */
1800 if (useDrawStridedSlow)
1801 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1803 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1805 /* Cleanup vertex program */
1806 if (useVertexShaderFunction) {
1807 /* disable any attribs (this is the same for both GLSL and ARB modes) */
1810 /* Leave all the attribs disabled */
1811 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1812 /* MESA does not support it right not */
1813 if (glGetError() != GL_NO_ERROR)
1815 for (i = 0; i < maxAttribs; ++i) {
1816 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1817 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1820 if (wined3d_settings.vs_selected_mode == SHADER_ARB)
1821 glDisable(GL_VERTEX_PROGRAM_ARB);
1824 /* Cleanup fragment program */
1825 if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB)
1826 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1829 inline void drawPrimitiveTraceDataLocations(
1830 WineDirect3DVertexStridedData *dataLocations) {
1832 /* Dump out what parts we have supplied */
1833 TRACE("Strided Data:\n");
1834 TRACE_STRIDED((dataLocations), position);
1835 TRACE_STRIDED((dataLocations), blendWeights);
1836 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1837 TRACE_STRIDED((dataLocations), normal);
1838 TRACE_STRIDED((dataLocations), pSize);
1839 TRACE_STRIDED((dataLocations), diffuse);
1840 TRACE_STRIDED((dataLocations), specular);
1841 TRACE_STRIDED((dataLocations), texCoords[0]);
1842 TRACE_STRIDED((dataLocations), texCoords[1]);
1843 TRACE_STRIDED((dataLocations), texCoords[2]);
1844 TRACE_STRIDED((dataLocations), texCoords[3]);
1845 TRACE_STRIDED((dataLocations), texCoords[4]);
1846 TRACE_STRIDED((dataLocations), texCoords[5]);
1847 TRACE_STRIDED((dataLocations), texCoords[6]);
1848 TRACE_STRIDED((dataLocations), texCoords[7]);
1849 TRACE_STRIDED((dataLocations), position2);
1850 TRACE_STRIDED((dataLocations), normal2);
1851 TRACE_STRIDED((dataLocations), tangent);
1852 TRACE_STRIDED((dataLocations), binormal);
1853 TRACE_STRIDED((dataLocations), tessFactor);
1854 TRACE_STRIDED((dataLocations), fog);
1855 TRACE_STRIDED((dataLocations), depth);
1856 TRACE_STRIDED((dataLocations), sample);
1862 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1865 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1866 /* Pixel shader support should imply multitexture support. */
1867 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1868 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1869 checkGLcall("glActiveTextureARB");
1871 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1874 if (!This->stateBlock->textures[i]) continue;
1876 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1877 glDisable(GL_TEXTURE_1D);
1878 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1879 switch(This->stateBlock->textureDimensions[i]) {
1881 glDisable(GL_TEXTURE_3D);
1882 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1885 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1886 glDisable(GL_TEXTURE_2D);
1888 case GLTEXTURECUBEMAP:
1889 glDisable(GL_TEXTURE_2D);
1890 glDisable(GL_TEXTURE_3D);
1893 glEnable(This->stateBlock->textureDimensions[i]);
1895 /* Upload texture, apply states */
1896 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1897 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1898 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1902 /* uploads textures and setup texture states ready for rendering */
1903 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1904 INT current_sampler = 0;
1905 float constant_color[4];
1908 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1909 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1910 * Register combiners however provide up to 8 combiner stages. In order to
1911 * take advantage of this, we need to be separate D3D texture stages from
1912 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1913 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1914 * corresponds to MaxTextureBlendStages in the caps. */
1916 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1917 glEnable(GL_REGISTER_COMBINERS_NV);
1918 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1919 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1922 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1923 INT texture_idx = -1;
1925 /* D3DTOP_DISABLE disables the current & any higher texture stages */
1926 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
1928 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1929 texture_idx = current_sampler++;
1931 /* Active the texture unit corresponding to the current texture stage */
1932 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1933 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1934 checkGLcall("glActiveTextureARB");
1936 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1940 if (This->stateBlock->textures[i]) {
1941 /* Enable the correct target. */
1942 glDisable(GL_TEXTURE_1D);
1943 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1944 switch(This->stateBlock->textureDimensions[i]) {
1946 glDisable(GL_TEXTURE_3D);
1947 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1950 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1951 glDisable(GL_TEXTURE_2D);
1953 case GLTEXTURECUBEMAP:
1954 glDisable(GL_TEXTURE_2D);
1955 glDisable(GL_TEXTURE_3D);
1959 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1960 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1961 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1963 glEnable(This->stateBlock->textureDimensions[i]);
1966 /* Upload texture, apply states */
1967 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1968 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
1969 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1970 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1971 /* ARB_texture_env_combine needs a valid texture bound to the
1972 * texture unit, even if it isn't used. Bind a dummy texture. */
1973 glDisable(GL_TEXTURE_2D);
1974 glDisable(GL_TEXTURE_3D);
1975 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1976 glEnable(GL_TEXTURE_1D);
1977 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1978 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1981 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1982 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1983 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1984 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1985 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1986 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1987 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
1990 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1991 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1992 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1993 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
1996 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1997 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1998 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1999 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2001 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2002 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2003 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2004 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2008 /* If we're using register combiners, set the amount of *used* combiners.
2009 * Ie, the number of stages below the first stage to have a color op of
2010 * D3DTOP_DISABLE. */
2011 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2012 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2013 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2014 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2017 /* Disable the remaining texture units. */
2018 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2019 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2020 glDisable(GL_TEXTURE_1D);
2021 glDisable(GL_TEXTURE_2D);
2022 glDisable(GL_TEXTURE_3D);
2023 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2027 /* Routine common to the draw primitive and draw indexed primitive routines */
2028 void drawPrimitive(IWineD3DDevice *iface,
2032 long StartVertexIndex,
2033 UINT numberOfVertices,
2036 const void *idxData,
2038 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2040 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2041 BOOL useVertexShaderFunction = FALSE;
2042 BOOL usePixelShaderFunction = FALSE;
2043 WineDirect3DVertexStridedData *dataLocations;
2044 IWineD3DSwapChainImpl *swapchain;
2048 BOOL lighting_changed, lighting_original = FALSE;
2050 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2051 * here simply check whether a shader was set, or the user disabled shaders */
2052 if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2053 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2054 useVertexShaderFunction = TRUE;
2056 if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2057 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2058 usePixelShaderFunction = TRUE;
2060 /* Invalidate the back buffer memory so LockRect will read it the next time */
2061 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2062 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2064 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2065 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2069 /* Ok, we will be updating the screen from here onwards so grab the lock */
2072 if(DrawPrimStrideData) {
2074 /* Note: this is a ddraw fixed-function code path */
2076 TRACE("================ Strided Input ===================\n");
2077 dataLocations = DrawPrimStrideData;
2078 drawPrimitiveTraceDataLocations(dataLocations);
2082 else if (This->stateBlock->vertexDecl != NULL || useVertexShaderFunction) {
2084 /* Note: This is a fixed function or shader codepath.
2085 * This means it must handle both types of strided data.
2086 * Shaders must go through here to zero the strided data, even if they
2087 * don't set any declaration at all */
2089 TRACE("================ Vertex Declaration ===================\n");
2090 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2091 if(!dataLocations) {
2092 ERR("Out of memory!\n");
2096 if (This->stateBlock->vertexDecl != NULL ||
2097 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2099 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2100 dataLocations, StartVertexIndex, &fixup);
2104 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2105 * It is reachable through d3d8, but only for fixed-function.
2106 * It will not work properly for shaders. */
2108 TRACE("================ FVF ===================\n");
2109 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2110 if(!dataLocations) {
2111 ERR("Out of memory!\n");
2114 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2115 drawPrimitiveTraceDataLocations(dataLocations);
2118 /* Setup transform matrices and sort out */
2119 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2121 /* Now initialize the materials state */
2122 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2124 if (usePixelShaderFunction) {
2125 drawPrimitiveUploadTexturesPS(This);
2127 drawPrimitiveUploadTextures(This);
2132 /* Ok, Work out which primitive is requested and how many vertexes that
2134 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2135 if (numberOfVertices == 0 )
2136 numberOfVertices = calculatedNumberOfindices;
2138 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2139 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2140 idxData, idxSize, minIndex, StartIdx, fixup);
2143 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2145 /* If vertex shaders or no normals, restore previous lighting state */
2146 if (lighting_changed) {
2147 if (lighting_original) glEnable(GL_LIGHTING);
2148 else glDisable(GL_LIGHTING);
2149 TRACE("Restored lighting to original state\n");
2152 /* Finshed updating the screen, restore lock */
2154 TRACE("Done all gl drawing\n");
2157 #ifdef SHOW_FRAME_MAKEUP
2159 static long int primCounter = 0;
2160 /* NOTE: set primCounter to the value reported by drawprim
2161 before you want to to write frame makeup to /tmp */
2162 if (primCounter >= 0) {
2163 WINED3DLOCKED_RECT r;
2165 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2166 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2167 TRACE("Saving screenshot %s\n", buffer);
2168 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2169 IWineD3DSurface_UnlockRect(This->renderTarget);
2171 #ifdef SHOW_TEXTURE_MAKEUP
2173 IWineD3DSurface *pSur;
2175 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2176 if (This->stateBlock->textures[textureNo] != NULL) {
2177 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2178 TRACE("Saving texture %s\n", buffer);
2179 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2180 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2181 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2182 IWineD3DSurface_Release(pSur);
2184 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2191 TRACE("drawprim #%ld\n", primCounter);