wined3d: Fix a few FIXME's.
[wine/hacks.git] / dlls / wined3d / drawprim.c
blobbf5bc54bc8ed7ae5a6e74f578365794348329b96
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) || (This->viewport_changed) ) {
205 double X, Y, height, width, minZ, maxZ;
206 This->last_was_rhw = TRUE;
207 This->viewport_changed = FALSE;
209 /* Transformed already into viewport coordinates, so we do not need transform
210 matrices. Reset all matrices to identity and leave the default matrix in world
211 mode. */
212 glMatrixMode(GL_MODELVIEW);
213 checkGLcall("glMatrixMode(GL_MODELVIEW)");
214 glLoadIdentity();
215 checkGLcall("glLoadIdentity");
217 glMatrixMode(GL_PROJECTION);
218 checkGLcall("glMatrixMode(GL_PROJECTION)");
219 glLoadIdentity();
220 checkGLcall("glLoadIdentity");
222 /* Set up the viewport to be full viewport */
223 X = This->stateBlock->viewport.X;
224 Y = This->stateBlock->viewport.Y;
225 height = This->stateBlock->viewport.Height;
226 width = This->stateBlock->viewport.Width;
227 minZ = This->stateBlock->viewport.MinZ;
228 maxZ = This->stateBlock->viewport.MaxZ;
229 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
230 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
231 checkGLcall("glOrtho");
233 /* Window Coord 0 is the middle of the first pixel, so translate by half
234 a pixel (See comment above glTranslate below) */
235 glTranslatef(0.5, 0.5, 0);
236 checkGLcall("glTranslatef(0.5, 0.5, 0)");
237 if (This->renderUpsideDown) {
238 glMultMatrixf(invymat);
239 checkGLcall("glMultMatrixf(invymat)");
243 } else {
245 /* Untransformed, so relies on the view and projection matrices */
247 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
248 /* Only reapply when have to */
249 This->modelview_valid = TRUE;
250 glMatrixMode(GL_MODELVIEW);
251 checkGLcall("glMatrixMode");
253 /* In the general case, the view matrix is the identity matrix */
254 if (This->view_ident) {
255 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
256 checkGLcall("glLoadMatrixf");
257 } else {
258 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
259 checkGLcall("glLoadMatrixf");
260 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
261 checkGLcall("glMultMatrixf");
265 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
266 /* Only reapply when have to */
267 This->proj_valid = TRUE;
268 glMatrixMode(GL_PROJECTION);
269 checkGLcall("glMatrixMode");
271 /* The rule is that the window coordinate 0 does not correspond to the
272 beginning of the first pixel, but the center of the first pixel.
273 As a consequence if you want to correctly draw one line exactly from
274 the left to the right end of the viewport (with all matrices set to
275 be identity), the x coords of both ends of the line would be not
276 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
277 instead. */
278 glLoadIdentity();
280 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
281 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
283 if (This->renderUpsideDown) {
284 glMultMatrixf(invymat);
285 checkGLcall("glMultMatrixf(invymat)");
287 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
288 checkGLcall("glLoadMatrixf");
291 /* Vertex Shader output is already transformed, so set up identity matrices */
292 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
293 come along this needs to take into account whether s/w ones were
294 requested or not */
295 if (useVS) {
296 glMatrixMode(GL_MODELVIEW);
297 checkGLcall("glMatrixMode");
298 glLoadIdentity();
299 glMatrixMode(GL_PROJECTION);
300 checkGLcall("glMatrixMode");
301 glLoadIdentity();
302 /* Window Coord 0 is the middle of the first pixel, so translate by half
303 a pixel (See comment above glTranslate above) */
304 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
305 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
306 if (This->renderUpsideDown) {
307 glMultMatrixf(invymat);
308 checkGLcall("glMultMatrixf(invymat)");
310 This->modelview_valid = FALSE;
311 This->proj_valid = FALSE;
313 This->last_was_rhw = FALSE;
315 return isLightingOn;
318 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, BOOL useVertexShaderFunction, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf, BOOL storeOrder, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
319 /* We need to deal with frequency data!*/
321 int textureNo =0;
322 BYTE *data = NULL;
323 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
324 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
325 int i;
326 WINED3DVERTEXELEMENT *element;
327 DWORD stride;
329 /* Locate the vertex declaration */
330 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
331 TRACE("Using vertex declaration from shader\n");
332 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
333 } else {
334 TRACE("Using vertex declaration\n");
335 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
338 /* Translate the declaration into strided data */
339 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
341 element = vertexDeclaration->pDeclarationWine + i;
342 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
343 if (This->stateBlock->streamIsUP) {
344 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
345 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
346 } else {
347 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
348 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
350 stride = This->stateBlock->streamStride[element->Stream];
351 data += (BaseVertexIndex * stride);
352 data += element->Offset;
354 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
355 switch (element->Usage) {
356 case D3DDECLUSAGE_POSITION:
357 switch (element->UsageIndex) {
358 case 0: /* N-patch */
359 strided->u.s.position.lpData = data;
360 strided->u.s.position.dwType = element->Type;
361 strided->u.s.position.dwStride = stride;
362 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data, element->Type, stride);
363 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = element->Reg;
364 break;
365 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
366 TRACE("Tweened positions\n");
367 strided->u.s.position2.lpData = data;
368 strided->u.s.position2.dwType = element->Type;
369 strided->u.s.position2.dwStride = stride;
370 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data, element->Type, stride);
371 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2] = element->Reg;
372 break;
374 break;
375 case D3DDECLUSAGE_NORMAL:
376 switch (element->UsageIndex) {
377 case 0: /* N-patch */
378 strided->u.s.normal.lpData = data;
379 strided->u.s.normal.dwType = element->Type;
380 strided->u.s.normal.dwStride = stride;
381 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data, element->Type, stride);
382 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = element->Reg;
383 break;
384 case 1: /* skinning */
385 TRACE("Skinning / tween normals\n");
386 strided->u.s.normal2.lpData = data;
387 strided->u.s.normal2.dwType = element->Type;
388 strided->u.s.normal2.dwStride = stride;
389 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data, element->Type, stride);
390 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = element->Reg;
391 break;
393 *fvf |= D3DFVF_NORMAL;
394 break;
395 case D3DDECLUSAGE_BLENDINDICES:
396 /* demo @http://www.ati.com/developer/vertexblend.html
397 and http://www.flipcode.com/articles/article_dx8shaders.shtml
399 strided->u.s.blendMatrixIndices.lpData = data;
400 strided->u.s.blendMatrixIndices.dwType = element->Type;
401 strided->u.s.blendMatrixIndices.dwStride= stride;
402 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendMatrixIndices", data, element->Type, stride);
403 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = element->Reg;
404 break;
405 case D3DDECLUSAGE_BLENDWEIGHT:
406 strided->u.s.blendWeights.lpData = data;
407 strided->u.s.blendWeights.dwType = element->Type;
408 strided->u.s.blendWeights.dwStride = stride;
409 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data, element->Type, stride);
410 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = element->Reg;
411 break;
412 case D3DDECLUSAGE_PSIZE:
413 strided->u.s.pSize.lpData = data;
414 strided->u.s.pSize.dwType = element->Type;
415 strided->u.s.pSize.dwStride = stride;
416 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data, element->Type, stride);
417 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = element->Reg;
418 break;
419 case D3DDECLUSAGE_COLOR:
420 switch (element->UsageIndex) {
421 case 0:/* diffuse */
422 strided->u.s.diffuse.lpData = data;
423 strided->u.s.diffuse.dwType = element->Type;
424 strided->u.s.diffuse.dwStride = stride;
425 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data, element->Type, stride);
426 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = element->Reg;
427 break;
428 case 1: /* specular */
429 strided->u.s.specular.lpData = data;
430 strided->u.s.specular.dwType = element->Type;
431 strided->u.s.specular.dwStride = stride;
432 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data, element->Type, stride);
433 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = element->Reg;
437 break;
438 case D3DDECLUSAGE_TEXCOORD:
439 /* For some odd reason Microsoft decided to sum usage accross all the streams,
440 which means we need to do a count and not just use the usage number */
442 strided->u.s.texCoords[textureNo].lpData = data;
443 strided->u.s.texCoords[textureNo].dwType = element->Type;
444 strided->u.s.texCoords[textureNo].dwStride = stride;
445 TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo, data, element->Type, stride);
446 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + textureNo] = element->Reg;
448 ++textureNo;
449 break;
450 case D3DDECLUSAGE_TANGENT:
451 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
452 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
453 normal using tangents where no normal data has been provided */
454 TRACE("Tangents\n");
455 strided->u.s.tangent.lpData = data;
456 strided->u.s.tangent.dwType = element->Type;
457 strided->u.s.tangent.dwStride = stride;
458 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data, element->Type, stride);
459 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = element->Reg;
460 break;
461 case D3DDECLUSAGE_BINORMAL:
462 /* 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.
463 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)
464 The only thing they are useful for in fixed function would be working out normals when none are given.
466 TRACE("BI-Normal\n");
467 strided->u.s.binormal.lpData = data;
468 strided->u.s.binormal.dwType = element->Type;
469 strided->u.s.binormal.dwStride = stride;
470 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data, element->Type, stride);
471 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = element->Reg;
472 break;
473 case D3DDECLUSAGE_TESSFACTOR:
474 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
476 TRACE("Tess Factor\n");
477 strided->u.s.tessFactor.lpData = data;
478 strided->u.s.tessFactor.dwType = element->Type;
479 strided->u.s.tessFactor.dwStride = stride;
480 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data, element->Type, stride);
481 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = element->Reg;
482 break;
483 case D3DDECLUSAGE_POSITIONT:
485 switch (element->UsageIndex) {
486 case 0: /* N-patch */
487 strided->u.s.position.lpData = data;
488 strided->u.s.position.dwType = element->Type;
489 strided->u.s.position.dwStride = stride;
490 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data, element->Type, stride);
491 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = element->Reg;
492 break;
493 case 1: /* skinning */
494 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
495 http://xface.blogspot.com/2004_08_01_xface_archive.html
497 TRACE("Skinning positionsT\n");
498 strided->u.s.position2.lpData = data;
499 strided->u.s.position2.dwType = element->Type;
500 strided->u.s.position2.dwStride = stride;
501 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data, element->Type, stride);
502 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = element->Reg;
503 break;
505 /* TODO: change fvf usage to a plain boolean flag */
506 *fvf |= D3DFVF_XYZRHW;
507 /* FIXME: were faking this flag so that we don't transform the data again */
508 break;
509 case D3DDECLUSAGE_FOG:
510 /* maybe GL_EXT_fog_coord ?
511 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
512 * This extension allows specifying an explicit per-vertex fog
513 * coordinate to be used in fog computations, rather than using a
514 * fragment depth-based fog equation.
516 * */
517 TRACE("Fog\n");
518 strided->u.s.fog.lpData = data;
519 strided->u.s.fog.dwType = element->Type;
520 strided->u.s.fog.dwStride = stride;
521 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data, element->Type, stride);
522 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = element->Reg;
523 break;
524 case D3DDECLUSAGE_DEPTH:
525 TRACE("depth\n");
526 strided->u.s.depth.lpData = data;
527 strided->u.s.depth.dwType = element->Type;
528 strided->u.s.depth.dwStride = stride;
529 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data, element->Type, stride);
530 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = element->Reg;
531 break;
532 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
533 TRACE("depth\n");
534 strided->u.s.sample.lpData = data;
535 strided->u.s.sample.dwType = element->Type;
536 strided->u.s.sample.dwStride = stride;
537 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data, element->Type, stride);
538 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = element->Reg;
539 break;
546 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
548 short LoopThroughTo = 0;
549 short nStream;
550 int numBlends;
551 int numTextures;
552 int textureNo;
553 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
554 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
558 /* OK, Now to setup the data locations
559 For the non-created vertex shaders, the VertexShader var holds the real
560 FVF and only stream 0 matters
561 For the created vertex shaders, there is an FVF per stream */
562 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
563 LoopThroughTo = MAX_STREAMS;
564 } else {
565 LoopThroughTo = 1;
568 /* Work through stream by stream */
569 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
570 DWORD stride = This->stateBlock->streamStride[nStream];
571 BYTE *data = NULL;
572 DWORD thisFVF = 0;
574 /* Skip empty streams */
575 if (This->stateBlock->streamSource[nStream] == NULL) continue;
577 /* Retrieve appropriate FVF */
578 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
579 thisFVF = This->stateBlock->fvf;
580 /* Handle memory passed directly as well as vertex buffers */
581 if (This->stateBlock->streamIsUP) {
582 data = (BYTE *)This->stateBlock->streamSource[nStream];
583 } else {
584 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
586 } else {
587 #if 0 /* TODO: Vertex shader support */
588 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
589 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
590 #endif
592 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
593 if (thisFVF == 0) continue;
595 /* Now convert the stream into pointers */
597 /* Shuffle to the beginning of the vertexes to render and index from there */
598 data = data + (BaseVertexIndex * stride);
600 /* Either 3 or 4 floats depending on the FVF */
601 /* FIXME: Can blending data be in a different stream to the position data?
602 and if so using the fixed pipeline how do we handle it */
603 if (thisFVF & D3DFVF_POSITION_MASK) {
604 strided->u.s.position.lpData = data;
605 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
606 strided->u.s.position.dwStride = stride;
607 data += 3 * sizeof(float);
608 if (thisFVF & D3DFVF_XYZRHW) {
609 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
610 data += sizeof(float);
614 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
615 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
616 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
617 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
619 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
620 TRACE("Setting blend Weights to %p\n", data);
621 strided->u.s.blendWeights.lpData = data;
622 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
623 strided->u.s.blendWeights.dwStride = stride;
624 data += numBlends * sizeof(FLOAT);
626 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
627 strided->u.s.blendMatrixIndices.lpData = data;
628 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
629 strided->u.s.blendMatrixIndices.dwStride= stride;
630 data += sizeof(DWORD);
634 /* Normal is always 3 floats */
635 if (thisFVF & D3DFVF_NORMAL) {
636 strided->u.s.normal.lpData = data;
637 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
638 strided->u.s.normal.dwStride = stride;
639 data += 3 * sizeof(FLOAT);
642 /* Pointsize is a single float */
643 if (thisFVF & D3DFVF_PSIZE) {
644 strided->u.s.pSize.lpData = data;
645 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
646 strided->u.s.pSize.dwStride = stride;
647 data += sizeof(FLOAT);
650 /* Diffuse is 4 unsigned bytes */
651 if (thisFVF & D3DFVF_DIFFUSE) {
652 strided->u.s.diffuse.lpData = data;
653 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
654 strided->u.s.diffuse.dwStride = stride;
655 data += sizeof(DWORD);
658 /* Specular is 4 unsigned bytes */
659 if (thisFVF & D3DFVF_SPECULAR) {
660 strided->u.s.specular.lpData = data;
661 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
662 strided->u.s.specular.dwStride = stride;
663 data += sizeof(DWORD);
666 /* Texture coords */
667 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
668 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
670 /* numTextures indicates the number of texture coordinates supplied */
671 /* However, the first set may not be for stage 0 texture - it all */
672 /* depends on D3DTSS_TEXCOORDINDEX. */
673 /* The number of bytes for each coordinate set is based off */
674 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
676 /* So, for each supplied texture extract the coords */
677 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
679 strided->u.s.texCoords[textureNo].lpData = data;
680 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
681 strided->u.s.texCoords[textureNo].dwStride = stride;
682 numCoords[textureNo] = coordIdxInfo & 0x03;
684 /* Always one set */
685 data += sizeof(float);
686 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
687 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
688 data += sizeof(float);
689 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
690 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
691 data += sizeof(float);
692 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
693 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
694 data += sizeof(float);
698 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
703 #if 0 /* TODO: Software Shaders */
704 /* Draw a single vertex using this information */
705 static void draw_vertex(IWineD3DDevice *iface, /* interface */
706 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
707 BOOL isNormal, float nx, float ny, float nz, /* normal */
708 BOOL isDiffuse, float *dRGBA, /* 1st colors */
709 BOOL isSpecular, float *sRGB, /* 2ndry colors */
710 BOOL isPtSize, float ptSize, /* pointSize */
711 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
713 unsigned int textureNo;
714 float s, t, r, q;
715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
717 /* Diffuse -------------------------------- */
718 if (isDiffuse) {
719 glColor4fv(dRGBA);
720 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
723 /* Specular Colour ------------------------------------------*/
724 if (isSpecular) {
725 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
726 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
727 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
728 } else {
729 VTRACE(("Specular color extensions not supplied\n"));
733 /* Normal -------------------------------- */
734 if (isNormal) {
735 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
736 glNormal3f(nx, ny, nz);
739 /* Point Size ----------------------------------------------*/
740 if (isPtSize) {
742 /* no such functionality in the fixed function GL pipeline */
743 FIXME("Cannot change ptSize here in openGl\n");
746 /* Texture coords --------------------------- */
747 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
749 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
750 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
751 continue ;
754 /* Query tex coords */
755 if (This->stateBlock->textures[textureNo] != NULL) {
757 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
758 if (coordIdx >= MAX_TEXTURES) {
759 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
760 continue;
761 } else if (numcoords[coordIdx] == 0) {
762 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
763 continue;
764 } else {
766 /* Initialize vars */
767 s = 0.0f;
768 t = 0.0f;
769 r = 0.0f;
770 q = 0.0f;
772 switch (numcoords[coordIdx]) {
773 case 4: q = texcoords[coordIdx].w; /* drop through */
774 case 3: r = texcoords[coordIdx].z; /* drop through */
775 case 2: t = texcoords[coordIdx].y; /* drop through */
776 case 1: s = texcoords[coordIdx].x;
779 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
780 case D3DTTFF_COUNT1:
781 VTRACE(("tex:%d, s=%f\n", textureNo, s));
782 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
783 GLMULTITEXCOORD1F(textureNo, s);
784 } else {
785 glTexCoord1f(s);
787 break;
788 case D3DTTFF_COUNT2:
789 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
790 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
791 GLMULTITEXCOORD2F(textureNo, s, t);
792 } else {
793 glTexCoord2f(s, t);
795 break;
796 case D3DTTFF_COUNT3:
797 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
798 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
799 GLMULTITEXCOORD3F(textureNo, s, t, r);
800 } else {
801 glTexCoord3f(s, t, r);
803 break;
804 case D3DTTFF_COUNT4:
805 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
806 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
807 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
808 } else {
809 glTexCoord4f(s, t, r, q);
811 break;
812 default:
813 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
817 } /* End of textures */
819 /* Position -------------------------------- */
820 if (isXYZ) {
821 if (1.0f == rhw || rhw < 0.00001f) {
822 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
823 glVertex3f(x, y, z);
824 } else {
825 /* Cannot optimize by dividing through by rhw as rhw is required
826 later for perspective in the GL pipeline for vertex shaders */
827 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
828 glVertex4f(x,y,z,rhw);
832 #endif /* TODO: Software shaders */
834 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
837 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
838 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
839 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
840 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
841 WINED3D_ATR_SIZE(_arrayName), \
842 WINED3D_ATR_GLTYPE(_arrayName), \
843 WINED3D_ATR_NORMALIZED(_arrayName), \
844 sd->u.s._arrayName.dwStride, \
845 sd->u.s._arrayName.lpData)); \
846 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
850 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
851 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
852 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
853 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
854 WINED3D_ATR_SIZE(position2), \
855 WINED3D_ATR_GLTYPE(position2), \
856 WINED3D_ATR_NORMALIZED(position2), \
857 sd->u.s.position2.dwStride, \
858 ((char *)sd->u.s.position2.lpData) + \
859 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
860 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
863 /* Generate some lookup tables */
864 /* drop the RHW coord, there must be a nicer way of doing this. */
865 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
866 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
868 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
869 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
870 LOAD_NUMBERED_ARRAY(position,POSITION);
871 LOAD_NUMBERED_ARRAY(normal,NORMAL);
872 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
873 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
874 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
875 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
876 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
877 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
878 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
879 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
880 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
881 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
882 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
883 #if 0 /* TODO: Samplers may allow for more texture coords */
884 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
885 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
886 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
887 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
888 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
889 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
890 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
891 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
892 #endif
893 LOAD_NUMBERED_ARRAY(position,POSITIONT);
894 /* d3d9 types */
895 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
896 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
897 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
898 LOAD_NUMBERED_ARRAY(position2,POSITION2);
899 /* there can be lots of position arrays */
900 LOAD_NUMBERED_POSITION_ARRAY(0);
901 LOAD_NUMBERED_POSITION_ARRAY(1);
902 LOAD_NUMBERED_POSITION_ARRAY(2);
903 LOAD_NUMBERED_POSITION_ARRAY(3);
904 LOAD_NUMBERED_POSITION_ARRAY(4);
905 LOAD_NUMBERED_POSITION_ARRAY(5);
906 LOAD_NUMBERED_POSITION_ARRAY(6);
907 LOAD_NUMBERED_POSITION_ARRAY(7);
908 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
909 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
910 LOAD_NUMBERED_ARRAY(fog,FOG);
911 LOAD_NUMBERED_ARRAY(depth,DEPTH);
912 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
914 #undef LOAD_NUMBERED_ARRAY
917 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
918 unsigned int textureNo = 0;
919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
921 TRACE("Using fast vertex array code\n");
922 /* Blend Data ---------------------------------------------- */
923 if ((sd->u.s.blendWeights.lpData != NULL) ||
924 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
927 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
929 #if 1
930 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
931 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
932 #endif
934 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
935 /* FIXME("TODO\n");*/
936 /* Note dwType == float3 or float4 == 2 or 3 */
938 #if 0
939 /* with this on, the normals appear to be being modified,
940 but the vertices aren't being translated as they should be
941 Maybe the world matrix aren't being setup properly? */
942 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
943 #endif
946 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
947 WINED3D_ATR_SIZE(blendWeights) ,
948 sd->u.s.blendWeights.dwStride,
949 sd->u.s.blendWeights.lpData));
951 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
952 sd->u.s.blendWeights.dwStride,
953 sd->u.s.blendWeights.lpData);
955 checkGLcall("glWeightPointerARB");
957 if(sd->u.s.blendMatrixIndices.lpData != NULL){
958 static BOOL showfixme = TRUE;
959 if(showfixme){
960 FIXME("blendMatrixIndices support\n");
961 showfixme = FALSE;
967 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
968 /* FIXME("TODO\n");*/
969 #if 0
971 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
972 sd->u.s.blendWeights.dwStride,
973 sd->u.s.blendWeights.lpData);
974 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
975 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
976 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
977 #endif
979 } else {
980 /* TODO: support blends in fixupVertices */
981 FIXME("unsupported blending in openGl\n");
983 } else {
984 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
985 #if 0 /* TODO: Vertex blending */
986 glDisable(GL_VERTEX_BLEND_ARB);
987 #endif
988 TRACE("ARB_VERTEX_BLEND\n");
989 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
990 TRACE(" EXT_VERTEX_WEIGHTING\n");
991 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
992 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
997 #if 0 /* FOG ----------------------------------------------*/
998 if (sd->u.s.fog.lpData != NULL) {
999 /* TODO: fog*/
1000 if (GL_SUPPORT(EXT_FOG_COORD) {
1001 glEnableClientState(GL_FOG_COORD_EXT);
1002 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
1003 sd->u.s.fog.dwStride,
1004 sd->u.s.fog.lpData);
1005 } else {
1006 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1007 /* FIXME: fixme once */
1008 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1010 } else {
1011 if (GL_SUPPRT(EXT_FOR_COORD) {
1012 /* make sure fog is disabled */
1013 glDisableClientState(GL_FOG_COORD_EXT);
1016 #endif
1018 #if 0 /* tangents ----------------------------------------------*/
1019 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
1020 /* TODO: tangents*/
1021 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1022 if (sd->u.s.tangent.lpData != NULL) {
1023 glEnable(GL_TANGENT_ARRAY_EXT);
1024 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
1025 sd->u.s.tangent.dwStride,
1026 sd->u.s.tangent.lpData);
1027 } else {
1028 glDisable(GL_TANGENT_ARRAY_EXT);
1030 if (sd->u.s.binormal.lpData != NULL) {
1031 glEnable(GL_BINORMAL_ARRAY_EXT);
1032 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
1033 sd->u.s.binormal.dwStride,
1034 sd->u.s.binormal.lpData);
1035 } else{
1036 glDisable(GL_BINORMAL_ARRAY_EXT);
1039 } else {
1040 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1041 /* FIXME: fixme once */
1042 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1044 } else {
1045 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1046 /* make sure fog is disabled */
1047 glDisable(GL_TANGENT_ARRAY_EXT);
1048 glDisable(GL_BINORMAL_ARRAY_EXT);
1051 #endif
1053 /* Point Size ----------------------------------------------*/
1054 if (sd->u.s.pSize.lpData != NULL) {
1056 /* no such functionality in the fixed function GL pipeline */
1057 TRACE("Cannot change ptSize here in openGl\n");
1058 /* TODO: Implement this function in using shaders if they are available */
1062 /* Vertex Pointers -----------------------------------------*/
1063 if (sd->u.s.position.lpData != NULL) {
1064 /* Note dwType == float3 or float4 == 2 or 3 */
1065 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1066 sd->u.s.position.dwStride,
1067 sd->u.s.position.dwType + 1,
1068 sd->u.s.position.lpData));
1070 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1071 handling for rhw mode should not impact screen position whereas in GL it does.
1072 This may result in very slightly distored textures in rhw mode, but
1073 a very minimal different. There's always the other option of
1074 fixing the view matrix to prevent w from having any effect */
1075 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1076 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1077 checkGLcall("glVertexPointer(...)");
1078 glEnableClientState(GL_VERTEX_ARRAY);
1079 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1081 } else {
1082 glDisableClientState(GL_VERTEX_ARRAY);
1083 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1086 /* Normals -------------------------------------------------*/
1087 if (sd->u.s.normal.lpData != NULL) {
1088 /* Note dwType == float3 or float4 == 2 or 3 */
1089 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1090 sd->u.s.normal.dwStride,
1091 sd->u.s.normal.lpData));
1092 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1093 sd->u.s.normal.dwStride,
1094 sd->u.s.normal.lpData);
1095 checkGLcall("glNormalPointer(...)");
1096 glEnableClientState(GL_NORMAL_ARRAY);
1097 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1099 } else {
1100 glDisableClientState(GL_NORMAL_ARRAY);
1101 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1102 glNormal3f(0, 0, 1);
1103 checkGLcall("glNormal3f(0, 0, 1)");
1106 /* Diffuse Colour --------------------------------------------*/
1107 /* WARNING: Data here MUST be in RGBA format, so cannot */
1108 /* go directly into fast mode from app pgm, because */
1109 /* directx requires data in BGRA format. */
1110 /* currently fixupVertices swizels the format, but this isn't */
1111 /* very practical when using VBOS */
1112 /* NOTE: Unless we write a vertex shader to swizel the colour */
1113 /* , or the user doesn't care and wants the speed advantage */
1115 if (sd->u.s.diffuse.lpData != NULL) {
1116 /* Note dwType == float3 or float4 == 2 or 3 */
1117 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1118 sd->u.s.diffuse.dwStride,
1119 sd->u.s.diffuse.lpData));
1121 glColorPointer(4, GL_UNSIGNED_BYTE,
1122 sd->u.s.diffuse.dwStride,
1123 sd->u.s.diffuse.lpData);
1124 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1125 glEnableClientState(GL_COLOR_ARRAY);
1126 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1128 } else {
1129 glDisableClientState(GL_COLOR_ARRAY);
1130 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1131 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1132 checkGLcall("glColor4f(1, 1, 1, 1)");
1135 /* Specular Colour ------------------------------------------*/
1136 if (sd->u.s.specular.lpData != NULL) {
1137 TRACE("setting specular colour\n");
1138 /* Note dwType == float3 or float4 == 2 or 3 */
1139 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1140 sd->u.s.specular.dwStride,
1141 sd->u.s.specular.lpData));
1142 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1143 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1144 sd->u.s.specular.dwStride,
1145 sd->u.s.specular.lpData);
1146 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1147 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1148 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1149 } else {
1151 /* Missing specular color is not critical, no warnings */
1152 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1155 } else {
1156 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1158 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1159 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1160 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1161 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1162 } else {
1164 /* Missing specular color is not critical, no warnings */
1165 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1169 /* Texture coords -------------------------------------------*/
1171 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1173 /* Select the correct texture stage */
1174 GLCLIENTACTIVETEXTURE(textureNo);
1175 if (This->stateBlock->textures[textureNo] != NULL) {
1176 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1177 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1178 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1179 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1180 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1181 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1182 continue;
1185 if (coordIdx >= MAX_TEXTURES) {
1186 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1187 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1188 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1190 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1191 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1192 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1193 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1195 } else {
1197 /* The coords to supply depend completely on the fvf / vertex shader */
1198 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1199 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1202 } else {
1203 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1204 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1209 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1210 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1211 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1213 if (idxData != NULL /* This crashes sometimes!*/) {
1214 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1215 idxData = idxData == (void *)-1 ? NULL : idxData;
1216 #if 1
1217 #if 0
1218 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1219 glEnableClientState(GL_INDEX_ARRAY);
1220 #endif
1221 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1222 (const char *)idxData+(idxSize * startIdx));
1223 #else /* using drawRangeElements may be faster */
1225 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1226 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1227 (const char *)idxData+(idxSize * startIdx));
1228 #endif
1229 checkGLcall("glDrawRangeElements");
1231 } else {
1233 /* Note first is now zero as we shuffled along earlier */
1234 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1235 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1236 checkGLcall("glDrawArrays");
1240 return;
1244 * Actually draw using the supplied information.
1245 * Slower GL version which extracts info about each vertex in turn
1248 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1249 UINT NumVertexes, GLenum glPrimType,
1250 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1252 unsigned int textureNo = 0;
1253 const short *pIdxBufS = NULL;
1254 const long *pIdxBufL = NULL;
1255 LONG SkipnStrides = 0;
1256 LONG vx_index;
1257 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1258 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1259 float rhw = 0.0f; /* rhw */
1260 float ptSize = 0.0f; /* Point size */
1261 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1262 DWORD specularColor = 0; /* Specular Color */
1263 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1265 TRACE("Using slow vertex array code\n");
1267 /* Variable Initialization */
1268 if (idxData != NULL) {
1269 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1270 else pIdxBufL = (const long *) idxData;
1273 /* Start drawing in GL */
1274 VTRACE(("glBegin(%x)\n", glPrimType));
1275 glBegin(glPrimType);
1277 /* For each primitive */
1278 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1280 /* Initialize diffuse color */
1281 diffuseColor = 0xFFFFFFFF;
1283 /* For indexed data, we need to go a few more strides in */
1284 if (idxData != NULL) {
1286 /* Indexed so work out the number of strides to skip */
1287 if (idxSize == 2) {
1288 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1289 SkipnStrides = pIdxBufS[startIdx + vx_index];
1290 } else {
1291 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1292 SkipnStrides = pIdxBufL[startIdx + vx_index];
1296 /* Position Information ------------------ */
1297 if (sd->u.s.position.lpData != NULL) {
1299 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1300 x = ptrToCoords[0];
1301 y = ptrToCoords[1];
1302 z = ptrToCoords[2];
1303 rhw = 1.0;
1304 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1306 /* RHW follows, only if transformed, ie 4 floats were provided */
1307 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1308 rhw = ptrToCoords[3];
1309 VTRACE(("rhw=%f\n", rhw));
1313 /* Blending data -------------------------- */
1314 if (sd->u.s.blendWeights.lpData != NULL) {
1315 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1316 FIXME("Blending not supported yet\n");
1318 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1319 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1323 /* Vertex Normal Data (untransformed only)- */
1324 if (sd->u.s.normal.lpData != NULL) {
1326 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1327 nx = ptrToCoords[0];
1328 ny = ptrToCoords[1];
1329 nz = ptrToCoords[2];
1330 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1333 /* Point Size ----------------------------- */
1334 if (sd->u.s.pSize.lpData != NULL) {
1336 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1337 ptSize = ptrToCoords[0];
1338 VTRACE(("ptSize=%f\n", ptSize));
1339 FIXME("No support for ptSize yet\n");
1342 /* Diffuse -------------------------------- */
1343 if (sd->u.s.diffuse.lpData != NULL) {
1345 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1346 diffuseColor = ptrToCoords[0];
1347 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1350 /* Specular -------------------------------- */
1351 if (sd->u.s.specular.lpData != NULL) {
1353 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1354 specularColor = ptrToCoords[0];
1355 VTRACE(("specularColor=%lx\n", specularColor));
1358 /* Texture coords --------------------------- */
1359 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1361 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1362 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1363 continue ;
1366 /* Query tex coords */
1367 if (This->stateBlock->textures[textureNo] != NULL) {
1369 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1370 float *ptrToCoords = NULL;
1371 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1373 if (coordIdx > 7) {
1374 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1375 continue;
1376 } else if (coordIdx < 0) {
1377 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1378 continue;
1381 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1382 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1383 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1384 continue;
1385 } else {
1387 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1389 /* The coords to supply depend completely on the fvf / vertex shader */
1390 switch (coordsToUse) {
1391 case 4: q = ptrToCoords[3]; /* drop through */
1392 case 3: r = ptrToCoords[2]; /* drop through */
1393 case 2: t = ptrToCoords[1]; /* drop through */
1394 case 1: s = ptrToCoords[0];
1397 /* Projected is more 'fun' - Move the last coord to the 'q'
1398 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1399 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1400 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1402 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1403 switch (coordsToUse) {
1404 case 0: /* Drop Through */
1405 case 1:
1406 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1407 break;
1408 case 2:
1409 q = t;
1410 t = 0.0;
1411 coordsToUse = 4;
1412 break;
1413 case 3:
1414 q = r;
1415 r = 0.0;
1416 coordsToUse = 4;
1417 break;
1418 case 4: /* Nop here */
1419 break;
1420 default:
1421 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1422 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1427 switch (coordsToUse) { /* Supply the provided texture coords */
1428 case D3DTTFF_COUNT1:
1429 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1430 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1431 GLMULTITEXCOORD1F(textureNo, s);
1432 } else {
1433 glTexCoord1f(s);
1435 break;
1436 case D3DTTFF_COUNT2:
1437 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1438 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1439 GLMULTITEXCOORD2F(textureNo, s, t);
1440 } else {
1441 glTexCoord2f(s, t);
1443 break;
1444 case D3DTTFF_COUNT3:
1445 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1446 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1447 GLMULTITEXCOORD3F(textureNo, s, t, r);
1448 } else {
1449 glTexCoord3f(s, t, r);
1451 break;
1452 case D3DTTFF_COUNT4:
1453 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1454 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1455 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1456 } else {
1457 glTexCoord4f(s, t, r, q);
1459 break;
1460 default:
1461 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1465 } /* End of textures */
1467 /* Diffuse -------------------------------- */
1468 if (sd->u.s.diffuse.lpData != NULL) {
1469 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1470 D3DCOLOR_B_G(diffuseColor),
1471 D3DCOLOR_B_B(diffuseColor),
1472 D3DCOLOR_B_A(diffuseColor));
1473 VTRACE(("glColor4ub: r,g,b,a=%u,%u,%u,%u\n",
1474 D3DCOLOR_B_R(diffuseColor),
1475 D3DCOLOR_B_G(diffuseColor),
1476 D3DCOLOR_B_B(diffuseColor),
1477 D3DCOLOR_B_A(diffuseColor)));
1478 } else {
1479 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1482 /* Specular ------------------------------- */
1483 if (sd->u.s.specular.lpData != NULL) {
1484 VTRACE(("glSecondaryColor4ub: r,g,b=%u,%u,%u\n",
1485 D3DCOLOR_B_R(specularColor),
1486 D3DCOLOR_B_G(specularColor),
1487 D3DCOLOR_B_B(specularColor)));
1488 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1489 GL_EXTCALL(glSecondaryColor3ubEXT)(
1490 D3DCOLOR_B_R(specularColor),
1491 D3DCOLOR_B_G(specularColor),
1492 D3DCOLOR_B_B(specularColor));
1493 } else {
1494 /* Do not worry if specular colour missing and disable request */
1495 VTRACE(("Specular color extensions not supplied\n"));
1497 } else {
1498 if (vx_index == 0) {
1499 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1500 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1501 } else {
1502 /* Do not worry if specular colour missing and disable request */
1503 VTRACE(("Specular color extensions not supplied\n"));
1508 /* Normal -------------------------------- */
1509 if (sd->u.s.normal.lpData != NULL) {
1510 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1511 glNormal3f(nx, ny, nz);
1512 } else {
1513 if (vx_index == 0) glNormal3f(0, 0, 1);
1516 /* Position -------------------------------- */
1517 if (sd->u.s.position.lpData != NULL) {
1518 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1519 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1520 glVertex3f(x, y, z);
1521 } else {
1522 GLfloat w = 1.0 / rhw;
1523 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1524 glVertex4f(x*w, y*w, z*w, w);
1528 /* For non indexed mode, step onto next parts */
1529 if (idxData == NULL) {
1530 ++SkipnStrides;
1534 glEnd();
1535 checkGLcall("glEnd and previous calls");
1538 #if 0 /* TODO: Software/Hardware vertex blending support */
1540 * Draw with emulated vertex shaders
1541 * Note: strided data is uninitialized, as we need to pass the vertex
1542 * shader directly as ordering irs yet
1544 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1545 int PrimitiveType, ULONG NumPrimitives,
1546 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1548 unsigned int textureNo = 0;
1549 GLenum glPrimType = GL_POINTS;
1550 int NumVertexes = NumPrimitives;
1551 const short *pIdxBufS = NULL;
1552 const long *pIdxBufL = NULL;
1553 LONG SkipnStrides = 0;
1554 LONG vx_index;
1555 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1556 float rhw = 0.0f; /* rhw */
1557 float ptSize = 0.0f; /* Point size */
1558 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1559 int numcoords[8]; /* Number of coords */
1560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1562 IDirect3DVertexShaderImpl* vertexShader = NULL;
1564 TRACE("Using slow software vertex shader code\n");
1566 /* Variable Initialization */
1567 if (idxData != NULL) {
1568 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1569 else pIdxBufL = (const long *) idxData;
1572 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1573 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1575 /* Retrieve the VS information */
1576 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1578 /* Start drawing in GL */
1579 VTRACE(("glBegin(%x)\n", glPrimType));
1580 glBegin(glPrimType);
1582 /* For each primitive */
1583 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1585 /* For indexed data, we need to go a few more strides in */
1586 if (idxData != NULL) {
1588 /* Indexed so work out the number of strides to skip */
1589 if (idxSize == 2) {
1590 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1591 SkipnStrides = pIdxBufS[startIdx+vx_index];
1592 } else {
1593 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1594 SkipnStrides = pIdxBufL[startIdx+vx_index];
1598 /* Fill the vertex shader input */
1599 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1601 /* Initialize the output fields to the same defaults as it would normally have */
1602 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1603 vertexShader->output.oD[0].x = 1.0;
1604 vertexShader->output.oD[0].y = 1.0;
1605 vertexShader->output.oD[0].z = 1.0;
1606 vertexShader->output.oD[0].w = 1.0;
1608 /* Now execute the vertex shader */
1609 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1612 TRACE_VECTOR(vertexShader->output.oPos);
1613 TRACE_VECTOR(vertexShader->output.oD[0]);
1614 TRACE_VECTOR(vertexShader->output.oD[1]);
1615 TRACE_VECTOR(vertexShader->output.oT[0]);
1616 TRACE_VECTOR(vertexShader->output.oT[1]);
1617 TRACE_VECTOR(vertexShader->input.V[0]);
1618 TRACE_VECTOR(vertexShader->data->C[0]);
1619 TRACE_VECTOR(vertexShader->data->C[1]);
1620 TRACE_VECTOR(vertexShader->data->C[2]);
1621 TRACE_VECTOR(vertexShader->data->C[3]);
1622 TRACE_VECTOR(vertexShader->data->C[4]);
1623 TRACE_VECTOR(vertexShader->data->C[5]);
1624 TRACE_VECTOR(vertexShader->data->C[6]);
1625 TRACE_VECTOR(vertexShader->data->C[7]);
1628 /* Extract out the output */
1629 /* FIXME: Fog coords? */
1630 x = vertexShader->output.oPos.x;
1631 y = vertexShader->output.oPos.y;
1632 z = vertexShader->output.oPos.z;
1633 rhw = vertexShader->output.oPos.w;
1634 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1636 /** Update textures coords using vertexShader->output.oT[0->7] */
1637 memset(texcoords, 0x00, sizeof(texcoords));
1638 memset(numcoords, 0x00, sizeof(numcoords));
1639 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1640 if (This->stateBlock->textures[textureNo] != NULL) {
1641 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1642 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1643 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1644 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1645 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1646 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1647 } else {
1648 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1649 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1650 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1651 default: numcoords[textureNo] = 4;
1654 } else {
1655 numcoords[textureNo] = 0;
1659 /* Draw using this information */
1660 draw_vertex(iface,
1661 TRUE, x, y, z, rhw,
1662 TRUE, 0.0f, 0.0f, 1.0f,
1663 TRUE, (float*) &vertexShader->output.oD[0],
1664 TRUE, (float*) &vertexShader->output.oD[1],
1665 FALSE, ptSize, /* FIXME: Change back when supported */
1666 texcoords, numcoords);
1668 /* For non indexed mode, step onto next parts */
1669 if (idxData == NULL) {
1670 ++SkipnStrides;
1673 } /* for each vertex */
1675 glEnd();
1676 checkGLcall("glEnd and previous calls");
1679 #endif
1681 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1682 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1685 /* Now draw the graphics to the screen */
1686 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1687 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1688 /* Ideally, we should have software FV and hardware VS, possibly
1689 depending on the device type? */
1690 #if 0 /* TODO: vertex and pixel shaders */
1691 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1692 idxData, idxSize, minIndex, StartIdx);
1693 #endif
1695 } else {
1697 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1698 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1699 int endStride = startStride;
1700 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1702 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1703 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1704 int t;
1705 if (idxSize == 2) {
1706 unsigned short *index = (unsigned short *)idxData;
1707 index += StartIdx;
1708 for (t = 0 ; t < numberOfIndicies; t++) {
1709 if (startStride > *index)
1710 startStride = *index;
1711 if (endStride < *index)
1712 endStride = *index;
1713 index++;
1715 } else { /* idxSize == 4 */
1716 unsigned int *index = (unsigned int *)idxData;
1717 index += StartIdx;
1718 for (t = 0 ; t < numberOfIndicies; t++) {
1719 if (startStride > *index)
1720 startStride = *index;
1721 if (endStride < *index)
1722 endStride = *index;
1723 index++;
1726 } else {
1727 endStride += numberOfvertices -1;
1729 #endif
1730 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1731 /* pre-transform verticex */
1732 /* TODO: Caching, VBO's etc.. */
1734 /* Generate some fixme's if unsupported functionality is being used */
1735 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1736 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1737 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1738 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1740 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1741 FIXME("Tweening is only valid with vertex shaders\n");
1743 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1744 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1746 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1747 FIXME("Extended attributes are only valid with vertex shaders\n");
1749 #undef BUFFER_OR_DATA
1751 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1752 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1753 #endif
1755 /* vertex shaders */
1757 /* If the only vertex data used by the shader is supported by OpenGL then*/
1758 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1759 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1760 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1762 /* Load the vertex data using named arrays */
1763 TRACE("(%p) Loading vertex data\n", This);
1764 loadVertexData(iface, dataLocations);
1766 } else /* Otherwise */
1767 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1769 /* load the array data using ordinal mapping */
1770 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1772 } else { /* If this happens we must drawStridedSlow later on */
1773 TRACE("Not loading vertex data\n");
1776 TRACE("Loaded arrays\n");
1778 if (useVertexShaderFunction) {
1779 int i;
1780 GLint errPos;
1781 IWineD3DVertexDeclarationImpl *vertexDeclaration;
1783 TRACE("Using vertex shader\n");
1785 /* Bind the vertex program */
1786 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1787 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1789 /* and enable gl vertex shaders */
1790 glEnable(GL_VERTEX_PROGRAM_ARB);
1791 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1792 TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1794 /* Vertex Shader 8 constants */
1795 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
1796 if (vertexDeclaration != NULL) {
1797 float *constants = vertexDeclaration->constants;
1798 if (constants != NULL) {
1799 for (i = 0; i <= WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1800 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]);
1801 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
1806 /* Update the constants */
1807 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1808 /* TODO: add support for Integer and Boolean constants */
1809 if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
1810 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1811 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]);
1812 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1816 /* always draw strided fast if a vertex shader is being used */
1817 drawStridedFast(iface, numberOfIndicies, glPrimType,
1818 idxData, idxSize, minIndex, StartIdx);
1820 /* check for any errors */
1821 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1822 if (errPos != -1) {
1823 FIXME("HW VertexShader Error at position %d: %s\n",
1824 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1827 /* disable any attribs */
1828 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1829 GLint maxAttribs;
1830 int i;
1831 /* Leave all the attribs disabled */
1832 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1833 /* MESA does not support it right not */
1834 if (glGetError() != GL_NO_ERROR)
1835 maxAttribs = 16;
1836 for (i = 0; i < maxAttribs; i++) {
1837 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1838 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1842 /* Done */
1843 glDisable(GL_VERTEX_PROGRAM_ARB);
1844 } else {
1846 /* DirectX colours are in a different format to opengl colours
1847 so if diffuse or specular are used then we need to use drawStridedSlow
1848 to correct the colours */
1849 if ((dataLocations->u.s.pSize.lpData != NULL)
1850 || (dataLocations->u.s.diffuse.lpData != NULL)
1851 || (dataLocations->u.s.specular.lpData != NULL)) {
1852 /* TODO: replace drawStridedSlow with veretx fixups */
1853 #if 1
1855 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1856 idxData, idxSize, minIndex, StartIdx) ;
1859 * drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1860 * idxData, idxSize, minIndex, StartIdx);
1862 #endif
1863 } else {
1864 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1865 drawStridedFast(iface, numberOfIndicies, glPrimType,
1866 idxData, idxSize, minIndex, StartIdx);
1872 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1874 /* Dump out what parts we have supplied */
1875 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1876 TRACE_STRIDED((dataLocations), position);
1877 TRACE_STRIDED((dataLocations), blendWeights);
1878 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1879 TRACE_STRIDED((dataLocations), normal);
1880 TRACE_STRIDED((dataLocations), pSize);
1881 TRACE_STRIDED((dataLocations), diffuse);
1882 TRACE_STRIDED((dataLocations), specular);
1883 TRACE_STRIDED((dataLocations), texCoords[0]);
1884 TRACE_STRIDED((dataLocations), texCoords[1]);
1885 TRACE_STRIDED((dataLocations), texCoords[2]);
1886 TRACE_STRIDED((dataLocations), texCoords[3]);
1887 TRACE_STRIDED((dataLocations), texCoords[4]);
1888 TRACE_STRIDED((dataLocations), texCoords[5]);
1889 TRACE_STRIDED((dataLocations), texCoords[6]);
1890 TRACE_STRIDED((dataLocations), texCoords[7]);
1891 TRACE_STRIDED((dataLocations), position2);
1892 TRACE_STRIDED((dataLocations), normal2);
1893 TRACE_STRIDED((dataLocations), tangent);
1894 TRACE_STRIDED((dataLocations), binormal);
1895 TRACE_STRIDED((dataLocations), tessFactor);
1896 TRACE_STRIDED((dataLocations), fog);
1897 TRACE_STRIDED((dataLocations), depth);
1898 TRACE_STRIDED((dataLocations), sample);
1900 return;
1904 /* uploads textures and setup texture states ready for rendering */
1905 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1907 unsigned int i;
1909 * OK, here we clear down any old junk iect in the context
1910 * enable the new texture and apply any state changes:
1912 * Loop through all textures
1913 * select texture unit
1914 * if there is a texture bound to that unit then..
1915 * disable all textures types on that unit
1916 * enable and bind the texture that is bound to that unit.
1917 * otherwise disable all texture types on that unit.
1919 /* upload the textures */
1920 for (i = 0; i< GL_LIMITS(textures); ++i) {
1921 /* Bind the texture to the stage here */
1922 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1923 GLACTIVETEXTURE(i);
1924 } else if (0 < i) {
1925 /* This isn't so much a warn as a message to the user about lack of hardware support */
1926 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1929 /* don't bother with textures that have a colorop of disable */
1930 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1931 if (This->stateBlock->textures[i] != NULL) {
1933 glDisable(GL_TEXTURE_1D);
1934 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1935 /* disable all texture states that aren't the selected textures' dimension */
1936 switch(This->stateBlock->textureDimensions[i]) {
1937 case GL_TEXTURE_2D:
1938 glDisable(GL_TEXTURE_3D);
1939 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1940 break;
1941 case GL_TEXTURE_3D:
1942 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1943 glDisable(GL_TEXTURE_2D);
1944 break;
1945 case GLTEXTURECUBEMAP:
1946 glDisable(GL_TEXTURE_2D);
1947 glDisable(GL_TEXTURE_3D);
1948 break;
1950 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1951 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1952 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1953 } else {
1954 glEnable(This->stateBlock->textureDimensions[i]);
1956 /* Load up the texture now */
1957 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1958 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1959 /* this is a stub function representing the state blocks
1960 * being separated here we are only updating the texture
1961 * state changes, other objects and units get updated when
1962 * they change (or need to be updated), e.g. states that
1963 * relate to a context member line the texture unit are
1964 * only updated when the context needs updating
1966 /* Tell the abse texture to sync it's states */
1967 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1970 /* Bind a default texture if no texture has been set, but colour-op is enabled */
1971 else {
1972 glDisable(GL_TEXTURE_2D);
1973 glDisable(GL_TEXTURE_3D);
1974 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1975 glEnable(GL_TEXTURE_1D);
1976 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1977 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1979 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1980 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1981 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1982 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1983 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1984 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1985 /* alphaop */
1986 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1987 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1988 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1989 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1990 } else {
1992 /* no colorop so disable all the texture states */
1993 glDisable(GL_TEXTURE_1D);
1994 glDisable(GL_TEXTURE_2D);
1995 glDisable(GL_TEXTURE_3D);
1996 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2003 /* Routine common to the draw primitive and draw indexed primitive routines */
2004 void drawPrimitive(IWineD3DDevice *iface,
2005 int PrimitiveType,
2006 long NumPrimitives,
2007 /* for Indexed: */
2008 long StartVertexIndex,
2009 UINT numberOfVertices,
2010 long StartIdx,
2011 short idxSize,
2012 const void *idxData,
2013 int minIndex) {
2015 BOOL rc = FALSE;
2016 DWORD fvf = 0;
2017 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2018 BOOL useVertexShaderFunction = FALSE;
2019 BOOL isLightingOn = FALSE;
2020 Direct3DVertexStridedData dataLocations;
2021 int useHW = FALSE;
2023 if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE
2024 &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL
2025 && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
2026 useVertexShaderFunction = TRUE;
2027 } else {
2028 useVertexShaderFunction = FALSE;
2031 if (This->stateBlock->vertexDecl == NULL) {
2032 /* Work out what the FVF should look like */
2033 rc = initializeFVF(iface, &fvf);
2034 if (rc) return;
2035 } else {
2036 TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
2039 /* Ok, we will be updating the screen from here onwards so grab the lock */
2040 ENTER_GL();
2042 #if 0 /* TODO: vertex and pixel shaders */
2043 /* If we will be using a pixel, do some initialization for it */
2044 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
2045 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
2046 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
2048 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
2049 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
2050 glEnable(GL_FRAGMENT_PROGRAM_ARB);
2051 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
2053 /* init Constants */
2054 if (This->stateBlock->Changed.pixelShaderConstant) {
2055 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
2056 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
2058 /* Update the constants */
2059 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
2060 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
2061 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
2064 #endif /* TODO: vertex and pixel shaders */
2066 /* Initialize all values to null */
2067 memset(&dataLocations, 0x00, sizeof(dataLocations));
2068 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2070 if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2071 BOOL storeArrays = useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays == FALSE && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays == FALSE;
2073 TRACE("================ Vertex Declaration ===================\n");
2074 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, &dataLocations, StartVertexIndex, &fvf, storeArrays,
2075 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
2076 } else {
2077 TRACE("================ FVF ===================\n");
2078 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
2081 /* write out some debug information*/
2082 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2084 /* Setup transform matrices and sort out */
2085 if (useHW) {
2086 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2087 So make sure lighting is disabled. */
2088 isLightingOn = glIsEnabled(GL_LIGHTING);
2089 glDisable(GL_LIGHTING);
2090 checkGLcall("glDisable(GL_LIGHTING);");
2091 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2092 } else {
2093 isLightingOn = primitiveInitState(iface,
2094 fvf & D3DFVF_XYZRHW,
2095 !(fvf & D3DFVF_NORMAL),
2096 useVertexShaderFunction);
2099 /* Now initialize the materials state */
2100 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2102 drawPrimitiveUploadTextures(This);
2106 GLenum glPrimType;
2107 /* Ok, Work out which primitive is requested and how many vertexes that
2108 will be */
2109 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2110 #if 0 /* debugging code... just information not an error */
2111 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2112 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2114 #endif
2115 if (numberOfVertices == 0 )
2116 numberOfVertices = calculatedNumberOfindices;
2117 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2120 /* If vertex shaders or no normals, restore previous lighting state */
2121 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2122 if (isLightingOn) glEnable(GL_LIGHTING);
2123 else glDisable(GL_LIGHTING);
2124 TRACE("Restored lighting to original state\n");
2127 #if 0 /* TODO: vertex and pixel shaders */
2128 if (pixel_shader)
2130 #if 0
2131 GLint errPos;
2132 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2133 if (errPos != -1)
2134 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2135 #endif
2136 glDisable(GL_FRAGMENT_PROGRAM_ARB);
2138 #endif
2140 /* Finshed updating the screen, restore lock */
2141 LEAVE_GL();
2142 TRACE("Done all gl drawing\n");
2144 /* Diagnostics */
2145 #ifdef SHOW_FRAME_MAKEUP
2147 static long int primCounter = 0;
2148 /* NOTE: set primCounter to the value reported by drawprim
2149 before you want to to write frame makeup to /tmp */
2150 if (primCounter >= 0) {
2151 D3DLOCKED_RECT r;
2152 char buffer[80];
2153 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2154 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2155 TRACE("Saving screenshot %s\n", buffer);
2156 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2157 IWineD3DSurface_UnlockRect(This->renderTarget);
2159 #ifdef SHOW_TEXTURE_MAKEUP
2161 IWineD3DSurface *pSur;
2162 int textureNo;
2163 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2164 if (This->stateBlock->textures[textureNo] != NULL) {
2165 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2166 TRACE("Saving texture %s\n", buffer);
2167 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == D3DRTYPE_TEXTURE) {
2168 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2169 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2170 IWineD3DSurface_Release(pSur);
2171 } else {
2172 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2177 #endif
2179 TRACE("drawprim #%ld\n", primCounter);
2180 ++primCounter;
2182 #endif