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(WINED3DPRIMITIVETYPE PrimitiveType,
46 DWORD NumVertexes = NumPrimitives;
48 switch (PrimitiveType) {
49 case WINED3DPT_POINTLIST:
51 *primType = GL_POINTS;
52 NumVertexes = NumPrimitives;
55 case WINED3DPT_LINELIST:
58 NumVertexes = NumPrimitives * 2;
61 case WINED3DPT_LINESTRIP:
62 TRACE("LINE_STRIP\n");
63 *primType = GL_LINE_STRIP;
64 NumVertexes = NumPrimitives + 1;
67 case WINED3DPT_TRIANGLELIST:
69 *primType = GL_TRIANGLES;
70 NumVertexes = NumPrimitives * 3;
73 case WINED3DPT_TRIANGLESTRIP:
74 TRACE("TRIANGLE_STRIP\n");
75 *primType = GL_TRIANGLE_STRIP;
76 NumVertexes = NumPrimitives + 2;
79 case WINED3DPT_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) ||
113 (This->tracking_color == NEEDS_TRACKING && !isDiffuseSupplied)) {
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 /* D3D texture coordinates are flipped compared to OpenGL ones, so
199 * render everything upside down when rendering offscreen. */
200 if (This->render_offscreen) {
201 glMultMatrixf(invymat);
202 checkGLcall("glMultMatrixf(invymat)");
205 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
206 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
207 if(GL_SUPPORT(EXT_FOG_COORD)) {
208 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
209 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
210 glFogi(GL_FOG_MODE, GL_LINEAR);
211 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
212 /* The dx fog range in this case is fixed to 0 - 255,
213 * but in GL it still depends on the fog start and end (according to the ext)
214 * Use this to turn around the fog as it's needed. That prevents some
215 * calculations during drawing :-)
217 glFogf(GL_FOG_START, (float) 0xff);
218 checkGLcall("glFogfv GL_FOG_END");
219 glFogf(GL_FOG_END, 0.0);
220 checkGLcall("glFogfv GL_FOG_START");
222 /* Disable GL fog, handle this in software in drawStridedSlow */
224 checkGLcall("glDisable(GL_FOG)");
229 /* Setup views - Transformed & lit if RHW, else untransformed.
230 Only unlit if Normals are supplied
231 Returns: Whether to restore lighting afterwards */
232 static void primitiveInitState(
233 IWineD3DDevice *iface,
234 WineDirect3DVertexStridedData* strided,
236 BOOL* lighting_changed,
237 BOOL* lighting_original) {
239 BOOL fixed_vtx_transformed =
240 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
241 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
242 strided->u.s.position_transformed;
245 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
246 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
250 *lighting_changed = FALSE;
252 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
253 set by the appropriate render state. Note Vertex Shader output is already lit */
254 if (fixed_vtx_lit || useVS) {
255 *lighting_changed = TRUE;
256 *lighting_original = glIsEnabled(GL_LIGHTING);
257 glDisable(GL_LIGHTING);
258 checkGLcall("glDisable(GL_LIGHTING);");
259 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
262 if (!useVS && fixed_vtx_transformed) {
263 d3ddevice_set_ortho(This);
267 /* Untransformed, so relies on the view and projection matrices */
268 This->untransformed = TRUE;
270 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
271 /* Only reapply when have to */
272 This->modelview_valid = TRUE;
273 glMatrixMode(GL_MODELVIEW);
274 checkGLcall("glMatrixMode");
276 /* In the general case, the view matrix is the identity matrix */
277 if (This->view_ident) {
278 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
279 checkGLcall("glLoadMatrixf");
281 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
282 checkGLcall("glLoadMatrixf");
283 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
284 checkGLcall("glMultMatrixf");
288 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
289 /* Only reapply when have to */
290 This->proj_valid = TRUE;
291 glMatrixMode(GL_PROJECTION);
292 checkGLcall("glMatrixMode");
294 /* The rule is that the window coordinate 0 does not correspond to the
295 beginning of the first pixel, but the center of the first pixel.
296 As a consequence if you want to correctly draw one line exactly from
297 the left to the right end of the viewport (with all matrices set to
298 be identity), the x coords of both ends of the line would be not
299 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
303 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
304 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
306 /* D3D texture coordinates are flipped compared to OpenGL ones, so
307 * render everything upside down when rendering offscreen. */
308 if (This->render_offscreen) {
309 glMultMatrixf(invymat);
310 checkGLcall("glMultMatrixf(invymat)");
312 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
313 checkGLcall("glLoadMatrixf");
316 /* Vertex Shader output is already transformed, so set up identity matrices */
318 This->posFixup[1] = This->render_offscreen ? -1.0 : 1.0;
319 This->posFixup[2] = 0.9 / This->stateBlock->viewport.Width;
320 This->posFixup[3] = -0.9 / This->stateBlock->viewport.Height;
322 This->last_was_rhw = FALSE;
325 if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
326 /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
327 * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
328 glFogi(GL_FOG_MODE, GL_LINEAR);
329 glFogf(GL_FOG_START, 1.0f);
330 glFogf(GL_FOG_END, 0.0f);
332 } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE]
333 && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
335 if(GL_SUPPORT(EXT_FOG_COORD)) {
336 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
337 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
338 /* Reapply the fog range */
339 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
340 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
341 /* Restore the fog mode */
342 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
344 /* Enable GL_FOG again because we disabled it above */
346 checkGLcall("glEnable(GL_FOG)");
352 static BOOL fixed_get_input(
353 BYTE usage, BYTE usage_idx,
354 unsigned int* regnum) {
358 /* Those positions must have the order in the
359 * named part of the strided data */
361 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
363 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
365 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
367 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
369 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
371 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
373 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
375 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
376 *regnum = 7 + usage_idx;
377 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
378 *regnum = 7 + WINED3DDP_MAXTEXCOORD;
379 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
380 *regnum = 8 + WINED3DDP_MAXTEXCOORD;
381 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
382 *regnum = 9 + WINED3DDP_MAXTEXCOORD;
383 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
384 *regnum = 10 + WINED3DDP_MAXTEXCOORD;
385 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
386 *regnum = 11 + WINED3DDP_MAXTEXCOORD;
387 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
388 *regnum = 12 + WINED3DDP_MAXTEXCOORD;
389 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
390 *regnum = 13 + WINED3DDP_MAXTEXCOORD;
391 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
392 *regnum = 14 + WINED3DDP_MAXTEXCOORD;
395 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
396 debug_d3ddeclusage(usage), usage_idx);
402 void primitiveDeclarationConvertToStridedData(
403 IWineD3DDevice *iface,
404 BOOL useVertexShaderFunction,
405 WineDirect3DVertexStridedData *strided,
406 LONG BaseVertexIndex,
409 /* We need to deal with frequency data!*/
412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
413 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
415 WINED3DVERTEXELEMENT *element;
419 /* Locate the vertex declaration */
420 if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
421 TRACE("Using vertex declaration from shader\n");
422 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
424 TRACE("Using vertex declaration\n");
425 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
428 /* Translate the declaration into strided data */
429 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
434 element = vertexDeclaration->pDeclarationWine + i;
435 TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
436 element, i + 1, vertexDeclaration->declarationWNumElements - 1);
438 if (This->stateBlock->streamSource[element->Stream] == NULL)
441 if (This->stateBlock->streamIsUP) {
442 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
444 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
445 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
447 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
448 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
449 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
451 if( streamVBO != 0) *fixup = TRUE;
452 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
455 stride = This->stateBlock->streamStride[element->Stream];
456 data += (BaseVertexIndex * stride);
457 data += element->Offset;
460 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
462 if (useVertexShaderFunction)
463 stride_used = vshader_get_input(This->stateBlock->vertexShader,
464 element->Usage, element->UsageIndex, &idx);
466 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
469 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
470 "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
471 useVertexShaderFunction? "shader": "fixed function", idx,
472 debug_d3ddeclusage(element->Usage), element->UsageIndex,
473 element->Stream, element->Offset, stride, streamVBO);
475 strided->u.input[idx].lpData = data;
476 strided->u.input[idx].dwType = element->Type;
477 strided->u.input[idx].dwStride = stride;
478 strided->u.input[idx].VBO = streamVBO;
479 if (!useVertexShaderFunction) {
480 if (element->Usage == D3DDECLUSAGE_POSITION)
481 strided->u.s.position_transformed = FALSE;
482 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
483 strided->u.s.position_transformed = TRUE;
489 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
493 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
494 int numCoords[8]; /* Holding place for WINED3DFVF_TEXTUREFORMATx */
496 /* Either 3 or 4 floats depending on the FVF */
497 /* FIXME: Can blending data be in a different stream to the position data?
498 and if so using the fixed pipeline how do we handle it */
499 if (thisFVF & WINED3DFVF_POSITION_MASK) {
500 strided->u.s.position.lpData = data;
501 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
502 strided->u.s.position.dwStride = stride;
503 strided->u.s.position.VBO = streamVBO;
504 data += 3 * sizeof(float);
505 if (thisFVF & WINED3DFVF_XYZRHW) {
506 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
507 strided->u.s.position_transformed = TRUE;
508 data += sizeof(float);
510 strided->u.s.position_transformed = FALSE;
513 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
514 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
515 numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
516 if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
518 if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
519 TRACE("Setting blend Weights to %p\n", data);
520 strided->u.s.blendWeights.lpData = data;
521 strided->u.s.blendWeights.dwType = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
522 strided->u.s.blendWeights.dwStride = stride;
523 strided->u.s.blendWeights.VBO = streamVBO;
524 data += numBlends * sizeof(FLOAT);
526 if (thisFVF & WINED3DFVF_LASTBETA_UBYTE4) {
527 strided->u.s.blendMatrixIndices.lpData = data;
528 strided->u.s.blendMatrixIndices.dwType = WINED3DDECLTYPE_UBYTE4;
529 strided->u.s.blendMatrixIndices.dwStride= stride;
530 strided->u.s.blendMatrixIndices.VBO = streamVBO;
531 data += sizeof(DWORD);
535 /* Normal is always 3 floats */
536 if (thisFVF & WINED3DFVF_NORMAL) {
537 strided->u.s.normal.lpData = data;
538 strided->u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
539 strided->u.s.normal.dwStride = stride;
540 strided->u.s.normal.VBO = streamVBO;
541 data += 3 * sizeof(FLOAT);
544 /* Pointsize is a single float */
545 if (thisFVF & WINED3DFVF_PSIZE) {
546 strided->u.s.pSize.lpData = data;
547 strided->u.s.pSize.dwType = WINED3DDECLTYPE_FLOAT1;
548 strided->u.s.pSize.dwStride = stride;
549 strided->u.s.pSize.VBO = streamVBO;
550 data += sizeof(FLOAT);
553 /* Diffuse is 4 unsigned bytes */
554 if (thisFVF & WINED3DFVF_DIFFUSE) {
555 strided->u.s.diffuse.lpData = data;
556 strided->u.s.diffuse.dwType = WINED3DDECLTYPE_SHORT4;
557 strided->u.s.diffuse.dwStride = stride;
558 strided->u.s.diffuse.VBO = streamVBO;
559 data += sizeof(DWORD);
562 /* Specular is 4 unsigned bytes */
563 if (thisFVF & WINED3DFVF_SPECULAR) {
564 strided->u.s.specular.lpData = data;
565 strided->u.s.specular.dwType = WINED3DDECLTYPE_SHORT4;
566 strided->u.s.specular.dwStride = stride;
567 strided->u.s.specular.VBO = streamVBO;
568 data += sizeof(DWORD);
572 numTextures = (thisFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
573 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
575 /* numTextures indicates the number of texture coordinates supplied */
576 /* However, the first set may not be for stage 0 texture - it all */
577 /* depends on WINED3DTSS_TEXCOORDINDEX. */
578 /* The number of bytes for each coordinate set is based off */
579 /* WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
581 /* So, for each supplied texture extract the coords */
582 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
584 strided->u.s.texCoords[textureNo].lpData = data;
585 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT1;
586 strided->u.s.texCoords[textureNo].dwStride = stride;
587 strided->u.s.texCoords[textureNo].VBO = streamVBO;
588 numCoords[textureNo] = coordIdxInfo & 0x03;
591 data += sizeof(float);
592 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT1) {
593 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
594 data += sizeof(float);
595 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT2) {
596 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
597 data += sizeof(float);
598 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT3) {
599 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
600 data += sizeof(float);
604 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
608 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
610 short LoopThroughTo = 0;
614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
616 /* OK, Now to setup the data locations
617 For the non-created vertex shaders, the VertexShader var holds the real
618 FVF and only stream 0 matters
619 For the created vertex shaders, there is an FVF per stream */
620 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
621 LoopThroughTo = MAX_STREAMS;
626 /* Work through stream by stream */
627 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
628 DWORD stride = This->stateBlock->streamStride[nStream];
632 /* Skip empty streams */
633 if (This->stateBlock->streamSource[nStream] == NULL) continue;
635 /* Retrieve appropriate FVF */
636 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
637 thisFVF = This->stateBlock->fvf;
638 /* Handle memory passed directly as well as vertex buffers */
639 if (This->stateBlock->streamIsUP) {
641 data = (BYTE *)This->stateBlock->streamSource[nStream];
643 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
644 /* GetMemory binds the VBO */
645 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
647 if(streamVBO != 0 ) *fixup = TRUE;
651 #if 0 /* TODO: Vertex shader support */
652 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
653 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
656 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
657 if (thisFVF == 0) continue;
659 /* Now convert the stream into pointers */
661 /* Shuffle to the beginning of the vertexes to render and index from there */
662 data = data + (BaseVertexIndex * stride);
664 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
668 #if 0 /* TODO: Software Shaders */
669 /* Draw a single vertex using this information */
670 static void draw_vertex(IWineD3DDevice *iface, /* interface */
671 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
672 BOOL isNormal, float nx, float ny, float nz, /* normal */
673 BOOL isDiffuse, float *dRGBA, /* 1st colors */
674 BOOL isSpecular, float *sRGB, /* 2ndry colors */
675 BOOL isPtSize, float ptSize, /* pointSize */
676 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
678 unsigned int textureNo;
680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
682 /* Diffuse -------------------------------- */
685 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
688 /* Specular Colour ------------------------------------------*/
690 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
691 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
692 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
694 VTRACE(("Specular color extensions not supplied\n"));
698 /* Normal -------------------------------- */
700 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
701 glNormal3f(nx, ny, nz);
704 /* Point Size ----------------------------------------------*/
707 /* no such functionality in the fixed function GL pipeline */
708 FIXME("Cannot change ptSize here in openGl\n");
711 /* Texture coords --------------------------- */
712 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
714 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
715 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
719 /* Query tex coords */
720 if (This->stateBlock->textures[textureNo] != NULL) {
722 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
723 if (coordIdx >= MAX_TEXTURES) {
724 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
726 } else if (numcoords[coordIdx] == 0) {
727 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
731 /* Initialize vars */
737 switch (numcoords[coordIdx]) {
738 case 4: q = texcoords[coordIdx].w; /* drop through */
739 case 3: r = texcoords[coordIdx].z; /* drop through */
740 case 2: t = texcoords[coordIdx].y; /* drop through */
741 case 1: s = texcoords[coordIdx].x;
744 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
745 case WINED3DTTFF_COUNT1:
746 VTRACE(("tex:%d, s=%f\n", textureNo, s));
747 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
748 GLMULTITEXCOORD1F(textureNo, s);
753 case WINED3DTTFF_COUNT2:
754 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
755 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
756 GLMULTITEXCOORD2F(textureNo, s, t);
761 case WINED3DTTFF_COUNT3:
762 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
763 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
764 GLMULTITEXCOORD3F(textureNo, s, t, r);
766 glTexCoord3f(s, t, r);
769 case WINED3DTTFF_COUNT4:
770 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
771 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
772 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
774 glTexCoord4f(s, t, r, q);
778 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
782 } /* End of textures */
784 /* Position -------------------------------- */
786 if (1.0f == rhw || rhw < 0.00001f) {
787 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
790 /* Cannot optimize by dividing through by rhw as rhw is required
791 later for perspective in the GL pipeline for vertex shaders */
792 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
793 glVertex4f(x,y,z,rhw);
797 #endif /* TODO: Software shaders */
799 /* This should match any arrays loaded in loadNumberedArrays. */
800 /* TODO: Only load / unload arrays if we have to. */
801 static void unloadNumberedArrays(IWineD3DDevice *iface) {
802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
804 /* disable any attribs (this is the same for both GLSL and ARB modes) */
808 /* Leave all the attribs disabled */
809 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
810 /* MESA does not support it right not */
811 if (glGetError() != GL_NO_ERROR)
813 for (i = 0; i < maxAttribs; ++i) {
814 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
815 checkGLcall("glDisableVertexAttribArrayARB(reg);");
819 /* TODO: Only load / unload arrays if we have to. */
820 static void loadNumberedArrays(
821 IWineD3DDevice *iface,
822 IWineD3DVertexShader *shader,
823 WineDirect3DVertexStridedData *strided) {
825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
826 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
829 for (i = 0; i < MAX_ATTRIBS; i++) {
831 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
834 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
836 if(curVBO != strided->u.input[i].VBO) {
837 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
838 checkGLcall("glBindBufferARB");
839 curVBO = strided->u.input[i].VBO;
841 GL_EXTCALL(glVertexAttribPointerARB(i,
842 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
843 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
844 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
845 strided->u.input[i].dwStride,
846 strided->u.input[i].lpData));
847 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
851 /* This should match any arrays loaded in loadVertexData. */
852 /* TODO: Only load / unload arrays if we have to. */
853 static void unloadVertexData(IWineD3DDevice *iface) {
854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
857 glDisableClientState(GL_VERTEX_ARRAY);
858 glDisableClientState(GL_NORMAL_ARRAY);
859 glDisableClientState(GL_COLOR_ARRAY);
860 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
861 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
863 for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
864 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
865 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
869 /* TODO: Only load / unload arrays if we have to. */
870 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
871 unsigned int textureNo = 0;
872 unsigned int texture_idx = 0;
873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
874 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
876 TRACE("Using fast vertex array code\n");
877 /* Blend Data ---------------------------------------------- */
878 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
879 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
882 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
885 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
886 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
889 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
890 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
891 /* FIXME("TODO\n");*/
892 /* Note dwType == float3 or float4 == 2 or 3 */
895 /* with this on, the normals appear to be being modified,
896 but the vertices aren't being translated as they should be
897 Maybe the world matrix aren't being setup properly? */
898 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
902 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
903 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
904 sd->u.s.blendWeights.dwStride,
905 sd->u.s.blendWeights.lpData));
907 if(curVBO != sd->u.s.blendWeights.VBO) {
908 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
909 checkGLcall("glBindBufferARB");
910 curVBO = sd->u.s.blendWeights.VBO;
913 GL_EXTCALL(glWeightPointerARB)(
914 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
915 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
916 sd->u.s.blendWeights.dwStride,
917 sd->u.s.blendWeights.lpData);
919 checkGLcall("glWeightPointerARB");
921 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
922 static BOOL showfixme = TRUE;
924 FIXME("blendMatrixIndices support\n");
929 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
930 /* FIXME("TODO\n");*/
933 GL_EXTCALL(glVertexWeightPointerEXT)(
934 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
935 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
936 sd->u.s.blendWeights.dwStride,
937 sd->u.s.blendWeights.lpData);
938 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
939 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
940 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
944 /* TODO: support blends in fixupVertices */
945 FIXME("unsupported blending in openGl\n");
948 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
949 #if 0 /* TODO: Vertex blending */
950 glDisable(GL_VERTEX_BLEND_ARB);
952 TRACE("ARB_VERTEX_BLEND\n");
953 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
954 TRACE(" EXT_VERTEX_WEIGHTING\n");
955 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
956 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
961 #if 0 /* FOG ----------------------------------------------*/
962 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
964 if (GL_SUPPORT(EXT_FOG_COORD) {
965 glEnableClientState(GL_FOG_COORDINATE_EXT);
966 (GL_EXTCALL)(FogCoordPointerEXT)(
967 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
968 sd->u.s.fog.dwStride,
971 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
972 /* FIXME: fixme once */
973 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
976 if (GL_SUPPRT(EXT_FOR_COORD) {
977 /* make sure fog is disabled */
978 glDisableClientState(GL_FOG_COORDINATE_EXT);
983 #if 0 /* tangents ----------------------------------------------*/
984 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
985 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
987 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
988 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
989 glEnable(GL_TANGENT_ARRAY_EXT);
990 (GL_EXTCALL)(TangentPointerEXT)(
991 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
992 sd->u.s.tangent.dwStride,
993 sd->u.s.tangent.lpData);
995 glDisable(GL_TANGENT_ARRAY_EXT);
997 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
998 glEnable(GL_BINORMAL_ARRAY_EXT);
999 (GL_EXTCALL)(BinormalPointerEXT)(
1000 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
1001 sd->u.s.binormal.dwStride,
1002 sd->u.s.binormal.lpData);
1004 glDisable(GL_BINORMAL_ARRAY_EXT);
1008 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1009 /* FIXME: fixme once */
1010 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1013 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1014 /* make sure fog is disabled */
1015 glDisable(GL_TANGENT_ARRAY_EXT);
1016 glDisable(GL_BINORMAL_ARRAY_EXT);
1021 /* Point Size ----------------------------------------------*/
1022 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
1024 /* no such functionality in the fixed function GL pipeline */
1025 TRACE("Cannot change ptSize here in openGl\n");
1026 /* TODO: Implement this function in using shaders if they are available */
1030 /* Vertex Pointers -----------------------------------------*/
1031 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
1032 /* Note dwType == float3 or float4 == 2 or 3 */
1033 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
1034 sd->u.s.position.dwStride,
1035 sd->u.s.position.dwType + 1,
1036 sd->u.s.position.lpData));
1038 if(curVBO != sd->u.s.position.VBO) {
1039 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1040 checkGLcall("glBindBufferARB");
1041 curVBO = sd->u.s.position.VBO;
1044 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1045 handling for rhw mode should not impact screen position whereas in GL it does.
1046 This may result in very slightly distored textures in rhw mode, but
1047 a very minimal different. There's always the other option of
1048 fixing the view matrix to prevent w from having any effect
1050 This only applies to user pointer sources, in VBOs the vertices are fixed up
1052 if(sd->u.s.position.VBO == 0) {
1053 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1054 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1055 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1058 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1059 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1060 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1062 checkGLcall("glVertexPointer(...)");
1063 glEnableClientState(GL_VERTEX_ARRAY);
1064 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1067 glDisableClientState(GL_VERTEX_ARRAY);
1068 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1071 /* Normals -------------------------------------------------*/
1072 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1073 /* Note dwType == float3 or float4 == 2 or 3 */
1074 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
1075 sd->u.s.normal.dwStride,
1076 sd->u.s.normal.lpData));
1077 if(curVBO != sd->u.s.normal.VBO) {
1078 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1079 checkGLcall("glBindBufferARB");
1080 curVBO = sd->u.s.normal.VBO;
1083 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1084 sd->u.s.normal.dwStride,
1085 sd->u.s.normal.lpData);
1086 checkGLcall("glNormalPointer(...)");
1087 glEnableClientState(GL_NORMAL_ARRAY);
1088 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1091 glDisableClientState(GL_NORMAL_ARRAY);
1092 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1093 glNormal3f(0, 0, 1);
1094 checkGLcall("glNormal3f(0, 0, 1)");
1097 /* Diffuse Colour --------------------------------------------*/
1098 /* WARNING: Data here MUST be in RGBA format, so cannot */
1099 /* go directly into fast mode from app pgm, because */
1100 /* directx requires data in BGRA format. */
1101 /* currently fixupVertices swizels the format, but this isn't */
1102 /* very practical when using VBOS */
1103 /* NOTE: Unless we write a vertex shader to swizel the colour */
1104 /* , or the user doesn't care and wants the speed advantage */
1106 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1107 /* Note dwType == float3 or float4 == 2 or 3 */
1108 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1109 sd->u.s.diffuse.dwStride,
1110 sd->u.s.diffuse.lpData));
1112 if(curVBO != sd->u.s.diffuse.VBO) {
1113 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1114 checkGLcall("glBindBufferARB");
1115 curVBO = sd->u.s.diffuse.VBO;
1117 glColorPointer(4, GL_UNSIGNED_BYTE,
1118 sd->u.s.diffuse.dwStride,
1119 sd->u.s.diffuse.lpData);
1120 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1121 glEnableClientState(GL_COLOR_ARRAY);
1122 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1125 glDisableClientState(GL_COLOR_ARRAY);
1126 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1127 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1128 checkGLcall("glColor4f(1, 1, 1, 1)");
1131 /* Specular Colour ------------------------------------------*/
1132 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1133 TRACE("setting specular colour\n");
1134 /* Note dwType == float3 or float4 == 2 or 3 */
1135 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1136 sd->u.s.specular.dwStride,
1137 sd->u.s.specular.lpData));
1138 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1139 if(curVBO != sd->u.s.specular.VBO) {
1140 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1141 checkGLcall("glBindBufferARB");
1142 curVBO = sd->u.s.specular.VBO;
1144 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1145 sd->u.s.specular.dwStride,
1146 sd->u.s.specular.lpData);
1147 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1148 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1149 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1152 /* Missing specular color is not critical, no warnings */
1153 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1157 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1159 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1160 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1161 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1162 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1165 /* Missing specular color is not critical, no warnings */
1166 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1170 /* Texture coords -------------------------------------------*/
1172 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1173 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1174 /* Abort if we don't support the extension. */
1175 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1176 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1180 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1181 /* Select the correct texture stage */
1182 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1185 if (This->stateBlock->textures[textureNo] != NULL) {
1186 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1188 if (coordIdx >= MAX_TEXTURES) {
1189 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1190 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1191 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1193 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1194 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1195 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1196 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1199 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1200 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1201 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1202 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1203 checkGLcall("glBindBufferARB");
1204 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1206 /* The coords to supply depend completely on the fvf / vertex shader */
1208 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1209 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1210 sd->u.s.texCoords[coordIdx].dwStride,
1211 sd->u.s.texCoords[coordIdx].lpData);
1212 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1214 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1215 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1216 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1218 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1220 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1221 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1222 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1223 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1224 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1229 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1230 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1233 if (idxData != NULL /* This crashes sometimes!*/) {
1234 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1235 idxData = idxData == (void *)-1 ? NULL : idxData;
1238 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1239 glEnableClientState(GL_INDEX_ARRAY);
1241 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1242 (const char *)idxData+(idxSize * startIdx));
1243 #else /* using drawRangeElements may be faster */
1245 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1246 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1247 (const char *)idxData+(idxSize * startIdx));
1249 checkGLcall("glDrawRangeElements");
1253 /* Note first is now zero as we shuffled along earlier */
1254 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1255 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1256 checkGLcall("glDrawArrays");
1264 * Actually draw using the supplied information.
1265 * Slower GL version which extracts info about each vertex in turn
1268 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1269 UINT NumVertexes, GLenum glPrimType,
1270 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1272 unsigned int textureNo = 0;
1273 unsigned int texture_idx = 0;
1274 const short *pIdxBufS = NULL;
1275 const long *pIdxBufL = NULL;
1276 LONG SkipnStrides = 0;
1278 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1279 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1280 float rhw = 0.0f; /* rhw */
1281 float ptSize = 0.0f; /* Point size */
1282 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1283 DWORD specularColor = 0; /* Specular Color */
1284 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1286 TRACE("Using slow vertex array code\n");
1288 /* Variable Initialization */
1289 if (idxData != NULL) {
1290 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1291 else pIdxBufL = (const long *) idxData;
1294 /* Start drawing in GL */
1295 VTRACE(("glBegin(%x)\n", glPrimType));
1296 glBegin(glPrimType);
1298 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1299 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1302 /* For each primitive */
1303 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1305 /* Initialize diffuse color */
1306 diffuseColor = 0xFFFFFFFF;
1308 /* For indexed data, we need to go a few more strides in */
1309 if (idxData != NULL) {
1311 /* Indexed so work out the number of strides to skip */
1313 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1314 SkipnStrides = pIdxBufS[startIdx + vx_index];
1316 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1317 SkipnStrides = pIdxBufL[startIdx + vx_index];
1321 /* Position Information ------------------ */
1322 if (sd->u.s.position.lpData != NULL) {
1324 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1329 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1331 /* RHW follows, only if transformed, ie 4 floats were provided */
1332 if (sd->u.s.position_transformed) {
1333 rhw = ptrToCoords[3];
1334 VTRACE(("rhw=%f\n", rhw));
1338 /* Blending data -------------------------- */
1339 if (sd->u.s.blendWeights.lpData != NULL) {
1340 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1341 FIXME("Blending not supported yet\n");
1343 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1344 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1348 /* Vertex Normal Data (untransformed only)- */
1349 if (sd->u.s.normal.lpData != NULL) {
1351 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1352 nx = ptrToCoords[0];
1353 ny = ptrToCoords[1];
1354 nz = ptrToCoords[2];
1355 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1358 /* Point Size ----------------------------- */
1359 if (sd->u.s.pSize.lpData != NULL) {
1361 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1362 ptSize = ptrToCoords[0];
1363 VTRACE(("ptSize=%f\n", ptSize));
1364 FIXME("No support for ptSize yet\n");
1367 /* Diffuse -------------------------------- */
1368 if (sd->u.s.diffuse.lpData != NULL) {
1370 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1371 diffuseColor = ptrToCoords[0];
1372 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1375 /* Specular -------------------------------- */
1376 if (sd->u.s.specular.lpData != NULL) {
1378 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1379 specularColor = ptrToCoords[0];
1380 VTRACE(("specularColor=%lx\n", specularColor));
1383 /* Texture coords --------------------------- */
1384 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1386 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1387 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1391 /* Query tex coords */
1392 if (This->stateBlock->textures[textureNo] != NULL) {
1394 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1395 float *ptrToCoords = NULL;
1396 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1399 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1402 } else if (coordIdx < 0) {
1403 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1408 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1409 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1410 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1415 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
1417 /* The coords to supply depend completely on the fvf / vertex shader */
1418 switch (coordsToUse) {
1419 case 4: q = ptrToCoords[3]; /* drop through */
1420 case 3: r = ptrToCoords[2]; /* drop through */
1421 case 2: t = ptrToCoords[1]; /* drop through */
1422 case 1: s = ptrToCoords[0];
1425 /* Projected is more 'fun' - Move the last coord to the 'q'
1426 parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
1427 if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
1428 (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
1430 if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
1431 switch (coordsToUse) {
1432 case 0: /* Drop Through */
1434 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
1446 case 4: /* Nop here */
1449 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
1450 This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
1455 switch (coordsToUse) { /* Supply the provided texture coords */
1456 case WINED3DTTFF_COUNT1:
1457 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1458 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1459 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1464 case WINED3DTTFF_COUNT2:
1465 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1466 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1467 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1472 case WINED3DTTFF_COUNT3:
1473 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1474 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1475 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1477 glTexCoord3f(s, t, r);
1480 case WINED3DTTFF_COUNT4:
1481 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1482 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1483 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1485 glTexCoord4f(s, t, r, q);
1489 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1493 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1494 } /* End of textures */
1496 /* Diffuse -------------------------------- */
1497 if (sd->u.s.diffuse.lpData != NULL) {
1498 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1499 D3DCOLOR_B_G(diffuseColor),
1500 D3DCOLOR_B_B(diffuseColor),
1501 D3DCOLOR_B_A(diffuseColor));
1502 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1503 D3DCOLOR_B_R(diffuseColor),
1504 D3DCOLOR_B_G(diffuseColor),
1505 D3DCOLOR_B_B(diffuseColor),
1506 D3DCOLOR_B_A(diffuseColor)));
1508 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1511 /* Specular ------------------------------- */
1512 if (sd->u.s.specular.lpData != NULL) {
1513 /* special case where the fog density is stored in the diffuse alpha channel */
1514 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1515 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
1516 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1517 if(GL_SUPPORT(EXT_FOG_COORD)) {
1518 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1520 static BOOL warned = FALSE;
1522 /* TODO: Use the fog table code from old ddraw */
1523 FIXME("Implement fog for transformed vertices in software\n");
1529 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1530 D3DCOLOR_B_R(specularColor),
1531 D3DCOLOR_B_G(specularColor),
1532 D3DCOLOR_B_B(specularColor)));
1533 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1534 GL_EXTCALL(glSecondaryColor3ubEXT)(
1535 D3DCOLOR_B_R(specularColor),
1536 D3DCOLOR_B_G(specularColor),
1537 D3DCOLOR_B_B(specularColor));
1539 /* Do not worry if specular colour missing and disable request */
1540 VTRACE(("Specular color extensions not supplied\n"));
1543 if (vx_index == 0) {
1544 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1545 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1547 /* Do not worry if specular colour missing and disable request */
1548 VTRACE(("Specular color extensions not supplied\n"));
1553 /* Normal -------------------------------- */
1554 if (sd->u.s.normal.lpData != NULL) {
1555 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1556 glNormal3f(nx, ny, nz);
1558 if (vx_index == 0) glNormal3f(0, 0, 1);
1561 /* Position -------------------------------- */
1562 if (sd->u.s.position.lpData != NULL) {
1563 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1564 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1565 glVertex3f(x, y, z);
1567 GLfloat w = 1.0 / rhw;
1568 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1569 glVertex4f(x*w, y*w, z*w, w);
1573 /* For non indexed mode, step onto next parts */
1574 if (idxData == NULL) {
1580 checkGLcall("glEnd and previous calls");
1583 #if 0 /* TODO: Software/Hardware vertex blending support */
1585 * Draw with emulated vertex shaders
1586 * Note: strided data is uninitialized, as we need to pass the vertex
1587 * shader directly as ordering irs yet
1589 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1590 int PrimitiveType, ULONG NumPrimitives,
1591 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1593 unsigned int textureNo = 0;
1594 GLenum glPrimType = GL_POINTS;
1595 int NumVertexes = NumPrimitives;
1596 const short *pIdxBufS = NULL;
1597 const long *pIdxBufL = NULL;
1598 LONG SkipnStrides = 0;
1600 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1601 float rhw = 0.0f; /* rhw */
1602 float ptSize = 0.0f; /* Point size */
1603 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1604 int numcoords[8]; /* Number of coords */
1605 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607 IDirect3DVertexShaderImpl* vertexShader = NULL;
1609 TRACE("Using slow software vertex shader code\n");
1611 /* Variable Initialization */
1612 if (idxData != NULL) {
1613 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1614 else pIdxBufL = (const long *) idxData;
1617 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1618 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1620 /* Retrieve the VS information */
1621 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1623 /* Start drawing in GL */
1624 VTRACE(("glBegin(%x)\n", glPrimType));
1625 glBegin(glPrimType);
1627 /* For each primitive */
1628 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1630 /* For indexed data, we need to go a few more strides in */
1631 if (idxData != NULL) {
1633 /* Indexed so work out the number of strides to skip */
1635 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1636 SkipnStrides = pIdxBufS[startIdx+vx_index];
1638 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1639 SkipnStrides = pIdxBufL[startIdx+vx_index];
1643 /* Fill the vertex shader input */
1644 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1646 /* Initialize the output fields to the same defaults as it would normally have */
1647 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1648 vertexShader->output.oD[0].x = 1.0;
1649 vertexShader->output.oD[0].y = 1.0;
1650 vertexShader->output.oD[0].z = 1.0;
1651 vertexShader->output.oD[0].w = 1.0;
1653 /* Now execute the vertex shader */
1654 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1657 TRACE_VECTOR(vertexShader->output.oPos);
1658 TRACE_VECTOR(vertexShader->output.oD[0]);
1659 TRACE_VECTOR(vertexShader->output.oD[1]);
1660 TRACE_VECTOR(vertexShader->output.oT[0]);
1661 TRACE_VECTOR(vertexShader->output.oT[1]);
1662 TRACE_VECTOR(vertexShader->input.V[0]);
1663 TRACE_VECTOR(vertexShader->data->C[0]);
1664 TRACE_VECTOR(vertexShader->data->C[1]);
1665 TRACE_VECTOR(vertexShader->data->C[2]);
1666 TRACE_VECTOR(vertexShader->data->C[3]);
1667 TRACE_VECTOR(vertexShader->data->C[4]);
1668 TRACE_VECTOR(vertexShader->data->C[5]);
1669 TRACE_VECTOR(vertexShader->data->C[6]);
1670 TRACE_VECTOR(vertexShader->data->C[7]);
1673 /* Extract out the output */
1674 /* FIXME: Fog coords? */
1675 x = vertexShader->output.oPos.x;
1676 y = vertexShader->output.oPos.y;
1677 z = vertexShader->output.oPos.z;
1678 rhw = vertexShader->output.oPos.w;
1679 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1681 /** Update textures coords using vertexShader->output.oT[0->7] */
1682 memset(texcoords, 0x00, sizeof(texcoords));
1683 memset(numcoords, 0x00, sizeof(numcoords));
1684 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1685 if (This->stateBlock->textures[textureNo] != NULL) {
1686 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1687 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1688 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1689 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1690 if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1691 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1693 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1694 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1695 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1696 default: numcoords[textureNo] = 4;
1700 numcoords[textureNo] = 0;
1704 /* Draw using this information */
1707 TRUE, 0.0f, 0.0f, 1.0f,
1708 TRUE, (float*) &vertexShader->output.oD[0],
1709 TRUE, (float*) &vertexShader->output.oD[1],
1710 FALSE, ptSize, /* FIXME: Change back when supported */
1711 texcoords, numcoords);
1713 /* For non indexed mode, step onto next parts */
1714 if (idxData == NULL) {
1718 } /* for each vertex */
1721 checkGLcall("glEnd and previous calls");
1726 inline static void drawPrimitiveDrawStrided(
1727 IWineD3DDevice *iface,
1728 BOOL useVertexShaderFunction,
1729 BOOL usePixelShaderFunction,
1730 WineDirect3DVertexStridedData *dataLocations,
1731 UINT numberOfvertices,
1732 UINT numberOfIndicies,
1734 const void *idxData,
1740 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1741 BOOL useDrawStridedSlow;
1743 int startStride = idxData == NULL ? 0 :
1744 idxData == (void *) -1 ? 0 :
1745 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1746 int endStride = startStride;
1747 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1748 startStride, endStride, numberOfIndicies, numberOfvertices);
1750 /* Generate some fixme's if unsupported functionality is being used */
1751 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1752 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1753 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1754 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1756 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1757 FIXME("Tweening is only valid with vertex shaders\n");
1759 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1760 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1762 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1763 FIXME("Extended attributes are only valid with vertex shaders\n");
1765 #undef BUFFER_OR_DATA
1767 /* Fixed pipeline, no fixups required - load arrays */
1768 if (!useVertexShaderFunction &&
1769 ((dataLocations->u.s.pSize.lpData == NULL &&
1770 dataLocations->u.s.diffuse.lpData == NULL &&
1771 dataLocations->u.s.specular.lpData == NULL) ||
1774 /* Load the vertex data using named arrays */
1775 TRACE("(%p) Loading vertex data\n", This);
1776 loadVertexData(iface, dataLocations);
1777 useDrawStridedSlow = FALSE;
1779 /* Shader pipeline - load attribute arrays */
1780 } else if(useVertexShaderFunction) {
1782 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1783 useDrawStridedSlow = FALSE;
1785 /* We compile the shader here because we need the vertex declaration
1786 * in order to determine if we need to do any swizzling for D3DCOLOR
1787 * registers. If the shader is already compiled this call will do nothing. */
1788 IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1789 /* Draw vertex by vertex */
1791 TRACE("Not loading vertex data\n");
1792 useDrawStridedSlow = TRUE;
1795 if(usePixelShaderFunction) {
1796 /* We compile the shader here because it depends on the texture stage state
1797 * setup of the bound textures. If the shader is already compiled and the texture stage
1798 * state setup matches the program this function will do nothing
1800 IWineD3DPixelShader_CompileShader(This->stateBlock->pixelShader);
1802 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1803 * Otherwise set NULL, to restore fixed function */
1804 if ((This->vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1805 (This->ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1806 set_glsl_shader_program(iface);
1808 This->stateBlock->glsl_program = NULL;
1810 /* If GLSL is used now, or might have been used before, (re)set the program */
1811 if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL) {
1813 GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
1815 TRACE_(d3d_shader)("Using GLSL program %u\n", progId);
1816 GL_EXTCALL(glUseProgramObjectARB(progId));
1817 checkGLcall("glUseProgramObjectARB");
1820 if (useVertexShaderFunction) {
1822 TRACE("Using vertex shader\n");
1824 if (This->vs_selected_mode == SHADER_ARB) {
1825 /* Bind the vertex program */
1826 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1827 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1828 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1830 /* Enable OpenGL vertex programs */
1831 glEnable(GL_VERTEX_PROGRAM_ARB);
1832 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1833 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1834 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1838 if (usePixelShaderFunction) {
1840 TRACE("Using pixel shader\n");
1842 if (This->ps_selected_mode == SHADER_ARB) {
1843 /* Bind the fragment program */
1844 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1845 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1846 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1848 /* Enable OpenGL fragment programs */
1849 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1850 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1851 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1852 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1856 /* Load any global constants/uniforms that may have been set by the application */
1857 if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL)
1858 shader_glsl_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1859 else if (This->vs_selected_mode == SHADER_ARB || This->ps_selected_mode == SHADER_ARB)
1860 shader_arb_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1862 /* Draw vertex-by-vertex */
1863 if (useDrawStridedSlow)
1864 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1866 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1868 /* Cleanup vertex program */
1869 if (useVertexShaderFunction) {
1870 unloadNumberedArrays(iface);
1872 if (This->vs_selected_mode == SHADER_ARB)
1873 glDisable(GL_VERTEX_PROGRAM_ARB);
1875 unloadVertexData(iface);
1878 /* Cleanup fragment program */
1879 if (usePixelShaderFunction && This->ps_selected_mode == SHADER_ARB)
1880 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1883 inline void drawPrimitiveTraceDataLocations(
1884 WineDirect3DVertexStridedData *dataLocations) {
1886 /* Dump out what parts we have supplied */
1887 TRACE("Strided Data:\n");
1888 TRACE_STRIDED((dataLocations), position);
1889 TRACE_STRIDED((dataLocations), blendWeights);
1890 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1891 TRACE_STRIDED((dataLocations), normal);
1892 TRACE_STRIDED((dataLocations), pSize);
1893 TRACE_STRIDED((dataLocations), diffuse);
1894 TRACE_STRIDED((dataLocations), specular);
1895 TRACE_STRIDED((dataLocations), texCoords[0]);
1896 TRACE_STRIDED((dataLocations), texCoords[1]);
1897 TRACE_STRIDED((dataLocations), texCoords[2]);
1898 TRACE_STRIDED((dataLocations), texCoords[3]);
1899 TRACE_STRIDED((dataLocations), texCoords[4]);
1900 TRACE_STRIDED((dataLocations), texCoords[5]);
1901 TRACE_STRIDED((dataLocations), texCoords[6]);
1902 TRACE_STRIDED((dataLocations), texCoords[7]);
1903 TRACE_STRIDED((dataLocations), position2);
1904 TRACE_STRIDED((dataLocations), normal2);
1905 TRACE_STRIDED((dataLocations), tangent);
1906 TRACE_STRIDED((dataLocations), binormal);
1907 TRACE_STRIDED((dataLocations), tessFactor);
1908 TRACE_STRIDED((dataLocations), fog);
1909 TRACE_STRIDED((dataLocations), depth);
1910 TRACE_STRIDED((dataLocations), sample);
1916 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1919 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1920 /* Pixel shader support should imply multitexture support. */
1921 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1922 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1923 checkGLcall("glActiveTextureARB");
1925 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1928 if (!This->stateBlock->textures[i]) continue;
1930 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1931 glDisable(GL_TEXTURE_1D);
1932 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1933 switch(This->stateBlock->textureDimensions[i]) {
1935 glDisable(GL_TEXTURE_3D);
1936 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1939 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1940 glDisable(GL_TEXTURE_2D);
1942 case GLTEXTURECUBEMAP:
1943 glDisable(GL_TEXTURE_2D);
1944 glDisable(GL_TEXTURE_3D);
1947 glEnable(This->stateBlock->textureDimensions[i]);
1949 /* Upload texture, apply states */
1950 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1951 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1952 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1956 /* uploads textures and setup texture states ready for rendering */
1957 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1958 INT current_sampler = 0;
1959 float constant_color[4];
1962 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1963 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1964 * Register combiners however provide up to 8 combiner stages. In order to
1965 * take advantage of this, we need to be separate D3D texture stages from
1966 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1967 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1968 * corresponds to MaxTextureBlendStages in the caps. */
1970 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1971 glEnable(GL_REGISTER_COMBINERS_NV);
1972 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1973 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1976 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1977 INT texture_idx = -1;
1979 /* WINED3DTOP_DISABLE disables the current & any higher texture stages */
1980 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) break;
1982 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1983 texture_idx = current_sampler++;
1985 /* Active the texture unit corresponding to the current texture stage */
1986 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1987 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1988 checkGLcall("glActiveTextureARB");
1990 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1994 if (This->stateBlock->textures[i]) {
1995 /* Enable the correct target. */
1996 glDisable(GL_TEXTURE_1D);
1997 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1998 switch(This->stateBlock->textureDimensions[i]) {
2000 glDisable(GL_TEXTURE_3D);
2001 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2004 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2005 glDisable(GL_TEXTURE_2D);
2007 case GLTEXTURECUBEMAP:
2008 glDisable(GL_TEXTURE_2D);
2009 glDisable(GL_TEXTURE_3D);
2013 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2014 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
2015 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2017 glEnable(This->stateBlock->textureDimensions[i]);
2020 /* Upload texture, apply states */
2021 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2022 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
2023 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2024 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2025 /* ARB_texture_env_combine needs a valid texture bound to the
2026 * texture unit, even if it isn't used. Bind a dummy texture. */
2027 glDisable(GL_TEXTURE_2D);
2028 glDisable(GL_TEXTURE_3D);
2029 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2030 glEnable(GL_TEXTURE_1D);
2031 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2032 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2035 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2036 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2037 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2038 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2039 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2040 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2041 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
2044 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2045 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2046 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2047 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2050 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2051 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2052 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2053 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2055 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2056 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2057 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2058 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2062 /* If we're using register combiners, set the amount of *used* combiners.
2063 * Ie, the number of stages below the first stage to have a color op of
2064 * WINED3DTOP_DISABLE. */
2065 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2066 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2067 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2068 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2071 /* Disable the remaining texture units. */
2072 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2073 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2074 glDisable(GL_TEXTURE_1D);
2075 glDisable(GL_TEXTURE_2D);
2076 glDisable(GL_TEXTURE_3D);
2077 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2081 /* Routine common to the draw primitive and draw indexed primitive routines */
2082 void drawPrimitive(IWineD3DDevice *iface,
2086 long StartVertexIndex,
2087 UINT numberOfVertices,
2090 const void *idxData,
2092 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2095 BOOL useVertexShaderFunction = FALSE;
2096 BOOL usePixelShaderFunction = FALSE;
2097 WineDirect3DVertexStridedData *dataLocations;
2098 IWineD3DSwapChainImpl *swapchain;
2102 BOOL lighting_changed, lighting_original = FALSE;
2104 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2105 * here simply check whether a shader was set, or the user disabled shaders */
2106 if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2107 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2108 useVertexShaderFunction = TRUE;
2110 if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2111 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2112 usePixelShaderFunction = TRUE;
2114 /* Invalidate the back buffer memory so LockRect will read it the next time */
2115 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2116 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2118 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2119 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2123 /* Ok, we will be updating the screen from here onwards so grab the lock */
2126 if(DrawPrimStrideData) {
2128 /* Note: this is a ddraw fixed-function code path */
2130 TRACE("================ Strided Input ===================\n");
2131 dataLocations = DrawPrimStrideData;
2132 drawPrimitiveTraceDataLocations(dataLocations);
2136 else if (This->stateBlock->vertexDecl || This->stateBlock->vertexShader) {
2138 /* Note: This is a fixed function or shader codepath.
2139 * This means it must handle both types of strided data.
2140 * Shaders must go through here to zero the strided data, even if they
2141 * don't set any declaration at all */
2143 TRACE("================ Vertex Declaration ===================\n");
2144 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2145 if(!dataLocations) {
2146 ERR("Out of memory!\n");
2150 if (This->stateBlock->vertexDecl != NULL ||
2151 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2153 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2154 dataLocations, StartVertexIndex, &fixup);
2158 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2159 * It is reachable through d3d8, but only for fixed-function.
2160 * It will not work properly for shaders. */
2162 TRACE("================ FVF ===================\n");
2163 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2164 if(!dataLocations) {
2165 ERR("Out of memory!\n");
2168 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2169 drawPrimitiveTraceDataLocations(dataLocations);
2172 /* Setup transform matrices and sort out */
2173 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2175 /* Now initialize the materials state */
2176 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2178 if (usePixelShaderFunction) {
2179 drawPrimitiveUploadTexturesPS(This);
2181 drawPrimitiveUploadTextures(This);
2186 /* Ok, Work out which primitive is requested and how many vertexes that
2188 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2189 if (numberOfVertices == 0 )
2190 numberOfVertices = calculatedNumberOfindices;
2192 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2193 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2194 idxData, idxSize, minIndex, StartIdx, fixup);
2197 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2199 /* If vertex shaders or no normals, restore previous lighting state */
2200 if (lighting_changed) {
2201 if (lighting_original) glEnable(GL_LIGHTING);
2202 else glDisable(GL_LIGHTING);
2203 TRACE("Restored lighting to original state\n");
2206 /* Finshed updating the screen, restore lock */
2208 TRACE("Done all gl drawing\n");
2211 #ifdef SHOW_FRAME_MAKEUP
2213 static long int primCounter = 0;
2214 /* NOTE: set primCounter to the value reported by drawprim
2215 before you want to to write frame makeup to /tmp */
2216 if (primCounter >= 0) {
2217 WINED3DLOCKED_RECT r;
2219 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2220 sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
2221 TRACE("Saving screenshot %s\n", buffer);
2222 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2223 IWineD3DSurface_UnlockRect(This->renderTarget);
2225 #ifdef SHOW_TEXTURE_MAKEUP
2227 IWineD3DSurface *pSur;
2229 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2230 if (This->stateBlock->textures[textureNo] != NULL) {
2231 sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2232 TRACE("Saving texture %s\n", buffer);
2233 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2234 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2235 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2236 IWineD3DSurface_Release(pSur);
2238 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2245 TRACE("drawprim #%d\n", primCounter);