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;
331 if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
332 /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
333 * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
334 glFogi(GL_FOG_MODE, GL_LINEAR);
335 glFogf(GL_FOG_START, 1.0f);
336 glFogf(GL_FOG_END, 0.0f);
338 } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE]
339 && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
341 if(GL_SUPPORT(EXT_FOG_COORD)) {
342 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
343 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
344 /* Reapply the fog range */
345 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
346 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
347 /* Restore the fog mode */
348 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
350 /* Enable GL_FOG again because we disabled it above */
352 checkGLcall("glEnable(GL_FOG)");
358 static BOOL fixed_get_input(
359 BYTE usage, BYTE usage_idx,
360 unsigned int* regnum) {
364 /* Those positions must have the order in the
365 * named part of the strided data */
367 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
369 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
371 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
373 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
375 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
377 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
379 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
381 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < D3DDP_MAXTEXCOORD)
382 *regnum = 7 + usage_idx;
383 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
384 *regnum = 7 + D3DDP_MAXTEXCOORD;
385 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
386 *regnum = 8 + D3DDP_MAXTEXCOORD;
387 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
388 *regnum = 9 + D3DDP_MAXTEXCOORD;
389 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
390 *regnum = 10 + D3DDP_MAXTEXCOORD;
391 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
392 *regnum = 11 + D3DDP_MAXTEXCOORD;
393 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
394 *regnum = 12 + D3DDP_MAXTEXCOORD;
395 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
396 *regnum = 13 + D3DDP_MAXTEXCOORD;
397 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
398 *regnum = 14 + D3DDP_MAXTEXCOORD;
401 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
402 debug_d3ddeclusage(usage), usage_idx);
408 void primitiveDeclarationConvertToStridedData(
409 IWineD3DDevice *iface,
410 BOOL useVertexShaderFunction,
411 WineDirect3DVertexStridedData *strided,
412 LONG BaseVertexIndex,
415 /* We need to deal with frequency data!*/
418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
419 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
421 WINED3DVERTEXELEMENT *element;
425 /* Locate the vertex declaration */
426 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
427 TRACE("Using vertex declaration from shader\n");
428 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
430 TRACE("Using vertex declaration\n");
431 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
434 /* Translate the declaration into strided data */
435 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
440 element = vertexDeclaration->pDeclarationWine + i;
441 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
442 if (This->stateBlock->streamIsUP) {
443 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
445 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
446 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
448 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
449 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
450 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
452 if( streamVBO != 0) *fixup = TRUE;
453 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
456 stride = This->stateBlock->streamStride[element->Stream];
457 data += (BaseVertexIndex * stride);
458 data += element->Offset;
461 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
463 if (useVertexShaderFunction)
464 stride_used = vshader_get_input(This->stateBlock->vertexShader,
465 element->Usage, element->UsageIndex, &idx);
467 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
470 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
471 "stream=%u, offset=%u, stride=%lu, VBO=%u]\n",
472 useVertexShaderFunction? "shader": "fixed function", idx,
473 debug_d3ddeclusage(element->Usage), element->UsageIndex,
474 element->Stream, element->Offset, stride, streamVBO);
476 strided->u.input[idx].lpData = data;
477 strided->u.input[idx].dwType = element->Type;
478 strided->u.input[idx].dwStride = stride;
479 strided->u.input[idx].VBO = streamVBO;
480 if (!useVertexShaderFunction) {
481 if (element->Usage == D3DDECLUSAGE_POSITION)
482 strided->u.s.position_transformed = FALSE;
483 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
484 strided->u.s.position_transformed = TRUE;
490 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
494 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
495 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
497 /* Either 3 or 4 floats depending on the FVF */
498 /* FIXME: Can blending data be in a different stream to the position data?
499 and if so using the fixed pipeline how do we handle it */
500 if (thisFVF & D3DFVF_POSITION_MASK) {
501 strided->u.s.position.lpData = data;
502 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
503 strided->u.s.position.dwStride = stride;
504 strided->u.s.position.VBO = streamVBO;
505 data += 3 * sizeof(float);
506 if (thisFVF & D3DFVF_XYZRHW) {
507 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
508 strided->u.s.position_transformed = TRUE;
509 data += sizeof(float);
511 strided->u.s.position_transformed = FALSE;
514 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
515 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
516 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
517 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
519 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
520 TRACE("Setting blend Weights to %p\n", data);
521 strided->u.s.blendWeights.lpData = data;
522 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
523 strided->u.s.blendWeights.dwStride = stride;
524 strided->u.s.blendWeights.VBO = streamVBO;
525 data += numBlends * sizeof(FLOAT);
527 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
528 strided->u.s.blendMatrixIndices.lpData = data;
529 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
530 strided->u.s.blendMatrixIndices.dwStride= stride;
531 strided->u.s.blendMatrixIndices.VBO = streamVBO;
532 data += sizeof(DWORD);
536 /* Normal is always 3 floats */
537 if (thisFVF & D3DFVF_NORMAL) {
538 strided->u.s.normal.lpData = data;
539 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
540 strided->u.s.normal.dwStride = stride;
541 strided->u.s.normal.VBO = streamVBO;
542 data += 3 * sizeof(FLOAT);
545 /* Pointsize is a single float */
546 if (thisFVF & D3DFVF_PSIZE) {
547 strided->u.s.pSize.lpData = data;
548 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
549 strided->u.s.pSize.dwStride = stride;
550 strided->u.s.pSize.VBO = streamVBO;
551 data += sizeof(FLOAT);
554 /* Diffuse is 4 unsigned bytes */
555 if (thisFVF & D3DFVF_DIFFUSE) {
556 strided->u.s.diffuse.lpData = data;
557 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
558 strided->u.s.diffuse.dwStride = stride;
559 strided->u.s.diffuse.VBO = streamVBO;
560 data += sizeof(DWORD);
563 /* Specular is 4 unsigned bytes */
564 if (thisFVF & D3DFVF_SPECULAR) {
565 strided->u.s.specular.lpData = data;
566 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
567 strided->u.s.specular.dwStride = stride;
568 strided->u.s.specular.VBO = streamVBO;
569 data += sizeof(DWORD);
573 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
574 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
576 /* numTextures indicates the number of texture coordinates supplied */
577 /* However, the first set may not be for stage 0 texture - it all */
578 /* depends on D3DTSS_TEXCOORDINDEX. */
579 /* The number of bytes for each coordinate set is based off */
580 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
582 /* So, for each supplied texture extract the coords */
583 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
585 strided->u.s.texCoords[textureNo].lpData = data;
586 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
587 strided->u.s.texCoords[textureNo].dwStride = stride;
588 strided->u.s.texCoords[textureNo].VBO = streamVBO;
589 numCoords[textureNo] = coordIdxInfo & 0x03;
592 data += sizeof(float);
593 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
594 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
595 data += sizeof(float);
596 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
597 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
598 data += sizeof(float);
599 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
600 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
601 data += sizeof(float);
605 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
609 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
611 short LoopThroughTo = 0;
615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
617 /* OK, Now to setup the data locations
618 For the non-created vertex shaders, the VertexShader var holds the real
619 FVF and only stream 0 matters
620 For the created vertex shaders, there is an FVF per stream */
621 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
622 LoopThroughTo = MAX_STREAMS;
627 /* Work through stream by stream */
628 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
629 DWORD stride = This->stateBlock->streamStride[nStream];
633 /* Skip empty streams */
634 if (This->stateBlock->streamSource[nStream] == NULL) continue;
636 /* Retrieve appropriate FVF */
637 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
638 thisFVF = This->stateBlock->fvf;
639 /* Handle memory passed directly as well as vertex buffers */
640 if (This->stateBlock->streamIsUP) {
642 data = (BYTE *)This->stateBlock->streamSource[nStream];
644 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
645 /* GetMemory binds the VBO */
646 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
648 if(streamVBO != 0 ) *fixup = TRUE;
652 #if 0 /* TODO: Vertex shader support */
653 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
654 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
657 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
658 if (thisFVF == 0) continue;
660 /* Now convert the stream into pointers */
662 /* Shuffle to the beginning of the vertexes to render and index from there */
663 data = data + (BaseVertexIndex * stride);
665 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
669 #if 0 /* TODO: Software Shaders */
670 /* Draw a single vertex using this information */
671 static void draw_vertex(IWineD3DDevice *iface, /* interface */
672 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
673 BOOL isNormal, float nx, float ny, float nz, /* normal */
674 BOOL isDiffuse, float *dRGBA, /* 1st colors */
675 BOOL isSpecular, float *sRGB, /* 2ndry colors */
676 BOOL isPtSize, float ptSize, /* pointSize */
677 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
679 unsigned int textureNo;
681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
683 /* Diffuse -------------------------------- */
686 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
689 /* Specular Colour ------------------------------------------*/
691 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
692 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
693 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
695 VTRACE(("Specular color extensions not supplied\n"));
699 /* Normal -------------------------------- */
701 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
702 glNormal3f(nx, ny, nz);
705 /* Point Size ----------------------------------------------*/
708 /* no such functionality in the fixed function GL pipeline */
709 FIXME("Cannot change ptSize here in openGl\n");
712 /* Texture coords --------------------------- */
713 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
715 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
716 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
720 /* Query tex coords */
721 if (This->stateBlock->textures[textureNo] != NULL) {
723 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
724 if (coordIdx >= MAX_TEXTURES) {
725 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
727 } else if (numcoords[coordIdx] == 0) {
728 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
732 /* Initialize vars */
738 switch (numcoords[coordIdx]) {
739 case 4: q = texcoords[coordIdx].w; /* drop through */
740 case 3: r = texcoords[coordIdx].z; /* drop through */
741 case 2: t = texcoords[coordIdx].y; /* drop through */
742 case 1: s = texcoords[coordIdx].x;
745 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
747 VTRACE(("tex:%d, s=%f\n", textureNo, s));
748 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
749 GLMULTITEXCOORD1F(textureNo, s);
755 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
756 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
757 GLMULTITEXCOORD2F(textureNo, s, t);
763 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
764 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
765 GLMULTITEXCOORD3F(textureNo, s, t, r);
767 glTexCoord3f(s, t, r);
771 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
772 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
773 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
775 glTexCoord4f(s, t, r, q);
779 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
783 } /* End of textures */
785 /* Position -------------------------------- */
787 if (1.0f == rhw || rhw < 0.00001f) {
788 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
791 /* Cannot optimize by dividing through by rhw as rhw is required
792 later for perspective in the GL pipeline for vertex shaders */
793 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
794 glVertex4f(x,y,z,rhw);
798 #endif /* TODO: Software shaders */
800 static void loadNumberedArrays(
801 IWineD3DDevice *iface,
802 IWineD3DVertexShader *shader,
803 WineDirect3DVertexStridedData *strided) {
805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
809 for (i = 0; i < MAX_ATTRIBS; i++) {
811 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
814 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
816 if(curVBO != strided->u.input[i].VBO) {
817 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
818 checkGLcall("glBindBufferARB");
819 curVBO = strided->u.input[i].VBO;
821 GL_EXTCALL(glVertexAttribPointerARB(i,
822 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
823 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
824 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
825 strided->u.input[i].dwStride,
826 strided->u.input[i].lpData));
827 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
831 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
832 unsigned int textureNo = 0;
833 unsigned int texture_idx = 0;
834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
837 TRACE("Using fast vertex array code\n");
838 /* Blend Data ---------------------------------------------- */
839 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
840 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
843 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
846 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
847 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
850 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
851 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
852 /* FIXME("TODO\n");*/
853 /* Note dwType == float3 or float4 == 2 or 3 */
856 /* with this on, the normals appear to be being modified,
857 but the vertices aren't being translated as they should be
858 Maybe the world matrix aren't being setup properly? */
859 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
863 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
864 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
865 sd->u.s.blendWeights.dwStride,
866 sd->u.s.blendWeights.lpData));
868 if(curVBO != sd->u.s.blendWeights.VBO) {
869 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
870 checkGLcall("glBindBufferARB");
871 curVBO = sd->u.s.blendWeights.VBO;
874 GL_EXTCALL(glWeightPointerARB)(
875 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
876 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
877 sd->u.s.blendWeights.dwStride,
878 sd->u.s.blendWeights.lpData);
880 checkGLcall("glWeightPointerARB");
882 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
883 static BOOL showfixme = TRUE;
885 FIXME("blendMatrixIndices support\n");
890 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
891 /* FIXME("TODO\n");*/
894 GL_EXTCALL(glVertexWeightPointerEXT)(
895 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
896 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
897 sd->u.s.blendWeights.dwStride,
898 sd->u.s.blendWeights.lpData);
899 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
900 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
901 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
905 /* TODO: support blends in fixupVertices */
906 FIXME("unsupported blending in openGl\n");
909 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
910 #if 0 /* TODO: Vertex blending */
911 glDisable(GL_VERTEX_BLEND_ARB);
913 TRACE("ARB_VERTEX_BLEND\n");
914 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
915 TRACE(" EXT_VERTEX_WEIGHTING\n");
916 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
917 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
922 #if 0 /* FOG ----------------------------------------------*/
923 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
925 if (GL_SUPPORT(EXT_FOG_COORD) {
926 glEnableClientState(GL_FOG_COORDINATE_EXT);
927 (GL_EXTCALL)(FogCoordPointerEXT)(
928 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
929 sd->u.s.fog.dwStride,
932 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
933 /* FIXME: fixme once */
934 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
937 if (GL_SUPPRT(EXT_FOR_COORD) {
938 /* make sure fog is disabled */
939 glDisableClientState(GL_FOG_COORDINATE_EXT);
944 #if 0 /* tangents ----------------------------------------------*/
945 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
946 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
948 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
949 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
950 glEnable(GL_TANGENT_ARRAY_EXT);
951 (GL_EXTCALL)(TangentPointerEXT)(
952 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
953 sd->u.s.tangent.dwStride,
954 sd->u.s.tangent.lpData);
956 glDisable(GL_TANGENT_ARRAY_EXT);
958 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
959 glEnable(GL_BINORMAL_ARRAY_EXT);
960 (GL_EXTCALL)(BinormalPointerEXT)(
961 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
962 sd->u.s.binormal.dwStride,
963 sd->u.s.binormal.lpData);
965 glDisable(GL_BINORMAL_ARRAY_EXT);
969 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
970 /* FIXME: fixme once */
971 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
974 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
975 /* make sure fog is disabled */
976 glDisable(GL_TANGENT_ARRAY_EXT);
977 glDisable(GL_BINORMAL_ARRAY_EXT);
982 /* Point Size ----------------------------------------------*/
983 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
985 /* no such functionality in the fixed function GL pipeline */
986 TRACE("Cannot change ptSize here in openGl\n");
987 /* TODO: Implement this function in using shaders if they are available */
991 /* Vertex Pointers -----------------------------------------*/
992 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
993 /* Note dwType == float3 or float4 == 2 or 3 */
994 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
995 sd->u.s.position.dwStride,
996 sd->u.s.position.dwType + 1,
997 sd->u.s.position.lpData));
999 if(curVBO != sd->u.s.position.VBO) {
1000 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1001 checkGLcall("glBindBufferARB");
1002 curVBO = sd->u.s.position.VBO;
1005 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1006 handling for rhw mode should not impact screen position whereas in GL it does.
1007 This may result in very slightly distored textures in rhw mode, but
1008 a very minimal different. There's always the other option of
1009 fixing the view matrix to prevent w from having any effect
1011 This only applies to user pointer sources, in VBOs the vertices are fixed up
1013 if(sd->u.s.position.VBO == 0) {
1014 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1015 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1016 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1019 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1020 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1021 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1023 checkGLcall("glVertexPointer(...)");
1024 glEnableClientState(GL_VERTEX_ARRAY);
1025 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1028 glDisableClientState(GL_VERTEX_ARRAY);
1029 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1032 /* Normals -------------------------------------------------*/
1033 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1034 /* Note dwType == float3 or float4 == 2 or 3 */
1035 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1036 sd->u.s.normal.dwStride,
1037 sd->u.s.normal.lpData));
1038 if(curVBO != sd->u.s.normal.VBO) {
1039 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1040 checkGLcall("glBindBufferARB");
1041 curVBO = sd->u.s.normal.VBO;
1044 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1045 sd->u.s.normal.dwStride,
1046 sd->u.s.normal.lpData);
1047 checkGLcall("glNormalPointer(...)");
1048 glEnableClientState(GL_NORMAL_ARRAY);
1049 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1052 glDisableClientState(GL_NORMAL_ARRAY);
1053 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1054 glNormal3f(0, 0, 1);
1055 checkGLcall("glNormal3f(0, 0, 1)");
1058 /* Diffuse Colour --------------------------------------------*/
1059 /* WARNING: Data here MUST be in RGBA format, so cannot */
1060 /* go directly into fast mode from app pgm, because */
1061 /* directx requires data in BGRA format. */
1062 /* currently fixupVertices swizels the format, but this isn't */
1063 /* very practical when using VBOS */
1064 /* NOTE: Unless we write a vertex shader to swizel the colour */
1065 /* , or the user doesn't care and wants the speed advantage */
1067 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1068 /* Note dwType == float3 or float4 == 2 or 3 */
1069 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1070 sd->u.s.diffuse.dwStride,
1071 sd->u.s.diffuse.lpData));
1073 if(curVBO != sd->u.s.diffuse.VBO) {
1074 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1075 checkGLcall("glBindBufferARB");
1076 curVBO = sd->u.s.diffuse.VBO;
1078 glColorPointer(4, GL_UNSIGNED_BYTE,
1079 sd->u.s.diffuse.dwStride,
1080 sd->u.s.diffuse.lpData);
1081 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1082 glEnableClientState(GL_COLOR_ARRAY);
1083 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1086 glDisableClientState(GL_COLOR_ARRAY);
1087 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1088 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1089 checkGLcall("glColor4f(1, 1, 1, 1)");
1092 /* Specular Colour ------------------------------------------*/
1093 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1094 TRACE("setting specular colour\n");
1095 /* Note dwType == float3 or float4 == 2 or 3 */
1096 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1097 sd->u.s.specular.dwStride,
1098 sd->u.s.specular.lpData));
1099 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1100 if(curVBO != sd->u.s.specular.VBO) {
1101 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1102 checkGLcall("glBindBufferARB");
1103 curVBO = sd->u.s.specular.VBO;
1105 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1106 sd->u.s.specular.dwStride,
1107 sd->u.s.specular.lpData);
1108 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1109 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1110 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1113 /* Missing specular color is not critical, no warnings */
1114 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1118 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1120 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1121 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1122 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1123 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1126 /* Missing specular color is not critical, no warnings */
1127 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1131 /* Texture coords -------------------------------------------*/
1133 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1134 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1135 /* Abort if we don't support the extension. */
1136 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1137 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1141 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1142 /* Select the correct texture stage */
1143 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1146 if (This->stateBlock->textures[textureNo] != NULL) {
1147 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1148 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1150 if (coordIdx >= MAX_TEXTURES) {
1151 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1152 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1153 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1155 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1156 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1157 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1158 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1161 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1162 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1163 checkGLcall("glBindBufferARB");
1164 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1166 /* The coords to supply depend completely on the fvf / vertex shader */
1168 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1169 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1170 sd->u.s.texCoords[coordIdx].dwStride,
1171 sd->u.s.texCoords[coordIdx].lpData);
1172 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1174 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1175 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1176 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1178 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1180 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1181 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1182 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1183 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1184 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1189 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1190 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1193 if (idxData != NULL /* This crashes sometimes!*/) {
1194 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1195 idxData = idxData == (void *)-1 ? NULL : idxData;
1198 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1199 glEnableClientState(GL_INDEX_ARRAY);
1201 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1202 (const char *)idxData+(idxSize * startIdx));
1203 #else /* using drawRangeElements may be faster */
1205 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1206 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1207 (const char *)idxData+(idxSize * startIdx));
1209 checkGLcall("glDrawRangeElements");
1213 /* Note first is now zero as we shuffled along earlier */
1214 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1215 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1216 checkGLcall("glDrawArrays");
1224 * Actually draw using the supplied information.
1225 * Slower GL version which extracts info about each vertex in turn
1228 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1229 UINT NumVertexes, GLenum glPrimType,
1230 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1232 unsigned int textureNo = 0;
1233 unsigned int texture_idx = 0;
1234 const short *pIdxBufS = NULL;
1235 const long *pIdxBufL = NULL;
1236 LONG SkipnStrides = 0;
1238 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1239 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1240 float rhw = 0.0f; /* rhw */
1241 float ptSize = 0.0f; /* Point size */
1242 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1243 DWORD specularColor = 0; /* Specular Color */
1244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1246 TRACE("Using slow vertex array code\n");
1248 /* Variable Initialization */
1249 if (idxData != NULL) {
1250 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1251 else pIdxBufL = (const long *) idxData;
1254 /* Start drawing in GL */
1255 VTRACE(("glBegin(%x)\n", glPrimType));
1256 glBegin(glPrimType);
1258 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1259 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1262 /* For each primitive */
1263 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1265 /* Initialize diffuse color */
1266 diffuseColor = 0xFFFFFFFF;
1268 /* For indexed data, we need to go a few more strides in */
1269 if (idxData != NULL) {
1271 /* Indexed so work out the number of strides to skip */
1273 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1274 SkipnStrides = pIdxBufS[startIdx + vx_index];
1276 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1277 SkipnStrides = pIdxBufL[startIdx + vx_index];
1281 /* Position Information ------------------ */
1282 if (sd->u.s.position.lpData != NULL) {
1284 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1289 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1291 /* RHW follows, only if transformed, ie 4 floats were provided */
1292 if (sd->u.s.position_transformed) {
1293 rhw = ptrToCoords[3];
1294 VTRACE(("rhw=%f\n", rhw));
1298 /* Blending data -------------------------- */
1299 if (sd->u.s.blendWeights.lpData != NULL) {
1300 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1301 FIXME("Blending not supported yet\n");
1303 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1304 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1308 /* Vertex Normal Data (untransformed only)- */
1309 if (sd->u.s.normal.lpData != NULL) {
1311 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1312 nx = ptrToCoords[0];
1313 ny = ptrToCoords[1];
1314 nz = ptrToCoords[2];
1315 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1318 /* Point Size ----------------------------- */
1319 if (sd->u.s.pSize.lpData != NULL) {
1321 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1322 ptSize = ptrToCoords[0];
1323 VTRACE(("ptSize=%f\n", ptSize));
1324 FIXME("No support for ptSize yet\n");
1327 /* Diffuse -------------------------------- */
1328 if (sd->u.s.diffuse.lpData != NULL) {
1330 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1331 diffuseColor = ptrToCoords[0];
1332 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1335 /* Specular -------------------------------- */
1336 if (sd->u.s.specular.lpData != NULL) {
1338 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1339 specularColor = ptrToCoords[0];
1340 VTRACE(("specularColor=%lx\n", specularColor));
1343 /* Texture coords --------------------------- */
1344 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1346 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1347 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1351 /* Query tex coords */
1352 if (This->stateBlock->textures[textureNo] != NULL) {
1354 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1355 float *ptrToCoords = NULL;
1356 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1359 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1362 } else if (coordIdx < 0) {
1363 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1368 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1369 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1370 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1375 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1377 /* The coords to supply depend completely on the fvf / vertex shader */
1378 switch (coordsToUse) {
1379 case 4: q = ptrToCoords[3]; /* drop through */
1380 case 3: r = ptrToCoords[2]; /* drop through */
1381 case 2: t = ptrToCoords[1]; /* drop through */
1382 case 1: s = ptrToCoords[0];
1385 /* Projected is more 'fun' - Move the last coord to the 'q'
1386 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1387 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1388 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1390 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1391 switch (coordsToUse) {
1392 case 0: /* Drop Through */
1394 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1406 case 4: /* Nop here */
1409 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1410 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1415 switch (coordsToUse) { /* Supply the provided texture coords */
1416 case D3DTTFF_COUNT1:
1417 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1418 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1419 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1424 case D3DTTFF_COUNT2:
1425 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1426 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1427 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1432 case D3DTTFF_COUNT3:
1433 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1434 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1435 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1437 glTexCoord3f(s, t, r);
1440 case D3DTTFF_COUNT4:
1441 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1442 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1443 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1445 glTexCoord4f(s, t, r, q);
1449 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1453 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1454 } /* End of textures */
1456 /* Diffuse -------------------------------- */
1457 if (sd->u.s.diffuse.lpData != NULL) {
1458 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1459 D3DCOLOR_B_G(diffuseColor),
1460 D3DCOLOR_B_B(diffuseColor),
1461 D3DCOLOR_B_A(diffuseColor));
1462 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1463 D3DCOLOR_B_R(diffuseColor),
1464 D3DCOLOR_B_G(diffuseColor),
1465 D3DCOLOR_B_B(diffuseColor),
1466 D3DCOLOR_B_A(diffuseColor)));
1468 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1471 /* Specular ------------------------------- */
1472 if (sd->u.s.specular.lpData != NULL) {
1473 /* special case where the fog density is stored in the diffuse alpha channel */
1474 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1475 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
1476 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1477 if(GL_SUPPORT(EXT_FOG_COORD)) {
1478 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1480 static BOOL warned = FALSE;
1482 /* TODO: Use the fog table code from old ddraw */
1483 FIXME("Implement fog for transformed vertices in software\n");
1489 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1490 D3DCOLOR_B_R(specularColor),
1491 D3DCOLOR_B_G(specularColor),
1492 D3DCOLOR_B_B(specularColor)));
1493 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1494 GL_EXTCALL(glSecondaryColor3ubEXT)(
1495 D3DCOLOR_B_R(specularColor),
1496 D3DCOLOR_B_G(specularColor),
1497 D3DCOLOR_B_B(specularColor));
1499 /* Do not worry if specular colour missing and disable request */
1500 VTRACE(("Specular color extensions not supplied\n"));
1503 if (vx_index == 0) {
1504 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1505 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1507 /* Do not worry if specular colour missing and disable request */
1508 VTRACE(("Specular color extensions not supplied\n"));
1513 /* Normal -------------------------------- */
1514 if (sd->u.s.normal.lpData != NULL) {
1515 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1516 glNormal3f(nx, ny, nz);
1518 if (vx_index == 0) glNormal3f(0, 0, 1);
1521 /* Position -------------------------------- */
1522 if (sd->u.s.position.lpData != NULL) {
1523 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1524 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1525 glVertex3f(x, y, z);
1527 GLfloat w = 1.0 / rhw;
1528 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1529 glVertex4f(x*w, y*w, z*w, w);
1533 /* For non indexed mode, step onto next parts */
1534 if (idxData == NULL) {
1540 checkGLcall("glEnd and previous calls");
1543 #if 0 /* TODO: Software/Hardware vertex blending support */
1545 * Draw with emulated vertex shaders
1546 * Note: strided data is uninitialized, as we need to pass the vertex
1547 * shader directly as ordering irs yet
1549 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1550 int PrimitiveType, ULONG NumPrimitives,
1551 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1553 unsigned int textureNo = 0;
1554 GLenum glPrimType = GL_POINTS;
1555 int NumVertexes = NumPrimitives;
1556 const short *pIdxBufS = NULL;
1557 const long *pIdxBufL = NULL;
1558 LONG SkipnStrides = 0;
1560 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1561 float rhw = 0.0f; /* rhw */
1562 float ptSize = 0.0f; /* Point size */
1563 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1564 int numcoords[8]; /* Number of coords */
1565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1567 IDirect3DVertexShaderImpl* vertexShader = NULL;
1569 TRACE("Using slow software vertex shader code\n");
1571 /* Variable Initialization */
1572 if (idxData != NULL) {
1573 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1574 else pIdxBufL = (const long *) idxData;
1577 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1578 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1580 /* Retrieve the VS information */
1581 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1583 /* Start drawing in GL */
1584 VTRACE(("glBegin(%x)\n", glPrimType));
1585 glBegin(glPrimType);
1587 /* For each primitive */
1588 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1590 /* For indexed data, we need to go a few more strides in */
1591 if (idxData != NULL) {
1593 /* Indexed so work out the number of strides to skip */
1595 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1596 SkipnStrides = pIdxBufS[startIdx+vx_index];
1598 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1599 SkipnStrides = pIdxBufL[startIdx+vx_index];
1603 /* Fill the vertex shader input */
1604 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1606 /* Initialize the output fields to the same defaults as it would normally have */
1607 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1608 vertexShader->output.oD[0].x = 1.0;
1609 vertexShader->output.oD[0].y = 1.0;
1610 vertexShader->output.oD[0].z = 1.0;
1611 vertexShader->output.oD[0].w = 1.0;
1613 /* Now execute the vertex shader */
1614 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1617 TRACE_VECTOR(vertexShader->output.oPos);
1618 TRACE_VECTOR(vertexShader->output.oD[0]);
1619 TRACE_VECTOR(vertexShader->output.oD[1]);
1620 TRACE_VECTOR(vertexShader->output.oT[0]);
1621 TRACE_VECTOR(vertexShader->output.oT[1]);
1622 TRACE_VECTOR(vertexShader->input.V[0]);
1623 TRACE_VECTOR(vertexShader->data->C[0]);
1624 TRACE_VECTOR(vertexShader->data->C[1]);
1625 TRACE_VECTOR(vertexShader->data->C[2]);
1626 TRACE_VECTOR(vertexShader->data->C[3]);
1627 TRACE_VECTOR(vertexShader->data->C[4]);
1628 TRACE_VECTOR(vertexShader->data->C[5]);
1629 TRACE_VECTOR(vertexShader->data->C[6]);
1630 TRACE_VECTOR(vertexShader->data->C[7]);
1633 /* Extract out the output */
1634 /* FIXME: Fog coords? */
1635 x = vertexShader->output.oPos.x;
1636 y = vertexShader->output.oPos.y;
1637 z = vertexShader->output.oPos.z;
1638 rhw = vertexShader->output.oPos.w;
1639 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1641 /** Update textures coords using vertexShader->output.oT[0->7] */
1642 memset(texcoords, 0x00, sizeof(texcoords));
1643 memset(numcoords, 0x00, sizeof(numcoords));
1644 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1645 if (This->stateBlock->textures[textureNo] != NULL) {
1646 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1647 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1648 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1649 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1650 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1651 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1653 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1654 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1655 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1656 default: numcoords[textureNo] = 4;
1660 numcoords[textureNo] = 0;
1664 /* Draw using this information */
1667 TRUE, 0.0f, 0.0f, 1.0f,
1668 TRUE, (float*) &vertexShader->output.oD[0],
1669 TRUE, (float*) &vertexShader->output.oD[1],
1670 FALSE, ptSize, /* FIXME: Change back when supported */
1671 texcoords, numcoords);
1673 /* For non indexed mode, step onto next parts */
1674 if (idxData == NULL) {
1678 } /* for each vertex */
1681 checkGLcall("glEnd and previous calls");
1686 inline static void drawPrimitiveDrawStrided(
1687 IWineD3DDevice *iface,
1688 BOOL useVertexShaderFunction,
1689 BOOL usePixelShaderFunction,
1690 WineDirect3DVertexStridedData *dataLocations,
1691 UINT numberOfvertices,
1692 UINT numberOfIndicies,
1694 const void *idxData,
1700 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1701 BOOL useDrawStridedSlow;
1703 int startStride = idxData == NULL ? 0 :
1704 idxData == (void *) -1 ? 0 :
1705 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1706 int endStride = startStride;
1707 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1708 startStride, endStride, numberOfIndicies, numberOfvertices);
1710 /* Generate some fixme's if unsupported functionality is being used */
1711 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1712 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1713 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1714 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1716 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1717 FIXME("Tweening is only valid with vertex shaders\n");
1719 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1720 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1722 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1723 FIXME("Extended attributes are only valid with vertex shaders\n");
1725 #undef BUFFER_OR_DATA
1727 /* Fixed pipeline, no fixups required - load arrays */
1728 if (!useVertexShaderFunction &&
1729 ((dataLocations->u.s.pSize.lpData == NULL &&
1730 dataLocations->u.s.diffuse.lpData == NULL &&
1731 dataLocations->u.s.specular.lpData == NULL) ||
1734 /* Load the vertex data using named arrays */
1735 TRACE("(%p) Loading vertex data\n", This);
1736 loadVertexData(iface, dataLocations);
1737 useDrawStridedSlow = FALSE;
1739 /* Shader pipeline - load attribute arrays */
1740 } else if(useVertexShaderFunction) {
1742 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1743 useDrawStridedSlow = FALSE;
1745 /* Draw vertex by vertex */
1747 TRACE("Not loading vertex data\n");
1748 useDrawStridedSlow = TRUE;
1751 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1752 * Otherwise set 0, which restores fixed function */
1753 if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1754 (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1755 set_glsl_shader_program(iface);
1757 This->stateBlock->shaderPrgId = 0;
1759 /* If GLSL is used now, or might have been used before, (re)set the program */
1760 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
1761 wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1763 if (This->stateBlock->shaderPrgId)
1764 TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
1765 GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
1766 checkGLcall("glUseProgramObjectARB");
1769 if (useVertexShaderFunction) {
1771 TRACE("Using vertex shader\n");
1773 if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1774 /* Bind the vertex program */
1775 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1776 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1777 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1779 /* Enable OpenGL vertex programs */
1780 glEnable(GL_VERTEX_PROGRAM_ARB);
1781 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1782 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1783 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1787 if (usePixelShaderFunction) {
1789 TRACE("Using pixel shader\n");
1791 if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1792 /* Bind the fragment program */
1793 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1794 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1795 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1797 /* Enable OpenGL fragment programs */
1798 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1799 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1800 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1801 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1805 /* Load any global constants/uniforms that may have been set by the application */
1806 if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
1807 shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1808 else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
1809 shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1811 /* Draw vertex-by-vertex */
1812 if (useDrawStridedSlow)
1813 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1815 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1817 /* Cleanup vertex program */
1818 if (useVertexShaderFunction) {
1819 /* disable any attribs (this is the same for both GLSL and ARB modes) */
1822 /* Leave all the attribs disabled */
1823 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1824 /* MESA does not support it right not */
1825 if (glGetError() != GL_NO_ERROR)
1827 for (i = 0; i < maxAttribs; ++i) {
1828 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1829 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1832 if (wined3d_settings.vs_selected_mode == SHADER_ARB)
1833 glDisable(GL_VERTEX_PROGRAM_ARB);
1836 /* Cleanup fragment program */
1837 if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB)
1838 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1841 inline void drawPrimitiveTraceDataLocations(
1842 WineDirect3DVertexStridedData *dataLocations) {
1844 /* Dump out what parts we have supplied */
1845 TRACE("Strided Data:\n");
1846 TRACE_STRIDED((dataLocations), position);
1847 TRACE_STRIDED((dataLocations), blendWeights);
1848 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1849 TRACE_STRIDED((dataLocations), normal);
1850 TRACE_STRIDED((dataLocations), pSize);
1851 TRACE_STRIDED((dataLocations), diffuse);
1852 TRACE_STRIDED((dataLocations), specular);
1853 TRACE_STRIDED((dataLocations), texCoords[0]);
1854 TRACE_STRIDED((dataLocations), texCoords[1]);
1855 TRACE_STRIDED((dataLocations), texCoords[2]);
1856 TRACE_STRIDED((dataLocations), texCoords[3]);
1857 TRACE_STRIDED((dataLocations), texCoords[4]);
1858 TRACE_STRIDED((dataLocations), texCoords[5]);
1859 TRACE_STRIDED((dataLocations), texCoords[6]);
1860 TRACE_STRIDED((dataLocations), texCoords[7]);
1861 TRACE_STRIDED((dataLocations), position2);
1862 TRACE_STRIDED((dataLocations), normal2);
1863 TRACE_STRIDED((dataLocations), tangent);
1864 TRACE_STRIDED((dataLocations), binormal);
1865 TRACE_STRIDED((dataLocations), tessFactor);
1866 TRACE_STRIDED((dataLocations), fog);
1867 TRACE_STRIDED((dataLocations), depth);
1868 TRACE_STRIDED((dataLocations), sample);
1874 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1877 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1878 /* Pixel shader support should imply multitexture support. */
1879 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1880 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1881 checkGLcall("glActiveTextureARB");
1883 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1886 if (!This->stateBlock->textures[i]) continue;
1888 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1889 glDisable(GL_TEXTURE_1D);
1890 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1891 switch(This->stateBlock->textureDimensions[i]) {
1893 glDisable(GL_TEXTURE_3D);
1894 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1897 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1898 glDisable(GL_TEXTURE_2D);
1900 case GLTEXTURECUBEMAP:
1901 glDisable(GL_TEXTURE_2D);
1902 glDisable(GL_TEXTURE_3D);
1905 glEnable(This->stateBlock->textureDimensions[i]);
1907 /* Upload texture, apply states */
1908 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1909 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1910 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1914 /* uploads textures and setup texture states ready for rendering */
1915 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1916 INT current_sampler = 0;
1917 float constant_color[4];
1920 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1921 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1922 * Register combiners however provide up to 8 combiner stages. In order to
1923 * take advantage of this, we need to be separate D3D texture stages from
1924 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1925 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1926 * corresponds to MaxTextureBlendStages in the caps. */
1928 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1929 glEnable(GL_REGISTER_COMBINERS_NV);
1930 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1931 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1934 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1935 INT texture_idx = -1;
1937 /* D3DTOP_DISABLE disables the current & any higher texture stages */
1938 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
1940 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1941 texture_idx = current_sampler++;
1943 /* Active the texture unit corresponding to the current texture stage */
1944 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1945 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1946 checkGLcall("glActiveTextureARB");
1948 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1952 if (This->stateBlock->textures[i]) {
1953 /* Enable the correct target. */
1954 glDisable(GL_TEXTURE_1D);
1955 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1956 switch(This->stateBlock->textureDimensions[i]) {
1958 glDisable(GL_TEXTURE_3D);
1959 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1962 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1963 glDisable(GL_TEXTURE_2D);
1965 case GLTEXTURECUBEMAP:
1966 glDisable(GL_TEXTURE_2D);
1967 glDisable(GL_TEXTURE_3D);
1971 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1972 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1973 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1975 glEnable(This->stateBlock->textureDimensions[i]);
1978 /* Upload texture, apply states */
1979 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1980 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
1981 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1982 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1983 /* ARB_texture_env_combine needs a valid texture bound to the
1984 * texture unit, even if it isn't used. Bind a dummy texture. */
1985 glDisable(GL_TEXTURE_2D);
1986 glDisable(GL_TEXTURE_3D);
1987 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1988 glEnable(GL_TEXTURE_1D);
1989 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1990 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1993 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1994 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1995 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1996 set_tex_op_nvrc((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],
2002 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2003 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2004 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2005 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2008 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2009 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2010 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2011 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2013 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2014 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2015 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2016 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2020 /* If we're using register combiners, set the amount of *used* combiners.
2021 * Ie, the number of stages below the first stage to have a color op of
2022 * D3DTOP_DISABLE. */
2023 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2024 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2025 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2026 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2029 /* Disable the remaining texture units. */
2030 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2031 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2032 glDisable(GL_TEXTURE_1D);
2033 glDisable(GL_TEXTURE_2D);
2034 glDisable(GL_TEXTURE_3D);
2035 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2039 /* Routine common to the draw primitive and draw indexed primitive routines */
2040 void drawPrimitive(IWineD3DDevice *iface,
2044 long StartVertexIndex,
2045 UINT numberOfVertices,
2048 const void *idxData,
2050 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2052 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2053 BOOL useVertexShaderFunction = FALSE;
2054 BOOL usePixelShaderFunction = FALSE;
2055 WineDirect3DVertexStridedData *dataLocations;
2056 IWineD3DSwapChainImpl *swapchain;
2060 BOOL lighting_changed, lighting_original = FALSE;
2062 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2063 * here simply check whether a shader was set, or the user disabled shaders */
2064 if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2065 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2066 useVertexShaderFunction = TRUE;
2068 if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2069 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2070 usePixelShaderFunction = TRUE;
2072 /* Invalidate the back buffer memory so LockRect will read it the next time */
2073 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2074 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2076 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2077 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2081 /* Ok, we will be updating the screen from here onwards so grab the lock */
2084 if(DrawPrimStrideData) {
2086 /* Note: this is a ddraw fixed-function code path */
2088 TRACE("================ Strided Input ===================\n");
2089 dataLocations = DrawPrimStrideData;
2090 drawPrimitiveTraceDataLocations(dataLocations);
2094 else if (This->stateBlock->vertexDecl != NULL || useVertexShaderFunction) {
2096 /* Note: This is a fixed function or shader codepath.
2097 * This means it must handle both types of strided data.
2098 * Shaders must go through here to zero the strided data, even if they
2099 * don't set any declaration at all */
2101 TRACE("================ Vertex Declaration ===================\n");
2102 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2103 if(!dataLocations) {
2104 ERR("Out of memory!\n");
2108 if (This->stateBlock->vertexDecl != NULL ||
2109 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2111 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2112 dataLocations, StartVertexIndex, &fixup);
2116 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2117 * It is reachable through d3d8, but only for fixed-function.
2118 * It will not work properly for shaders. */
2120 TRACE("================ FVF ===================\n");
2121 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2122 if(!dataLocations) {
2123 ERR("Out of memory!\n");
2126 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2127 drawPrimitiveTraceDataLocations(dataLocations);
2130 /* Setup transform matrices and sort out */
2131 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2133 /* Now initialize the materials state */
2134 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2136 if (usePixelShaderFunction) {
2137 drawPrimitiveUploadTexturesPS(This);
2139 drawPrimitiveUploadTextures(This);
2144 /* Ok, Work out which primitive is requested and how many vertexes that
2146 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2147 if (numberOfVertices == 0 )
2148 numberOfVertices = calculatedNumberOfindices;
2150 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2151 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2152 idxData, idxSize, minIndex, StartIdx, fixup);
2155 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2157 /* If vertex shaders or no normals, restore previous lighting state */
2158 if (lighting_changed) {
2159 if (lighting_original) glEnable(GL_LIGHTING);
2160 else glDisable(GL_LIGHTING);
2161 TRACE("Restored lighting to original state\n");
2164 /* Finshed updating the screen, restore lock */
2166 TRACE("Done all gl drawing\n");
2169 #ifdef SHOW_FRAME_MAKEUP
2171 static long int primCounter = 0;
2172 /* NOTE: set primCounter to the value reported by drawprim
2173 before you want to to write frame makeup to /tmp */
2174 if (primCounter >= 0) {
2175 WINED3DLOCKED_RECT r;
2177 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2178 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2179 TRACE("Saving screenshot %s\n", buffer);
2180 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2181 IWineD3DSurface_UnlockRect(This->renderTarget);
2183 #ifdef SHOW_TEXTURE_MAKEUP
2185 IWineD3DSurface *pSur;
2187 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2188 if (This->stateBlock->textures[textureNo] != NULL) {
2189 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2190 TRACE("Saving texture %s\n", buffer);
2191 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2192 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2193 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2194 IWineD3DSurface_Release(pSur);
2196 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2203 TRACE("drawprim #%ld\n", primCounter);