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[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
271 checkGLcall("glLoadMatrixf");
273 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
274 checkGLcall("glLoadMatrixf");
275 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_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[WINED3DTS_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 (This->stateBlock->vertexShader && ((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];
1149 if (coordIdx >= MAX_TEXTURES) {
1150 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1151 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1152 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1154 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1155 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1156 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1157 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1160 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1161 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1162 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1163 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1164 checkGLcall("glBindBufferARB");
1165 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1167 /* The coords to supply depend completely on the fvf / vertex shader */
1169 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1170 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1171 sd->u.s.texCoords[coordIdx].dwStride,
1172 sd->u.s.texCoords[coordIdx].lpData);
1173 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1175 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1176 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1177 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1179 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1181 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1182 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1183 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1184 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1185 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1190 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1191 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1192 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1194 if (idxData != NULL /* This crashes sometimes!*/) {
1195 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1196 idxData = idxData == (void *)-1 ? NULL : idxData;
1199 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1200 glEnableClientState(GL_INDEX_ARRAY);
1202 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1203 (const char *)idxData+(idxSize * startIdx));
1204 #else /* using drawRangeElements may be faster */
1206 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1207 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1208 (const char *)idxData+(idxSize * startIdx));
1210 checkGLcall("glDrawRangeElements");
1214 /* Note first is now zero as we shuffled along earlier */
1215 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1216 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1217 checkGLcall("glDrawArrays");
1225 * Actually draw using the supplied information.
1226 * Slower GL version which extracts info about each vertex in turn
1229 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1230 UINT NumVertexes, GLenum glPrimType,
1231 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1233 unsigned int textureNo = 0;
1234 unsigned int texture_idx = 0;
1235 const short *pIdxBufS = NULL;
1236 const long *pIdxBufL = NULL;
1237 LONG SkipnStrides = 0;
1239 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1240 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1241 float rhw = 0.0f; /* rhw */
1242 float ptSize = 0.0f; /* Point size */
1243 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1244 DWORD specularColor = 0; /* Specular Color */
1245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1247 TRACE("Using slow vertex array code\n");
1249 /* Variable Initialization */
1250 if (idxData != NULL) {
1251 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1252 else pIdxBufL = (const long *) idxData;
1255 /* Start drawing in GL */
1256 VTRACE(("glBegin(%x)\n", glPrimType));
1257 glBegin(glPrimType);
1259 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1260 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1263 /* For each primitive */
1264 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1266 /* Initialize diffuse color */
1267 diffuseColor = 0xFFFFFFFF;
1269 /* For indexed data, we need to go a few more strides in */
1270 if (idxData != NULL) {
1272 /* Indexed so work out the number of strides to skip */
1274 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1275 SkipnStrides = pIdxBufS[startIdx + vx_index];
1277 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1278 SkipnStrides = pIdxBufL[startIdx + vx_index];
1282 /* Position Information ------------------ */
1283 if (sd->u.s.position.lpData != NULL) {
1285 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1290 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1292 /* RHW follows, only if transformed, ie 4 floats were provided */
1293 if (sd->u.s.position_transformed) {
1294 rhw = ptrToCoords[3];
1295 VTRACE(("rhw=%f\n", rhw));
1299 /* Blending data -------------------------- */
1300 if (sd->u.s.blendWeights.lpData != NULL) {
1301 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1302 FIXME("Blending not supported yet\n");
1304 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1305 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1309 /* Vertex Normal Data (untransformed only)- */
1310 if (sd->u.s.normal.lpData != NULL) {
1312 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1313 nx = ptrToCoords[0];
1314 ny = ptrToCoords[1];
1315 nz = ptrToCoords[2];
1316 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1319 /* Point Size ----------------------------- */
1320 if (sd->u.s.pSize.lpData != NULL) {
1322 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1323 ptSize = ptrToCoords[0];
1324 VTRACE(("ptSize=%f\n", ptSize));
1325 FIXME("No support for ptSize yet\n");
1328 /* Diffuse -------------------------------- */
1329 if (sd->u.s.diffuse.lpData != NULL) {
1331 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1332 diffuseColor = ptrToCoords[0];
1333 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1336 /* Specular -------------------------------- */
1337 if (sd->u.s.specular.lpData != NULL) {
1339 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1340 specularColor = ptrToCoords[0];
1341 VTRACE(("specularColor=%lx\n", specularColor));
1344 /* Texture coords --------------------------- */
1345 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1347 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1348 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1352 /* Query tex coords */
1353 if (This->stateBlock->textures[textureNo] != NULL) {
1355 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1356 float *ptrToCoords = NULL;
1357 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1360 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1363 } else if (coordIdx < 0) {
1364 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1369 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1370 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1371 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1376 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1378 /* The coords to supply depend completely on the fvf / vertex shader */
1379 switch (coordsToUse) {
1380 case 4: q = ptrToCoords[3]; /* drop through */
1381 case 3: r = ptrToCoords[2]; /* drop through */
1382 case 2: t = ptrToCoords[1]; /* drop through */
1383 case 1: s = ptrToCoords[0];
1386 /* Projected is more 'fun' - Move the last coord to the 'q'
1387 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1388 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1389 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1391 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1392 switch (coordsToUse) {
1393 case 0: /* Drop Through */
1395 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1407 case 4: /* Nop here */
1410 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1411 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1416 switch (coordsToUse) { /* Supply the provided texture coords */
1417 case D3DTTFF_COUNT1:
1418 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1419 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1420 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1425 case D3DTTFF_COUNT2:
1426 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1427 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1428 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1433 case D3DTTFF_COUNT3:
1434 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1435 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1436 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1438 glTexCoord3f(s, t, r);
1441 case D3DTTFF_COUNT4:
1442 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1443 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1444 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1446 glTexCoord4f(s, t, r, q);
1450 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1454 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1455 } /* End of textures */
1457 /* Diffuse -------------------------------- */
1458 if (sd->u.s.diffuse.lpData != NULL) {
1459 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1460 D3DCOLOR_B_G(diffuseColor),
1461 D3DCOLOR_B_B(diffuseColor),
1462 D3DCOLOR_B_A(diffuseColor));
1463 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1464 D3DCOLOR_B_R(diffuseColor),
1465 D3DCOLOR_B_G(diffuseColor),
1466 D3DCOLOR_B_B(diffuseColor),
1467 D3DCOLOR_B_A(diffuseColor)));
1469 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1472 /* Specular ------------------------------- */
1473 if (sd->u.s.specular.lpData != NULL) {
1474 /* special case where the fog density is stored in the diffuse alpha channel */
1475 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1476 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
1477 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1478 if(GL_SUPPORT(EXT_FOG_COORD)) {
1479 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1481 static BOOL warned = FALSE;
1483 /* TODO: Use the fog table code from old ddraw */
1484 FIXME("Implement fog for transformed vertices in software\n");
1490 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1491 D3DCOLOR_B_R(specularColor),
1492 D3DCOLOR_B_G(specularColor),
1493 D3DCOLOR_B_B(specularColor)));
1494 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1495 GL_EXTCALL(glSecondaryColor3ubEXT)(
1496 D3DCOLOR_B_R(specularColor),
1497 D3DCOLOR_B_G(specularColor),
1498 D3DCOLOR_B_B(specularColor));
1500 /* Do not worry if specular colour missing and disable request */
1501 VTRACE(("Specular color extensions not supplied\n"));
1504 if (vx_index == 0) {
1505 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1506 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1508 /* Do not worry if specular colour missing and disable request */
1509 VTRACE(("Specular color extensions not supplied\n"));
1514 /* Normal -------------------------------- */
1515 if (sd->u.s.normal.lpData != NULL) {
1516 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1517 glNormal3f(nx, ny, nz);
1519 if (vx_index == 0) glNormal3f(0, 0, 1);
1522 /* Position -------------------------------- */
1523 if (sd->u.s.position.lpData != NULL) {
1524 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1525 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1526 glVertex3f(x, y, z);
1528 GLfloat w = 1.0 / rhw;
1529 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1530 glVertex4f(x*w, y*w, z*w, w);
1534 /* For non indexed mode, step onto next parts */
1535 if (idxData == NULL) {
1541 checkGLcall("glEnd and previous calls");
1544 #if 0 /* TODO: Software/Hardware vertex blending support */
1546 * Draw with emulated vertex shaders
1547 * Note: strided data is uninitialized, as we need to pass the vertex
1548 * shader directly as ordering irs yet
1550 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1551 int PrimitiveType, ULONG NumPrimitives,
1552 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1554 unsigned int textureNo = 0;
1555 GLenum glPrimType = GL_POINTS;
1556 int NumVertexes = NumPrimitives;
1557 const short *pIdxBufS = NULL;
1558 const long *pIdxBufL = NULL;
1559 LONG SkipnStrides = 0;
1561 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1562 float rhw = 0.0f; /* rhw */
1563 float ptSize = 0.0f; /* Point size */
1564 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1565 int numcoords[8]; /* Number of coords */
1566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1568 IDirect3DVertexShaderImpl* vertexShader = NULL;
1570 TRACE("Using slow software vertex shader code\n");
1572 /* Variable Initialization */
1573 if (idxData != NULL) {
1574 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1575 else pIdxBufL = (const long *) idxData;
1578 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1579 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1581 /* Retrieve the VS information */
1582 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1584 /* Start drawing in GL */
1585 VTRACE(("glBegin(%x)\n", glPrimType));
1586 glBegin(glPrimType);
1588 /* For each primitive */
1589 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1591 /* For indexed data, we need to go a few more strides in */
1592 if (idxData != NULL) {
1594 /* Indexed so work out the number of strides to skip */
1596 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1597 SkipnStrides = pIdxBufS[startIdx+vx_index];
1599 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1600 SkipnStrides = pIdxBufL[startIdx+vx_index];
1604 /* Fill the vertex shader input */
1605 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1607 /* Initialize the output fields to the same defaults as it would normally have */
1608 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1609 vertexShader->output.oD[0].x = 1.0;
1610 vertexShader->output.oD[0].y = 1.0;
1611 vertexShader->output.oD[0].z = 1.0;
1612 vertexShader->output.oD[0].w = 1.0;
1614 /* Now execute the vertex shader */
1615 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1618 TRACE_VECTOR(vertexShader->output.oPos);
1619 TRACE_VECTOR(vertexShader->output.oD[0]);
1620 TRACE_VECTOR(vertexShader->output.oD[1]);
1621 TRACE_VECTOR(vertexShader->output.oT[0]);
1622 TRACE_VECTOR(vertexShader->output.oT[1]);
1623 TRACE_VECTOR(vertexShader->input.V[0]);
1624 TRACE_VECTOR(vertexShader->data->C[0]);
1625 TRACE_VECTOR(vertexShader->data->C[1]);
1626 TRACE_VECTOR(vertexShader->data->C[2]);
1627 TRACE_VECTOR(vertexShader->data->C[3]);
1628 TRACE_VECTOR(vertexShader->data->C[4]);
1629 TRACE_VECTOR(vertexShader->data->C[5]);
1630 TRACE_VECTOR(vertexShader->data->C[6]);
1631 TRACE_VECTOR(vertexShader->data->C[7]);
1634 /* Extract out the output */
1635 /* FIXME: Fog coords? */
1636 x = vertexShader->output.oPos.x;
1637 y = vertexShader->output.oPos.y;
1638 z = vertexShader->output.oPos.z;
1639 rhw = vertexShader->output.oPos.w;
1640 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1642 /** Update textures coords using vertexShader->output.oT[0->7] */
1643 memset(texcoords, 0x00, sizeof(texcoords));
1644 memset(numcoords, 0x00, sizeof(numcoords));
1645 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1646 if (This->stateBlock->textures[textureNo] != NULL) {
1647 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1648 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1649 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1650 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1651 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1652 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1654 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1655 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1656 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1657 default: numcoords[textureNo] = 4;
1661 numcoords[textureNo] = 0;
1665 /* Draw using this information */
1668 TRUE, 0.0f, 0.0f, 1.0f,
1669 TRUE, (float*) &vertexShader->output.oD[0],
1670 TRUE, (float*) &vertexShader->output.oD[1],
1671 FALSE, ptSize, /* FIXME: Change back when supported */
1672 texcoords, numcoords);
1674 /* For non indexed mode, step onto next parts */
1675 if (idxData == NULL) {
1679 } /* for each vertex */
1682 checkGLcall("glEnd and previous calls");
1687 inline static void drawPrimitiveDrawStrided(
1688 IWineD3DDevice *iface,
1689 BOOL useVertexShaderFunction,
1690 BOOL usePixelShaderFunction,
1691 WineDirect3DVertexStridedData *dataLocations,
1692 UINT numberOfvertices,
1693 UINT numberOfIndicies,
1695 const void *idxData,
1701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1702 BOOL useDrawStridedSlow;
1704 int startStride = idxData == NULL ? 0 :
1705 idxData == (void *) -1 ? 0 :
1706 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1707 int endStride = startStride;
1708 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1709 startStride, endStride, numberOfIndicies, numberOfvertices);
1711 /* Generate some fixme's if unsupported functionality is being used */
1712 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1713 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1714 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1715 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1717 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1718 FIXME("Tweening is only valid with vertex shaders\n");
1720 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1721 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1723 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1724 FIXME("Extended attributes are only valid with vertex shaders\n");
1726 #undef BUFFER_OR_DATA
1728 /* Fixed pipeline, no fixups required - load arrays */
1729 if (!useVertexShaderFunction &&
1730 ((dataLocations->u.s.pSize.lpData == NULL &&
1731 dataLocations->u.s.diffuse.lpData == NULL &&
1732 dataLocations->u.s.specular.lpData == NULL) ||
1735 /* Load the vertex data using named arrays */
1736 TRACE("(%p) Loading vertex data\n", This);
1737 loadVertexData(iface, dataLocations);
1738 useDrawStridedSlow = FALSE;
1740 /* Shader pipeline - load attribute arrays */
1741 } else if(useVertexShaderFunction) {
1743 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1744 useDrawStridedSlow = FALSE;
1746 /* Draw vertex by vertex */
1748 TRACE("Not loading vertex data\n");
1749 useDrawStridedSlow = TRUE;
1752 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1753 * Otherwise set 0, which restores fixed function */
1754 if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1755 (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1756 set_glsl_shader_program(iface);
1758 This->stateBlock->shaderPrgId = 0;
1760 /* If GLSL is used now, or might have been used before, (re)set the program */
1761 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
1762 wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1764 if (This->stateBlock->shaderPrgId)
1765 TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
1766 GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
1767 checkGLcall("glUseProgramObjectARB");
1770 if (useVertexShaderFunction) {
1772 TRACE("Using vertex shader\n");
1774 if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1775 /* Bind the vertex program */
1776 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1777 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1778 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1780 /* Enable OpenGL vertex programs */
1781 glEnable(GL_VERTEX_PROGRAM_ARB);
1782 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1783 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1784 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1788 if (usePixelShaderFunction) {
1790 TRACE("Using pixel shader\n");
1792 if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1793 /* Bind the fragment program */
1794 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1795 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1796 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1798 /* Enable OpenGL fragment programs */
1799 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1800 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1801 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1802 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1806 /* Load any global constants/uniforms that may have been set by the application */
1807 if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
1808 shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1809 else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
1810 shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1812 /* Draw vertex-by-vertex */
1813 if (useDrawStridedSlow)
1814 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1816 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1818 /* Cleanup vertex program */
1819 if (useVertexShaderFunction) {
1820 /* disable any attribs (this is the same for both GLSL and ARB modes) */
1823 /* Leave all the attribs disabled */
1824 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1825 /* MESA does not support it right not */
1826 if (glGetError() != GL_NO_ERROR)
1828 for (i = 0; i < maxAttribs; ++i) {
1829 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1830 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1833 if (wined3d_settings.vs_selected_mode == SHADER_ARB)
1834 glDisable(GL_VERTEX_PROGRAM_ARB);
1837 /* Cleanup fragment program */
1838 if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB)
1839 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1842 inline void drawPrimitiveTraceDataLocations(
1843 WineDirect3DVertexStridedData *dataLocations) {
1845 /* Dump out what parts we have supplied */
1846 TRACE("Strided Data:\n");
1847 TRACE_STRIDED((dataLocations), position);
1848 TRACE_STRIDED((dataLocations), blendWeights);
1849 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1850 TRACE_STRIDED((dataLocations), normal);
1851 TRACE_STRIDED((dataLocations), pSize);
1852 TRACE_STRIDED((dataLocations), diffuse);
1853 TRACE_STRIDED((dataLocations), specular);
1854 TRACE_STRIDED((dataLocations), texCoords[0]);
1855 TRACE_STRIDED((dataLocations), texCoords[1]);
1856 TRACE_STRIDED((dataLocations), texCoords[2]);
1857 TRACE_STRIDED((dataLocations), texCoords[3]);
1858 TRACE_STRIDED((dataLocations), texCoords[4]);
1859 TRACE_STRIDED((dataLocations), texCoords[5]);
1860 TRACE_STRIDED((dataLocations), texCoords[6]);
1861 TRACE_STRIDED((dataLocations), texCoords[7]);
1862 TRACE_STRIDED((dataLocations), position2);
1863 TRACE_STRIDED((dataLocations), normal2);
1864 TRACE_STRIDED((dataLocations), tangent);
1865 TRACE_STRIDED((dataLocations), binormal);
1866 TRACE_STRIDED((dataLocations), tessFactor);
1867 TRACE_STRIDED((dataLocations), fog);
1868 TRACE_STRIDED((dataLocations), depth);
1869 TRACE_STRIDED((dataLocations), sample);
1875 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1878 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1879 /* Pixel shader support should imply multitexture support. */
1880 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1881 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1882 checkGLcall("glActiveTextureARB");
1884 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1887 if (!This->stateBlock->textures[i]) continue;
1889 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1890 glDisable(GL_TEXTURE_1D);
1891 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1892 switch(This->stateBlock->textureDimensions[i]) {
1894 glDisable(GL_TEXTURE_3D);
1895 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1898 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1899 glDisable(GL_TEXTURE_2D);
1901 case GLTEXTURECUBEMAP:
1902 glDisable(GL_TEXTURE_2D);
1903 glDisable(GL_TEXTURE_3D);
1906 glEnable(This->stateBlock->textureDimensions[i]);
1908 /* Upload texture, apply states */
1909 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1910 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1911 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1915 /* uploads textures and setup texture states ready for rendering */
1916 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1917 INT current_sampler = 0;
1918 float constant_color[4];
1921 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1922 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1923 * Register combiners however provide up to 8 combiner stages. In order to
1924 * take advantage of this, we need to be separate D3D texture stages from
1925 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1926 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1927 * corresponds to MaxTextureBlendStages in the caps. */
1929 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1930 glEnable(GL_REGISTER_COMBINERS_NV);
1931 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1932 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1935 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1936 INT texture_idx = -1;
1938 /* D3DTOP_DISABLE disables the current & any higher texture stages */
1939 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
1941 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1942 texture_idx = current_sampler++;
1944 /* Active the texture unit corresponding to the current texture stage */
1945 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1946 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1947 checkGLcall("glActiveTextureARB");
1949 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1953 if (This->stateBlock->textures[i]) {
1954 /* Enable the correct target. */
1955 glDisable(GL_TEXTURE_1D);
1956 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1957 switch(This->stateBlock->textureDimensions[i]) {
1959 glDisable(GL_TEXTURE_3D);
1960 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1963 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1964 glDisable(GL_TEXTURE_2D);
1966 case GLTEXTURECUBEMAP:
1967 glDisable(GL_TEXTURE_2D);
1968 glDisable(GL_TEXTURE_3D);
1972 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1973 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1974 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1976 glEnable(This->stateBlock->textureDimensions[i]);
1979 /* Upload texture, apply states */
1980 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1981 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
1982 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1983 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1984 /* ARB_texture_env_combine needs a valid texture bound to the
1985 * texture unit, even if it isn't used. Bind a dummy texture. */
1986 glDisable(GL_TEXTURE_2D);
1987 glDisable(GL_TEXTURE_3D);
1988 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1989 glEnable(GL_TEXTURE_1D);
1990 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1991 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1994 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1995 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1996 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1997 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1998 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1999 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2000 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
2003 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2004 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2005 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2006 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2009 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2010 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2011 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2012 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2014 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2015 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2016 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2017 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2021 /* If we're using register combiners, set the amount of *used* combiners.
2022 * Ie, the number of stages below the first stage to have a color op of
2023 * D3DTOP_DISABLE. */
2024 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2025 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2026 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2027 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2030 /* Disable the remaining texture units. */
2031 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2032 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2033 glDisable(GL_TEXTURE_1D);
2034 glDisable(GL_TEXTURE_2D);
2035 glDisable(GL_TEXTURE_3D);
2036 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2040 /* Routine common to the draw primitive and draw indexed primitive routines */
2041 void drawPrimitive(IWineD3DDevice *iface,
2045 long StartVertexIndex,
2046 UINT numberOfVertices,
2049 const void *idxData,
2051 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2054 BOOL useVertexShaderFunction = FALSE;
2055 BOOL usePixelShaderFunction = FALSE;
2056 WineDirect3DVertexStridedData *dataLocations;
2057 IWineD3DSwapChainImpl *swapchain;
2061 BOOL lighting_changed, lighting_original = FALSE;
2063 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2064 * here simply check whether a shader was set, or the user disabled shaders */
2065 if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2066 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2067 useVertexShaderFunction = TRUE;
2069 if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2070 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2071 usePixelShaderFunction = TRUE;
2073 /* Invalidate the back buffer memory so LockRect will read it the next time */
2074 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2075 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2077 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2078 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2082 /* Ok, we will be updating the screen from here onwards so grab the lock */
2085 if(DrawPrimStrideData) {
2087 /* Note: this is a ddraw fixed-function code path */
2089 TRACE("================ Strided Input ===================\n");
2090 dataLocations = DrawPrimStrideData;
2091 drawPrimitiveTraceDataLocations(dataLocations);
2095 else if (This->stateBlock->vertexDecl || This->stateBlock->vertexShader) {
2097 /* Note: This is a fixed function or shader codepath.
2098 * This means it must handle both types of strided data.
2099 * Shaders must go through here to zero the strided data, even if they
2100 * don't set any declaration at all */
2102 TRACE("================ Vertex Declaration ===================\n");
2103 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2104 if(!dataLocations) {
2105 ERR("Out of memory!\n");
2109 if (This->stateBlock->vertexDecl != NULL ||
2110 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2112 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2113 dataLocations, StartVertexIndex, &fixup);
2117 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2118 * It is reachable through d3d8, but only for fixed-function.
2119 * It will not work properly for shaders. */
2121 TRACE("================ FVF ===================\n");
2122 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2123 if(!dataLocations) {
2124 ERR("Out of memory!\n");
2127 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2128 drawPrimitiveTraceDataLocations(dataLocations);
2131 /* Setup transform matrices and sort out */
2132 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2134 /* Now initialize the materials state */
2135 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2137 if (usePixelShaderFunction) {
2138 drawPrimitiveUploadTexturesPS(This);
2140 drawPrimitiveUploadTextures(This);
2145 /* Ok, Work out which primitive is requested and how many vertexes that
2147 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2148 if (numberOfVertices == 0 )
2149 numberOfVertices = calculatedNumberOfindices;
2151 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2152 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2153 idxData, idxSize, minIndex, StartIdx, fixup);
2156 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2158 /* If vertex shaders or no normals, restore previous lighting state */
2159 if (lighting_changed) {
2160 if (lighting_original) glEnable(GL_LIGHTING);
2161 else glDisable(GL_LIGHTING);
2162 TRACE("Restored lighting to original state\n");
2165 /* Finshed updating the screen, restore lock */
2167 TRACE("Done all gl drawing\n");
2170 #ifdef SHOW_FRAME_MAKEUP
2172 static long int primCounter = 0;
2173 /* NOTE: set primCounter to the value reported by drawprim
2174 before you want to to write frame makeup to /tmp */
2175 if (primCounter >= 0) {
2176 WINED3DLOCKED_RECT r;
2178 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2179 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2180 TRACE("Saving screenshot %s\n", buffer);
2181 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2182 IWineD3DSurface_UnlockRect(This->renderTarget);
2184 #ifdef SHOW_TEXTURE_MAKEUP
2186 IWineD3DSurface *pSur;
2188 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2189 if (This->stateBlock->textures[textureNo] != NULL) {
2190 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2191 TRACE("Saving texture %s\n", buffer);
2192 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2193 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2194 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2195 IWineD3DSurface_Release(pSur);
2197 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2204 TRACE("drawprim #%ld\n", primCounter);