wined3d: Always return the number of elements in the vertex
[wine/hacks.git] / dlls / wined3d / drawprim.c
blob1328967878540f2120c541c72462ad753d229158
1 /*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
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
32 #include <stdio.h>
33 #endif
35 #if 0 /* TODO */
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 */
41 #endif
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
46 to stream 0 */
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
58 streams */
59 #endif
60 *FVFbits = This->stateBlock->fvf;
61 #if 0
62 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
63 #endif
64 return FALSE;
67 /* Issues the glBegin call for gl given the primitive type and count */
68 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
69 DWORD NumPrimitives,
70 GLenum *primType)
72 DWORD NumVertexes = NumPrimitives;
74 switch (PrimitiveType) {
75 case D3DPT_POINTLIST:
76 TRACE("POINTS\n");
77 *primType = GL_POINTS;
78 NumVertexes = NumPrimitives;
79 break;
81 case D3DPT_LINELIST:
82 TRACE("LINES\n");
83 *primType = GL_LINES;
84 NumVertexes = NumPrimitives * 2;
85 break;
87 case D3DPT_LINESTRIP:
88 TRACE("LINE_STRIP\n");
89 *primType = GL_LINE_STRIP;
90 NumVertexes = NumPrimitives + 1;
91 break;
93 case D3DPT_TRIANGLELIST:
94 TRACE("TRIANGLES\n");
95 *primType = GL_TRIANGLES;
96 NumVertexes = NumPrimitives * 3;
97 break;
99 case D3DPT_TRIANGLESTRIP:
100 TRACE("TRIANGLE_STRIP\n");
101 *primType = GL_TRIANGLE_STRIP;
102 NumVertexes = NumPrimitives + 2;
103 break;
105 case D3DPT_TRIANGLEFAN:
106 TRACE("TRIANGLE_FAN\n");
107 *primType = GL_TRIANGLE_FAN;
108 NumVertexes = NumPrimitives + 2;
109 break;
111 default:
112 FIXME("Unhandled primitive\n");
113 *primType = GL_POINTS;
114 break;
116 return NumVertexes;
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");
166 } else {
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 /* Setup views - Transformed & lit if RHW, else untransformed.
184 Only unlit if Normals are supplied
185 Returns: Whether to restore lighting afterwards */
186 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
188 BOOL isLightingOn = FALSE;
189 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
191 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
192 set by the appropriate render state. Note Vertex Shader output is already lit */
193 if (vtx_lit || useVS) {
194 isLightingOn = glIsEnabled(GL_LIGHTING);
195 glDisable(GL_LIGHTING);
196 checkGLcall("glDisable(GL_LIGHTING);");
197 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
200 if (!useVS && vtx_transformed) {
202 /* If the last draw was transformed as well, no need to reapply all the matrixes */
203 if (!This->last_was_rhw) {
205 double X, Y, height, width, minZ, maxZ;
206 This->last_was_rhw = TRUE;
208 /* Transformed already into viewport coordinates, so we do not need transform
209 matrices. Reset all matrices to identity and leave the default matrix in world
210 mode. */
211 glMatrixMode(GL_MODELVIEW);
212 checkGLcall("glMatrixMode(GL_MODELVIEW)");
213 glLoadIdentity();
214 checkGLcall("glLoadIdentity");
216 glMatrixMode(GL_PROJECTION);
217 checkGLcall("glMatrixMode(GL_PROJECTION)");
218 glLoadIdentity();
219 checkGLcall("glLoadIdentity");
221 /* Set up the viewport to be full viewport */
222 X = This->stateBlock->viewport.X;
223 Y = This->stateBlock->viewport.Y;
224 height = This->stateBlock->viewport.Height;
225 width = This->stateBlock->viewport.Width;
226 minZ = This->stateBlock->viewport.MinZ;
227 maxZ = This->stateBlock->viewport.MaxZ;
228 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
229 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
230 checkGLcall("glOrtho");
232 /* Window Coord 0 is the middle of the first pixel, so translate by half
233 a pixel (See comment above glTranslate below) */
234 glTranslatef(0.5, 0.5, 0);
235 checkGLcall("glTranslatef(0.5, 0.5, 0)");
236 if (This->renderUpsideDown) {
237 glMultMatrixf(invymat);
238 checkGLcall("glMultMatrixf(invymat)");
242 } else {
244 /* Untransformed, so relies on the view and projection matrices */
246 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
247 /* Only reapply when have to */
248 This->modelview_valid = TRUE;
249 glMatrixMode(GL_MODELVIEW);
250 checkGLcall("glMatrixMode");
252 /* In the general case, the view matrix is the identity matrix */
253 if (This->view_ident) {
254 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
255 checkGLcall("glLoadMatrixf");
256 } else {
257 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
258 checkGLcall("glLoadMatrixf");
259 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
260 checkGLcall("glMultMatrixf");
264 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
265 /* Only reapply when have to */
266 This->proj_valid = TRUE;
267 glMatrixMode(GL_PROJECTION);
268 checkGLcall("glMatrixMode");
270 /* The rule is that the window coordinate 0 does not correspond to the
271 beginning of the first pixel, but the center of the first pixel.
272 As a consequence if you want to correctly draw one line exactly from
273 the left to the right end of the viewport (with all matrices set to
274 be identity), the x coords of both ends of the line would be not
275 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
276 instead. */
277 glLoadIdentity();
279 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
280 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
282 if (This->renderUpsideDown) {
283 glMultMatrixf(invymat);
284 checkGLcall("glMultMatrixf(invymat)");
286 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
287 checkGLcall("glLoadMatrixf");
290 /* Vertex Shader output is already transformed, so set up identity matrices */
291 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
292 come along this needs to take into account whether s/w ones were
293 requested or not */
294 if (useVS) {
295 glMatrixMode(GL_MODELVIEW);
296 checkGLcall("glMatrixMode");
297 glLoadIdentity();
298 glMatrixMode(GL_PROJECTION);
299 checkGLcall("glMatrixMode");
300 glLoadIdentity();
301 /* Window Coord 0 is the middle of the first pixel, so translate by half
302 a pixel (See comment above glTranslate above) */
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)");
305 if (This->renderUpsideDown) {
306 glMultMatrixf(invymat);
307 checkGLcall("glMultMatrixf(invymat)");
309 This->modelview_valid = FALSE;
310 This->proj_valid = FALSE;
312 This->last_was_rhw = FALSE;
314 return isLightingOn;
317 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, BOOL useVertexShaderFunction, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf, BOOL storeOrder, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
318 /* We need to deal with frequency data!*/
320 int textureNo =0;
321 BYTE *data = NULL;
322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
323 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
324 int i;
325 WINED3DVERTEXELEMENT *element;
326 DWORD stride;
328 /* Locate the vertex declaration */
329 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
330 TRACE("Using vertex declaration from shader\n");
331 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
332 } else {
333 TRACE("Using vertex declaration\n");
334 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
337 /* Translate the declaration into strided data */
338 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
340 element = vertexDeclaration->pDeclarationWine + i;
341 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
342 if (This->stateBlock->streamIsUP) {
343 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
344 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
345 } else {
346 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
347 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
349 stride = This->stateBlock->streamStride[element->Stream];
350 data += (BaseVertexIndex * stride);
351 data += element->Offset;
353 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
354 switch (element->Usage) {
355 case D3DDECLUSAGE_POSITION:
356 switch (element->UsageIndex) {
357 case 0: /* N-patch */
358 strided->u.s.position.lpData = data;
359 strided->u.s.position.dwType = element->Type;
360 strided->u.s.position.dwStride = stride;
361 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data, element->Type, stride);
362 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = element->Reg;
363 break;
364 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
365 TRACE("Tweened positions\n");
366 strided->u.s.position2.lpData = data;
367 strided->u.s.position2.dwType = element->Type;
368 strided->u.s.position2.dwStride = stride;
369 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data, element->Type, stride);
370 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2] = element->Reg;
371 break;
373 break;
374 case D3DDECLUSAGE_NORMAL:
375 switch (element->UsageIndex) {
376 case 0: /* N-patch */
377 strided->u.s.normal.lpData = data;
378 strided->u.s.normal.dwType = element->Type;
379 strided->u.s.normal.dwStride = stride;
380 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data, element->Type, stride);
381 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = element->Reg;
382 break;
383 case 1: /* skinning */
384 TRACE("Skinning / tween normals\n");
385 strided->u.s.normal2.lpData = data;
386 strided->u.s.normal2.dwType = element->Type;
387 strided->u.s.normal2.dwStride = stride;
388 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data, element->Type, stride);
389 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = element->Reg;
390 break;
392 *fvf |= D3DFVF_NORMAL;
393 break;
394 case D3DDECLUSAGE_BLENDINDICES:
395 /* demo @http://www.ati.com/developer/vertexblend.html
396 and http://www.flipcode.com/articles/article_dx8shaders.shtml
398 strided->u.s.blendMatrixIndices.lpData = data;
399 strided->u.s.blendMatrixIndices.dwType = element->Type;
400 strided->u.s.blendMatrixIndices.dwStride= stride;
401 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendMatrixIndices", data, element->Type, stride);
402 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = element->Reg;
403 break;
404 case D3DDECLUSAGE_BLENDWEIGHT:
405 strided->u.s.blendWeights.lpData = data;
406 strided->u.s.blendWeights.dwType = element->Type;
407 strided->u.s.blendWeights.dwStride = stride;
408 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data, element->Type, stride);
409 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = element->Reg;
410 break;
411 case D3DDECLUSAGE_PSIZE:
412 strided->u.s.pSize.lpData = data;
413 strided->u.s.pSize.dwType = element->Type;
414 strided->u.s.pSize.dwStride = stride;
415 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data, element->Type, stride);
416 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = element->Reg;
417 break;
418 case D3DDECLUSAGE_COLOR:
419 switch (element->UsageIndex) {
420 case 0:/* diffuse */
421 strided->u.s.diffuse.lpData = data;
422 strided->u.s.diffuse.dwType = element->Type;
423 strided->u.s.diffuse.dwStride = stride;
424 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data, element->Type, stride);
425 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = element->Reg;
426 break;
427 case 1: /* specular */
428 strided->u.s.specular.lpData = data;
429 strided->u.s.specular.dwType = element->Type;
430 strided->u.s.specular.dwStride = stride;
431 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data, element->Type, stride);
432 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = element->Reg;
436 break;
437 case D3DDECLUSAGE_TEXCOORD:
438 /* For some odd reason Microsoft decided to sum usage accross all the streams,
439 which means we need to do a count and not just use the usage number */
441 strided->u.s.texCoords[textureNo].lpData = data;
442 strided->u.s.texCoords[textureNo].dwType = element->Type;
443 strided->u.s.texCoords[textureNo].dwStride = stride;
444 TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo, data, element->Type, stride);
445 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + textureNo] = element->Reg;
447 ++textureNo;
448 break;
449 case D3DDECLUSAGE_TANGENT:
450 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
451 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
452 normal using tangents where no normal data has been provided */
453 TRACE("Tangents\n");
454 strided->u.s.tangent.lpData = data;
455 strided->u.s.tangent.dwType = element->Type;
456 strided->u.s.tangent.dwStride = stride;
457 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data, element->Type, stride);
458 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = element->Reg;
459 break;
460 case D3DDECLUSAGE_BINORMAL:
461 /* 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.
462 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)
463 The only thing they are useful for in fixed function would be working out normals when none are given.
465 TRACE("BI-Normal\n");
466 strided->u.s.binormal.lpData = data;
467 strided->u.s.binormal.dwType = element->Type;
468 strided->u.s.binormal.dwStride = stride;
469 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data, element->Type, stride);
470 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = element->Reg;
471 break;
472 case D3DDECLUSAGE_TESSFACTOR:
473 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
475 TRACE("Tess Factor\n");
476 strided->u.s.tessFactor.lpData = data;
477 strided->u.s.tessFactor.dwType = element->Type;
478 strided->u.s.tessFactor.dwStride = stride;
479 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data, element->Type, stride);
480 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = element->Reg;
481 break;
482 case D3DDECLUSAGE_POSITIONT:
484 switch (element->UsageIndex) {
485 case 0: /* N-patch */
486 strided->u.s.position.lpData = data;
487 strided->u.s.position.dwType = element->Type;
488 strided->u.s.position.dwStride = stride;
489 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data, element->Type, stride);
490 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = element->Reg;
491 break;
492 case 1: /* skinning */
493 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
494 http://xface.blogspot.com/2004_08_01_xface_archive.html
496 TRACE("Skinning positionsT\n");
497 strided->u.s.position2.lpData = data;
498 strided->u.s.position2.dwType = element->Type;
499 strided->u.s.position2.dwStride = stride;
500 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data, element->Type, stride);
501 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = element->Reg;
502 break;
504 /* TODO: change fvf usage to a plain boolean flag */
505 *fvf |= D3DFVF_XYZRHW;
506 /* FIXME: were faking this flag so that we don't transform the data again */
507 break;
508 case D3DDECLUSAGE_FOG:
509 /* maybe GL_EXT_fog_coord ?
510 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
511 * This extension allows specifying an explicit per-vertex fog
512 * coordinate to be used in fog computations, rather than using a
513 * fragment depth-based fog equation.
515 * */
516 TRACE("Fog\n");
517 strided->u.s.fog.lpData = data;
518 strided->u.s.fog.dwType = element->Type;
519 strided->u.s.fog.dwStride = stride;
520 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data, element->Type, stride);
521 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = element->Reg;
522 break;
523 case D3DDECLUSAGE_DEPTH:
524 TRACE("depth\n");
525 strided->u.s.depth.lpData = data;
526 strided->u.s.depth.dwType = element->Type;
527 strided->u.s.depth.dwStride = stride;
528 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data, element->Type, stride);
529 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = element->Reg;
530 break;
531 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
532 TRACE("depth\n");
533 strided->u.s.sample.lpData = data;
534 strided->u.s.sample.dwType = element->Type;
535 strided->u.s.sample.dwStride = stride;
536 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data, element->Type, stride);
537 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = element->Reg;
538 break;
545 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
547 short LoopThroughTo = 0;
548 short nStream;
549 int numBlends;
550 int numTextures;
551 int textureNo;
552 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
553 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
557 /* OK, Now to setup the data locations
558 For the non-created vertex shaders, the VertexShader var holds the real
559 FVF and only stream 0 matters
560 For the created vertex shaders, there is an FVF per stream */
561 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
562 LoopThroughTo = MAX_STREAMS;
563 } else {
564 LoopThroughTo = 1;
567 /* Work through stream by stream */
568 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
569 DWORD stride = This->stateBlock->streamStride[nStream];
570 BYTE *data = NULL;
571 DWORD thisFVF = 0;
573 /* Skip empty streams */
574 if (This->stateBlock->streamSource[nStream] == NULL) continue;
576 /* Retrieve appropriate FVF */
577 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
578 thisFVF = This->stateBlock->fvf;
579 /* Handle memory passed directly as well as vertex buffers */
580 if (This->stateBlock->streamIsUP) {
581 data = (BYTE *)This->stateBlock->streamSource[nStream];
582 } else {
583 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
585 } else {
586 #if 0 /* TODO: Vertex shader support */
587 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
588 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
589 #endif
591 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
592 if (thisFVF == 0) continue;
594 /* Now convert the stream into pointers */
596 /* Shuffle to the beginning of the vertexes to render and index from there */
597 data = data + (BaseVertexIndex * stride);
599 /* Either 3 or 4 floats depending on the FVF */
600 /* FIXME: Can blending data be in a different stream to the position data?
601 and if so using the fixed pipeline how do we handle it */
602 if (thisFVF & D3DFVF_POSITION_MASK) {
603 strided->u.s.position.lpData = data;
604 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
605 strided->u.s.position.dwStride = stride;
606 data += 3 * sizeof(float);
607 if (thisFVF & D3DFVF_XYZRHW) {
608 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
609 data += sizeof(float);
613 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
614 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
615 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
616 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
618 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
619 TRACE("Setting blend Weights to %p\n", data);
620 strided->u.s.blendWeights.lpData = data;
621 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
622 strided->u.s.blendWeights.dwStride = stride;
623 data += numBlends * sizeof(FLOAT);
625 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
626 strided->u.s.blendMatrixIndices.lpData = data;
627 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
628 strided->u.s.blendMatrixIndices.dwStride= stride;
629 data += sizeof(DWORD);
633 /* Normal is always 3 floats */
634 if (thisFVF & D3DFVF_NORMAL) {
635 strided->u.s.normal.lpData = data;
636 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
637 strided->u.s.normal.dwStride = stride;
638 data += 3 * sizeof(FLOAT);
641 /* Pointsize is a single float */
642 if (thisFVF & D3DFVF_PSIZE) {
643 strided->u.s.pSize.lpData = data;
644 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
645 strided->u.s.pSize.dwStride = stride;
646 data += sizeof(FLOAT);
649 /* Diffuse is 4 unsigned bytes */
650 if (thisFVF & D3DFVF_DIFFUSE) {
651 strided->u.s.diffuse.lpData = data;
652 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
653 strided->u.s.diffuse.dwStride = stride;
654 data += sizeof(DWORD);
657 /* Specular is 4 unsigned bytes */
658 if (thisFVF & D3DFVF_SPECULAR) {
659 strided->u.s.specular.lpData = data;
660 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
661 strided->u.s.specular.dwStride = stride;
662 data += sizeof(DWORD);
665 /* Texture coords */
666 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
667 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
669 /* numTextures indicates the number of texture coordinates supplied */
670 /* However, the first set may not be for stage 0 texture - it all */
671 /* depends on D3DTSS_TEXCOORDINDEX. */
672 /* The number of bytes for each coordinate set is based off */
673 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
675 /* So, for each supplied texture extract the coords */
676 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
678 strided->u.s.texCoords[textureNo].lpData = data;
679 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
680 strided->u.s.texCoords[textureNo].dwStride = stride;
681 numCoords[textureNo] = coordIdxInfo & 0x03;
683 /* Always one set */
684 data += sizeof(float);
685 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
686 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
687 data += sizeof(float);
688 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
689 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
690 data += sizeof(float);
691 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
692 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
693 data += sizeof(float);
697 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
702 #if 0 /* TODO: Software Shaders */
703 /* Draw a single vertex using this information */
704 static void draw_vertex(IWineD3DDevice *iface, /* interface */
705 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
706 BOOL isNormal, float nx, float ny, float nz, /* normal */
707 BOOL isDiffuse, float *dRGBA, /* 1st colors */
708 BOOL isSpecular, float *sRGB, /* 2ndry colors */
709 BOOL isPtSize, float ptSize, /* pointSize */
710 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
712 unsigned int textureNo;
713 float s, t, r, q;
714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
716 /* Diffuse -------------------------------- */
717 if (isDiffuse) {
718 glColor4fv(dRGBA);
719 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
722 /* Specular Colour ------------------------------------------*/
723 if (isSpecular) {
724 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
725 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
726 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
727 } else {
728 VTRACE(("Specular color extensions not supplied\n"));
732 /* Normal -------------------------------- */
733 if (isNormal) {
734 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
735 glNormal3f(nx, ny, nz);
738 /* Point Size ----------------------------------------------*/
739 if (isPtSize) {
741 /* no such functionality in the fixed function GL pipeline */
742 FIXME("Cannot change ptSize here in openGl\n");
745 /* Texture coords --------------------------- */
746 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
748 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
749 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
750 continue ;
753 /* Query tex coords */
754 if (This->stateBlock->textures[textureNo] != NULL) {
756 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
757 if (coordIdx >= MAX_TEXTURES) {
758 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
759 continue;
760 } else if (numcoords[coordIdx] == 0) {
761 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
762 continue;
763 } else {
765 /* Initialize vars */
766 s = 0.0f;
767 t = 0.0f;
768 r = 0.0f;
769 q = 0.0f;
771 switch (numcoords[coordIdx]) {
772 case 4: q = texcoords[coordIdx].w; /* drop through */
773 case 3: r = texcoords[coordIdx].z; /* drop through */
774 case 2: t = texcoords[coordIdx].y; /* drop through */
775 case 1: s = texcoords[coordIdx].x;
778 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
779 case D3DTTFF_COUNT1:
780 VTRACE(("tex:%d, s=%f\n", textureNo, s));
781 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
782 GLMULTITEXCOORD1F(textureNo, s);
783 } else {
784 glTexCoord1f(s);
786 break;
787 case D3DTTFF_COUNT2:
788 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
789 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
790 GLMULTITEXCOORD2F(textureNo, s, t);
791 } else {
792 glTexCoord2f(s, t);
794 break;
795 case D3DTTFF_COUNT3:
796 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
797 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
798 GLMULTITEXCOORD3F(textureNo, s, t, r);
799 } else {
800 glTexCoord3f(s, t, r);
802 break;
803 case D3DTTFF_COUNT4:
804 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
805 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
806 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
807 } else {
808 glTexCoord4f(s, t, r, q);
810 break;
811 default:
812 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
816 } /* End of textures */
818 /* Position -------------------------------- */
819 if (isXYZ) {
820 if (1.0f == rhw || rhw < 0.00001f) {
821 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
822 glVertex3f(x, y, z);
823 } else {
824 /* Cannot optimize by dividing through by rhw as rhw is required
825 later for perspective in the GL pipeline for vertex shaders */
826 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
827 glVertex4f(x,y,z,rhw);
831 #endif /* TODO: Software shaders */
833 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
836 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
837 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
838 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
839 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
840 WINED3D_ATR_SIZE(_arrayName), \
841 WINED3D_ATR_GLTYPE(_arrayName), \
842 WINED3D_ATR_NORMALIZED(_arrayName), \
843 sd->u.s._arrayName.dwStride, \
844 sd->u.s._arrayName.lpData)); \
845 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
849 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
850 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
851 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
852 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
853 WINED3D_ATR_SIZE(position2), \
854 WINED3D_ATR_GLTYPE(position2), \
855 WINED3D_ATR_NORMALIZED(position2), \
856 sd->u.s.position2.dwStride, \
857 ((char *)sd->u.s.position2.lpData) + \
858 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
859 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
862 /* Generate some lookup tables */
863 /* drop the RHW coord, there must be a nicer way of doing this. */
864 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
865 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
867 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
868 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
869 LOAD_NUMBERED_ARRAY(position,POSITION);
870 LOAD_NUMBERED_ARRAY(normal,NORMAL);
871 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
872 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
873 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
874 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
875 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
876 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
877 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
878 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
879 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
880 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
881 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
882 #if 0 /* TODO: Samplers may allow for more texture coords */
883 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
884 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
885 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
886 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
887 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
888 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
889 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
890 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
891 #endif
892 LOAD_NUMBERED_ARRAY(position,POSITIONT);
893 /* d3d9 types */
894 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
895 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
896 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
897 LOAD_NUMBERED_ARRAY(position2,POSITION2);
898 /* there can be lots of position arrays */
899 LOAD_NUMBERED_POSITION_ARRAY(0);
900 LOAD_NUMBERED_POSITION_ARRAY(1);
901 LOAD_NUMBERED_POSITION_ARRAY(2);
902 LOAD_NUMBERED_POSITION_ARRAY(3);
903 LOAD_NUMBERED_POSITION_ARRAY(4);
904 LOAD_NUMBERED_POSITION_ARRAY(5);
905 LOAD_NUMBERED_POSITION_ARRAY(6);
906 LOAD_NUMBERED_POSITION_ARRAY(7);
907 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
908 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
909 LOAD_NUMBERED_ARRAY(fog,FOG);
910 LOAD_NUMBERED_ARRAY(depth,DEPTH);
911 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
913 #undef LOAD_NUMBERED_ARRAY
916 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
917 unsigned int textureNo = 0;
918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
920 TRACE("Using fast vertex array code\n");
921 /* Blend Data ---------------------------------------------- */
922 if ((sd->u.s.blendWeights.lpData != NULL) ||
923 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
926 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
928 #if 1
929 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
930 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
931 #endif
933 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
934 /* FIXME("TODO\n");*/
935 /* Note dwType == float3 or float4 == 2 or 3 */
937 #if 0
938 /* with this on, the normals appear to be being modified,
939 but the vertices aren't being translated as they should be
940 Maybe the world matrix aren't being setup properly? */
941 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
942 #endif
945 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
946 WINED3D_ATR_SIZE(blendWeights) ,
947 sd->u.s.blendWeights.dwStride,
948 sd->u.s.blendWeights.lpData));
950 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
951 sd->u.s.blendWeights.dwStride,
952 sd->u.s.blendWeights.lpData);
954 checkGLcall("glWeightPointerARB");
956 if(sd->u.s.blendMatrixIndices.lpData != NULL){
957 static BOOL showfixme = TRUE;
958 if(showfixme){
959 FIXME("blendMatrixIndices support\n");
960 showfixme = FALSE;
966 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
967 /* FIXME("TODO\n");*/
968 #if 0
970 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
971 sd->u.s.blendWeights.dwStride,
972 sd->u.s.blendWeights.lpData);
973 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
974 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
975 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
976 #endif
978 } else {
979 /* TODO: support blends in fixupVertices */
980 FIXME("unsupported blending in openGl\n");
982 } else {
983 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
984 #if 0 /* TODO: Vertex blending */
985 glDisable(GL_VERTEX_BLEND_ARB);
986 #endif
987 TRACE("ARB_VERTEX_BLEND\n");
988 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
989 TRACE(" EXT_VERTEX_WEIGHTING\n");
990 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
991 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
996 #if 0 /* FOG ----------------------------------------------*/
997 if (sd->u.s.fog.lpData != NULL) {
998 /* TODO: fog*/
999 if (GL_SUPPORT(EXT_FOG_COORD) {
1000 glEnableClientState(GL_FOG_COORD_EXT);
1001 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
1002 sd->u.s.fog.dwStride,
1003 sd->u.s.fog.lpData);
1004 } else {
1005 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1006 /* FIXME: fixme once */
1007 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1009 } else {
1010 if (GL_SUPPRT(EXT_FOR_COORD) {
1011 /* make sure fog is disabled */
1012 glDisableClientState(GL_FOG_COORD_EXT);
1015 #endif
1017 #if 0 /* tangents ----------------------------------------------*/
1018 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
1019 /* TODO: tangents*/
1020 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1021 if (sd->u.s.tangent.lpData != NULL) {
1022 glEnable(GL_TANGENT_ARRAY_EXT);
1023 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
1024 sd->u.s.tangent.dwStride,
1025 sd->u.s.tangent.lpData);
1026 } else {
1027 glDisable(GL_TANGENT_ARRAY_EXT);
1029 if (sd->u.s.binormal.lpData != NULL) {
1030 glEnable(GL_BINORMAL_ARRAY_EXT);
1031 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
1032 sd->u.s.binormal.dwStride,
1033 sd->u.s.binormal.lpData);
1034 } else{
1035 glDisable(GL_BINORMAL_ARRAY_EXT);
1038 } else {
1039 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1040 /* FIXME: fixme once */
1041 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1043 } else {
1044 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1045 /* make sure fog is disabled */
1046 glDisable(GL_TANGENT_ARRAY_EXT);
1047 glDisable(GL_BINORMAL_ARRAY_EXT);
1050 #endif
1052 /* Point Size ----------------------------------------------*/
1053 if (sd->u.s.pSize.lpData != NULL) {
1055 /* no such functionality in the fixed function GL pipeline */
1056 TRACE("Cannot change ptSize here in openGl\n");
1057 /* TODO: Implement this function in using shaders if they are available */
1061 /* Vertex Pointers -----------------------------------------*/
1062 if (sd->u.s.position.lpData != NULL) {
1063 /* Note dwType == float3 or float4 == 2 or 3 */
1064 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1065 sd->u.s.position.dwStride,
1066 sd->u.s.position.dwType + 1,
1067 sd->u.s.position.lpData));
1069 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1070 handling for rhw mode should not impact screen position whereas in GL it does.
1071 This may result in very slightly distored textures in rhw mode, but
1072 a very minimal different. There's always the other option of
1073 fixing the view matrix to prevent w from having any effect */
1074 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1075 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1076 checkGLcall("glVertexPointer(...)");
1077 glEnableClientState(GL_VERTEX_ARRAY);
1078 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1080 } else {
1081 glDisableClientState(GL_VERTEX_ARRAY);
1082 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1085 /* Normals -------------------------------------------------*/
1086 if (sd->u.s.normal.lpData != NULL) {
1087 /* Note dwType == float3 or float4 == 2 or 3 */
1088 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1089 sd->u.s.normal.dwStride,
1090 sd->u.s.normal.lpData));
1091 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1092 sd->u.s.normal.dwStride,
1093 sd->u.s.normal.lpData);
1094 checkGLcall("glNormalPointer(...)");
1095 glEnableClientState(GL_NORMAL_ARRAY);
1096 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1098 } else {
1099 glDisableClientState(GL_NORMAL_ARRAY);
1100 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1101 glNormal3f(0, 0, 1);
1102 checkGLcall("glNormal3f(0, 0, 1)");
1105 /* Diffuse Colour --------------------------------------------*/
1106 /* WARNING: Data here MUST be in RGBA format, so cannot */
1107 /* go directly into fast mode from app pgm, because */
1108 /* directx requires data in BGRA format. */
1109 /* currently fixupVertices swizels the format, but this isn't */
1110 /* very practical when using VBOS */
1111 /* NOTE: Unless we write a vertex shader to swizel the colour */
1112 /* , or the user doesn't care and wants the speed advantage */
1114 if (sd->u.s.diffuse.lpData != NULL) {
1115 /* Note dwType == float3 or float4 == 2 or 3 */
1116 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1117 sd->u.s.diffuse.dwStride,
1118 sd->u.s.diffuse.lpData));
1120 glColorPointer(4, GL_UNSIGNED_BYTE,
1121 sd->u.s.diffuse.dwStride,
1122 sd->u.s.diffuse.lpData);
1123 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1124 glEnableClientState(GL_COLOR_ARRAY);
1125 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1127 } else {
1128 glDisableClientState(GL_COLOR_ARRAY);
1129 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1130 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1131 checkGLcall("glColor4f(1, 1, 1, 1)");
1134 /* Specular Colour ------------------------------------------*/
1135 if (sd->u.s.specular.lpData != NULL) {
1136 TRACE("setting specular colour\n");
1137 /* Note dwType == float3 or float4 == 2 or 3 */
1138 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1139 sd->u.s.specular.dwStride,
1140 sd->u.s.specular.lpData));
1141 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1142 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1143 sd->u.s.specular.dwStride,
1144 sd->u.s.specular.lpData);
1145 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1146 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1147 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1148 } else {
1150 /* Missing specular color is not critical, no warnings */
1151 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1154 } else {
1155 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1157 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1158 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1159 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1160 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1161 } else {
1163 /* Missing specular color is not critical, no warnings */
1164 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1168 /* Texture coords -------------------------------------------*/
1170 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1172 /* Select the correct texture stage */
1173 GLCLIENTACTIVETEXTURE(textureNo);
1174 if (This->stateBlock->textures[textureNo] != NULL) {
1175 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1176 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1177 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1178 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1179 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1180 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1181 continue;
1184 if (coordIdx >= MAX_TEXTURES) {
1185 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1186 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1187 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1189 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1190 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1191 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1192 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1194 } else {
1196 /* The coords to supply depend completely on the fvf / vertex shader */
1197 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1198 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1201 } else {
1202 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1203 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1208 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1209 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1210 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1212 if (idxData != NULL /* This crashes sometimes!*/) {
1213 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1214 idxData = idxData == (void *)-1 ? NULL : idxData;
1215 #if 1
1216 #if 0
1217 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1218 glEnableClientState(GL_INDEX_ARRAY);
1219 #endif
1220 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1221 (const char *)idxData+(idxSize * startIdx));
1222 #else /* using drawRangeElements may be faster */
1224 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1225 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1226 (const char *)idxData+(idxSize * startIdx));
1227 #endif
1228 checkGLcall("glDrawRangeElements");
1230 } else {
1232 /* Note first is now zero as we shuffled along earlier */
1233 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1234 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1235 checkGLcall("glDrawArrays");
1239 return;
1243 * Actually draw using the supplied information.
1244 * Slower GL version which extracts info about each vertex in turn
1247 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1248 UINT NumVertexes, GLenum glPrimType,
1249 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1251 unsigned int textureNo = 0;
1252 const short *pIdxBufS = NULL;
1253 const long *pIdxBufL = NULL;
1254 LONG SkipnStrides = 0;
1255 LONG vx_index;
1256 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1257 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1258 float rhw = 0.0f; /* rhw */
1259 float ptSize = 0.0f; /* Point size */
1260 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1261 DWORD specularColor = 0; /* Specular Color */
1262 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1264 TRACE("Using slow vertex array code\n");
1266 /* Variable Initialization */
1267 if (idxData != NULL) {
1268 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1269 else pIdxBufL = (const long *) idxData;
1272 /* Start drawing in GL */
1273 VTRACE(("glBegin(%x)\n", glPrimType));
1274 glBegin(glPrimType);
1276 /* For each primitive */
1277 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1279 /* Initialize diffuse color */
1280 diffuseColor = 0xFFFFFFFF;
1282 /* For indexed data, we need to go a few more strides in */
1283 if (idxData != NULL) {
1285 /* Indexed so work out the number of strides to skip */
1286 if (idxSize == 2) {
1287 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1288 SkipnStrides = pIdxBufS[startIdx + vx_index];
1289 } else {
1290 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1291 SkipnStrides = pIdxBufL[startIdx + vx_index];
1295 /* Position Information ------------------ */
1296 if (sd->u.s.position.lpData != NULL) {
1298 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1299 x = ptrToCoords[0];
1300 y = ptrToCoords[1];
1301 z = ptrToCoords[2];
1302 rhw = 1.0;
1303 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1305 /* RHW follows, only if transformed, ie 4 floats were provided */
1306 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1307 rhw = ptrToCoords[3];
1308 VTRACE(("rhw=%f\n", rhw));
1312 /* Blending data -------------------------- */
1313 if (sd->u.s.blendWeights.lpData != NULL) {
1314 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1315 FIXME("Blending not supported yet\n");
1317 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1318 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1322 /* Vertex Normal Data (untransformed only)- */
1323 if (sd->u.s.normal.lpData != NULL) {
1325 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1326 nx = ptrToCoords[0];
1327 ny = ptrToCoords[1];
1328 nz = ptrToCoords[2];
1329 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1332 /* Point Size ----------------------------- */
1333 if (sd->u.s.pSize.lpData != NULL) {
1335 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1336 ptSize = ptrToCoords[0];
1337 VTRACE(("ptSize=%f\n", ptSize));
1338 FIXME("No support for ptSize yet\n");
1341 /* Diffuse -------------------------------- */
1342 if (sd->u.s.diffuse.lpData != NULL) {
1344 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1345 diffuseColor = ptrToCoords[0];
1346 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1349 /* Specular -------------------------------- */
1350 if (sd->u.s.specular.lpData != NULL) {
1352 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1353 specularColor = ptrToCoords[0];
1354 VTRACE(("specularColor=%lx\n", specularColor));
1357 /* Texture coords --------------------------- */
1358 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1360 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1361 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1362 continue ;
1365 /* Query tex coords */
1366 if (This->stateBlock->textures[textureNo] != NULL) {
1368 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1369 float *ptrToCoords = NULL;
1370 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1372 if (coordIdx > 7) {
1373 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1374 continue;
1375 } else if (coordIdx < 0) {
1376 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1377 continue;
1380 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1381 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1382 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1383 continue;
1384 } else {
1386 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1388 /* The coords to supply depend completely on the fvf / vertex shader */
1389 switch (coordsToUse) {
1390 case 4: q = ptrToCoords[3]; /* drop through */
1391 case 3: r = ptrToCoords[2]; /* drop through */
1392 case 2: t = ptrToCoords[1]; /* drop through */
1393 case 1: s = ptrToCoords[0];
1396 /* Projected is more 'fun' - Move the last coord to the 'q'
1397 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1398 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1399 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1401 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1402 switch (coordsToUse) {
1403 case 0: /* Drop Through */
1404 case 1:
1405 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1406 break;
1407 case 2:
1408 q = t;
1409 t = 0.0;
1410 coordsToUse = 4;
1411 break;
1412 case 3:
1413 q = r;
1414 r = 0.0;
1415 coordsToUse = 4;
1416 break;
1417 case 4: /* Nop here */
1418 break;
1419 default:
1420 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1421 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1426 switch (coordsToUse) { /* Supply the provided texture coords */
1427 case D3DTTFF_COUNT1:
1428 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1429 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1430 GLMULTITEXCOORD1F(textureNo, s);
1431 } else {
1432 glTexCoord1f(s);
1434 break;
1435 case D3DTTFF_COUNT2:
1436 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1437 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1438 GLMULTITEXCOORD2F(textureNo, s, t);
1439 } else {
1440 glTexCoord2f(s, t);
1442 break;
1443 case D3DTTFF_COUNT3:
1444 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1445 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1446 GLMULTITEXCOORD3F(textureNo, s, t, r);
1447 } else {
1448 glTexCoord3f(s, t, r);
1450 break;
1451 case D3DTTFF_COUNT4:
1452 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1453 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1454 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1455 } else {
1456 glTexCoord4f(s, t, r, q);
1458 break;
1459 default:
1460 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1464 } /* End of textures */
1466 /* Diffuse -------------------------------- */
1467 if (sd->u.s.diffuse.lpData != NULL) {
1468 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1469 D3DCOLOR_B_G(diffuseColor),
1470 D3DCOLOR_B_B(diffuseColor),
1471 D3DCOLOR_B_A(diffuseColor));
1472 VTRACE(("glColor4ub: r,g,b,a=%u,%u,%u,%u\n",
1473 D3DCOLOR_B_R(diffuseColor),
1474 D3DCOLOR_B_G(diffuseColor),
1475 D3DCOLOR_B_B(diffuseColor),
1476 D3DCOLOR_B_A(diffuseColor)));
1477 } else {
1478 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1481 /* Specular ------------------------------- */
1482 if (sd->u.s.specular.lpData != NULL) {
1483 VTRACE(("glSecondaryColor4ub: r,g,b=%u,%u,%u\n",
1484 D3DCOLOR_B_R(specularColor),
1485 D3DCOLOR_B_G(specularColor),
1486 D3DCOLOR_B_B(specularColor)));
1487 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1488 GL_EXTCALL(glSecondaryColor3ubEXT)(
1489 D3DCOLOR_B_R(specularColor),
1490 D3DCOLOR_B_G(specularColor),
1491 D3DCOLOR_B_B(specularColor));
1492 } else {
1493 /* Do not worry if specular colour missing and disable request */
1494 VTRACE(("Specular color extensions not supplied\n"));
1496 } else {
1497 if (vx_index == 0) {
1498 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1499 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1500 } else {
1501 /* Do not worry if specular colour missing and disable request */
1502 VTRACE(("Specular color extensions not supplied\n"));
1507 /* Normal -------------------------------- */
1508 if (sd->u.s.normal.lpData != NULL) {
1509 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1510 glNormal3f(nx, ny, nz);
1511 } else {
1512 if (vx_index == 0) glNormal3f(0, 0, 1);
1515 /* Position -------------------------------- */
1516 if (sd->u.s.position.lpData != NULL) {
1517 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1518 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1519 glVertex3f(x, y, z);
1520 } else {
1521 GLfloat w = 1.0 / rhw;
1522 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1523 glVertex4f(x*w, y*w, z*w, w);
1527 /* For non indexed mode, step onto next parts */
1528 if (idxData == NULL) {
1529 ++SkipnStrides;
1533 glEnd();
1534 checkGLcall("glEnd and previous calls");
1537 #if 0 /* TODO: Software/Hardware vertex blending support */
1539 * Draw with emulated vertex shaders
1540 * Note: strided data is uninitialized, as we need to pass the vertex
1541 * shader directly as ordering irs yet
1543 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1544 int PrimitiveType, ULONG NumPrimitives,
1545 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1547 unsigned int textureNo = 0;
1548 GLenum glPrimType = GL_POINTS;
1549 int NumVertexes = NumPrimitives;
1550 const short *pIdxBufS = NULL;
1551 const long *pIdxBufL = NULL;
1552 LONG SkipnStrides = 0;
1553 LONG vx_index;
1554 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1555 float rhw = 0.0f; /* rhw */
1556 float ptSize = 0.0f; /* Point size */
1557 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1558 int numcoords[8]; /* Number of coords */
1559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1561 IDirect3DVertexShaderImpl* vertexShader = NULL;
1563 TRACE("Using slow software vertex shader code\n");
1565 /* Variable Initialization */
1566 if (idxData != NULL) {
1567 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1568 else pIdxBufL = (const long *) idxData;
1571 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1572 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1574 /* Retrieve the VS information */
1575 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1577 /* Start drawing in GL */
1578 VTRACE(("glBegin(%x)\n", glPrimType));
1579 glBegin(glPrimType);
1581 /* For each primitive */
1582 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1584 /* For indexed data, we need to go a few more strides in */
1585 if (idxData != NULL) {
1587 /* Indexed so work out the number of strides to skip */
1588 if (idxSize == 2) {
1589 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1590 SkipnStrides = pIdxBufS[startIdx+vx_index];
1591 } else {
1592 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1593 SkipnStrides = pIdxBufL[startIdx+vx_index];
1597 /* Fill the vertex shader input */
1598 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1600 /* Initialize the output fields to the same defaults as it would normally have */
1601 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1602 vertexShader->output.oD[0].x = 1.0;
1603 vertexShader->output.oD[0].y = 1.0;
1604 vertexShader->output.oD[0].z = 1.0;
1605 vertexShader->output.oD[0].w = 1.0;
1607 /* Now execute the vertex shader */
1608 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1611 TRACE_VECTOR(vertexShader->output.oPos);
1612 TRACE_VECTOR(vertexShader->output.oD[0]);
1613 TRACE_VECTOR(vertexShader->output.oD[1]);
1614 TRACE_VECTOR(vertexShader->output.oT[0]);
1615 TRACE_VECTOR(vertexShader->output.oT[1]);
1616 TRACE_VECTOR(vertexShader->input.V[0]);
1617 TRACE_VECTOR(vertexShader->data->C[0]);
1618 TRACE_VECTOR(vertexShader->data->C[1]);
1619 TRACE_VECTOR(vertexShader->data->C[2]);
1620 TRACE_VECTOR(vertexShader->data->C[3]);
1621 TRACE_VECTOR(vertexShader->data->C[4]);
1622 TRACE_VECTOR(vertexShader->data->C[5]);
1623 TRACE_VECTOR(vertexShader->data->C[6]);
1624 TRACE_VECTOR(vertexShader->data->C[7]);
1627 /* Extract out the output */
1628 /* FIXME: Fog coords? */
1629 x = vertexShader->output.oPos.x;
1630 y = vertexShader->output.oPos.y;
1631 z = vertexShader->output.oPos.z;
1632 rhw = vertexShader->output.oPos.w;
1633 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1635 /** Update textures coords using vertexShader->output.oT[0->7] */
1636 memset(texcoords, 0x00, sizeof(texcoords));
1637 memset(numcoords, 0x00, sizeof(numcoords));
1638 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1639 if (This->stateBlock->textures[textureNo] != NULL) {
1640 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1641 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1642 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1643 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1644 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1645 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1646 } else {
1647 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1648 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1649 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1650 default: numcoords[textureNo] = 4;
1653 } else {
1654 numcoords[textureNo] = 0;
1658 /* Draw using this information */
1659 draw_vertex(iface,
1660 TRUE, x, y, z, rhw,
1661 TRUE, 0.0f, 0.0f, 1.0f,
1662 TRUE, (float*) &vertexShader->output.oD[0],
1663 TRUE, (float*) &vertexShader->output.oD[1],
1664 FALSE, ptSize, /* FIXME: Change back when supported */
1665 texcoords, numcoords);
1667 /* For non indexed mode, step onto next parts */
1668 if (idxData == NULL) {
1669 ++SkipnStrides;
1672 } /* for each vertex */
1674 glEnd();
1675 checkGLcall("glEnd and previous calls");
1678 #endif
1680 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1681 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1682 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1684 /* Now draw the graphics to the screen */
1685 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1686 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1687 /* Ideally, we should have software FV and hardware VS, possibly
1688 depending on the device type? */
1689 #if 0 /* TODO: vertex and pixel shaders */
1690 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1691 idxData, idxSize, minIndex, StartIdx);
1692 #endif
1694 } else {
1696 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1697 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1698 int endStride = startStride;
1699 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1701 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1702 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1703 int t;
1704 if (idxSize == 2) {
1705 unsigned short *index = (unsigned short *)idxData;
1706 index += StartIdx;
1707 for (t = 0 ; t < numberOfIndicies; t++) {
1708 if (startStride > *index)
1709 startStride = *index;
1710 if (endStride < *index)
1711 endStride = *index;
1712 index++;
1714 } else { /* idxSize == 4 */
1715 unsigned int *index = (unsigned int *)idxData;
1716 index += StartIdx;
1717 for (t = 0 ; t < numberOfIndicies; t++) {
1718 if (startStride > *index)
1719 startStride = *index;
1720 if (endStride < *index)
1721 endStride = *index;
1722 index++;
1725 } else {
1726 endStride += numberOfvertices -1;
1728 #endif
1729 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1730 /* pre-transform verticex */
1731 /* TODO: Caching, VBO's etc.. */
1733 /* Generate some fixme's if unsupported functionality is being used */
1734 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1735 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1736 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1737 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1739 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1740 FIXME("Tweening is only valid with vertex shaders\n");
1742 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1743 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1745 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1746 FIXME("Extended attributes are only valid with vertex shaders\n");
1748 #undef BUFFER_OR_DATA
1750 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1751 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1752 #endif
1754 /* vertex shaders */
1756 /* If the only vertex data used by the shader is supported by OpenGL then*/
1757 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1758 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1759 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1761 /* Load the vertex data using named arrays */
1762 TRACE("(%p) Loading vertex data\n", This);
1763 loadVertexData(iface, dataLocations);
1765 } else /* Otherwise */
1766 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1768 /* load the array data using ordinal mapping */
1769 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1771 } else { /* If this happens we must drawStridedSlow later on */
1772 TRACE("Not loading vertex data\n");
1775 TRACE("Loaded arrays\n");
1777 if (useVertexShaderFunction) {
1778 int i;
1779 GLint errPos;
1780 IWineD3DVertexDeclarationImpl *vertexDeclaration;
1782 TRACE("Using vertex shader\n");
1784 /* Bind the vertex program */
1785 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1786 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1788 /* and enable gl vertex shaders */
1789 glEnable(GL_VERTEX_PROGRAM_ARB);
1790 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1791 TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1793 /* Vertex Shader 8 constants */
1794 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
1795 if (vertexDeclaration != NULL) {
1796 float *constants = vertexDeclaration->constants;
1797 if (constants != NULL) {
1798 for (i = 0; i <= WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1799 TRACE_(d3d_shader)("Not Loading constants %u = %f %f %f %f\n", i, constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
1800 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
1805 /* Update the constants */
1806 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1807 /* TODO: add support for Integer and Boolean constants */
1808 if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
1809 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1810 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->vertexShaderConstantF[i *4 ], This->stateBlock->vertexShaderConstantF[i * 4 + 1], This->stateBlock->vertexShaderConstantF[i *4 + 2], This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
1811 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1815 /* always draw strided fast if a vertex shader is being used */
1816 drawStridedFast(iface, numberOfIndicies, glPrimType,
1817 idxData, idxSize, minIndex, StartIdx);
1819 /* check for any errors */
1820 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1821 if (errPos != -1) {
1822 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1825 /* disable any attribs */
1826 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1827 GLint maxAttribs;
1828 int i;
1829 /* Leave all the attribs disabled */
1830 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1831 /* MESA does not support it right not */
1832 if (glGetError() != GL_NO_ERROR)
1833 maxAttribs = 16;
1834 for (i = 0; i < maxAttribs; i++) {
1835 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1836 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1840 /* Done */
1841 glDisable(GL_VERTEX_PROGRAM_ARB);
1842 } else {
1844 /* DirectX colours are in a different format to opengl colours
1845 so if diffuse or specular are used then we need to use drawStridedSlow
1846 to correct the colours */
1847 if ((dataLocations->u.s.pSize.lpData != NULL)
1848 || (dataLocations->u.s.diffuse.lpData != NULL)
1849 || (dataLocations->u.s.specular.lpData != NULL)) {
1850 /* TODO: replace drawStridedSlow with veretx fixups */
1851 #if 1
1853 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1854 idxData, idxSize, minIndex, StartIdx) ;
1857 * drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1858 * idxData, idxSize, minIndex, StartIdx);
1860 #endif
1861 } else {
1862 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1863 drawStridedFast(iface, numberOfIndicies, glPrimType,
1864 idxData, idxSize, minIndex, StartIdx);
1870 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1872 /* Dump out what parts we have supplied */
1873 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1874 TRACE_STRIDED((dataLocations), position);
1875 TRACE_STRIDED((dataLocations), blendWeights);
1876 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1877 TRACE_STRIDED((dataLocations), normal);
1878 TRACE_STRIDED((dataLocations), pSize);
1879 TRACE_STRIDED((dataLocations), diffuse);
1880 TRACE_STRIDED((dataLocations), specular);
1881 TRACE_STRIDED((dataLocations), texCoords[0]);
1882 TRACE_STRIDED((dataLocations), texCoords[1]);
1883 TRACE_STRIDED((dataLocations), texCoords[2]);
1884 TRACE_STRIDED((dataLocations), texCoords[3]);
1885 TRACE_STRIDED((dataLocations), texCoords[4]);
1886 TRACE_STRIDED((dataLocations), texCoords[5]);
1887 TRACE_STRIDED((dataLocations), texCoords[6]);
1888 TRACE_STRIDED((dataLocations), texCoords[7]);
1889 TRACE_STRIDED((dataLocations), position2);
1890 TRACE_STRIDED((dataLocations), normal2);
1891 TRACE_STRIDED((dataLocations), tangent);
1892 TRACE_STRIDED((dataLocations), binormal);
1893 TRACE_STRIDED((dataLocations), tessFactor);
1894 TRACE_STRIDED((dataLocations), fog);
1895 TRACE_STRIDED((dataLocations), depth);
1896 TRACE_STRIDED((dataLocations), sample);
1898 return;
1902 /* uploads textures and setup texture states ready for rendering */
1903 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1905 unsigned int i;
1907 * OK, here we clear down any old junk iect in the context
1908 * enable the new texture and apply any state changes:
1910 * Loop through all textures
1911 * select texture unit
1912 * if there is a texture bound to that unit then..
1913 * disable all textures types on that unit
1914 * enable and bind the texture that is bound to that unit.
1915 * otherwise disable all texture types on that unit.
1917 /* upload the textures */
1918 for (i = 0; i< GL_LIMITS(textures); ++i) {
1919 /* Bind the texture to the stage here */
1920 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1921 GLACTIVETEXTURE(i);
1922 } else if (0 < i) {
1923 /* This isn't so much a warn as a message to the user about lack of hardware support */
1924 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1927 /* don't bother with textures that have a colorop of disable */
1928 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1929 if (This->stateBlock->textures[i] != NULL) {
1931 glDisable(GL_TEXTURE_1D);
1932 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1933 /* disable all texture states that aren't the selected textures' dimension */
1934 switch(This->stateBlock->textureDimensions[i]) {
1935 case GL_TEXTURE_2D:
1936 glDisable(GL_TEXTURE_3D);
1937 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1938 break;
1939 case GL_TEXTURE_3D:
1940 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1941 glDisable(GL_TEXTURE_2D);
1942 break;
1943 case GLTEXTURECUBEMAP:
1944 glDisable(GL_TEXTURE_2D);
1945 glDisable(GL_TEXTURE_3D);
1946 break;
1948 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1949 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1950 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1951 } else {
1952 glEnable(This->stateBlock->textureDimensions[i]);
1954 /* Load up the texture now */
1955 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1956 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1957 /* this is a stub function representing the state blocks
1958 * being separated here we are only updating the texture
1959 * state changes, other objects and units get updated when
1960 * they change (or need to be updated), e.g. states that
1961 * relate to a context member line the texture unit are
1962 * only updated when the context needs updating
1964 /* Tell the abse texture to sync it's states */
1965 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1968 /* Bind a default texture if no texture has been set, but colour-op is enabled */
1969 else {
1970 glDisable(GL_TEXTURE_2D);
1971 glDisable(GL_TEXTURE_3D);
1972 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1973 glEnable(GL_TEXTURE_1D);
1974 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1975 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1977 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1978 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1979 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1980 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1981 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1982 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1983 /* alphaop */
1984 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1985 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1986 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1987 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1988 } else {
1990 /* no colorop so disable all the texture states */
1991 glDisable(GL_TEXTURE_1D);
1992 glDisable(GL_TEXTURE_2D);
1993 glDisable(GL_TEXTURE_3D);
1994 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2001 /* Routine common to the draw primitive and draw indexed primitive routines */
2002 void drawPrimitive(IWineD3DDevice *iface,
2003 int PrimitiveType,
2004 long NumPrimitives,
2005 /* for Indexed: */
2006 long StartVertexIndex,
2007 UINT numberOfVertices,
2008 long StartIdx,
2009 short idxSize,
2010 const void *idxData,
2011 int minIndex) {
2013 BOOL rc = FALSE;
2014 DWORD fvf = 0;
2015 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2016 BOOL useVertexShaderFunction = FALSE;
2017 BOOL isLightingOn = FALSE;
2018 Direct3DVertexStridedData dataLocations;
2019 int useHW = FALSE;
2021 if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE
2022 &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL
2023 && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
2024 useVertexShaderFunction = TRUE;
2025 } else {
2026 useVertexShaderFunction = FALSE;
2029 if (This->stateBlock->vertexDecl == NULL) {
2030 /* Work out what the FVF should look like */
2031 rc = initializeFVF(iface, &fvf);
2032 if (rc) return;
2033 } else {
2034 TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
2037 /* Ok, we will be updating the screen from here onwards so grab the lock */
2038 ENTER_GL();
2040 #if 0 /* TODO: vertex and pixel shaders */
2041 /* If we will be using a pixel, do some initialization for it */
2042 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
2043 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
2044 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
2046 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
2047 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
2048 glEnable(GL_FRAGMENT_PROGRAM_ARB);
2049 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
2051 /* init Constants */
2052 if (This->stateBlock->Changed.pixelShaderConstant) {
2053 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
2054 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
2056 /* Update the constants */
2057 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
2058 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
2059 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
2062 #endif /* TODO: vertex and pixel shaders */
2064 /* Initialize all values to null */
2065 memset(&dataLocations, 0x00, sizeof(dataLocations));
2066 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2068 if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2069 BOOL storeArrays = useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays == FALSE && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays == FALSE;
2071 TRACE("================ Vertex Declaration ===================\n");
2072 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, &dataLocations, StartVertexIndex, &fvf, storeArrays,
2073 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
2074 } else {
2075 TRACE("================ FVF ===================\n");
2076 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
2079 /* write out some debug information*/
2080 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2082 /* Setup transform matrices and sort out */
2083 if (useHW) {
2084 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2085 So make sure lighting is disabled. */
2086 isLightingOn = glIsEnabled(GL_LIGHTING);
2087 glDisable(GL_LIGHTING);
2088 checkGLcall("glDisable(GL_LIGHTING);");
2089 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2090 } else {
2091 isLightingOn = primitiveInitState(iface,
2092 fvf & D3DFVF_XYZRHW,
2093 !(fvf & D3DFVF_NORMAL),
2094 useVertexShaderFunction);
2097 /* Now initialize the materials state */
2098 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2100 drawPrimitiveUploadTextures(This);
2104 GLenum glPrimType;
2105 /* Ok, Work out which primitive is requested and how many vertexes that
2106 will be */
2107 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2108 #if 0 /* debugging code... just information not an error */
2109 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2110 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2112 #endif
2113 if (numberOfVertices == 0 )
2114 numberOfVertices = calculatedNumberOfindices;
2115 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2118 /* If vertex shaders or no normals, restore previous lighting state */
2119 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2120 if (isLightingOn) glEnable(GL_LIGHTING);
2121 else glDisable(GL_LIGHTING);
2122 TRACE("Restored lighting to original state\n");
2125 #if 0 /* TODO: vertex and pixel shaders */
2126 if (pixel_shader)
2128 #if 0
2129 GLint errPos;
2130 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2131 if (errPos != -1)
2132 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2133 #endif
2134 glDisable(GL_FRAGMENT_PROGRAM_ARB);
2136 #endif
2138 /* Finshed updating the screen, restore lock */
2139 LEAVE_GL();
2140 TRACE("Done all gl drawing\n");
2142 /* Diagnostics */
2143 #ifdef SHOW_FRAME_MAKEUP
2145 static long int primCounter = 0;
2146 /* NOTE: set primCounter to the value reported by drawprim
2147 before you want to to write frame makeup to /tmp */
2148 if (primCounter >= 0) {
2149 D3DLOCKED_RECT r;
2150 char buffer[80];
2151 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2152 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2153 TRACE("Saving screenshot %s\n", buffer);
2154 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2155 IWineD3DSurface_UnlockRect(This->renderTarget);
2157 #ifdef SHOW_TEXTURE_MAKEUP
2159 IWineD3DSurface *pSur;
2160 int textureNo;
2161 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2162 if (This->stateBlock->textures[textureNo] != NULL) {
2163 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2164 TRACE("Saving texture %s\n", buffer);
2165 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == D3DRTYPE_TEXTURE) {
2166 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2167 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2168 IWineD3DSurface_Release(pSur);
2169 } else {
2170 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2175 #endif
2177 TRACE("drawprim #%ld\n", primCounter);
2178 ++primCounter;
2180 #endif