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
31 #ifdef SHOW_FRAME_MAKEUP
36 extern IWineD3DVertexShaderImpl* VertexShaders[64];
37 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
38 extern IWineD3DPixelShaderImpl* PixelShaders[64];
40 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
43 /* Returns bits for what is expected from the fixed function pipeline, and whether
44 a vertex shader will be in use. Note the fvf bits returned may be split over
45 multiple streams only if the vertex shader was created, otherwise it all relates
47 static BOOL initializeFVF(IWineD3DDevice *iface, DWORD *FVFbits)
50 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
52 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
53 /* The first thing to work out is if we are using the fixed function pipeline
54 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
55 is the FVF, or with a shader which was created with no function - in which
56 case there is an FVF per declared stream. If this occurs, we also maintain
57 an 'OR' of all the FVF's together so we know what to expect across all the
60 *FVFbits = This->stateBlock->fvf;
62 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
67 /* Issues the glBegin call for gl given the primitive type and count */
68 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
72 DWORD NumVertexes = NumPrimitives;
74 switch (PrimitiveType) {
77 *primType = GL_POINTS;
78 NumVertexes = NumPrimitives;
84 NumVertexes = NumPrimitives * 2;
88 TRACE("LINE_STRIP\n");
89 *primType = GL_LINE_STRIP;
90 NumVertexes = NumPrimitives + 1;
93 case D3DPT_TRIANGLELIST:
95 *primType = GL_TRIANGLES;
96 NumVertexes = NumPrimitives * 3;
99 case D3DPT_TRIANGLESTRIP:
100 TRACE("TRIANGLE_STRIP\n");
101 *primType = GL_TRIANGLE_STRIP;
102 NumVertexes = NumPrimitives + 2;
105 case D3DPT_TRIANGLEFAN:
106 TRACE("TRIANGLE_FAN\n");
107 *primType = GL_TRIANGLE_FAN;
108 NumVertexes = NumPrimitives + 2;
112 FIXME("Unhandled primitive\n");
113 *primType = GL_POINTS;
119 /* Ensure the appropriate material states are set up - only change
120 state if really required */
121 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
123 BOOL requires_material_reset = FALSE;
124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
126 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
127 /* If we have not set up the material color tracking, do it now as required */
128 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
129 checkGLcall("glDisable GL_COLOR_MATERIAL");
130 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
131 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
132 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
133 glEnable(GL_COLOR_MATERIAL);
134 checkGLcall("glEnable GL_COLOR_MATERIAL");
135 This->tracking_color = IS_TRACKING;
136 requires_material_reset = TRUE; /* Restore material settings as will be used */
138 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
139 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
140 /* If we are tracking the current color but one isn't supplied, don't! */
141 glDisable(GL_COLOR_MATERIAL);
142 checkGLcall("glDisable GL_COLOR_MATERIAL");
143 This->tracking_color = NEEDS_TRACKING;
144 requires_material_reset = TRUE; /* Restore material settings as will be used */
146 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
147 /* No need to reset material colors since no change to gl_color_material */
148 requires_material_reset = FALSE;
150 } else if (This->tracking_color == NEEDS_DISABLE) {
151 glDisable(GL_COLOR_MATERIAL);
152 checkGLcall("glDisable GL_COLOR_MATERIAL");
153 This->tracking_color = DISABLED_TRACKING;
154 requires_material_reset = TRUE; /* Restore material settings as will be used */
157 /* Reset the material colors which may have been tracking the color*/
158 if (requires_material_reset) {
159 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
160 checkGLcall("glMaterialfv");
161 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
162 checkGLcall("glMaterialfv");
163 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
164 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
165 checkGLcall("glMaterialfv");
167 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
168 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
169 checkGLcall("glMaterialfv");
171 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
172 checkGLcall("glMaterialfv");
177 static GLfloat invymat[16] = {
178 1.0f, 0.0f, 0.0f, 0.0f,
179 0.0f, -1.0f, 0.0f, 0.0f,
180 0.0f, 0.0f, 1.0f, 0.0f,
181 0.0f, 0.0f, 0.0f, 1.0f};
183 void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
184 /* If the last draw was transformed as well, no need to reapply all the matrixes */
185 if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
187 double X, Y, height, width, minZ, maxZ;
188 This->last_was_rhw = TRUE;
189 This->viewport_changed = FALSE;
191 /* Transformed already into viewport coordinates, so we do not need transform
192 matrices. Reset all matrices to identity and leave the default matrix in world
194 glMatrixMode(GL_MODELVIEW);
195 checkGLcall("glMatrixMode(GL_MODELVIEW)");
197 checkGLcall("glLoadIdentity");
199 glMatrixMode(GL_PROJECTION);
200 checkGLcall("glMatrixMode(GL_PROJECTION)");
202 checkGLcall("glLoadIdentity");
204 /* Set up the viewport to be full viewport */
205 X = This->stateBlock->viewport.X;
206 Y = This->stateBlock->viewport.Y;
207 height = This->stateBlock->viewport.Height;
208 width = This->stateBlock->viewport.Width;
209 minZ = This->stateBlock->viewport.MinZ;
210 maxZ = This->stateBlock->viewport.MaxZ;
211 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
212 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
213 checkGLcall("glOrtho");
215 /* Window Coord 0 is the middle of the first pixel, so translate by half
216 a pixel (See comment above glTranslate below) */
217 glTranslatef(0.375, 0.375, 0);
218 checkGLcall("glTranslatef(0.375, 0.375, 0)");
219 if (This->renderUpsideDown) {
220 glMultMatrixf(invymat);
221 checkGLcall("glMultMatrixf(invymat)");
226 /* Setup views - Transformed & lit if RHW, else untransformed.
227 Only unlit if Normals are supplied
228 Returns: Whether to restore lighting afterwards */
229 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
231 BOOL isLightingOn = FALSE;
232 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
234 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
235 set by the appropriate render state. Note Vertex Shader output is already lit */
236 if (vtx_lit || useVS) {
237 isLightingOn = glIsEnabled(GL_LIGHTING);
238 glDisable(GL_LIGHTING);
239 checkGLcall("glDisable(GL_LIGHTING);");
240 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
243 if (!useVS && vtx_transformed) {
244 d3ddevice_set_ortho(This);
247 /* Untransformed, so relies on the view and projection matrices */
249 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
250 /* Only reapply when have to */
251 This->modelview_valid = TRUE;
252 glMatrixMode(GL_MODELVIEW);
253 checkGLcall("glMatrixMode");
255 /* In the general case, the view matrix is the identity matrix */
256 if (This->view_ident) {
257 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
258 checkGLcall("glLoadMatrixf");
260 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
261 checkGLcall("glLoadMatrixf");
262 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
263 checkGLcall("glMultMatrixf");
267 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
268 /* Only reapply when have to */
269 This->proj_valid = TRUE;
270 glMatrixMode(GL_PROJECTION);
271 checkGLcall("glMatrixMode");
273 /* The rule is that the window coordinate 0 does not correspond to the
274 beginning of the first pixel, but the center of the first pixel.
275 As a consequence if you want to correctly draw one line exactly from
276 the left to the right end of the viewport (with all matrices set to
277 be identity), the x coords of both ends of the line would be not
278 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
282 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
283 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
285 if (This->renderUpsideDown) {
286 glMultMatrixf(invymat);
287 checkGLcall("glMultMatrixf(invymat)");
289 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
290 checkGLcall("glLoadMatrixf");
293 /* Vertex Shader output is already transformed, so set up identity matrices */
294 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
295 come along this needs to take into account whether s/w ones were
298 glMatrixMode(GL_MODELVIEW);
299 checkGLcall("glMatrixMode");
301 glMatrixMode(GL_PROJECTION);
302 checkGLcall("glMatrixMode");
304 /* Window Coord 0 is the middle of the first pixel, so translate by half
305 a pixel (See comment above glTranslate above) */
306 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
307 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
308 if (This->renderUpsideDown) {
309 glMultMatrixf(invymat);
310 checkGLcall("glMultMatrixf(invymat)");
312 This->modelview_valid = FALSE;
313 This->proj_valid = FALSE;
315 This->last_was_rhw = FALSE;
320 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, BOOL useVertexShaderFunction, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf, BOOL storeOrder, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
321 /* We need to deal with frequency data!*/
325 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
326 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
328 WINED3DVERTEXELEMENT *element;
332 /* Locate the vertex declaration */
333 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
334 TRACE("Using vertex declaration from shader\n");
335 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
337 TRACE("Using vertex declaration\n");
338 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
341 /* Translate the declaration into strided data */
342 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
344 element = vertexDeclaration->pDeclarationWine + i;
345 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
346 if (This->stateBlock->streamIsUP) {
347 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
348 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
350 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
351 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
353 stride = This->stateBlock->streamStride[element->Stream];
354 data += (BaseVertexIndex * stride);
355 data += element->Offset;
358 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
360 if (useVertexShaderFunction && reg != -1 && data) {
361 WINED3DGLTYPE glType = glTypeLookup[element->Type];
363 TRACE("(%p) : Set vertex attrib pointer: reg 0x%08x, d3d type 0x%08x, stride 0x%08lx, data %p)\n", This, reg, element->Type, stride, data);
365 GL_EXTCALL(glVertexAttribPointerARB(reg, glType.size, glType.glType, glType.normalized, stride, data));
366 checkGLcall("glVertexAttribPointerARB");
367 GL_EXTCALL(glEnableVertexAttribArrayARB(reg));
368 checkGLcall("glEnableVertexAttribArrayARB");
371 switch (element->Usage) {
372 case D3DDECLUSAGE_POSITION:
373 switch (element->UsageIndex) {
374 case 0: /* N-patch */
375 strided->u.s.position.lpData = data;
376 strided->u.s.position.dwType = element->Type;
377 strided->u.s.position.dwStride = stride;
378 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data, element->Type, stride);
379 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = element->Reg;
381 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
382 TRACE("Tweened positions\n");
383 strided->u.s.position2.lpData = data;
384 strided->u.s.position2.dwType = element->Type;
385 strided->u.s.position2.dwStride = stride;
386 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data, element->Type, stride);
387 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2] = element->Reg;
391 case D3DDECLUSAGE_NORMAL:
392 switch (element->UsageIndex) {
393 case 0: /* N-patch */
394 strided->u.s.normal.lpData = data;
395 strided->u.s.normal.dwType = element->Type;
396 strided->u.s.normal.dwStride = stride;
397 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data, element->Type, stride);
398 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = element->Reg;
400 case 1: /* skinning */
401 TRACE("Skinning / tween normals\n");
402 strided->u.s.normal2.lpData = data;
403 strided->u.s.normal2.dwType = element->Type;
404 strided->u.s.normal2.dwStride = stride;
405 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data, element->Type, stride);
406 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = element->Reg;
409 *fvf |= D3DFVF_NORMAL;
411 case D3DDECLUSAGE_BLENDINDICES:
412 /* demo @http://www.ati.com/developer/vertexblend.html
413 and http://www.flipcode.com/articles/article_dx8shaders.shtml
415 strided->u.s.blendMatrixIndices.lpData = data;
416 strided->u.s.blendMatrixIndices.dwType = element->Type;
417 strided->u.s.blendMatrixIndices.dwStride= stride;
418 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendMatrixIndices", data, element->Type, stride);
419 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = element->Reg;
421 case D3DDECLUSAGE_BLENDWEIGHT:
422 strided->u.s.blendWeights.lpData = data;
423 strided->u.s.blendWeights.dwType = element->Type;
424 strided->u.s.blendWeights.dwStride = stride;
425 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data, element->Type, stride);
426 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = element->Reg;
428 case D3DDECLUSAGE_PSIZE:
429 strided->u.s.pSize.lpData = data;
430 strided->u.s.pSize.dwType = element->Type;
431 strided->u.s.pSize.dwStride = stride;
432 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data, element->Type, stride);
433 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = element->Reg;
435 case D3DDECLUSAGE_COLOR:
436 switch (element->UsageIndex) {
438 strided->u.s.diffuse.lpData = data;
439 strided->u.s.diffuse.dwType = element->Type;
440 strided->u.s.diffuse.dwStride = stride;
441 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data, element->Type, stride);
442 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = element->Reg;
444 case 1: /* specular */
445 strided->u.s.specular.lpData = data;
446 strided->u.s.specular.dwType = element->Type;
447 strided->u.s.specular.dwStride = stride;
448 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data, element->Type, stride);
449 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = element->Reg;
454 case D3DDECLUSAGE_TEXCOORD:
455 /* For some odd reason Microsoft decided to sum usage accross all the streams,
456 which means we need to do a count and not just use the usage number */
458 strided->u.s.texCoords[textureNo].lpData = data;
459 strided->u.s.texCoords[textureNo].dwType = element->Type;
460 strided->u.s.texCoords[textureNo].dwStride = stride;
461 TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo, data, element->Type, stride);
462 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + textureNo] = element->Reg;
466 case D3DDECLUSAGE_TANGENT:
467 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
468 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
469 normal using tangents where no normal data has been provided */
471 strided->u.s.tangent.lpData = data;
472 strided->u.s.tangent.dwType = element->Type;
473 strided->u.s.tangent.dwStride = stride;
474 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data, element->Type, stride);
475 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = element->Reg;
477 case D3DDECLUSAGE_BINORMAL:
478 /* Binormals are really bitangents perpendicular to the normal but s-aligned to the tangent, basically they are the vectors of any two lines on the plain at right angles to the normal and at right angles to each other, like the x,y,z axis.
479 tangent data makes it easier to perform some calculations (a bit like using 2d graph paper instead of the normal of the piece of paper)
480 The only thing they are useful for in fixed function would be working out normals when none are given.
482 TRACE("BI-Normal\n");
483 strided->u.s.binormal.lpData = data;
484 strided->u.s.binormal.dwType = element->Type;
485 strided->u.s.binormal.dwStride = stride;
486 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data, element->Type, stride);
487 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = element->Reg;
489 case D3DDECLUSAGE_TESSFACTOR:
490 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
492 TRACE("Tess Factor\n");
493 strided->u.s.tessFactor.lpData = data;
494 strided->u.s.tessFactor.dwType = element->Type;
495 strided->u.s.tessFactor.dwStride = stride;
496 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data, element->Type, stride);
497 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = element->Reg;
499 case D3DDECLUSAGE_POSITIONT:
501 switch (element->UsageIndex) {
502 case 0: /* N-patch */
503 strided->u.s.position.lpData = data;
504 strided->u.s.position.dwType = element->Type;
505 strided->u.s.position.dwStride = stride;
506 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data, element->Type, stride);
507 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = element->Reg;
509 case 1: /* skinning */
510 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
511 http://xface.blogspot.com/2004_08_01_xface_archive.html
513 TRACE("Skinning positionsT\n");
514 strided->u.s.position2.lpData = data;
515 strided->u.s.position2.dwType = element->Type;
516 strided->u.s.position2.dwStride = stride;
517 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data, element->Type, stride);
518 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = element->Reg;
521 /* TODO: change fvf usage to a plain boolean flag */
522 *fvf |= D3DFVF_XYZRHW;
523 /* FIXME: were faking this flag so that we don't transform the data again */
525 case D3DDECLUSAGE_FOG:
526 /* maybe GL_EXT_fog_coord ?
527 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
528 * This extension allows specifying an explicit per-vertex fog
529 * coordinate to be used in fog computations, rather than using a
530 * fragment depth-based fog equation.
534 strided->u.s.fog.lpData = data;
535 strided->u.s.fog.dwType = element->Type;
536 strided->u.s.fog.dwStride = stride;
537 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data, element->Type, stride);
538 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = element->Reg;
540 case D3DDECLUSAGE_DEPTH:
542 strided->u.s.depth.lpData = data;
543 strided->u.s.depth.dwType = element->Type;
544 strided->u.s.depth.dwStride = stride;
545 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data, element->Type, stride);
546 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = element->Reg;
548 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
550 strided->u.s.sample.lpData = data;
551 strided->u.s.sample.dwType = element->Type;
552 strided->u.s.sample.dwStride = stride;
553 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data, element->Type, stride);
554 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = element->Reg;
562 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex) {
564 short LoopThroughTo = 0;
569 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
570 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
574 /* OK, Now to setup the data locations
575 For the non-created vertex shaders, the VertexShader var holds the real
576 FVF and only stream 0 matters
577 For the created vertex shaders, there is an FVF per stream */
578 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
579 LoopThroughTo = MAX_STREAMS;
584 /* Work through stream by stream */
585 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
586 DWORD stride = This->stateBlock->streamStride[nStream];
590 /* Skip empty streams */
591 if (This->stateBlock->streamSource[nStream] == NULL) continue;
593 /* Retrieve appropriate FVF */
594 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
595 thisFVF = This->stateBlock->fvf;
596 /* Handle memory passed directly as well as vertex buffers */
597 if (This->stateBlock->streamIsUP) {
598 data = (BYTE *)This->stateBlock->streamSource[nStream];
600 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
603 #if 0 /* TODO: Vertex shader support */
604 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
605 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
608 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
609 if (thisFVF == 0) continue;
611 /* Now convert the stream into pointers */
613 /* Shuffle to the beginning of the vertexes to render and index from there */
614 data = data + (BaseVertexIndex * stride);
616 /* Either 3 or 4 floats depending on the FVF */
617 /* FIXME: Can blending data be in a different stream to the position data?
618 and if so using the fixed pipeline how do we handle it */
619 if (thisFVF & D3DFVF_POSITION_MASK) {
620 strided->u.s.position.lpData = data;
621 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
622 strided->u.s.position.dwStride = stride;
623 data += 3 * sizeof(float);
624 if (thisFVF & D3DFVF_XYZRHW) {
625 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
626 data += sizeof(float);
630 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
631 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
632 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
633 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
635 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
636 TRACE("Setting blend Weights to %p\n", data);
637 strided->u.s.blendWeights.lpData = data;
638 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
639 strided->u.s.blendWeights.dwStride = stride;
640 data += numBlends * sizeof(FLOAT);
642 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
643 strided->u.s.blendMatrixIndices.lpData = data;
644 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
645 strided->u.s.blendMatrixIndices.dwStride= stride;
646 data += sizeof(DWORD);
650 /* Normal is always 3 floats */
651 if (thisFVF & D3DFVF_NORMAL) {
652 strided->u.s.normal.lpData = data;
653 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
654 strided->u.s.normal.dwStride = stride;
655 data += 3 * sizeof(FLOAT);
658 /* Pointsize is a single float */
659 if (thisFVF & D3DFVF_PSIZE) {
660 strided->u.s.pSize.lpData = data;
661 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
662 strided->u.s.pSize.dwStride = stride;
663 data += sizeof(FLOAT);
666 /* Diffuse is 4 unsigned bytes */
667 if (thisFVF & D3DFVF_DIFFUSE) {
668 strided->u.s.diffuse.lpData = data;
669 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
670 strided->u.s.diffuse.dwStride = stride;
671 data += sizeof(DWORD);
674 /* Specular is 4 unsigned bytes */
675 if (thisFVF & D3DFVF_SPECULAR) {
676 strided->u.s.specular.lpData = data;
677 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
678 strided->u.s.specular.dwStride = stride;
679 data += sizeof(DWORD);
683 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
684 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
686 /* numTextures indicates the number of texture coordinates supplied */
687 /* However, the first set may not be for stage 0 texture - it all */
688 /* depends on D3DTSS_TEXCOORDINDEX. */
689 /* The number of bytes for each coordinate set is based off */
690 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
692 /* So, for each supplied texture extract the coords */
693 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
695 strided->u.s.texCoords[textureNo].lpData = data;
696 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
697 strided->u.s.texCoords[textureNo].dwStride = stride;
698 numCoords[textureNo] = coordIdxInfo & 0x03;
701 data += sizeof(float);
702 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
703 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
704 data += sizeof(float);
705 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
706 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
707 data += sizeof(float);
708 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
709 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
710 data += sizeof(float);
714 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
719 #if 0 /* TODO: Software Shaders */
720 /* Draw a single vertex using this information */
721 static void draw_vertex(IWineD3DDevice *iface, /* interface */
722 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
723 BOOL isNormal, float nx, float ny, float nz, /* normal */
724 BOOL isDiffuse, float *dRGBA, /* 1st colors */
725 BOOL isSpecular, float *sRGB, /* 2ndry colors */
726 BOOL isPtSize, float ptSize, /* pointSize */
727 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
729 unsigned int textureNo;
731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
733 /* Diffuse -------------------------------- */
736 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
739 /* Specular Colour ------------------------------------------*/
741 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
742 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
743 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
745 VTRACE(("Specular color extensions not supplied\n"));
749 /* Normal -------------------------------- */
751 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
752 glNormal3f(nx, ny, nz);
755 /* Point Size ----------------------------------------------*/
758 /* no such functionality in the fixed function GL pipeline */
759 FIXME("Cannot change ptSize here in openGl\n");
762 /* Texture coords --------------------------- */
763 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
765 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
766 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
770 /* Query tex coords */
771 if (This->stateBlock->textures[textureNo] != NULL) {
773 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
774 if (coordIdx >= MAX_TEXTURES) {
775 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
777 } else if (numcoords[coordIdx] == 0) {
778 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
782 /* Initialize vars */
788 switch (numcoords[coordIdx]) {
789 case 4: q = texcoords[coordIdx].w; /* drop through */
790 case 3: r = texcoords[coordIdx].z; /* drop through */
791 case 2: t = texcoords[coordIdx].y; /* drop through */
792 case 1: s = texcoords[coordIdx].x;
795 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
797 VTRACE(("tex:%d, s=%f\n", textureNo, s));
798 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
799 GLMULTITEXCOORD1F(textureNo, s);
805 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
806 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
807 GLMULTITEXCOORD2F(textureNo, s, t);
813 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
814 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
815 GLMULTITEXCOORD3F(textureNo, s, t, r);
817 glTexCoord3f(s, t, r);
821 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
822 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
823 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
825 glTexCoord4f(s, t, r, q);
829 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
833 } /* End of textures */
835 /* Position -------------------------------- */
837 if (1.0f == rhw || rhw < 0.00001f) {
838 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
841 /* Cannot optimize by dividing through by rhw as rhw is required
842 later for perspective in the GL pipeline for vertex shaders */
843 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
844 glVertex4f(x,y,z,rhw);
848 #endif /* TODO: Software shaders */
850 void loadNumberedArrays(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
851 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
853 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
854 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
855 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
856 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
857 WINED3D_ATR_SIZE(_arrayName), \
858 WINED3D_ATR_GLTYPE(_arrayName), \
859 WINED3D_ATR_NORMALIZED(_arrayName), \
860 sd->u.s._arrayName.dwStride, \
861 sd->u.s._arrayName.lpData)); \
862 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
866 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
867 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
868 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
869 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
870 WINED3D_ATR_SIZE(position2), \
871 WINED3D_ATR_GLTYPE(position2), \
872 WINED3D_ATR_NORMALIZED(position2), \
873 sd->u.s.position2.dwStride, \
874 ((char *)sd->u.s.position2.lpData) + \
875 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
876 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
879 /* Generate some lookup tables */
880 /* drop the RHW coord, there must be a nicer way of doing this. */
881 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
882 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
884 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
885 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
886 LOAD_NUMBERED_ARRAY(position,POSITION);
887 LOAD_NUMBERED_ARRAY(normal,NORMAL);
888 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
889 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
890 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
891 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
892 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
893 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
894 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
895 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
896 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
897 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
898 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
899 #if 0 /* TODO: Samplers may allow for more texture coords */
900 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
901 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
902 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
903 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
904 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
905 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
906 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
907 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
909 LOAD_NUMBERED_ARRAY(position,POSITIONT);
911 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
912 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
913 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
914 LOAD_NUMBERED_ARRAY(position2,POSITION2);
915 /* there can be lots of position arrays */
916 LOAD_NUMBERED_POSITION_ARRAY(0);
917 LOAD_NUMBERED_POSITION_ARRAY(1);
918 LOAD_NUMBERED_POSITION_ARRAY(2);
919 LOAD_NUMBERED_POSITION_ARRAY(3);
920 LOAD_NUMBERED_POSITION_ARRAY(4);
921 LOAD_NUMBERED_POSITION_ARRAY(5);
922 LOAD_NUMBERED_POSITION_ARRAY(6);
923 LOAD_NUMBERED_POSITION_ARRAY(7);
924 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
925 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
926 LOAD_NUMBERED_ARRAY(fog,FOG);
927 LOAD_NUMBERED_ARRAY(depth,DEPTH);
928 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
930 #undef LOAD_NUMBERED_ARRAY
933 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
934 unsigned int textureNo = 0;
935 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
937 TRACE("Using fast vertex array code\n");
938 /* Blend Data ---------------------------------------------- */
939 if ((sd->u.s.blendWeights.lpData != NULL) ||
940 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
943 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
946 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
947 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
950 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
951 /* FIXME("TODO\n");*/
952 /* Note dwType == float3 or float4 == 2 or 3 */
955 /* with this on, the normals appear to be being modified,
956 but the vertices aren't being translated as they should be
957 Maybe the world matrix aren't being setup properly? */
958 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
962 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
963 WINED3D_ATR_SIZE(blendWeights) ,
964 sd->u.s.blendWeights.dwStride,
965 sd->u.s.blendWeights.lpData));
967 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
968 sd->u.s.blendWeights.dwStride,
969 sd->u.s.blendWeights.lpData);
971 checkGLcall("glWeightPointerARB");
973 if(sd->u.s.blendMatrixIndices.lpData != NULL){
974 static BOOL showfixme = TRUE;
976 FIXME("blendMatrixIndices support\n");
983 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
984 /* FIXME("TODO\n");*/
987 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
988 sd->u.s.blendWeights.dwStride,
989 sd->u.s.blendWeights.lpData);
990 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
991 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
992 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
996 /* TODO: support blends in fixupVertices */
997 FIXME("unsupported blending in openGl\n");
1000 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
1001 #if 0 /* TODO: Vertex blending */
1002 glDisable(GL_VERTEX_BLEND_ARB);
1004 TRACE("ARB_VERTEX_BLEND\n");
1005 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
1006 TRACE(" EXT_VERTEX_WEIGHTING\n");
1007 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
1008 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
1013 #if 0 /* FOG ----------------------------------------------*/
1014 if (sd->u.s.fog.lpData != NULL) {
1016 if (GL_SUPPORT(EXT_FOG_COORD) {
1017 glEnableClientState(GL_FOG_COORD_EXT);
1018 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
1019 sd->u.s.fog.dwStride,
1020 sd->u.s.fog.lpData);
1022 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1023 /* FIXME: fixme once */
1024 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1027 if (GL_SUPPRT(EXT_FOR_COORD) {
1028 /* make sure fog is disabled */
1029 glDisableClientState(GL_FOG_COORD_EXT);
1034 #if 0 /* tangents ----------------------------------------------*/
1035 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
1037 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1038 if (sd->u.s.tangent.lpData != NULL) {
1039 glEnable(GL_TANGENT_ARRAY_EXT);
1040 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
1041 sd->u.s.tangent.dwStride,
1042 sd->u.s.tangent.lpData);
1044 glDisable(GL_TANGENT_ARRAY_EXT);
1046 if (sd->u.s.binormal.lpData != NULL) {
1047 glEnable(GL_BINORMAL_ARRAY_EXT);
1048 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
1049 sd->u.s.binormal.dwStride,
1050 sd->u.s.binormal.lpData);
1052 glDisable(GL_BINORMAL_ARRAY_EXT);
1056 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1057 /* FIXME: fixme once */
1058 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1061 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1062 /* make sure fog is disabled */
1063 glDisable(GL_TANGENT_ARRAY_EXT);
1064 glDisable(GL_BINORMAL_ARRAY_EXT);
1069 /* Point Size ----------------------------------------------*/
1070 if (sd->u.s.pSize.lpData != NULL) {
1072 /* no such functionality in the fixed function GL pipeline */
1073 TRACE("Cannot change ptSize here in openGl\n");
1074 /* TODO: Implement this function in using shaders if they are available */
1078 /* Vertex Pointers -----------------------------------------*/
1079 if (sd->u.s.position.lpData != NULL) {
1080 /* Note dwType == float3 or float4 == 2 or 3 */
1081 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1082 sd->u.s.position.dwStride,
1083 sd->u.s.position.dwType + 1,
1084 sd->u.s.position.lpData));
1086 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1087 handling for rhw mode should not impact screen position whereas in GL it does.
1088 This may result in very slightly distored textures in rhw mode, but
1089 a very minimal different. There's always the other option of
1090 fixing the view matrix to prevent w from having any effect */
1091 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1092 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1093 checkGLcall("glVertexPointer(...)");
1094 glEnableClientState(GL_VERTEX_ARRAY);
1095 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1098 glDisableClientState(GL_VERTEX_ARRAY);
1099 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1102 /* Normals -------------------------------------------------*/
1103 if (sd->u.s.normal.lpData != NULL) {
1104 /* Note dwType == float3 or float4 == 2 or 3 */
1105 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1106 sd->u.s.normal.dwStride,
1107 sd->u.s.normal.lpData));
1108 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1109 sd->u.s.normal.dwStride,
1110 sd->u.s.normal.lpData);
1111 checkGLcall("glNormalPointer(...)");
1112 glEnableClientState(GL_NORMAL_ARRAY);
1113 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1116 glDisableClientState(GL_NORMAL_ARRAY);
1117 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1118 glNormal3f(0, 0, 1);
1119 checkGLcall("glNormal3f(0, 0, 1)");
1122 /* Diffuse Colour --------------------------------------------*/
1123 /* WARNING: Data here MUST be in RGBA format, so cannot */
1124 /* go directly into fast mode from app pgm, because */
1125 /* directx requires data in BGRA format. */
1126 /* currently fixupVertices swizels the format, but this isn't */
1127 /* very practical when using VBOS */
1128 /* NOTE: Unless we write a vertex shader to swizel the colour */
1129 /* , or the user doesn't care and wants the speed advantage */
1131 if (sd->u.s.diffuse.lpData != NULL) {
1132 /* Note dwType == float3 or float4 == 2 or 3 */
1133 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1134 sd->u.s.diffuse.dwStride,
1135 sd->u.s.diffuse.lpData));
1137 glColorPointer(4, GL_UNSIGNED_BYTE,
1138 sd->u.s.diffuse.dwStride,
1139 sd->u.s.diffuse.lpData);
1140 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1141 glEnableClientState(GL_COLOR_ARRAY);
1142 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1145 glDisableClientState(GL_COLOR_ARRAY);
1146 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1147 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1148 checkGLcall("glColor4f(1, 1, 1, 1)");
1151 /* Specular Colour ------------------------------------------*/
1152 if (sd->u.s.specular.lpData != NULL) {
1153 TRACE("setting specular colour\n");
1154 /* Note dwType == float3 or float4 == 2 or 3 */
1155 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1156 sd->u.s.specular.dwStride,
1157 sd->u.s.specular.lpData));
1158 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1159 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1160 sd->u.s.specular.dwStride,
1161 sd->u.s.specular.lpData);
1162 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1163 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1164 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1167 /* Missing specular color is not critical, no warnings */
1168 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1172 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1174 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1175 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1176 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1177 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1180 /* Missing specular color is not critical, no warnings */
1181 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1185 /* Texture coords -------------------------------------------*/
1187 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1188 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1189 /* Abort if we don't support the extension. */
1190 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1191 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1195 /* Select the correct texture stage */
1196 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1197 if (This->stateBlock->textures[textureNo] != NULL) {
1198 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1199 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1201 if (coordIdx >= MAX_TEXTURES) {
1202 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1203 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1204 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1206 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1207 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1208 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1209 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1213 /* The coords to supply depend completely on the fvf / vertex shader */
1214 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1215 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1220 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1225 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1226 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1229 if (idxData != NULL /* This crashes sometimes!*/) {
1230 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1231 idxData = idxData == (void *)-1 ? NULL : idxData;
1234 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1235 glEnableClientState(GL_INDEX_ARRAY);
1237 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1238 (const char *)idxData+(idxSize * startIdx));
1239 #else /* using drawRangeElements may be faster */
1241 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1242 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1243 (const char *)idxData+(idxSize * startIdx));
1245 checkGLcall("glDrawRangeElements");
1249 /* Note first is now zero as we shuffled along earlier */
1250 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1251 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1252 checkGLcall("glDrawArrays");
1260 * Actually draw using the supplied information.
1261 * Slower GL version which extracts info about each vertex in turn
1264 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1265 UINT NumVertexes, GLenum glPrimType,
1266 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1268 unsigned int textureNo = 0;
1269 const short *pIdxBufS = NULL;
1270 const long *pIdxBufL = NULL;
1271 LONG SkipnStrides = 0;
1273 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1274 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1275 float rhw = 0.0f; /* rhw */
1276 float ptSize = 0.0f; /* Point size */
1277 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1278 DWORD specularColor = 0; /* Specular Color */
1279 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1281 TRACE("Using slow vertex array code\n");
1283 /* Variable Initialization */
1284 if (idxData != NULL) {
1285 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1286 else pIdxBufL = (const long *) idxData;
1289 /* Start drawing in GL */
1290 VTRACE(("glBegin(%x)\n", glPrimType));
1291 glBegin(glPrimType);
1293 /* For each primitive */
1294 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1296 /* Initialize diffuse color */
1297 diffuseColor = 0xFFFFFFFF;
1299 /* For indexed data, we need to go a few more strides in */
1300 if (idxData != NULL) {
1302 /* Indexed so work out the number of strides to skip */
1304 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1305 SkipnStrides = pIdxBufS[startIdx + vx_index];
1307 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1308 SkipnStrides = pIdxBufL[startIdx + vx_index];
1312 /* Position Information ------------------ */
1313 if (sd->u.s.position.lpData != NULL) {
1315 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1320 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1322 /* RHW follows, only if transformed, ie 4 floats were provided */
1323 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1324 rhw = ptrToCoords[3];
1325 VTRACE(("rhw=%f\n", rhw));
1329 /* Blending data -------------------------- */
1330 if (sd->u.s.blendWeights.lpData != NULL) {
1331 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1332 FIXME("Blending not supported yet\n");
1334 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1335 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1339 /* Vertex Normal Data (untransformed only)- */
1340 if (sd->u.s.normal.lpData != NULL) {
1342 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1343 nx = ptrToCoords[0];
1344 ny = ptrToCoords[1];
1345 nz = ptrToCoords[2];
1346 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1349 /* Point Size ----------------------------- */
1350 if (sd->u.s.pSize.lpData != NULL) {
1352 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1353 ptSize = ptrToCoords[0];
1354 VTRACE(("ptSize=%f\n", ptSize));
1355 FIXME("No support for ptSize yet\n");
1358 /* Diffuse -------------------------------- */
1359 if (sd->u.s.diffuse.lpData != NULL) {
1361 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1362 diffuseColor = ptrToCoords[0];
1363 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1366 /* Specular -------------------------------- */
1367 if (sd->u.s.specular.lpData != NULL) {
1369 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1370 specularColor = ptrToCoords[0];
1371 VTRACE(("specularColor=%lx\n", specularColor));
1374 /* Texture coords --------------------------- */
1375 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1377 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1378 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1382 /* Query tex coords */
1383 if (This->stateBlock->textures[textureNo] != NULL) {
1385 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1386 float *ptrToCoords = NULL;
1387 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1390 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1392 } else if (coordIdx < 0) {
1393 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1397 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1398 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1399 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1403 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1405 /* The coords to supply depend completely on the fvf / vertex shader */
1406 switch (coordsToUse) {
1407 case 4: q = ptrToCoords[3]; /* drop through */
1408 case 3: r = ptrToCoords[2]; /* drop through */
1409 case 2: t = ptrToCoords[1]; /* drop through */
1410 case 1: s = ptrToCoords[0];
1413 /* Projected is more 'fun' - Move the last coord to the 'q'
1414 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1415 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1416 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1418 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1419 switch (coordsToUse) {
1420 case 0: /* Drop Through */
1422 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1434 case 4: /* Nop here */
1437 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1438 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1443 switch (coordsToUse) { /* Supply the provided texture coords */
1444 case D3DTTFF_COUNT1:
1445 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1446 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1447 GL_EXTCALL(glMultiTexCoord1fARB(textureNo, s));
1452 case D3DTTFF_COUNT2:
1453 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1454 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1455 GL_EXTCALL(glMultiTexCoord2fARB(textureNo, s, t));
1460 case D3DTTFF_COUNT3:
1461 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1462 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1463 GL_EXTCALL(glMultiTexCoord3fARB(textureNo, s, t, r));
1465 glTexCoord3f(s, t, r);
1468 case D3DTTFF_COUNT4:
1469 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1470 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1471 GL_EXTCALL(glMultiTexCoord4fARB(textureNo, s, t, r, q));
1473 glTexCoord4f(s, t, r, q);
1477 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1481 } /* End of textures */
1483 /* Diffuse -------------------------------- */
1484 if (sd->u.s.diffuse.lpData != NULL) {
1485 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1486 D3DCOLOR_B_G(diffuseColor),
1487 D3DCOLOR_B_B(diffuseColor),
1488 D3DCOLOR_B_A(diffuseColor));
1489 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1490 D3DCOLOR_B_R(diffuseColor),
1491 D3DCOLOR_B_G(diffuseColor),
1492 D3DCOLOR_B_B(diffuseColor),
1493 D3DCOLOR_B_A(diffuseColor)));
1495 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1498 /* Specular ------------------------------- */
1499 if (sd->u.s.specular.lpData != NULL) {
1500 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1501 D3DCOLOR_B_R(specularColor),
1502 D3DCOLOR_B_G(specularColor),
1503 D3DCOLOR_B_B(specularColor)));
1504 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1505 GL_EXTCALL(glSecondaryColor3ubEXT)(
1506 D3DCOLOR_B_R(specularColor),
1507 D3DCOLOR_B_G(specularColor),
1508 D3DCOLOR_B_B(specularColor));
1510 /* Do not worry if specular colour missing and disable request */
1511 VTRACE(("Specular color extensions not supplied\n"));
1514 if (vx_index == 0) {
1515 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1516 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1518 /* Do not worry if specular colour missing and disable request */
1519 VTRACE(("Specular color extensions not supplied\n"));
1524 /* Normal -------------------------------- */
1525 if (sd->u.s.normal.lpData != NULL) {
1526 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1527 glNormal3f(nx, ny, nz);
1529 if (vx_index == 0) glNormal3f(0, 0, 1);
1532 /* Position -------------------------------- */
1533 if (sd->u.s.position.lpData != NULL) {
1534 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1535 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1536 glVertex3f(x, y, z);
1538 GLfloat w = 1.0 / rhw;
1539 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1540 glVertex4f(x*w, y*w, z*w, w);
1544 /* For non indexed mode, step onto next parts */
1545 if (idxData == NULL) {
1551 checkGLcall("glEnd and previous calls");
1554 #if 0 /* TODO: Software/Hardware vertex blending support */
1556 * Draw with emulated vertex shaders
1557 * Note: strided data is uninitialized, as we need to pass the vertex
1558 * shader directly as ordering irs yet
1560 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1561 int PrimitiveType, ULONG NumPrimitives,
1562 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1564 unsigned int textureNo = 0;
1565 GLenum glPrimType = GL_POINTS;
1566 int NumVertexes = NumPrimitives;
1567 const short *pIdxBufS = NULL;
1568 const long *pIdxBufL = NULL;
1569 LONG SkipnStrides = 0;
1571 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1572 float rhw = 0.0f; /* rhw */
1573 float ptSize = 0.0f; /* Point size */
1574 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1575 int numcoords[8]; /* Number of coords */
1576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1578 IDirect3DVertexShaderImpl* vertexShader = NULL;
1580 TRACE("Using slow software vertex shader code\n");
1582 /* Variable Initialization */
1583 if (idxData != NULL) {
1584 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1585 else pIdxBufL = (const long *) idxData;
1588 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1589 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1591 /* Retrieve the VS information */
1592 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1594 /* Start drawing in GL */
1595 VTRACE(("glBegin(%x)\n", glPrimType));
1596 glBegin(glPrimType);
1598 /* For each primitive */
1599 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1601 /* For indexed data, we need to go a few more strides in */
1602 if (idxData != NULL) {
1604 /* Indexed so work out the number of strides to skip */
1606 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1607 SkipnStrides = pIdxBufS[startIdx+vx_index];
1609 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1610 SkipnStrides = pIdxBufL[startIdx+vx_index];
1614 /* Fill the vertex shader input */
1615 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1617 /* Initialize the output fields to the same defaults as it would normally have */
1618 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1619 vertexShader->output.oD[0].x = 1.0;
1620 vertexShader->output.oD[0].y = 1.0;
1621 vertexShader->output.oD[0].z = 1.0;
1622 vertexShader->output.oD[0].w = 1.0;
1624 /* Now execute the vertex shader */
1625 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1628 TRACE_VECTOR(vertexShader->output.oPos);
1629 TRACE_VECTOR(vertexShader->output.oD[0]);
1630 TRACE_VECTOR(vertexShader->output.oD[1]);
1631 TRACE_VECTOR(vertexShader->output.oT[0]);
1632 TRACE_VECTOR(vertexShader->output.oT[1]);
1633 TRACE_VECTOR(vertexShader->input.V[0]);
1634 TRACE_VECTOR(vertexShader->data->C[0]);
1635 TRACE_VECTOR(vertexShader->data->C[1]);
1636 TRACE_VECTOR(vertexShader->data->C[2]);
1637 TRACE_VECTOR(vertexShader->data->C[3]);
1638 TRACE_VECTOR(vertexShader->data->C[4]);
1639 TRACE_VECTOR(vertexShader->data->C[5]);
1640 TRACE_VECTOR(vertexShader->data->C[6]);
1641 TRACE_VECTOR(vertexShader->data->C[7]);
1644 /* Extract out the output */
1645 /* FIXME: Fog coords? */
1646 x = vertexShader->output.oPos.x;
1647 y = vertexShader->output.oPos.y;
1648 z = vertexShader->output.oPos.z;
1649 rhw = vertexShader->output.oPos.w;
1650 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1652 /** Update textures coords using vertexShader->output.oT[0->7] */
1653 memset(texcoords, 0x00, sizeof(texcoords));
1654 memset(numcoords, 0x00, sizeof(numcoords));
1655 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1656 if (This->stateBlock->textures[textureNo] != NULL) {
1657 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1658 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1659 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1660 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1661 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1662 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1664 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1665 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1666 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1667 default: numcoords[textureNo] = 4;
1671 numcoords[textureNo] = 0;
1675 /* Draw using this information */
1678 TRUE, 0.0f, 0.0f, 1.0f,
1679 TRUE, (float*) &vertexShader->output.oD[0],
1680 TRUE, (float*) &vertexShader->output.oD[1],
1681 FALSE, ptSize, /* FIXME: Change back when supported */
1682 texcoords, numcoords);
1684 /* For non indexed mode, step onto next parts */
1685 if (idxData == NULL) {
1689 } /* for each vertex */
1692 checkGLcall("glEnd and previous calls");
1697 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, BOOL usePixelShaderFunction, int useHW, WineDirect3DVertexStridedData *dataLocations,
1698 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1701 /* Now draw the graphics to the screen */
1702 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1703 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1704 /* Ideally, we should have software FV and hardware VS, possibly
1705 depending on the device type? */
1706 #if 0 /* TODO: vertex and pixel shaders */
1707 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1708 idxData, idxSize, minIndex, StartIdx);
1713 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1714 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1715 int endStride = startStride;
1716 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1718 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1719 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1722 unsigned short *index = (unsigned short *)idxData;
1724 for (t = 0 ; t < numberOfIndicies; t++) {
1725 if (startStride > *index)
1726 startStride = *index;
1727 if (endStride < *index)
1731 } else { /* idxSize == 4 */
1732 unsigned int *index = (unsigned int *)idxData;
1734 for (t = 0 ; t < numberOfIndicies; t++) {
1735 if (startStride > *index)
1736 startStride = *index;
1737 if (endStride < *index)
1743 endStride += numberOfvertices -1;
1746 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1747 /* pre-transform verticex */
1748 /* TODO: Caching, VBO's etc.. */
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 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1768 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1771 /* vertex shaders */
1773 /* If the only vertex data used by the shader is supported by OpenGL then*/
1774 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1775 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1776 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1778 /* Load the vertex data using named arrays */
1779 TRACE("(%p) Loading vertex data\n", This);
1780 loadVertexData(iface, dataLocations);
1782 } else /* Otherwise */
1783 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1785 /* load the array data using ordinal mapping */
1786 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1788 } else { /* If this happens we must drawStridedSlow later on */
1789 TRACE("Not loading vertex data\n");
1792 TRACE("Loaded arrays\n");
1794 if (useVertexShaderFunction) {
1795 IWineD3DVertexDeclarationImpl *vertexDeclaration;
1798 TRACE("Using vertex shader\n");
1800 /* Bind the vertex program */
1801 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1802 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1803 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1805 /* Enable OpenGL vertex programs */
1806 glEnable(GL_VERTEX_PROGRAM_ARB);
1807 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1808 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1809 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1811 /* Vertex Shader 8 constants */
1812 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)
1813 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
1814 if (vertexDeclaration != NULL) {
1815 float *constants = vertexDeclaration->constants;
1816 if (constants != NULL) {
1817 for (i = 0; i <= WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1818 TRACE_(d3d_shader)("Not loading constants %u = %f %f %f %f\n", i,
1819 constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
1820 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
1825 /* Update the constants */
1826 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1827 /* TODO: add support for Integer and Boolean constants */
1828 if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
1830 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i,
1831 &This->stateBlock->vertexShaderConstantF[i * 4]));
1833 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
1834 This->stateBlock->vertexShaderConstantF[i * 4],
1835 This->stateBlock->vertexShaderConstantF[i * 4 + 1],
1836 This->stateBlock->vertexShaderConstantF[i * 4 + 2],
1837 This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
1838 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1843 if (usePixelShaderFunction) {
1846 TRACE("Using pixel shader\n");
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);
1859 /* Update the constants */
1860 for (i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; ++i) {
1861 /* TODO: add support for Integer and Boolean constants */
1862 if (WINESHADERCNST_FLOAT == This->stateBlock->pixelShaderConstantT[i]) {
1863 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
1864 &This->stateBlock->pixelShaderConstantF[i * 4]));
1865 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
1866 This->stateBlock->pixelShaderConstantF[i * 4],
1867 This->stateBlock->pixelShaderConstantF[i * 4 + 1],
1868 This->stateBlock->pixelShaderConstantF[i * 4 + 2],
1869 This->stateBlock->pixelShaderConstantF[i * 4 + 3]);
1870 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1875 /* DirectX colours are in a different format to opengl colours
1876 * so if diffuse or specular are used then we need to use drawStridedSlow
1877 * to correct the colours */
1878 if (!useVertexShaderFunction &&
1879 ((dataLocations->u.s.pSize.lpData != NULL)
1880 || (dataLocations->u.s.diffuse.lpData != NULL)
1881 || (dataLocations->u.s.specular.lpData != NULL))) {
1882 /* TODO: replace drawStridedSlow with veretx fixups */
1884 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1885 idxData, idxSize, minIndex, StartIdx);
1888 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1889 drawStridedFast(iface, numberOfIndicies, glPrimType,
1890 idxData, idxSize, minIndex, StartIdx);
1893 /* Cleanup vertex program */
1894 if (useVertexShaderFunction) {
1895 /* disable any attribs */
1896 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1899 /* Leave all the attribs disabled */
1900 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1901 /* MESA does not support it right not */
1902 if (glGetError() != GL_NO_ERROR)
1904 for (i = 0; i < maxAttribs; ++i) {
1905 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1906 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1910 glDisable(GL_VERTEX_PROGRAM_ARB);
1913 /* Cleanup fragment program */
1914 if (usePixelShaderFunction) {
1915 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1920 void inline drawPrimitiveTraceDataLocations(WineDirect3DVertexStridedData *dataLocations,DWORD fvf) {
1922 /* Dump out what parts we have supplied */
1923 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1924 TRACE_STRIDED((dataLocations), position);
1925 TRACE_STRIDED((dataLocations), blendWeights);
1926 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1927 TRACE_STRIDED((dataLocations), normal);
1928 TRACE_STRIDED((dataLocations), pSize);
1929 TRACE_STRIDED((dataLocations), diffuse);
1930 TRACE_STRIDED((dataLocations), specular);
1931 TRACE_STRIDED((dataLocations), texCoords[0]);
1932 TRACE_STRIDED((dataLocations), texCoords[1]);
1933 TRACE_STRIDED((dataLocations), texCoords[2]);
1934 TRACE_STRIDED((dataLocations), texCoords[3]);
1935 TRACE_STRIDED((dataLocations), texCoords[4]);
1936 TRACE_STRIDED((dataLocations), texCoords[5]);
1937 TRACE_STRIDED((dataLocations), texCoords[6]);
1938 TRACE_STRIDED((dataLocations), texCoords[7]);
1939 TRACE_STRIDED((dataLocations), position2);
1940 TRACE_STRIDED((dataLocations), normal2);
1941 TRACE_STRIDED((dataLocations), tangent);
1942 TRACE_STRIDED((dataLocations), binormal);
1943 TRACE_STRIDED((dataLocations), tessFactor);
1944 TRACE_STRIDED((dataLocations), fog);
1945 TRACE_STRIDED((dataLocations), depth);
1946 TRACE_STRIDED((dataLocations), sample);
1952 /* uploads textures and setup texture states ready for rendering */
1953 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1957 * OK, here we clear down any old junk iect in the context
1958 * enable the new texture and apply any state changes:
1960 * Loop through all textures
1961 * select texture unit
1962 * if there is a texture bound to that unit then..
1963 * disable all textures types on that unit
1964 * enable and bind the texture that is bound to that unit.
1965 * otherwise disable all texture types on that unit.
1967 /* upload the textures */
1968 for (i = 0; i< GL_LIMITS(textures); ++i) {
1969 /* Bind the texture to the stage here */
1970 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1971 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1972 checkGLcall("glActiveTextureARB");
1974 /* This isn't so much a warn as a message to the user about lack of hardware support */
1975 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1978 /* don't bother with textures that have a colorop of disable */
1979 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1980 if (This->stateBlock->textures[i] != NULL) {
1982 glDisable(GL_TEXTURE_1D);
1983 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1984 /* disable all texture states that aren't the selected textures' dimension */
1985 switch(This->stateBlock->textureDimensions[i]) {
1987 glDisable(GL_TEXTURE_3D);
1988 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1991 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1992 glDisable(GL_TEXTURE_2D);
1994 case GLTEXTURECUBEMAP:
1995 glDisable(GL_TEXTURE_2D);
1996 glDisable(GL_TEXTURE_3D);
1999 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2000 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
2001 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2003 glEnable(This->stateBlock->textureDimensions[i]);
2005 /* Load up the texture now */
2006 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2007 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
2008 /* this is a stub function representing the state blocks
2009 * being separated here we are only updating the texture
2010 * state changes, other objects and units get updated when
2011 * they change (or need to be updated), e.g. states that
2012 * relate to a context member line the texture unit are
2013 * only updated when the context needs updating
2015 /* Tell the abse texture to sync it's states */
2016 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2019 /* Bind a default texture if no texture has been set, but colour-op is enabled */
2021 glDisable(GL_TEXTURE_2D);
2022 glDisable(GL_TEXTURE_3D);
2023 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2024 glEnable(GL_TEXTURE_1D);
2025 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2026 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2028 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2029 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2030 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2031 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2032 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2033 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2035 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2036 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2037 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2038 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2041 /* no colorop so disable all the texture states */
2042 glDisable(GL_TEXTURE_1D);
2043 glDisable(GL_TEXTURE_2D);
2044 glDisable(GL_TEXTURE_3D);
2045 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2052 /* Routine common to the draw primitive and draw indexed primitive routines */
2053 void drawPrimitive(IWineD3DDevice *iface,
2057 long StartVertexIndex,
2058 UINT numberOfVertices,
2061 const void *idxData,
2063 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2068 BOOL useVertexShaderFunction = FALSE;
2069 BOOL usePixelShaderFunction = FALSE;
2070 BOOL isLightingOn = FALSE;
2071 WineDirect3DVertexStridedData *dataLocations;
2072 IWineD3DSwapChainImpl *swapchain;
2073 int useHW = FALSE, i;
2075 if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE
2076 &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL
2077 && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
2078 useVertexShaderFunction = TRUE;
2080 useVertexShaderFunction = FALSE;
2083 if (wined3d_settings.ps_mode != PS_NONE && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)
2084 && This->stateBlock->pixelShader
2085 && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function) {
2086 usePixelShaderFunction = TRUE;
2089 if (This->stateBlock->vertexDecl == NULL) {
2090 /* Work out what the FVF should look like */
2091 rc = initializeFVF(iface, &fvf);
2094 TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
2097 /* Invalidate the back buffer memory so LockRect will read it the next time */
2098 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2099 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2101 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer)->Flags |= SFLAG_GLDIRTY;
2102 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2106 /* Ok, we will be updating the screen from here onwards so grab the lock */
2109 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2111 if(DrawPrimStrideData) {
2112 TRACE("================ Strided Input ===================\n");
2113 dataLocations = DrawPrimStrideData;
2115 else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2116 BOOL storeArrays = useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays == FALSE && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays == FALSE;
2118 TRACE("================ Vertex Declaration ===================\n");
2119 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2120 if(!dataLocations) {
2121 ERR("Out of memory!\n");
2124 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fvf, storeArrays,
2125 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
2127 TRACE("================ FVF ===================\n");
2128 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2129 if(!dataLocations) {
2130 ERR("Out of memory!\n");
2133 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex);
2136 /* write out some debug information*/
2137 drawPrimitiveTraceDataLocations(dataLocations, fvf);
2139 /* Setup transform matrices and sort out */
2141 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2142 So make sure lighting is disabled. */
2143 isLightingOn = glIsEnabled(GL_LIGHTING);
2144 glDisable(GL_LIGHTING);
2145 checkGLcall("glDisable(GL_LIGHTING);");
2146 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2148 isLightingOn = primitiveInitState(iface,
2149 fvf & D3DFVF_XYZRHW,
2150 !(fvf & D3DFVF_NORMAL),
2151 useVertexShaderFunction);
2154 /* Now initialize the materials state */
2155 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL));
2157 drawPrimitiveUploadTextures(This);
2162 /* Ok, Work out which primitive is requested and how many vertexes that
2164 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2165 #if 0 /* debugging code... just information not an error */
2166 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2167 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2170 if (numberOfVertices == 0 )
2171 numberOfVertices = calculatedNumberOfindices;
2172 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2175 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2177 /* If vertex shaders or no normals, restore previous lighting state */
2178 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2179 if (isLightingOn) glEnable(GL_LIGHTING);
2180 else glDisable(GL_LIGHTING);
2181 TRACE("Restored lighting to original state\n");
2184 /* Finshed updating the screen, restore lock */
2186 TRACE("Done all gl drawing\n");
2189 #ifdef SHOW_FRAME_MAKEUP
2191 static long int primCounter = 0;
2192 /* NOTE: set primCounter to the value reported by drawprim
2193 before you want to to write frame makeup to /tmp */
2194 if (primCounter >= 0) {
2195 WINED3DLOCKED_RECT r;
2197 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2198 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2199 TRACE("Saving screenshot %s\n", buffer);
2200 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2201 IWineD3DSurface_UnlockRect(This->renderTarget);
2203 #ifdef SHOW_TEXTURE_MAKEUP
2205 IWineD3DSurface *pSur;
2207 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2208 if (This->stateBlock->textures[textureNo] != NULL) {
2209 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2210 TRACE("Saving texture %s\n", buffer);
2211 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2212 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2213 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2214 IWineD3DSurface_Release(pSur);
2216 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2223 TRACE("drawprim #%ld\n", primCounter);