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 if(!This->untransformed) {
186 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
187 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
189 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
190 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
192 checkGLcall("glOrtho");
194 /* Window Coord 0 is the middle of the first pixel, so translate by half
195 a pixel (See comment above glTranslate below) */
196 glTranslatef(0.375, 0.375, 0);
197 checkGLcall("glTranslatef(0.375, 0.375, 0)");
198 if (This->renderUpsideDown) {
199 glMultMatrixf(invymat);
200 checkGLcall("glMultMatrixf(invymat)");
203 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
204 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
205 if(GL_SUPPORT(EXT_FOG_COORD)) {
206 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
207 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
208 glFogi(GL_FOG_MODE, GL_LINEAR);
209 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
210 /* The dx fog range in this case is fixed to 0 - 255,
211 * but in GL it still depends on the fog start and end (according to the ext)
212 * Use this to turn around the fog as it's needed. That prevents some
213 * calculations during drawing :-)
215 glFogf(GL_FOG_START, (float) 0xff);
216 checkGLcall("glFogfv GL_FOG_END");
217 glFogf(GL_FOG_END, 0.0);
218 checkGLcall("glFogfv GL_FOG_START");
220 /* Disable GL fog, handle this in software in drawStridedSlow */
222 checkGLcall("glDisable(GL_FOG)");
227 /* Setup views - Transformed & lit if RHW, else untransformed.
228 Only unlit if Normals are supplied
229 Returns: Whether to restore lighting afterwards */
230 static void primitiveInitState(
231 IWineD3DDevice *iface,
232 WineDirect3DVertexStridedData* strided,
234 BOOL* lighting_changed,
235 BOOL* lighting_original) {
237 BOOL fixed_vtx_transformed =
238 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
239 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
240 strided->u.s.position_transformed;
243 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
244 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
248 *lighting_changed = FALSE;
250 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
251 set by the appropriate render state. Note Vertex Shader output is already lit */
252 if (fixed_vtx_lit || useVS) {
253 *lighting_changed = TRUE;
254 *lighting_original = glIsEnabled(GL_LIGHTING);
255 glDisable(GL_LIGHTING);
256 checkGLcall("glDisable(GL_LIGHTING);");
257 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
260 if (!useVS && fixed_vtx_transformed) {
261 d3ddevice_set_ortho(This);
265 /* Untransformed, so relies on the view and projection matrices */
266 This->untransformed = TRUE;
268 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
269 /* Only reapply when have to */
270 This->modelview_valid = TRUE;
271 glMatrixMode(GL_MODELVIEW);
272 checkGLcall("glMatrixMode");
274 /* In the general case, the view matrix is the identity matrix */
275 if (This->view_ident) {
276 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
277 checkGLcall("glLoadMatrixf");
279 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
280 checkGLcall("glLoadMatrixf");
281 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
282 checkGLcall("glMultMatrixf");
286 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
287 /* Only reapply when have to */
288 This->proj_valid = TRUE;
289 glMatrixMode(GL_PROJECTION);
290 checkGLcall("glMatrixMode");
292 /* The rule is that the window coordinate 0 does not correspond to the
293 beginning of the first pixel, but the center of the first pixel.
294 As a consequence if you want to correctly draw one line exactly from
295 the left to the right end of the viewport (with all matrices set to
296 be identity), the x coords of both ends of the line would be not
297 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
301 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
302 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
304 if (This->renderUpsideDown) {
305 glMultMatrixf(invymat);
306 checkGLcall("glMultMatrixf(invymat)");
308 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
309 checkGLcall("glLoadMatrixf");
312 /* Vertex Shader output is already transformed, so set up identity matrices */
314 glMatrixMode(GL_MODELVIEW);
315 checkGLcall("glMatrixMode");
317 glMatrixMode(GL_PROJECTION);
318 checkGLcall("glMatrixMode");
320 /* Window Coord 0 is the middle of the first pixel, so translate by half
321 a pixel (See comment above glTranslate above) */
322 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
323 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
324 if (This->renderUpsideDown) {
325 glMultMatrixf(invymat);
326 checkGLcall("glMultMatrixf(invymat)");
328 This->modelview_valid = FALSE;
329 This->proj_valid = FALSE;
331 This->last_was_rhw = FALSE;
334 if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
335 /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
336 * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
337 glFogi(GL_FOG_MODE, GL_LINEAR);
338 glFogf(GL_FOG_START, 1.0f);
339 glFogf(GL_FOG_END, 0.0f);
341 } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE]
342 && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
344 if(GL_SUPPORT(EXT_FOG_COORD)) {
345 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
346 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
347 /* Reapply the fog range */
348 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
349 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
350 /* Restore the fog mode */
351 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
353 /* Enable GL_FOG again because we disabled it above */
355 checkGLcall("glEnable(GL_FOG)");
361 static BOOL fixed_get_input(
362 BYTE usage, BYTE usage_idx,
363 unsigned int* regnum) {
367 /* Those positions must have the order in the
368 * named part of the strided data */
370 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
372 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
374 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
376 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
378 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
380 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
382 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
384 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < D3DDP_MAXTEXCOORD)
385 *regnum = 7 + usage_idx;
386 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
387 *regnum = 7 + D3DDP_MAXTEXCOORD;
388 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
389 *regnum = 8 + D3DDP_MAXTEXCOORD;
390 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
391 *regnum = 9 + D3DDP_MAXTEXCOORD;
392 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
393 *regnum = 10 + D3DDP_MAXTEXCOORD;
394 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
395 *regnum = 11 + D3DDP_MAXTEXCOORD;
396 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
397 *regnum = 12 + D3DDP_MAXTEXCOORD;
398 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
399 *regnum = 13 + D3DDP_MAXTEXCOORD;
400 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
401 *regnum = 14 + D3DDP_MAXTEXCOORD;
404 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
405 debug_d3ddeclusage(usage), usage_idx);
411 void primitiveDeclarationConvertToStridedData(
412 IWineD3DDevice *iface,
413 BOOL useVertexShaderFunction,
414 WineDirect3DVertexStridedData *strided,
415 LONG BaseVertexIndex,
418 /* We need to deal with frequency data!*/
421 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
422 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
424 WINED3DVERTEXELEMENT *element;
428 /* Locate the vertex declaration */
429 if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
430 TRACE("Using vertex declaration from shader\n");
431 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
433 TRACE("Using vertex declaration\n");
434 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
437 /* Translate the declaration into strided data */
438 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
443 element = vertexDeclaration->pDeclarationWine + i;
444 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
445 if (This->stateBlock->streamIsUP) {
446 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
448 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
449 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
451 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
452 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
453 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
455 if( streamVBO != 0) *fixup = TRUE;
456 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
459 stride = This->stateBlock->streamStride[element->Stream];
460 data += (BaseVertexIndex * stride);
461 data += element->Offset;
464 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
466 if (useVertexShaderFunction)
467 stride_used = vshader_get_input(This->stateBlock->vertexShader,
468 element->Usage, element->UsageIndex, &idx);
470 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
473 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
474 "stream=%u, offset=%u, stride=%lu, VBO=%u]\n",
475 useVertexShaderFunction? "shader": "fixed function", idx,
476 debug_d3ddeclusage(element->Usage), element->UsageIndex,
477 element->Stream, element->Offset, stride, streamVBO);
479 strided->u.input[idx].lpData = data;
480 strided->u.input[idx].dwType = element->Type;
481 strided->u.input[idx].dwStride = stride;
482 strided->u.input[idx].VBO = streamVBO;
483 if (!useVertexShaderFunction) {
484 if (element->Usage == D3DDECLUSAGE_POSITION)
485 strided->u.s.position_transformed = FALSE;
486 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
487 strided->u.s.position_transformed = TRUE;
493 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
497 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
498 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
500 /* Either 3 or 4 floats depending on the FVF */
501 /* FIXME: Can blending data be in a different stream to the position data?
502 and if so using the fixed pipeline how do we handle it */
503 if (thisFVF & D3DFVF_POSITION_MASK) {
504 strided->u.s.position.lpData = data;
505 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
506 strided->u.s.position.dwStride = stride;
507 strided->u.s.position.VBO = streamVBO;
508 data += 3 * sizeof(float);
509 if (thisFVF & D3DFVF_XYZRHW) {
510 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
511 strided->u.s.position_transformed = TRUE;
512 data += sizeof(float);
514 strided->u.s.position_transformed = FALSE;
517 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
518 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
519 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
520 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
522 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
523 TRACE("Setting blend Weights to %p\n", data);
524 strided->u.s.blendWeights.lpData = data;
525 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
526 strided->u.s.blendWeights.dwStride = stride;
527 strided->u.s.blendWeights.VBO = streamVBO;
528 data += numBlends * sizeof(FLOAT);
530 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
531 strided->u.s.blendMatrixIndices.lpData = data;
532 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
533 strided->u.s.blendMatrixIndices.dwStride= stride;
534 strided->u.s.blendMatrixIndices.VBO = streamVBO;
535 data += sizeof(DWORD);
539 /* Normal is always 3 floats */
540 if (thisFVF & D3DFVF_NORMAL) {
541 strided->u.s.normal.lpData = data;
542 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
543 strided->u.s.normal.dwStride = stride;
544 strided->u.s.normal.VBO = streamVBO;
545 data += 3 * sizeof(FLOAT);
548 /* Pointsize is a single float */
549 if (thisFVF & D3DFVF_PSIZE) {
550 strided->u.s.pSize.lpData = data;
551 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
552 strided->u.s.pSize.dwStride = stride;
553 strided->u.s.pSize.VBO = streamVBO;
554 data += sizeof(FLOAT);
557 /* Diffuse is 4 unsigned bytes */
558 if (thisFVF & D3DFVF_DIFFUSE) {
559 strided->u.s.diffuse.lpData = data;
560 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
561 strided->u.s.diffuse.dwStride = stride;
562 strided->u.s.diffuse.VBO = streamVBO;
563 data += sizeof(DWORD);
566 /* Specular is 4 unsigned bytes */
567 if (thisFVF & D3DFVF_SPECULAR) {
568 strided->u.s.specular.lpData = data;
569 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
570 strided->u.s.specular.dwStride = stride;
571 strided->u.s.specular.VBO = streamVBO;
572 data += sizeof(DWORD);
576 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
577 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
579 /* numTextures indicates the number of texture coordinates supplied */
580 /* However, the first set may not be for stage 0 texture - it all */
581 /* depends on D3DTSS_TEXCOORDINDEX. */
582 /* The number of bytes for each coordinate set is based off */
583 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
585 /* So, for each supplied texture extract the coords */
586 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
588 strided->u.s.texCoords[textureNo].lpData = data;
589 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
590 strided->u.s.texCoords[textureNo].dwStride = stride;
591 strided->u.s.texCoords[textureNo].VBO = streamVBO;
592 numCoords[textureNo] = coordIdxInfo & 0x03;
595 data += sizeof(float);
596 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
597 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
598 data += sizeof(float);
599 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
600 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
601 data += sizeof(float);
602 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
603 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
604 data += sizeof(float);
608 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
612 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
614 short LoopThroughTo = 0;
618 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
620 /* OK, Now to setup the data locations
621 For the non-created vertex shaders, the VertexShader var holds the real
622 FVF and only stream 0 matters
623 For the created vertex shaders, there is an FVF per stream */
624 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
625 LoopThroughTo = MAX_STREAMS;
630 /* Work through stream by stream */
631 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
632 DWORD stride = This->stateBlock->streamStride[nStream];
636 /* Skip empty streams */
637 if (This->stateBlock->streamSource[nStream] == NULL) continue;
639 /* Retrieve appropriate FVF */
640 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
641 thisFVF = This->stateBlock->fvf;
642 /* Handle memory passed directly as well as vertex buffers */
643 if (This->stateBlock->streamIsUP) {
645 data = (BYTE *)This->stateBlock->streamSource[nStream];
647 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
648 /* GetMemory binds the VBO */
649 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
651 if(streamVBO != 0 ) *fixup = TRUE;
655 #if 0 /* TODO: Vertex shader support */
656 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
657 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
660 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
661 if (thisFVF == 0) continue;
663 /* Now convert the stream into pointers */
665 /* Shuffle to the beginning of the vertexes to render and index from there */
666 data = data + (BaseVertexIndex * stride);
668 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
672 #if 0 /* TODO: Software Shaders */
673 /* Draw a single vertex using this information */
674 static void draw_vertex(IWineD3DDevice *iface, /* interface */
675 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
676 BOOL isNormal, float nx, float ny, float nz, /* normal */
677 BOOL isDiffuse, float *dRGBA, /* 1st colors */
678 BOOL isSpecular, float *sRGB, /* 2ndry colors */
679 BOOL isPtSize, float ptSize, /* pointSize */
680 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
682 unsigned int textureNo;
684 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
686 /* Diffuse -------------------------------- */
689 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
692 /* Specular Colour ------------------------------------------*/
694 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
695 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
696 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
698 VTRACE(("Specular color extensions not supplied\n"));
702 /* Normal -------------------------------- */
704 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
705 glNormal3f(nx, ny, nz);
708 /* Point Size ----------------------------------------------*/
711 /* no such functionality in the fixed function GL pipeline */
712 FIXME("Cannot change ptSize here in openGl\n");
715 /* Texture coords --------------------------- */
716 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
718 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
719 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
723 /* Query tex coords */
724 if (This->stateBlock->textures[textureNo] != NULL) {
726 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
727 if (coordIdx >= MAX_TEXTURES) {
728 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
730 } else if (numcoords[coordIdx] == 0) {
731 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
735 /* Initialize vars */
741 switch (numcoords[coordIdx]) {
742 case 4: q = texcoords[coordIdx].w; /* drop through */
743 case 3: r = texcoords[coordIdx].z; /* drop through */
744 case 2: t = texcoords[coordIdx].y; /* drop through */
745 case 1: s = texcoords[coordIdx].x;
748 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
750 VTRACE(("tex:%d, s=%f\n", textureNo, s));
751 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
752 GLMULTITEXCOORD1F(textureNo, s);
758 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
759 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
760 GLMULTITEXCOORD2F(textureNo, s, t);
766 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
767 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
768 GLMULTITEXCOORD3F(textureNo, s, t, r);
770 glTexCoord3f(s, t, r);
774 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
775 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
776 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
778 glTexCoord4f(s, t, r, q);
782 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
786 } /* End of textures */
788 /* Position -------------------------------- */
790 if (1.0f == rhw || rhw < 0.00001f) {
791 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
794 /* Cannot optimize by dividing through by rhw as rhw is required
795 later for perspective in the GL pipeline for vertex shaders */
796 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
797 glVertex4f(x,y,z,rhw);
801 #endif /* TODO: Software shaders */
803 /* This should match any arrays loaded in loadNumberedArrays. */
804 /* TODO: Only load / unload arrays if we have to. */
805 static void unloadNumberedArrays(IWineD3DDevice *iface) {
806 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
808 /* disable any attribs (this is the same for both GLSL and ARB modes) */
812 /* Leave all the attribs disabled */
813 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
814 /* MESA does not support it right not */
815 if (glGetError() != GL_NO_ERROR)
817 for (i = 0; i < maxAttribs; ++i) {
818 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
819 checkGLcall("glDisableVertexAttribArrayARB(reg);");
823 /* TODO: Only load / unload arrays if we have to. */
824 static void loadNumberedArrays(
825 IWineD3DDevice *iface,
826 IWineD3DVertexShader *shader,
827 WineDirect3DVertexStridedData *strided) {
829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
833 for (i = 0; i < MAX_ATTRIBS; i++) {
835 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
838 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
840 if(curVBO != strided->u.input[i].VBO) {
841 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
842 checkGLcall("glBindBufferARB");
843 curVBO = strided->u.input[i].VBO;
845 GL_EXTCALL(glVertexAttribPointerARB(i,
846 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
847 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
848 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
849 strided->u.input[i].dwStride,
850 strided->u.input[i].lpData));
851 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
855 /* This should match any arrays loaded in loadVertexData. */
856 /* TODO: Only load / unload arrays if we have to. */
857 static void unloadVertexData(IWineD3DDevice *iface) {
858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
861 glDisableClientState(GL_VERTEX_ARRAY);
862 glDisableClientState(GL_NORMAL_ARRAY);
863 glDisableClientState(GL_COLOR_ARRAY);
864 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
865 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
867 for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
868 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
869 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
873 /* TODO: Only load / unload arrays if we have to. */
874 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
875 unsigned int textureNo = 0;
876 unsigned int texture_idx = 0;
877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
880 TRACE("Using fast vertex array code\n");
881 /* Blend Data ---------------------------------------------- */
882 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
883 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
886 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
889 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
890 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
893 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
894 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
895 /* FIXME("TODO\n");*/
896 /* Note dwType == float3 or float4 == 2 or 3 */
899 /* with this on, the normals appear to be being modified,
900 but the vertices aren't being translated as they should be
901 Maybe the world matrix aren't being setup properly? */
902 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
906 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
907 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
908 sd->u.s.blendWeights.dwStride,
909 sd->u.s.blendWeights.lpData));
911 if(curVBO != sd->u.s.blendWeights.VBO) {
912 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
913 checkGLcall("glBindBufferARB");
914 curVBO = sd->u.s.blendWeights.VBO;
917 GL_EXTCALL(glWeightPointerARB)(
918 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
919 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
920 sd->u.s.blendWeights.dwStride,
921 sd->u.s.blendWeights.lpData);
923 checkGLcall("glWeightPointerARB");
925 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
926 static BOOL showfixme = TRUE;
928 FIXME("blendMatrixIndices support\n");
933 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
934 /* FIXME("TODO\n");*/
937 GL_EXTCALL(glVertexWeightPointerEXT)(
938 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
939 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
940 sd->u.s.blendWeights.dwStride,
941 sd->u.s.blendWeights.lpData);
942 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
943 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
944 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
948 /* TODO: support blends in fixupVertices */
949 FIXME("unsupported blending in openGl\n");
952 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
953 #if 0 /* TODO: Vertex blending */
954 glDisable(GL_VERTEX_BLEND_ARB);
956 TRACE("ARB_VERTEX_BLEND\n");
957 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
958 TRACE(" EXT_VERTEX_WEIGHTING\n");
959 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
960 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
965 #if 0 /* FOG ----------------------------------------------*/
966 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
968 if (GL_SUPPORT(EXT_FOG_COORD) {
969 glEnableClientState(GL_FOG_COORDINATE_EXT);
970 (GL_EXTCALL)(FogCoordPointerEXT)(
971 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
972 sd->u.s.fog.dwStride,
975 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
976 /* FIXME: fixme once */
977 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
980 if (GL_SUPPRT(EXT_FOR_COORD) {
981 /* make sure fog is disabled */
982 glDisableClientState(GL_FOG_COORDINATE_EXT);
987 #if 0 /* tangents ----------------------------------------------*/
988 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
989 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
991 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
992 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
993 glEnable(GL_TANGENT_ARRAY_EXT);
994 (GL_EXTCALL)(TangentPointerEXT)(
995 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
996 sd->u.s.tangent.dwStride,
997 sd->u.s.tangent.lpData);
999 glDisable(GL_TANGENT_ARRAY_EXT);
1001 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
1002 glEnable(GL_BINORMAL_ARRAY_EXT);
1003 (GL_EXTCALL)(BinormalPointerEXT)(
1004 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
1005 sd->u.s.binormal.dwStride,
1006 sd->u.s.binormal.lpData);
1008 glDisable(GL_BINORMAL_ARRAY_EXT);
1012 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1013 /* FIXME: fixme once */
1014 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1017 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1018 /* make sure fog is disabled */
1019 glDisable(GL_TANGENT_ARRAY_EXT);
1020 glDisable(GL_BINORMAL_ARRAY_EXT);
1025 /* Point Size ----------------------------------------------*/
1026 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
1028 /* no such functionality in the fixed function GL pipeline */
1029 TRACE("Cannot change ptSize here in openGl\n");
1030 /* TODO: Implement this function in using shaders if they are available */
1034 /* Vertex Pointers -----------------------------------------*/
1035 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
1036 /* Note dwType == float3 or float4 == 2 or 3 */
1037 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1038 sd->u.s.position.dwStride,
1039 sd->u.s.position.dwType + 1,
1040 sd->u.s.position.lpData));
1042 if(curVBO != sd->u.s.position.VBO) {
1043 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1044 checkGLcall("glBindBufferARB");
1045 curVBO = sd->u.s.position.VBO;
1048 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1049 handling for rhw mode should not impact screen position whereas in GL it does.
1050 This may result in very slightly distored textures in rhw mode, but
1051 a very minimal different. There's always the other option of
1052 fixing the view matrix to prevent w from having any effect
1054 This only applies to user pointer sources, in VBOs the vertices are fixed up
1056 if(sd->u.s.position.VBO == 0) {
1057 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1058 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1059 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1062 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1063 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1064 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1066 checkGLcall("glVertexPointer(...)");
1067 glEnableClientState(GL_VERTEX_ARRAY);
1068 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1071 glDisableClientState(GL_VERTEX_ARRAY);
1072 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1075 /* Normals -------------------------------------------------*/
1076 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1077 /* Note dwType == float3 or float4 == 2 or 3 */
1078 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1079 sd->u.s.normal.dwStride,
1080 sd->u.s.normal.lpData));
1081 if(curVBO != sd->u.s.normal.VBO) {
1082 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1083 checkGLcall("glBindBufferARB");
1084 curVBO = sd->u.s.normal.VBO;
1087 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1088 sd->u.s.normal.dwStride,
1089 sd->u.s.normal.lpData);
1090 checkGLcall("glNormalPointer(...)");
1091 glEnableClientState(GL_NORMAL_ARRAY);
1092 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1095 glDisableClientState(GL_NORMAL_ARRAY);
1096 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1097 glNormal3f(0, 0, 1);
1098 checkGLcall("glNormal3f(0, 0, 1)");
1101 /* Diffuse Colour --------------------------------------------*/
1102 /* WARNING: Data here MUST be in RGBA format, so cannot */
1103 /* go directly into fast mode from app pgm, because */
1104 /* directx requires data in BGRA format. */
1105 /* currently fixupVertices swizels the format, but this isn't */
1106 /* very practical when using VBOS */
1107 /* NOTE: Unless we write a vertex shader to swizel the colour */
1108 /* , or the user doesn't care and wants the speed advantage */
1110 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1111 /* Note dwType == float3 or float4 == 2 or 3 */
1112 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1113 sd->u.s.diffuse.dwStride,
1114 sd->u.s.diffuse.lpData));
1116 if(curVBO != sd->u.s.diffuse.VBO) {
1117 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1118 checkGLcall("glBindBufferARB");
1119 curVBO = sd->u.s.diffuse.VBO;
1121 glColorPointer(4, GL_UNSIGNED_BYTE,
1122 sd->u.s.diffuse.dwStride,
1123 sd->u.s.diffuse.lpData);
1124 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1125 glEnableClientState(GL_COLOR_ARRAY);
1126 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1129 glDisableClientState(GL_COLOR_ARRAY);
1130 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1131 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1132 checkGLcall("glColor4f(1, 1, 1, 1)");
1135 /* Specular Colour ------------------------------------------*/
1136 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1137 TRACE("setting specular colour\n");
1138 /* Note dwType == float3 or float4 == 2 or 3 */
1139 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1140 sd->u.s.specular.dwStride,
1141 sd->u.s.specular.lpData));
1142 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1143 if(curVBO != sd->u.s.specular.VBO) {
1144 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1145 checkGLcall("glBindBufferARB");
1146 curVBO = sd->u.s.specular.VBO;
1148 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1149 sd->u.s.specular.dwStride,
1150 sd->u.s.specular.lpData);
1151 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1152 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1153 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1156 /* Missing specular color is not critical, no warnings */
1157 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1161 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1163 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1164 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1165 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1166 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1169 /* Missing specular color is not critical, no warnings */
1170 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1174 /* Texture coords -------------------------------------------*/
1176 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1177 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1178 /* Abort if we don't support the extension. */
1179 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1180 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1184 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1185 /* Select the correct texture stage */
1186 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1189 if (This->stateBlock->textures[textureNo] != NULL) {
1190 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1192 if (coordIdx >= MAX_TEXTURES) {
1193 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1194 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1195 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1197 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1198 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1199 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1200 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1203 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1204 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1205 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1206 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1207 checkGLcall("glBindBufferARB");
1208 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1210 /* The coords to supply depend completely on the fvf / vertex shader */
1212 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1213 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1214 sd->u.s.texCoords[coordIdx].dwStride,
1215 sd->u.s.texCoords[coordIdx].lpData);
1216 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1218 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1220 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1222 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1224 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1225 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1226 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1227 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1228 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1233 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1234 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1237 if (idxData != NULL /* This crashes sometimes!*/) {
1238 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1239 idxData = idxData == (void *)-1 ? NULL : idxData;
1242 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1243 glEnableClientState(GL_INDEX_ARRAY);
1245 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1246 (const char *)idxData+(idxSize * startIdx));
1247 #else /* using drawRangeElements may be faster */
1249 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1250 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1251 (const char *)idxData+(idxSize * startIdx));
1253 checkGLcall("glDrawRangeElements");
1257 /* Note first is now zero as we shuffled along earlier */
1258 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1259 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1260 checkGLcall("glDrawArrays");
1268 * Actually draw using the supplied information.
1269 * Slower GL version which extracts info about each vertex in turn
1272 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1273 UINT NumVertexes, GLenum glPrimType,
1274 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1276 unsigned int textureNo = 0;
1277 unsigned int texture_idx = 0;
1278 const short *pIdxBufS = NULL;
1279 const long *pIdxBufL = NULL;
1280 LONG SkipnStrides = 0;
1282 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1283 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1284 float rhw = 0.0f; /* rhw */
1285 float ptSize = 0.0f; /* Point size */
1286 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1287 DWORD specularColor = 0; /* Specular Color */
1288 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1290 TRACE("Using slow vertex array code\n");
1292 /* Variable Initialization */
1293 if (idxData != NULL) {
1294 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1295 else pIdxBufL = (const long *) idxData;
1298 /* Start drawing in GL */
1299 VTRACE(("glBegin(%x)\n", glPrimType));
1300 glBegin(glPrimType);
1302 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1303 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1306 /* For each primitive */
1307 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1309 /* Initialize diffuse color */
1310 diffuseColor = 0xFFFFFFFF;
1312 /* For indexed data, we need to go a few more strides in */
1313 if (idxData != NULL) {
1315 /* Indexed so work out the number of strides to skip */
1317 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1318 SkipnStrides = pIdxBufS[startIdx + vx_index];
1320 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1321 SkipnStrides = pIdxBufL[startIdx + vx_index];
1325 /* Position Information ------------------ */
1326 if (sd->u.s.position.lpData != NULL) {
1328 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1333 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1335 /* RHW follows, only if transformed, ie 4 floats were provided */
1336 if (sd->u.s.position_transformed) {
1337 rhw = ptrToCoords[3];
1338 VTRACE(("rhw=%f\n", rhw));
1342 /* Blending data -------------------------- */
1343 if (sd->u.s.blendWeights.lpData != NULL) {
1344 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1345 FIXME("Blending not supported yet\n");
1347 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1348 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1352 /* Vertex Normal Data (untransformed only)- */
1353 if (sd->u.s.normal.lpData != NULL) {
1355 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1356 nx = ptrToCoords[0];
1357 ny = ptrToCoords[1];
1358 nz = ptrToCoords[2];
1359 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1362 /* Point Size ----------------------------- */
1363 if (sd->u.s.pSize.lpData != NULL) {
1365 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1366 ptSize = ptrToCoords[0];
1367 VTRACE(("ptSize=%f\n", ptSize));
1368 FIXME("No support for ptSize yet\n");
1371 /* Diffuse -------------------------------- */
1372 if (sd->u.s.diffuse.lpData != NULL) {
1374 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1375 diffuseColor = ptrToCoords[0];
1376 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1379 /* Specular -------------------------------- */
1380 if (sd->u.s.specular.lpData != NULL) {
1382 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1383 specularColor = ptrToCoords[0];
1384 VTRACE(("specularColor=%lx\n", specularColor));
1387 /* Texture coords --------------------------- */
1388 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1390 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1391 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1395 /* Query tex coords */
1396 if (This->stateBlock->textures[textureNo] != NULL) {
1398 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1399 float *ptrToCoords = NULL;
1400 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1403 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1406 } else if (coordIdx < 0) {
1407 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1412 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1413 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1414 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1419 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1421 /* The coords to supply depend completely on the fvf / vertex shader */
1422 switch (coordsToUse) {
1423 case 4: q = ptrToCoords[3]; /* drop through */
1424 case 3: r = ptrToCoords[2]; /* drop through */
1425 case 2: t = ptrToCoords[1]; /* drop through */
1426 case 1: s = ptrToCoords[0];
1429 /* Projected is more 'fun' - Move the last coord to the 'q'
1430 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1431 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1432 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1434 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1435 switch (coordsToUse) {
1436 case 0: /* Drop Through */
1438 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1450 case 4: /* Nop here */
1453 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1454 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1459 switch (coordsToUse) { /* Supply the provided texture coords */
1460 case D3DTTFF_COUNT1:
1461 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1462 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1463 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1468 case D3DTTFF_COUNT2:
1469 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1470 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1471 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1476 case D3DTTFF_COUNT3:
1477 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1478 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1479 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1481 glTexCoord3f(s, t, r);
1484 case D3DTTFF_COUNT4:
1485 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1486 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1487 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1489 glTexCoord4f(s, t, r, q);
1493 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1497 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1498 } /* End of textures */
1500 /* Diffuse -------------------------------- */
1501 if (sd->u.s.diffuse.lpData != NULL) {
1502 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1503 D3DCOLOR_B_G(diffuseColor),
1504 D3DCOLOR_B_B(diffuseColor),
1505 D3DCOLOR_B_A(diffuseColor));
1506 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1507 D3DCOLOR_B_R(diffuseColor),
1508 D3DCOLOR_B_G(diffuseColor),
1509 D3DCOLOR_B_B(diffuseColor),
1510 D3DCOLOR_B_A(diffuseColor)));
1512 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1515 /* Specular ------------------------------- */
1516 if (sd->u.s.specular.lpData != NULL) {
1517 /* special case where the fog density is stored in the diffuse alpha channel */
1518 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1519 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
1520 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1521 if(GL_SUPPORT(EXT_FOG_COORD)) {
1522 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1524 static BOOL warned = FALSE;
1526 /* TODO: Use the fog table code from old ddraw */
1527 FIXME("Implement fog for transformed vertices in software\n");
1533 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1534 D3DCOLOR_B_R(specularColor),
1535 D3DCOLOR_B_G(specularColor),
1536 D3DCOLOR_B_B(specularColor)));
1537 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1538 GL_EXTCALL(glSecondaryColor3ubEXT)(
1539 D3DCOLOR_B_R(specularColor),
1540 D3DCOLOR_B_G(specularColor),
1541 D3DCOLOR_B_B(specularColor));
1543 /* Do not worry if specular colour missing and disable request */
1544 VTRACE(("Specular color extensions not supplied\n"));
1547 if (vx_index == 0) {
1548 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1549 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1551 /* Do not worry if specular colour missing and disable request */
1552 VTRACE(("Specular color extensions not supplied\n"));
1557 /* Normal -------------------------------- */
1558 if (sd->u.s.normal.lpData != NULL) {
1559 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1560 glNormal3f(nx, ny, nz);
1562 if (vx_index == 0) glNormal3f(0, 0, 1);
1565 /* Position -------------------------------- */
1566 if (sd->u.s.position.lpData != NULL) {
1567 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1568 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1569 glVertex3f(x, y, z);
1571 GLfloat w = 1.0 / rhw;
1572 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1573 glVertex4f(x*w, y*w, z*w, w);
1577 /* For non indexed mode, step onto next parts */
1578 if (idxData == NULL) {
1584 checkGLcall("glEnd and previous calls");
1587 #if 0 /* TODO: Software/Hardware vertex blending support */
1589 * Draw with emulated vertex shaders
1590 * Note: strided data is uninitialized, as we need to pass the vertex
1591 * shader directly as ordering irs yet
1593 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1594 int PrimitiveType, ULONG NumPrimitives,
1595 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1597 unsigned int textureNo = 0;
1598 GLenum glPrimType = GL_POINTS;
1599 int NumVertexes = NumPrimitives;
1600 const short *pIdxBufS = NULL;
1601 const long *pIdxBufL = NULL;
1602 LONG SkipnStrides = 0;
1604 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1605 float rhw = 0.0f; /* rhw */
1606 float ptSize = 0.0f; /* Point size */
1607 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1608 int numcoords[8]; /* Number of coords */
1609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1611 IDirect3DVertexShaderImpl* vertexShader = NULL;
1613 TRACE("Using slow software vertex shader code\n");
1615 /* Variable Initialization */
1616 if (idxData != NULL) {
1617 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1618 else pIdxBufL = (const long *) idxData;
1621 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1622 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1624 /* Retrieve the VS information */
1625 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1627 /* Start drawing in GL */
1628 VTRACE(("glBegin(%x)\n", glPrimType));
1629 glBegin(glPrimType);
1631 /* For each primitive */
1632 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1634 /* For indexed data, we need to go a few more strides in */
1635 if (idxData != NULL) {
1637 /* Indexed so work out the number of strides to skip */
1639 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1640 SkipnStrides = pIdxBufS[startIdx+vx_index];
1642 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1643 SkipnStrides = pIdxBufL[startIdx+vx_index];
1647 /* Fill the vertex shader input */
1648 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1650 /* Initialize the output fields to the same defaults as it would normally have */
1651 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1652 vertexShader->output.oD[0].x = 1.0;
1653 vertexShader->output.oD[0].y = 1.0;
1654 vertexShader->output.oD[0].z = 1.0;
1655 vertexShader->output.oD[0].w = 1.0;
1657 /* Now execute the vertex shader */
1658 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1661 TRACE_VECTOR(vertexShader->output.oPos);
1662 TRACE_VECTOR(vertexShader->output.oD[0]);
1663 TRACE_VECTOR(vertexShader->output.oD[1]);
1664 TRACE_VECTOR(vertexShader->output.oT[0]);
1665 TRACE_VECTOR(vertexShader->output.oT[1]);
1666 TRACE_VECTOR(vertexShader->input.V[0]);
1667 TRACE_VECTOR(vertexShader->data->C[0]);
1668 TRACE_VECTOR(vertexShader->data->C[1]);
1669 TRACE_VECTOR(vertexShader->data->C[2]);
1670 TRACE_VECTOR(vertexShader->data->C[3]);
1671 TRACE_VECTOR(vertexShader->data->C[4]);
1672 TRACE_VECTOR(vertexShader->data->C[5]);
1673 TRACE_VECTOR(vertexShader->data->C[6]);
1674 TRACE_VECTOR(vertexShader->data->C[7]);
1677 /* Extract out the output */
1678 /* FIXME: Fog coords? */
1679 x = vertexShader->output.oPos.x;
1680 y = vertexShader->output.oPos.y;
1681 z = vertexShader->output.oPos.z;
1682 rhw = vertexShader->output.oPos.w;
1683 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1685 /** Update textures coords using vertexShader->output.oT[0->7] */
1686 memset(texcoords, 0x00, sizeof(texcoords));
1687 memset(numcoords, 0x00, sizeof(numcoords));
1688 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1689 if (This->stateBlock->textures[textureNo] != NULL) {
1690 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1691 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1692 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1693 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1694 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1695 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1697 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1698 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1699 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1700 default: numcoords[textureNo] = 4;
1704 numcoords[textureNo] = 0;
1708 /* Draw using this information */
1711 TRUE, 0.0f, 0.0f, 1.0f,
1712 TRUE, (float*) &vertexShader->output.oD[0],
1713 TRUE, (float*) &vertexShader->output.oD[1],
1714 FALSE, ptSize, /* FIXME: Change back when supported */
1715 texcoords, numcoords);
1717 /* For non indexed mode, step onto next parts */
1718 if (idxData == NULL) {
1722 } /* for each vertex */
1725 checkGLcall("glEnd and previous calls");
1730 inline static void drawPrimitiveDrawStrided(
1731 IWineD3DDevice *iface,
1732 BOOL useVertexShaderFunction,
1733 BOOL usePixelShaderFunction,
1734 WineDirect3DVertexStridedData *dataLocations,
1735 UINT numberOfvertices,
1736 UINT numberOfIndicies,
1738 const void *idxData,
1744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1745 BOOL useDrawStridedSlow;
1747 int startStride = idxData == NULL ? 0 :
1748 idxData == (void *) -1 ? 0 :
1749 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1750 int endStride = startStride;
1751 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1752 startStride, endStride, numberOfIndicies, numberOfvertices);
1754 /* Generate some fixme's if unsupported functionality is being used */
1755 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1756 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1757 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1758 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1760 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1761 FIXME("Tweening is only valid with vertex shaders\n");
1763 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1764 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1766 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1767 FIXME("Extended attributes are only valid with vertex shaders\n");
1769 #undef BUFFER_OR_DATA
1771 /* Fixed pipeline, no fixups required - load arrays */
1772 if (!useVertexShaderFunction &&
1773 ((dataLocations->u.s.pSize.lpData == NULL &&
1774 dataLocations->u.s.diffuse.lpData == NULL &&
1775 dataLocations->u.s.specular.lpData == NULL) ||
1778 /* Load the vertex data using named arrays */
1779 TRACE("(%p) Loading vertex data\n", This);
1780 loadVertexData(iface, dataLocations);
1781 useDrawStridedSlow = FALSE;
1783 /* Shader pipeline - load attribute arrays */
1784 } else if(useVertexShaderFunction) {
1786 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1787 useDrawStridedSlow = FALSE;
1789 /* We compile the shader here because we need the vertex declaration
1790 * in order to determine if we need to do any swizzling for D3DCOLOR
1791 * registers. If the shader is already compiled this call will do nothing. */
1792 IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1793 /* Draw vertex by vertex */
1795 TRACE("Not loading vertex data\n");
1796 useDrawStridedSlow = TRUE;
1799 if(usePixelShaderFunction) {
1800 /* We compile the shader here because it depends on the texture stage state
1801 * setup of the bound textures. If the shader is already compiled and the texture stage
1802 * state setup matches the program this function will do nothing
1804 IWineD3DPixelShader_CompileShader(This->stateBlock->pixelShader);
1806 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1807 * Otherwise set NULL, to restore fixed function */
1808 if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1809 (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1810 set_glsl_shader_program(iface);
1812 This->stateBlock->glsl_program = NULL;
1814 /* If GLSL is used now, or might have been used before, (re)set the program */
1815 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
1816 wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1818 GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
1820 TRACE_(d3d_shader)("Using GLSL program %u\n", progId);
1821 GL_EXTCALL(glUseProgramObjectARB(progId));
1822 checkGLcall("glUseProgramObjectARB");
1825 if (useVertexShaderFunction) {
1827 TRACE("Using vertex shader\n");
1829 if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1830 /* Bind the vertex program */
1831 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1832 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1833 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1835 /* Enable OpenGL vertex programs */
1836 glEnable(GL_VERTEX_PROGRAM_ARB);
1837 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1838 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1839 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1843 if (usePixelShaderFunction) {
1845 TRACE("Using pixel shader\n");
1847 if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1848 /* Bind the fragment program */
1849 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1850 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1851 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1853 /* Enable OpenGL fragment programs */
1854 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1855 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1856 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1857 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1861 /* Load any global constants/uniforms that may have been set by the application */
1862 if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
1863 shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1864 else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
1865 shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1867 /* Draw vertex-by-vertex */
1868 if (useDrawStridedSlow)
1869 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1871 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1873 /* Cleanup vertex program */
1874 if (useVertexShaderFunction) {
1875 unloadNumberedArrays(iface);
1877 if (wined3d_settings.vs_selected_mode == SHADER_ARB)
1878 glDisable(GL_VERTEX_PROGRAM_ARB);
1880 unloadVertexData(iface);
1883 /* Cleanup fragment program */
1884 if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB)
1885 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1888 inline void drawPrimitiveTraceDataLocations(
1889 WineDirect3DVertexStridedData *dataLocations) {
1891 /* Dump out what parts we have supplied */
1892 TRACE("Strided Data:\n");
1893 TRACE_STRIDED((dataLocations), position);
1894 TRACE_STRIDED((dataLocations), blendWeights);
1895 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1896 TRACE_STRIDED((dataLocations), normal);
1897 TRACE_STRIDED((dataLocations), pSize);
1898 TRACE_STRIDED((dataLocations), diffuse);
1899 TRACE_STRIDED((dataLocations), specular);
1900 TRACE_STRIDED((dataLocations), texCoords[0]);
1901 TRACE_STRIDED((dataLocations), texCoords[1]);
1902 TRACE_STRIDED((dataLocations), texCoords[2]);
1903 TRACE_STRIDED((dataLocations), texCoords[3]);
1904 TRACE_STRIDED((dataLocations), texCoords[4]);
1905 TRACE_STRIDED((dataLocations), texCoords[5]);
1906 TRACE_STRIDED((dataLocations), texCoords[6]);
1907 TRACE_STRIDED((dataLocations), texCoords[7]);
1908 TRACE_STRIDED((dataLocations), position2);
1909 TRACE_STRIDED((dataLocations), normal2);
1910 TRACE_STRIDED((dataLocations), tangent);
1911 TRACE_STRIDED((dataLocations), binormal);
1912 TRACE_STRIDED((dataLocations), tessFactor);
1913 TRACE_STRIDED((dataLocations), fog);
1914 TRACE_STRIDED((dataLocations), depth);
1915 TRACE_STRIDED((dataLocations), sample);
1921 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1924 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1925 /* Pixel shader support should imply multitexture support. */
1926 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1927 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1928 checkGLcall("glActiveTextureARB");
1930 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1933 if (!This->stateBlock->textures[i]) continue;
1935 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1936 glDisable(GL_TEXTURE_1D);
1937 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1938 switch(This->stateBlock->textureDimensions[i]) {
1940 glDisable(GL_TEXTURE_3D);
1941 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1944 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1945 glDisable(GL_TEXTURE_2D);
1947 case GLTEXTURECUBEMAP:
1948 glDisable(GL_TEXTURE_2D);
1949 glDisable(GL_TEXTURE_3D);
1952 glEnable(This->stateBlock->textureDimensions[i]);
1954 /* Upload texture, apply states */
1955 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1956 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1957 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1961 /* uploads textures and setup texture states ready for rendering */
1962 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1963 INT current_sampler = 0;
1964 float constant_color[4];
1967 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1968 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1969 * Register combiners however provide up to 8 combiner stages. In order to
1970 * take advantage of this, we need to be separate D3D texture stages from
1971 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1972 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1973 * corresponds to MaxTextureBlendStages in the caps. */
1975 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1976 glEnable(GL_REGISTER_COMBINERS_NV);
1977 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1978 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1981 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1982 INT texture_idx = -1;
1984 /* D3DTOP_DISABLE disables the current & any higher texture stages */
1985 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
1987 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1988 texture_idx = current_sampler++;
1990 /* Active the texture unit corresponding to the current texture stage */
1991 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1992 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1993 checkGLcall("glActiveTextureARB");
1995 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1999 if (This->stateBlock->textures[i]) {
2000 /* Enable the correct target. */
2001 glDisable(GL_TEXTURE_1D);
2002 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
2003 switch(This->stateBlock->textureDimensions[i]) {
2005 glDisable(GL_TEXTURE_3D);
2006 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2009 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2010 glDisable(GL_TEXTURE_2D);
2012 case GLTEXTURECUBEMAP:
2013 glDisable(GL_TEXTURE_2D);
2014 glDisable(GL_TEXTURE_3D);
2018 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2019 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
2020 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2022 glEnable(This->stateBlock->textureDimensions[i]);
2025 /* Upload texture, apply states */
2026 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2027 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
2028 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2029 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2030 /* ARB_texture_env_combine needs a valid texture bound to the
2031 * texture unit, even if it isn't used. Bind a dummy texture. */
2032 glDisable(GL_TEXTURE_2D);
2033 glDisable(GL_TEXTURE_3D);
2034 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2035 glEnable(GL_TEXTURE_1D);
2036 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2037 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2040 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2041 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2042 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2043 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2044 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2045 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2046 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
2049 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2050 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2051 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2052 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2055 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2056 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2057 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2058 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2060 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2061 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2062 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2063 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2067 /* If we're using register combiners, set the amount of *used* combiners.
2068 * Ie, the number of stages below the first stage to have a color op of
2069 * D3DTOP_DISABLE. */
2070 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2071 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2072 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2073 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2076 /* Disable the remaining texture units. */
2077 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2078 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2079 glDisable(GL_TEXTURE_1D);
2080 glDisable(GL_TEXTURE_2D);
2081 glDisable(GL_TEXTURE_3D);
2082 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2086 /* Routine common to the draw primitive and draw indexed primitive routines */
2087 void drawPrimitive(IWineD3DDevice *iface,
2091 long StartVertexIndex,
2092 UINT numberOfVertices,
2095 const void *idxData,
2097 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2100 BOOL useVertexShaderFunction = FALSE;
2101 BOOL usePixelShaderFunction = FALSE;
2102 WineDirect3DVertexStridedData *dataLocations;
2103 IWineD3DSwapChainImpl *swapchain;
2107 BOOL lighting_changed, lighting_original = FALSE;
2109 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2110 * here simply check whether a shader was set, or the user disabled shaders */
2111 if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2112 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2113 useVertexShaderFunction = TRUE;
2115 if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2116 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2117 usePixelShaderFunction = TRUE;
2119 /* Invalidate the back buffer memory so LockRect will read it the next time */
2120 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2121 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2123 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2124 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2128 /* Ok, we will be updating the screen from here onwards so grab the lock */
2131 if(DrawPrimStrideData) {
2133 /* Note: this is a ddraw fixed-function code path */
2135 TRACE("================ Strided Input ===================\n");
2136 dataLocations = DrawPrimStrideData;
2137 drawPrimitiveTraceDataLocations(dataLocations);
2141 else if (This->stateBlock->vertexDecl || This->stateBlock->vertexShader) {
2143 /* Note: This is a fixed function or shader codepath.
2144 * This means it must handle both types of strided data.
2145 * Shaders must go through here to zero the strided data, even if they
2146 * don't set any declaration at all */
2148 TRACE("================ Vertex Declaration ===================\n");
2149 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2150 if(!dataLocations) {
2151 ERR("Out of memory!\n");
2155 if (This->stateBlock->vertexDecl != NULL ||
2156 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2158 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2159 dataLocations, StartVertexIndex, &fixup);
2163 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2164 * It is reachable through d3d8, but only for fixed-function.
2165 * It will not work properly for shaders. */
2167 TRACE("================ FVF ===================\n");
2168 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2169 if(!dataLocations) {
2170 ERR("Out of memory!\n");
2173 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2174 drawPrimitiveTraceDataLocations(dataLocations);
2177 /* Setup transform matrices and sort out */
2178 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2180 /* Now initialize the materials state */
2181 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2183 if (usePixelShaderFunction) {
2184 drawPrimitiveUploadTexturesPS(This);
2186 drawPrimitiveUploadTextures(This);
2191 /* Ok, Work out which primitive is requested and how many vertexes that
2193 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2194 if (numberOfVertices == 0 )
2195 numberOfVertices = calculatedNumberOfindices;
2197 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2198 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2199 idxData, idxSize, minIndex, StartIdx, fixup);
2202 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2204 /* If vertex shaders or no normals, restore previous lighting state */
2205 if (lighting_changed) {
2206 if (lighting_original) glEnable(GL_LIGHTING);
2207 else glDisable(GL_LIGHTING);
2208 TRACE("Restored lighting to original state\n");
2211 /* Finshed updating the screen, restore lock */
2213 TRACE("Done all gl drawing\n");
2216 #ifdef SHOW_FRAME_MAKEUP
2218 static long int primCounter = 0;
2219 /* NOTE: set primCounter to the value reported by drawprim
2220 before you want to to write frame makeup to /tmp */
2221 if (primCounter >= 0) {
2222 WINED3DLOCKED_RECT r;
2224 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2225 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2226 TRACE("Saving screenshot %s\n", buffer);
2227 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2228 IWineD3DSurface_UnlockRect(This->renderTarget);
2230 #ifdef SHOW_TEXTURE_MAKEUP
2232 IWineD3DSurface *pSur;
2234 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2235 if (This->stateBlock->textures[textureNo] != NULL) {
2236 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2237 TRACE("Saving texture %s\n", buffer);
2238 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2239 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2240 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2241 IWineD3DSurface_Release(pSur);
2243 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2250 TRACE("drawprim #%ld\n", primCounter);