wined3d: Move fields common to vertex shaders and pixel shaders to IWineD3DBaseShader.
[wine/multimedia.git] / dlls / wined3d / drawprim.c
blobbe8c038b273f2bffd4cb76ddc31de3b053c2c47b
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;
328 int reg;
330 /* Locate the vertex declaration */
331 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
332 TRACE("Using vertex declaration from shader\n");
333 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
334 } else {
335 TRACE("Using vertex declaration\n");
336 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
339 /* Translate the declaration into strided data */
340 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
342 element = vertexDeclaration->pDeclarationWine + i;
343 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
344 if (This->stateBlock->streamIsUP) {
345 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
346 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
347 } else {
348 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
349 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
351 stride = This->stateBlock->streamStride[element->Stream];
352 data += (BaseVertexIndex * stride);
353 data += element->Offset;
354 reg = element->Reg;
356 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
358 if (useVertexShaderFunction && reg != -1 && data) {
359 WINED3DGLTYPE glType = glTypeLookup[element->Type];
361 TRACE("(%p) : Set vertex attrib pointer: reg 0x%08x, d3d type 0x%08x, stride 0x%08lx, data %p)\n", This, reg, element->Type, stride, data);
363 GL_EXTCALL(glVertexAttribPointerARB(reg, glType.size, glType.glType, glType.normalized, stride, data));
364 checkGLcall("glVertexAttribPointerARB");
365 GL_EXTCALL(glEnableVertexAttribArrayARB(reg));
366 checkGLcall("glEnableVertexAttribArrayARB");
369 switch (element->Usage) {
370 case D3DDECLUSAGE_POSITION:
371 switch (element->UsageIndex) {
372 case 0: /* N-patch */
373 strided->u.s.position.lpData = data;
374 strided->u.s.position.dwType = element->Type;
375 strided->u.s.position.dwStride = stride;
376 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data, element->Type, stride);
377 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = element->Reg;
378 break;
379 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
380 TRACE("Tweened positions\n");
381 strided->u.s.position2.lpData = data;
382 strided->u.s.position2.dwType = element->Type;
383 strided->u.s.position2.dwStride = stride;
384 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data, element->Type, stride);
385 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2] = element->Reg;
386 break;
388 break;
389 case D3DDECLUSAGE_NORMAL:
390 switch (element->UsageIndex) {
391 case 0: /* N-patch */
392 strided->u.s.normal.lpData = data;
393 strided->u.s.normal.dwType = element->Type;
394 strided->u.s.normal.dwStride = stride;
395 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data, element->Type, stride);
396 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = element->Reg;
397 break;
398 case 1: /* skinning */
399 TRACE("Skinning / tween normals\n");
400 strided->u.s.normal2.lpData = data;
401 strided->u.s.normal2.dwType = element->Type;
402 strided->u.s.normal2.dwStride = stride;
403 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data, element->Type, stride);
404 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = element->Reg;
405 break;
407 *fvf |= D3DFVF_NORMAL;
408 break;
409 case D3DDECLUSAGE_BLENDINDICES:
410 /* demo @http://www.ati.com/developer/vertexblend.html
411 and http://www.flipcode.com/articles/article_dx8shaders.shtml
413 strided->u.s.blendMatrixIndices.lpData = data;
414 strided->u.s.blendMatrixIndices.dwType = element->Type;
415 strided->u.s.blendMatrixIndices.dwStride= stride;
416 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendMatrixIndices", data, element->Type, stride);
417 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = element->Reg;
418 break;
419 case D3DDECLUSAGE_BLENDWEIGHT:
420 strided->u.s.blendWeights.lpData = data;
421 strided->u.s.blendWeights.dwType = element->Type;
422 strided->u.s.blendWeights.dwStride = stride;
423 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data, element->Type, stride);
424 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = element->Reg;
425 break;
426 case D3DDECLUSAGE_PSIZE:
427 strided->u.s.pSize.lpData = data;
428 strided->u.s.pSize.dwType = element->Type;
429 strided->u.s.pSize.dwStride = stride;
430 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data, element->Type, stride);
431 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = element->Reg;
432 break;
433 case D3DDECLUSAGE_COLOR:
434 switch (element->UsageIndex) {
435 case 0:/* diffuse */
436 strided->u.s.diffuse.lpData = data;
437 strided->u.s.diffuse.dwType = element->Type;
438 strided->u.s.diffuse.dwStride = stride;
439 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data, element->Type, stride);
440 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = element->Reg;
441 break;
442 case 1: /* specular */
443 strided->u.s.specular.lpData = data;
444 strided->u.s.specular.dwType = element->Type;
445 strided->u.s.specular.dwStride = stride;
446 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data, element->Type, stride);
447 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = element->Reg;
451 break;
452 case D3DDECLUSAGE_TEXCOORD:
453 /* For some odd reason Microsoft decided to sum usage accross all the streams,
454 which means we need to do a count and not just use the usage number */
456 strided->u.s.texCoords[textureNo].lpData = data;
457 strided->u.s.texCoords[textureNo].dwType = element->Type;
458 strided->u.s.texCoords[textureNo].dwStride = stride;
459 TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo, data, element->Type, stride);
460 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + textureNo] = element->Reg;
462 ++textureNo;
463 break;
464 case D3DDECLUSAGE_TANGENT:
465 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
466 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
467 normal using tangents where no normal data has been provided */
468 TRACE("Tangents\n");
469 strided->u.s.tangent.lpData = data;
470 strided->u.s.tangent.dwType = element->Type;
471 strided->u.s.tangent.dwStride = stride;
472 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data, element->Type, stride);
473 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = element->Reg;
474 break;
475 case D3DDECLUSAGE_BINORMAL:
476 /* 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.
477 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)
478 The only thing they are useful for in fixed function would be working out normals when none are given.
480 TRACE("BI-Normal\n");
481 strided->u.s.binormal.lpData = data;
482 strided->u.s.binormal.dwType = element->Type;
483 strided->u.s.binormal.dwStride = stride;
484 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data, element->Type, stride);
485 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = element->Reg;
486 break;
487 case D3DDECLUSAGE_TESSFACTOR:
488 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
490 TRACE("Tess Factor\n");
491 strided->u.s.tessFactor.lpData = data;
492 strided->u.s.tessFactor.dwType = element->Type;
493 strided->u.s.tessFactor.dwStride = stride;
494 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data, element->Type, stride);
495 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = element->Reg;
496 break;
497 case D3DDECLUSAGE_POSITIONT:
499 switch (element->UsageIndex) {
500 case 0: /* N-patch */
501 strided->u.s.position.lpData = data;
502 strided->u.s.position.dwType = element->Type;
503 strided->u.s.position.dwStride = stride;
504 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data, element->Type, stride);
505 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = element->Reg;
506 break;
507 case 1: /* skinning */
508 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
509 http://xface.blogspot.com/2004_08_01_xface_archive.html
511 TRACE("Skinning positionsT\n");
512 strided->u.s.position2.lpData = data;
513 strided->u.s.position2.dwType = element->Type;
514 strided->u.s.position2.dwStride = stride;
515 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data, element->Type, stride);
516 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = element->Reg;
517 break;
519 /* TODO: change fvf usage to a plain boolean flag */
520 *fvf |= D3DFVF_XYZRHW;
521 /* FIXME: were faking this flag so that we don't transform the data again */
522 break;
523 case D3DDECLUSAGE_FOG:
524 /* maybe GL_EXT_fog_coord ?
525 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
526 * This extension allows specifying an explicit per-vertex fog
527 * coordinate to be used in fog computations, rather than using a
528 * fragment depth-based fog equation.
530 * */
531 TRACE("Fog\n");
532 strided->u.s.fog.lpData = data;
533 strided->u.s.fog.dwType = element->Type;
534 strided->u.s.fog.dwStride = stride;
535 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data, element->Type, stride);
536 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = element->Reg;
537 break;
538 case D3DDECLUSAGE_DEPTH:
539 TRACE("depth\n");
540 strided->u.s.depth.lpData = data;
541 strided->u.s.depth.dwType = element->Type;
542 strided->u.s.depth.dwStride = stride;
543 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data, element->Type, stride);
544 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = element->Reg;
545 break;
546 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
547 TRACE("depth\n");
548 strided->u.s.sample.lpData = data;
549 strided->u.s.sample.dwType = element->Type;
550 strided->u.s.sample.dwStride = stride;
551 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data, element->Type, stride);
552 if (storeOrder) arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = element->Reg;
553 break;
560 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
562 short LoopThroughTo = 0;
563 short nStream;
564 int numBlends;
565 int numTextures;
566 int textureNo;
567 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
568 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
570 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
572 /* OK, Now to setup the data locations
573 For the non-created vertex shaders, the VertexShader var holds the real
574 FVF and only stream 0 matters
575 For the created vertex shaders, there is an FVF per stream */
576 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
577 LoopThroughTo = MAX_STREAMS;
578 } else {
579 LoopThroughTo = 1;
582 /* Work through stream by stream */
583 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
584 DWORD stride = This->stateBlock->streamStride[nStream];
585 BYTE *data = NULL;
586 DWORD thisFVF = 0;
588 /* Skip empty streams */
589 if (This->stateBlock->streamSource[nStream] == NULL) continue;
591 /* Retrieve appropriate FVF */
592 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
593 thisFVF = This->stateBlock->fvf;
594 /* Handle memory passed directly as well as vertex buffers */
595 if (This->stateBlock->streamIsUP) {
596 data = (BYTE *)This->stateBlock->streamSource[nStream];
597 } else {
598 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
600 } else {
601 #if 0 /* TODO: Vertex shader support */
602 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
603 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
604 #endif
606 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
607 if (thisFVF == 0) continue;
609 /* Now convert the stream into pointers */
611 /* Shuffle to the beginning of the vertexes to render and index from there */
612 data = data + (BaseVertexIndex * stride);
614 /* Either 3 or 4 floats depending on the FVF */
615 /* FIXME: Can blending data be in a different stream to the position data?
616 and if so using the fixed pipeline how do we handle it */
617 if (thisFVF & D3DFVF_POSITION_MASK) {
618 strided->u.s.position.lpData = data;
619 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
620 strided->u.s.position.dwStride = stride;
621 data += 3 * sizeof(float);
622 if (thisFVF & D3DFVF_XYZRHW) {
623 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
624 data += sizeof(float);
628 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
629 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
630 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
631 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
633 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
634 TRACE("Setting blend Weights to %p\n", data);
635 strided->u.s.blendWeights.lpData = data;
636 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
637 strided->u.s.blendWeights.dwStride = stride;
638 data += numBlends * sizeof(FLOAT);
640 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
641 strided->u.s.blendMatrixIndices.lpData = data;
642 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
643 strided->u.s.blendMatrixIndices.dwStride= stride;
644 data += sizeof(DWORD);
648 /* Normal is always 3 floats */
649 if (thisFVF & D3DFVF_NORMAL) {
650 strided->u.s.normal.lpData = data;
651 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
652 strided->u.s.normal.dwStride = stride;
653 data += 3 * sizeof(FLOAT);
656 /* Pointsize is a single float */
657 if (thisFVF & D3DFVF_PSIZE) {
658 strided->u.s.pSize.lpData = data;
659 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
660 strided->u.s.pSize.dwStride = stride;
661 data += sizeof(FLOAT);
664 /* Diffuse is 4 unsigned bytes */
665 if (thisFVF & D3DFVF_DIFFUSE) {
666 strided->u.s.diffuse.lpData = data;
667 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
668 strided->u.s.diffuse.dwStride = stride;
669 data += sizeof(DWORD);
672 /* Specular is 4 unsigned bytes */
673 if (thisFVF & D3DFVF_SPECULAR) {
674 strided->u.s.specular.lpData = data;
675 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
676 strided->u.s.specular.dwStride = stride;
677 data += sizeof(DWORD);
680 /* Texture coords */
681 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
682 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
684 /* numTextures indicates the number of texture coordinates supplied */
685 /* However, the first set may not be for stage 0 texture - it all */
686 /* depends on D3DTSS_TEXCOORDINDEX. */
687 /* The number of bytes for each coordinate set is based off */
688 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
690 /* So, for each supplied texture extract the coords */
691 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
693 strided->u.s.texCoords[textureNo].lpData = data;
694 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
695 strided->u.s.texCoords[textureNo].dwStride = stride;
696 numCoords[textureNo] = coordIdxInfo & 0x03;
698 /* Always one set */
699 data += sizeof(float);
700 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
701 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
702 data += sizeof(float);
703 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
704 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
705 data += sizeof(float);
706 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
707 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
708 data += sizeof(float);
712 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
717 #if 0 /* TODO: Software Shaders */
718 /* Draw a single vertex using this information */
719 static void draw_vertex(IWineD3DDevice *iface, /* interface */
720 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
721 BOOL isNormal, float nx, float ny, float nz, /* normal */
722 BOOL isDiffuse, float *dRGBA, /* 1st colors */
723 BOOL isSpecular, float *sRGB, /* 2ndry colors */
724 BOOL isPtSize, float ptSize, /* pointSize */
725 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
727 unsigned int textureNo;
728 float s, t, r, q;
729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
731 /* Diffuse -------------------------------- */
732 if (isDiffuse) {
733 glColor4fv(dRGBA);
734 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
737 /* Specular Colour ------------------------------------------*/
738 if (isSpecular) {
739 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
740 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
741 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
742 } else {
743 VTRACE(("Specular color extensions not supplied\n"));
747 /* Normal -------------------------------- */
748 if (isNormal) {
749 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
750 glNormal3f(nx, ny, nz);
753 /* Point Size ----------------------------------------------*/
754 if (isPtSize) {
756 /* no such functionality in the fixed function GL pipeline */
757 FIXME("Cannot change ptSize here in openGl\n");
760 /* Texture coords --------------------------- */
761 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
763 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
764 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
765 continue ;
768 /* Query tex coords */
769 if (This->stateBlock->textures[textureNo] != NULL) {
771 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
772 if (coordIdx >= MAX_TEXTURES) {
773 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
774 continue;
775 } else if (numcoords[coordIdx] == 0) {
776 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
777 continue;
778 } else {
780 /* Initialize vars */
781 s = 0.0f;
782 t = 0.0f;
783 r = 0.0f;
784 q = 0.0f;
786 switch (numcoords[coordIdx]) {
787 case 4: q = texcoords[coordIdx].w; /* drop through */
788 case 3: r = texcoords[coordIdx].z; /* drop through */
789 case 2: t = texcoords[coordIdx].y; /* drop through */
790 case 1: s = texcoords[coordIdx].x;
793 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
794 case D3DTTFF_COUNT1:
795 VTRACE(("tex:%d, s=%f\n", textureNo, s));
796 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
797 GLMULTITEXCOORD1F(textureNo, s);
798 } else {
799 glTexCoord1f(s);
801 break;
802 case D3DTTFF_COUNT2:
803 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
804 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
805 GLMULTITEXCOORD2F(textureNo, s, t);
806 } else {
807 glTexCoord2f(s, t);
809 break;
810 case D3DTTFF_COUNT3:
811 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
812 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
813 GLMULTITEXCOORD3F(textureNo, s, t, r);
814 } else {
815 glTexCoord3f(s, t, r);
817 break;
818 case D3DTTFF_COUNT4:
819 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
820 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
821 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
822 } else {
823 glTexCoord4f(s, t, r, q);
825 break;
826 default:
827 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
831 } /* End of textures */
833 /* Position -------------------------------- */
834 if (isXYZ) {
835 if (1.0f == rhw || rhw < 0.00001f) {
836 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
837 glVertex3f(x, y, z);
838 } else {
839 /* Cannot optimize by dividing through by rhw as rhw is required
840 later for perspective in the GL pipeline for vertex shaders */
841 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
842 glVertex4f(x,y,z,rhw);
846 #endif /* TODO: Software shaders */
848 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
849 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
851 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
852 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
853 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
854 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
855 WINED3D_ATR_SIZE(_arrayName), \
856 WINED3D_ATR_GLTYPE(_arrayName), \
857 WINED3D_ATR_NORMALIZED(_arrayName), \
858 sd->u.s._arrayName.dwStride, \
859 sd->u.s._arrayName.lpData)); \
860 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
864 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
865 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
866 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
867 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
868 WINED3D_ATR_SIZE(position2), \
869 WINED3D_ATR_GLTYPE(position2), \
870 WINED3D_ATR_NORMALIZED(position2), \
871 sd->u.s.position2.dwStride, \
872 ((char *)sd->u.s.position2.lpData) + \
873 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
874 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
877 /* Generate some lookup tables */
878 /* drop the RHW coord, there must be a nicer way of doing this. */
879 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
880 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
882 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
883 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
884 LOAD_NUMBERED_ARRAY(position,POSITION);
885 LOAD_NUMBERED_ARRAY(normal,NORMAL);
886 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
887 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
888 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
889 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
890 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
891 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
892 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
893 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
894 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
895 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
896 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
897 #if 0 /* TODO: Samplers may allow for more texture coords */
898 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
899 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
900 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
901 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
902 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
903 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
904 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
905 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
906 #endif
907 LOAD_NUMBERED_ARRAY(position,POSITIONT);
908 /* d3d9 types */
909 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
910 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
911 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
912 LOAD_NUMBERED_ARRAY(position2,POSITION2);
913 /* there can be lots of position arrays */
914 LOAD_NUMBERED_POSITION_ARRAY(0);
915 LOAD_NUMBERED_POSITION_ARRAY(1);
916 LOAD_NUMBERED_POSITION_ARRAY(2);
917 LOAD_NUMBERED_POSITION_ARRAY(3);
918 LOAD_NUMBERED_POSITION_ARRAY(4);
919 LOAD_NUMBERED_POSITION_ARRAY(5);
920 LOAD_NUMBERED_POSITION_ARRAY(6);
921 LOAD_NUMBERED_POSITION_ARRAY(7);
922 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
923 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
924 LOAD_NUMBERED_ARRAY(fog,FOG);
925 LOAD_NUMBERED_ARRAY(depth,DEPTH);
926 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
928 #undef LOAD_NUMBERED_ARRAY
931 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
932 unsigned int textureNo = 0;
933 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 TRACE("Using fast vertex array code\n");
936 /* Blend Data ---------------------------------------------- */
937 if ((sd->u.s.blendWeights.lpData != NULL) ||
938 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
941 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
943 #if 1
944 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
945 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
946 #endif
948 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
949 /* FIXME("TODO\n");*/
950 /* Note dwType == float3 or float4 == 2 or 3 */
952 #if 0
953 /* with this on, the normals appear to be being modified,
954 but the vertices aren't being translated as they should be
955 Maybe the world matrix aren't being setup properly? */
956 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
957 #endif
960 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
961 WINED3D_ATR_SIZE(blendWeights) ,
962 sd->u.s.blendWeights.dwStride,
963 sd->u.s.blendWeights.lpData));
965 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
966 sd->u.s.blendWeights.dwStride,
967 sd->u.s.blendWeights.lpData);
969 checkGLcall("glWeightPointerARB");
971 if(sd->u.s.blendMatrixIndices.lpData != NULL){
972 static BOOL showfixme = TRUE;
973 if(showfixme){
974 FIXME("blendMatrixIndices support\n");
975 showfixme = FALSE;
981 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
982 /* FIXME("TODO\n");*/
983 #if 0
985 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
986 sd->u.s.blendWeights.dwStride,
987 sd->u.s.blendWeights.lpData);
988 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
989 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
990 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
991 #endif
993 } else {
994 /* TODO: support blends in fixupVertices */
995 FIXME("unsupported blending in openGl\n");
997 } else {
998 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
999 #if 0 /* TODO: Vertex blending */
1000 glDisable(GL_VERTEX_BLEND_ARB);
1001 #endif
1002 TRACE("ARB_VERTEX_BLEND\n");
1003 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
1004 TRACE(" EXT_VERTEX_WEIGHTING\n");
1005 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
1006 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
1011 #if 0 /* FOG ----------------------------------------------*/
1012 if (sd->u.s.fog.lpData != NULL) {
1013 /* TODO: fog*/
1014 if (GL_SUPPORT(EXT_FOG_COORD) {
1015 glEnableClientState(GL_FOG_COORD_EXT);
1016 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
1017 sd->u.s.fog.dwStride,
1018 sd->u.s.fog.lpData);
1019 } else {
1020 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1021 /* FIXME: fixme once */
1022 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1024 } else {
1025 if (GL_SUPPRT(EXT_FOR_COORD) {
1026 /* make sure fog is disabled */
1027 glDisableClientState(GL_FOG_COORD_EXT);
1030 #endif
1032 #if 0 /* tangents ----------------------------------------------*/
1033 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
1034 /* TODO: tangents*/
1035 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1036 if (sd->u.s.tangent.lpData != NULL) {
1037 glEnable(GL_TANGENT_ARRAY_EXT);
1038 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
1039 sd->u.s.tangent.dwStride,
1040 sd->u.s.tangent.lpData);
1041 } else {
1042 glDisable(GL_TANGENT_ARRAY_EXT);
1044 if (sd->u.s.binormal.lpData != NULL) {
1045 glEnable(GL_BINORMAL_ARRAY_EXT);
1046 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
1047 sd->u.s.binormal.dwStride,
1048 sd->u.s.binormal.lpData);
1049 } else{
1050 glDisable(GL_BINORMAL_ARRAY_EXT);
1053 } else {
1054 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1055 /* FIXME: fixme once */
1056 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1058 } else {
1059 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1060 /* make sure fog is disabled */
1061 glDisable(GL_TANGENT_ARRAY_EXT);
1062 glDisable(GL_BINORMAL_ARRAY_EXT);
1065 #endif
1067 /* Point Size ----------------------------------------------*/
1068 if (sd->u.s.pSize.lpData != NULL) {
1070 /* no such functionality in the fixed function GL pipeline */
1071 TRACE("Cannot change ptSize here in openGl\n");
1072 /* TODO: Implement this function in using shaders if they are available */
1076 /* Vertex Pointers -----------------------------------------*/
1077 if (sd->u.s.position.lpData != NULL) {
1078 /* Note dwType == float3 or float4 == 2 or 3 */
1079 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1080 sd->u.s.position.dwStride,
1081 sd->u.s.position.dwType + 1,
1082 sd->u.s.position.lpData));
1084 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1085 handling for rhw mode should not impact screen position whereas in GL it does.
1086 This may result in very slightly distored textures in rhw mode, but
1087 a very minimal different. There's always the other option of
1088 fixing the view matrix to prevent w from having any effect */
1089 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1090 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1091 checkGLcall("glVertexPointer(...)");
1092 glEnableClientState(GL_VERTEX_ARRAY);
1093 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1095 } else {
1096 glDisableClientState(GL_VERTEX_ARRAY);
1097 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1100 /* Normals -------------------------------------------------*/
1101 if (sd->u.s.normal.lpData != NULL) {
1102 /* Note dwType == float3 or float4 == 2 or 3 */
1103 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1104 sd->u.s.normal.dwStride,
1105 sd->u.s.normal.lpData));
1106 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1107 sd->u.s.normal.dwStride,
1108 sd->u.s.normal.lpData);
1109 checkGLcall("glNormalPointer(...)");
1110 glEnableClientState(GL_NORMAL_ARRAY);
1111 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1113 } else {
1114 glDisableClientState(GL_NORMAL_ARRAY);
1115 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1116 glNormal3f(0, 0, 1);
1117 checkGLcall("glNormal3f(0, 0, 1)");
1120 /* Diffuse Colour --------------------------------------------*/
1121 /* WARNING: Data here MUST be in RGBA format, so cannot */
1122 /* go directly into fast mode from app pgm, because */
1123 /* directx requires data in BGRA format. */
1124 /* currently fixupVertices swizels the format, but this isn't */
1125 /* very practical when using VBOS */
1126 /* NOTE: Unless we write a vertex shader to swizel the colour */
1127 /* , or the user doesn't care and wants the speed advantage */
1129 if (sd->u.s.diffuse.lpData != NULL) {
1130 /* Note dwType == float3 or float4 == 2 or 3 */
1131 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1132 sd->u.s.diffuse.dwStride,
1133 sd->u.s.diffuse.lpData));
1135 glColorPointer(4, GL_UNSIGNED_BYTE,
1136 sd->u.s.diffuse.dwStride,
1137 sd->u.s.diffuse.lpData);
1138 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1139 glEnableClientState(GL_COLOR_ARRAY);
1140 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1142 } else {
1143 glDisableClientState(GL_COLOR_ARRAY);
1144 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1145 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1146 checkGLcall("glColor4f(1, 1, 1, 1)");
1149 /* Specular Colour ------------------------------------------*/
1150 if (sd->u.s.specular.lpData != NULL) {
1151 TRACE("setting specular colour\n");
1152 /* Note dwType == float3 or float4 == 2 or 3 */
1153 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1154 sd->u.s.specular.dwStride,
1155 sd->u.s.specular.lpData));
1156 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1157 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1158 sd->u.s.specular.dwStride,
1159 sd->u.s.specular.lpData);
1160 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1161 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1162 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1163 } else {
1165 /* Missing specular color is not critical, no warnings */
1166 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1169 } else {
1170 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1172 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1173 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1174 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1175 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1176 } else {
1178 /* Missing specular color is not critical, no warnings */
1179 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1183 /* Texture coords -------------------------------------------*/
1185 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1187 /* Select the correct texture stage */
1188 GLCLIENTACTIVETEXTURE(textureNo);
1189 if (This->stateBlock->textures[textureNo] != NULL) {
1190 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1191 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1192 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1193 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1194 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1195 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1196 continue;
1199 if (coordIdx >= MAX_TEXTURES) {
1200 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1201 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1202 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1204 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1205 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1206 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1207 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1209 } else {
1211 /* The coords to supply depend completely on the fvf / vertex shader */
1212 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1213 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1216 } else {
1217 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1218 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1223 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1224 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1225 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1227 if (idxData != NULL /* This crashes sometimes!*/) {
1228 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1229 idxData = idxData == (void *)-1 ? NULL : idxData;
1230 #if 1
1231 #if 0
1232 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1233 glEnableClientState(GL_INDEX_ARRAY);
1234 #endif
1235 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1236 (const char *)idxData+(idxSize * startIdx));
1237 #else /* using drawRangeElements may be faster */
1239 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1240 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1241 (const char *)idxData+(idxSize * startIdx));
1242 #endif
1243 checkGLcall("glDrawRangeElements");
1245 } else {
1247 /* Note first is now zero as we shuffled along earlier */
1248 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1249 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1250 checkGLcall("glDrawArrays");
1254 return;
1258 * Actually draw using the supplied information.
1259 * Slower GL version which extracts info about each vertex in turn
1262 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1263 UINT NumVertexes, GLenum glPrimType,
1264 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1266 unsigned int textureNo = 0;
1267 const short *pIdxBufS = NULL;
1268 const long *pIdxBufL = NULL;
1269 LONG SkipnStrides = 0;
1270 LONG vx_index;
1271 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1272 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1273 float rhw = 0.0f; /* rhw */
1274 float ptSize = 0.0f; /* Point size */
1275 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1276 DWORD specularColor = 0; /* Specular Color */
1277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1279 TRACE("Using slow vertex array code\n");
1281 /* Variable Initialization */
1282 if (idxData != NULL) {
1283 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1284 else pIdxBufL = (const long *) idxData;
1287 /* Start drawing in GL */
1288 VTRACE(("glBegin(%x)\n", glPrimType));
1289 glBegin(glPrimType);
1291 /* For each primitive */
1292 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1294 /* Initialize diffuse color */
1295 diffuseColor = 0xFFFFFFFF;
1297 /* For indexed data, we need to go a few more strides in */
1298 if (idxData != NULL) {
1300 /* Indexed so work out the number of strides to skip */
1301 if (idxSize == 2) {
1302 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1303 SkipnStrides = pIdxBufS[startIdx + vx_index];
1304 } else {
1305 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1306 SkipnStrides = pIdxBufL[startIdx + vx_index];
1310 /* Position Information ------------------ */
1311 if (sd->u.s.position.lpData != NULL) {
1313 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1314 x = ptrToCoords[0];
1315 y = ptrToCoords[1];
1316 z = ptrToCoords[2];
1317 rhw = 1.0;
1318 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1320 /* RHW follows, only if transformed, ie 4 floats were provided */
1321 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1322 rhw = ptrToCoords[3];
1323 VTRACE(("rhw=%f\n", rhw));
1327 /* Blending data -------------------------- */
1328 if (sd->u.s.blendWeights.lpData != NULL) {
1329 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1330 FIXME("Blending not supported yet\n");
1332 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1333 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1337 /* Vertex Normal Data (untransformed only)- */
1338 if (sd->u.s.normal.lpData != NULL) {
1340 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1341 nx = ptrToCoords[0];
1342 ny = ptrToCoords[1];
1343 nz = ptrToCoords[2];
1344 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1347 /* Point Size ----------------------------- */
1348 if (sd->u.s.pSize.lpData != NULL) {
1350 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1351 ptSize = ptrToCoords[0];
1352 VTRACE(("ptSize=%f\n", ptSize));
1353 FIXME("No support for ptSize yet\n");
1356 /* Diffuse -------------------------------- */
1357 if (sd->u.s.diffuse.lpData != NULL) {
1359 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1360 diffuseColor = ptrToCoords[0];
1361 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1364 /* Specular -------------------------------- */
1365 if (sd->u.s.specular.lpData != NULL) {
1367 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1368 specularColor = ptrToCoords[0];
1369 VTRACE(("specularColor=%lx\n", specularColor));
1372 /* Texture coords --------------------------- */
1373 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1375 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1376 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1377 continue ;
1380 /* Query tex coords */
1381 if (This->stateBlock->textures[textureNo] != NULL) {
1383 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1384 float *ptrToCoords = NULL;
1385 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1387 if (coordIdx > 7) {
1388 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1389 continue;
1390 } else if (coordIdx < 0) {
1391 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1392 continue;
1395 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1396 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1397 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1398 continue;
1399 } else {
1401 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1403 /* The coords to supply depend completely on the fvf / vertex shader */
1404 switch (coordsToUse) {
1405 case 4: q = ptrToCoords[3]; /* drop through */
1406 case 3: r = ptrToCoords[2]; /* drop through */
1407 case 2: t = ptrToCoords[1]; /* drop through */
1408 case 1: s = ptrToCoords[0];
1411 /* Projected is more 'fun' - Move the last coord to the 'q'
1412 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1413 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1414 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1416 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1417 switch (coordsToUse) {
1418 case 0: /* Drop Through */
1419 case 1:
1420 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1421 break;
1422 case 2:
1423 q = t;
1424 t = 0.0;
1425 coordsToUse = 4;
1426 break;
1427 case 3:
1428 q = r;
1429 r = 0.0;
1430 coordsToUse = 4;
1431 break;
1432 case 4: /* Nop here */
1433 break;
1434 default:
1435 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1436 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1441 switch (coordsToUse) { /* Supply the provided texture coords */
1442 case D3DTTFF_COUNT1:
1443 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1444 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1445 GLMULTITEXCOORD1F(textureNo, s);
1446 } else {
1447 glTexCoord1f(s);
1449 break;
1450 case D3DTTFF_COUNT2:
1451 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1452 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1453 GLMULTITEXCOORD2F(textureNo, s, t);
1454 } else {
1455 glTexCoord2f(s, t);
1457 break;
1458 case D3DTTFF_COUNT3:
1459 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1460 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1461 GLMULTITEXCOORD3F(textureNo, s, t, r);
1462 } else {
1463 glTexCoord3f(s, t, r);
1465 break;
1466 case D3DTTFF_COUNT4:
1467 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1468 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1469 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1470 } else {
1471 glTexCoord4f(s, t, r, q);
1473 break;
1474 default:
1475 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1479 } /* End of textures */
1481 /* Diffuse -------------------------------- */
1482 if (sd->u.s.diffuse.lpData != NULL) {
1483 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1484 D3DCOLOR_B_G(diffuseColor),
1485 D3DCOLOR_B_B(diffuseColor),
1486 D3DCOLOR_B_A(diffuseColor));
1487 VTRACE(("glColor4ub: r,g,b,a=%u,%u,%u,%u\n",
1488 D3DCOLOR_B_R(diffuseColor),
1489 D3DCOLOR_B_G(diffuseColor),
1490 D3DCOLOR_B_B(diffuseColor),
1491 D3DCOLOR_B_A(diffuseColor)));
1492 } else {
1493 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1496 /* Specular ------------------------------- */
1497 if (sd->u.s.specular.lpData != NULL) {
1498 VTRACE(("glSecondaryColor4ub: r,g,b=%u,%u,%u\n",
1499 D3DCOLOR_B_R(specularColor),
1500 D3DCOLOR_B_G(specularColor),
1501 D3DCOLOR_B_B(specularColor)));
1502 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1503 GL_EXTCALL(glSecondaryColor3ubEXT)(
1504 D3DCOLOR_B_R(specularColor),
1505 D3DCOLOR_B_G(specularColor),
1506 D3DCOLOR_B_B(specularColor));
1507 } else {
1508 /* Do not worry if specular colour missing and disable request */
1509 VTRACE(("Specular color extensions not supplied\n"));
1511 } else {
1512 if (vx_index == 0) {
1513 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1514 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1515 } else {
1516 /* Do not worry if specular colour missing and disable request */
1517 VTRACE(("Specular color extensions not supplied\n"));
1522 /* Normal -------------------------------- */
1523 if (sd->u.s.normal.lpData != NULL) {
1524 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1525 glNormal3f(nx, ny, nz);
1526 } else {
1527 if (vx_index == 0) glNormal3f(0, 0, 1);
1530 /* Position -------------------------------- */
1531 if (sd->u.s.position.lpData != NULL) {
1532 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1533 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1534 glVertex3f(x, y, z);
1535 } else {
1536 GLfloat w = 1.0 / rhw;
1537 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1538 glVertex4f(x*w, y*w, z*w, w);
1542 /* For non indexed mode, step onto next parts */
1543 if (idxData == NULL) {
1544 ++SkipnStrides;
1548 glEnd();
1549 checkGLcall("glEnd and previous calls");
1552 #if 0 /* TODO: Software/Hardware vertex blending support */
1554 * Draw with emulated vertex shaders
1555 * Note: strided data is uninitialized, as we need to pass the vertex
1556 * shader directly as ordering irs yet
1558 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1559 int PrimitiveType, ULONG NumPrimitives,
1560 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1562 unsigned int textureNo = 0;
1563 GLenum glPrimType = GL_POINTS;
1564 int NumVertexes = NumPrimitives;
1565 const short *pIdxBufS = NULL;
1566 const long *pIdxBufL = NULL;
1567 LONG SkipnStrides = 0;
1568 LONG vx_index;
1569 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1570 float rhw = 0.0f; /* rhw */
1571 float ptSize = 0.0f; /* Point size */
1572 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1573 int numcoords[8]; /* Number of coords */
1574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1576 IDirect3DVertexShaderImpl* vertexShader = NULL;
1578 TRACE("Using slow software vertex shader code\n");
1580 /* Variable Initialization */
1581 if (idxData != NULL) {
1582 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1583 else pIdxBufL = (const long *) idxData;
1586 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1587 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1589 /* Retrieve the VS information */
1590 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1592 /* Start drawing in GL */
1593 VTRACE(("glBegin(%x)\n", glPrimType));
1594 glBegin(glPrimType);
1596 /* For each primitive */
1597 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1599 /* For indexed data, we need to go a few more strides in */
1600 if (idxData != NULL) {
1602 /* Indexed so work out the number of strides to skip */
1603 if (idxSize == 2) {
1604 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1605 SkipnStrides = pIdxBufS[startIdx+vx_index];
1606 } else {
1607 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1608 SkipnStrides = pIdxBufL[startIdx+vx_index];
1612 /* Fill the vertex shader input */
1613 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1615 /* Initialize the output fields to the same defaults as it would normally have */
1616 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1617 vertexShader->output.oD[0].x = 1.0;
1618 vertexShader->output.oD[0].y = 1.0;
1619 vertexShader->output.oD[0].z = 1.0;
1620 vertexShader->output.oD[0].w = 1.0;
1622 /* Now execute the vertex shader */
1623 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1626 TRACE_VECTOR(vertexShader->output.oPos);
1627 TRACE_VECTOR(vertexShader->output.oD[0]);
1628 TRACE_VECTOR(vertexShader->output.oD[1]);
1629 TRACE_VECTOR(vertexShader->output.oT[0]);
1630 TRACE_VECTOR(vertexShader->output.oT[1]);
1631 TRACE_VECTOR(vertexShader->input.V[0]);
1632 TRACE_VECTOR(vertexShader->data->C[0]);
1633 TRACE_VECTOR(vertexShader->data->C[1]);
1634 TRACE_VECTOR(vertexShader->data->C[2]);
1635 TRACE_VECTOR(vertexShader->data->C[3]);
1636 TRACE_VECTOR(vertexShader->data->C[4]);
1637 TRACE_VECTOR(vertexShader->data->C[5]);
1638 TRACE_VECTOR(vertexShader->data->C[6]);
1639 TRACE_VECTOR(vertexShader->data->C[7]);
1642 /* Extract out the output */
1643 /* FIXME: Fog coords? */
1644 x = vertexShader->output.oPos.x;
1645 y = vertexShader->output.oPos.y;
1646 z = vertexShader->output.oPos.z;
1647 rhw = vertexShader->output.oPos.w;
1648 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1650 /** Update textures coords using vertexShader->output.oT[0->7] */
1651 memset(texcoords, 0x00, sizeof(texcoords));
1652 memset(numcoords, 0x00, sizeof(numcoords));
1653 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1654 if (This->stateBlock->textures[textureNo] != NULL) {
1655 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1656 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1657 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1658 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1659 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1660 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1661 } else {
1662 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1663 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1664 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1665 default: numcoords[textureNo] = 4;
1668 } else {
1669 numcoords[textureNo] = 0;
1673 /* Draw using this information */
1674 draw_vertex(iface,
1675 TRUE, x, y, z, rhw,
1676 TRUE, 0.0f, 0.0f, 1.0f,
1677 TRUE, (float*) &vertexShader->output.oD[0],
1678 TRUE, (float*) &vertexShader->output.oD[1],
1679 FALSE, ptSize, /* FIXME: Change back when supported */
1680 texcoords, numcoords);
1682 /* For non indexed mode, step onto next parts */
1683 if (idxData == NULL) {
1684 ++SkipnStrides;
1687 } /* for each vertex */
1689 glEnd();
1690 checkGLcall("glEnd and previous calls");
1693 #endif
1695 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, BOOL usePixelShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1696 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1699 /* Now draw the graphics to the screen */
1700 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1701 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1702 /* Ideally, we should have software FV and hardware VS, possibly
1703 depending on the device type? */
1704 #if 0 /* TODO: vertex and pixel shaders */
1705 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1706 idxData, idxSize, minIndex, StartIdx);
1707 #endif
1709 } else {
1711 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1712 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1713 int endStride = startStride;
1714 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1716 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1717 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1718 int t;
1719 if (idxSize == 2) {
1720 unsigned short *index = (unsigned short *)idxData;
1721 index += StartIdx;
1722 for (t = 0 ; t < numberOfIndicies; t++) {
1723 if (startStride > *index)
1724 startStride = *index;
1725 if (endStride < *index)
1726 endStride = *index;
1727 index++;
1729 } else { /* idxSize == 4 */
1730 unsigned int *index = (unsigned int *)idxData;
1731 index += StartIdx;
1732 for (t = 0 ; t < numberOfIndicies; t++) {
1733 if (startStride > *index)
1734 startStride = *index;
1735 if (endStride < *index)
1736 endStride = *index;
1737 index++;
1740 } else {
1741 endStride += numberOfvertices -1;
1743 #endif
1744 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1745 /* pre-transform verticex */
1746 /* TODO: Caching, VBO's etc.. */
1748 /* Generate some fixme's if unsupported functionality is being used */
1749 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1750 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1751 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1752 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1754 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1755 FIXME("Tweening is only valid with vertex shaders\n");
1757 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1758 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1760 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1761 FIXME("Extended attributes are only valid with vertex shaders\n");
1763 #undef BUFFER_OR_DATA
1765 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1766 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1767 #endif
1769 /* vertex shaders */
1771 /* If the only vertex data used by the shader is supported by OpenGL then*/
1772 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1773 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1774 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1776 /* Load the vertex data using named arrays */
1777 TRACE("(%p) Loading vertex data\n", This);
1778 loadVertexData(iface, dataLocations);
1780 } else /* Otherwise */
1781 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1783 /* load the array data using ordinal mapping */
1784 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1786 } else { /* If this happens we must drawStridedSlow later on */
1787 TRACE("Not loading vertex data\n");
1790 TRACE("Loaded arrays\n");
1792 if (useVertexShaderFunction || usePixelShaderFunction) {
1793 if (useVertexShaderFunction) {
1794 IWineD3DVertexDeclarationImpl *vertexDeclaration;
1795 int i;
1797 TRACE("Using vertex shader\n");
1799 /* Bind the vertex program */
1800 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1801 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1803 /* Enable OpenGL vertex programs */
1804 glEnable(GL_VERTEX_PROGRAM_ARB);
1805 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1806 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1808 /* Vertex Shader 8 constants */
1809 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
1810 if (vertexDeclaration != NULL) {
1811 float *constants = vertexDeclaration->constants;
1812 if (constants != NULL) {
1813 for (i = 0; i <= WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1814 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]);
1815 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
1820 /* Update the constants */
1821 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1822 /* TODO: add support for Integer and Boolean constants */
1823 if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
1824 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1825 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]);
1826 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1831 if (usePixelShaderFunction) {
1832 int i;
1834 TRACE("Using pixel shader\n");
1836 /* Bind the fragment program */
1837 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1838 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1840 /* Enable OpenGL fragment programs */
1841 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1842 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1843 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1845 /* Update the constants */
1846 for (i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; ++i) {
1847 /* TODO: add support for Integer and Boolean constants */
1848 if (WINESHADERCNST_FLOAT == This->stateBlock->pixelShaderConstantT[i]) {
1849 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, &This->stateBlock->pixelShaderConstantF[i * 4]));
1850 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->pixelShaderConstantF[i *4 ], This->stateBlock->pixelShaderConstantF[i * 4 + 1], This->stateBlock->pixelShaderConstantF[i *4 + 2], This->stateBlock->pixelShaderConstantF[i * 4 + 3]);
1851 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1856 /* always draw strided fast if a vertex shader is being used */
1857 drawStridedFast(iface, numberOfIndicies, glPrimType,
1858 idxData, idxSize, minIndex, StartIdx);
1860 /* Cleanup vertex program */
1861 if (useVertexShaderFunction) {
1862 /* disable any attribs */
1863 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1864 GLint maxAttribs;
1865 int i;
1866 /* Leave all the attribs disabled */
1867 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1868 /* MESA does not support it right not */
1869 if (glGetError() != GL_NO_ERROR)
1870 maxAttribs = 16;
1871 for (i = 0; i < maxAttribs; ++i) {
1872 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1873 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1877 glDisable(GL_VERTEX_PROGRAM_ARB);
1880 /* Cleanup fragment program */
1881 if (usePixelShaderFunction) {
1882 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1884 } else {
1886 /* DirectX colours are in a different format to opengl colours
1887 so if diffuse or specular are used then we need to use drawStridedSlow
1888 to correct the colours */
1889 if ((dataLocations->u.s.pSize.lpData != NULL)
1890 || (dataLocations->u.s.diffuse.lpData != NULL)
1891 || (dataLocations->u.s.specular.lpData != NULL)) {
1892 /* TODO: replace drawStridedSlow with veretx fixups */
1893 #if 1
1895 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1896 idxData, idxSize, minIndex, StartIdx) ;
1899 * drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1900 * idxData, idxSize, minIndex, StartIdx);
1902 #endif
1903 } else {
1904 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1905 drawStridedFast(iface, numberOfIndicies, glPrimType,
1906 idxData, idxSize, minIndex, StartIdx);
1912 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1914 /* Dump out what parts we have supplied */
1915 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1916 TRACE_STRIDED((dataLocations), position);
1917 TRACE_STRIDED((dataLocations), blendWeights);
1918 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1919 TRACE_STRIDED((dataLocations), normal);
1920 TRACE_STRIDED((dataLocations), pSize);
1921 TRACE_STRIDED((dataLocations), diffuse);
1922 TRACE_STRIDED((dataLocations), specular);
1923 TRACE_STRIDED((dataLocations), texCoords[0]);
1924 TRACE_STRIDED((dataLocations), texCoords[1]);
1925 TRACE_STRIDED((dataLocations), texCoords[2]);
1926 TRACE_STRIDED((dataLocations), texCoords[3]);
1927 TRACE_STRIDED((dataLocations), texCoords[4]);
1928 TRACE_STRIDED((dataLocations), texCoords[5]);
1929 TRACE_STRIDED((dataLocations), texCoords[6]);
1930 TRACE_STRIDED((dataLocations), texCoords[7]);
1931 TRACE_STRIDED((dataLocations), position2);
1932 TRACE_STRIDED((dataLocations), normal2);
1933 TRACE_STRIDED((dataLocations), tangent);
1934 TRACE_STRIDED((dataLocations), binormal);
1935 TRACE_STRIDED((dataLocations), tessFactor);
1936 TRACE_STRIDED((dataLocations), fog);
1937 TRACE_STRIDED((dataLocations), depth);
1938 TRACE_STRIDED((dataLocations), sample);
1940 return;
1944 /* uploads textures and setup texture states ready for rendering */
1945 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1947 unsigned int i;
1949 * OK, here we clear down any old junk iect in the context
1950 * enable the new texture and apply any state changes:
1952 * Loop through all textures
1953 * select texture unit
1954 * if there is a texture bound to that unit then..
1955 * disable all textures types on that unit
1956 * enable and bind the texture that is bound to that unit.
1957 * otherwise disable all texture types on that unit.
1959 /* upload the textures */
1960 for (i = 0; i< GL_LIMITS(textures); ++i) {
1961 /* Bind the texture to the stage here */
1962 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1963 GLACTIVETEXTURE(i);
1964 } else if (0 < i) {
1965 /* This isn't so much a warn as a message to the user about lack of hardware support */
1966 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1969 /* don't bother with textures that have a colorop of disable */
1970 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1971 if (This->stateBlock->textures[i] != NULL) {
1973 glDisable(GL_TEXTURE_1D);
1974 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1975 /* disable all texture states that aren't the selected textures' dimension */
1976 switch(This->stateBlock->textureDimensions[i]) {
1977 case GL_TEXTURE_2D:
1978 glDisable(GL_TEXTURE_3D);
1979 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1980 break;
1981 case GL_TEXTURE_3D:
1982 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1983 glDisable(GL_TEXTURE_2D);
1984 break;
1985 case GLTEXTURECUBEMAP:
1986 glDisable(GL_TEXTURE_2D);
1987 glDisable(GL_TEXTURE_3D);
1988 break;
1990 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1991 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1992 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1993 } else {
1994 glEnable(This->stateBlock->textureDimensions[i]);
1996 /* Load up the texture now */
1997 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1998 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1999 /* this is a stub function representing the state blocks
2000 * being separated here we are only updating the texture
2001 * state changes, other objects and units get updated when
2002 * they change (or need to be updated), e.g. states that
2003 * relate to a context member line the texture unit are
2004 * only updated when the context needs updating
2006 /* Tell the abse texture to sync it's states */
2007 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2010 /* Bind a default texture if no texture has been set, but colour-op is enabled */
2011 else {
2012 glDisable(GL_TEXTURE_2D);
2013 glDisable(GL_TEXTURE_3D);
2014 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2015 glEnable(GL_TEXTURE_1D);
2016 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2017 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2019 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2020 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2021 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2022 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2023 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2024 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2025 /* alphaop */
2026 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2027 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2028 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2029 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2030 } else {
2032 /* no colorop so disable all the texture states */
2033 glDisable(GL_TEXTURE_1D);
2034 glDisable(GL_TEXTURE_2D);
2035 glDisable(GL_TEXTURE_3D);
2036 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2043 /* Routine common to the draw primitive and draw indexed primitive routines */
2044 void drawPrimitive(IWineD3DDevice *iface,
2045 int PrimitiveType,
2046 long NumPrimitives,
2047 /* for Indexed: */
2048 long StartVertexIndex,
2049 UINT numberOfVertices,
2050 long StartIdx,
2051 short idxSize,
2052 const void *idxData,
2053 int minIndex) {
2055 BOOL rc = FALSE;
2056 DWORD fvf = 0;
2057 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2058 BOOL useVertexShaderFunction = FALSE;
2059 BOOL usePixelShaderFunction = FALSE;
2060 BOOL isLightingOn = FALSE;
2061 Direct3DVertexStridedData dataLocations;
2062 int useHW = FALSE;
2064 if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE
2065 &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL
2066 && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
2067 useVertexShaderFunction = TRUE;
2068 } else {
2069 useVertexShaderFunction = FALSE;
2072 if (wined3d_settings.ps_mode != PS_NONE && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)
2073 && This->stateBlock->pixelShader
2074 && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function) {
2075 usePixelShaderFunction = TRUE;
2078 if (This->stateBlock->vertexDecl == NULL) {
2079 /* Work out what the FVF should look like */
2080 rc = initializeFVF(iface, &fvf);
2081 if (rc) return;
2082 } else {
2083 TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
2086 /* Ok, we will be updating the screen from here onwards so grab the lock */
2087 ENTER_GL();
2089 #if 0 /* TODO: vertex and pixel shaders */
2090 /* If we will be using a pixel, do some initialization for it */
2091 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
2092 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
2093 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
2095 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
2096 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
2097 glEnable(GL_FRAGMENT_PROGRAM_ARB);
2098 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
2100 /* init Constants */
2101 if (This->stateBlock->Changed.pixelShaderConstant) {
2102 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
2103 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
2105 /* Update the constants */
2106 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
2107 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
2108 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
2111 #endif /* TODO: vertex and pixel shaders */
2113 /* Initialize all values to null */
2114 memset(&dataLocations, 0x00, sizeof(dataLocations));
2115 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2117 if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2118 BOOL storeArrays = useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays == FALSE && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays == FALSE;
2120 TRACE("================ Vertex Declaration ===================\n");
2121 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, &dataLocations, StartVertexIndex, &fvf, storeArrays,
2122 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
2123 } else {
2124 TRACE("================ FVF ===================\n");
2125 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
2128 /* write out some debug information*/
2129 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2131 /* Setup transform matrices and sort out */
2132 if (useHW) {
2133 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2134 So make sure lighting is disabled. */
2135 isLightingOn = glIsEnabled(GL_LIGHTING);
2136 glDisable(GL_LIGHTING);
2137 checkGLcall("glDisable(GL_LIGHTING);");
2138 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2139 } else {
2140 isLightingOn = primitiveInitState(iface,
2141 fvf & D3DFVF_XYZRHW,
2142 !(fvf & D3DFVF_NORMAL),
2143 useVertexShaderFunction);
2146 /* Now initialize the materials state */
2147 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2149 drawPrimitiveUploadTextures(This);
2153 GLenum glPrimType;
2154 /* Ok, Work out which primitive is requested and how many vertexes that
2155 will be */
2156 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2157 #if 0 /* debugging code... just information not an error */
2158 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2159 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2161 #endif
2162 if (numberOfVertices == 0 )
2163 numberOfVertices = calculatedNumberOfindices;
2164 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2167 /* If vertex shaders or no normals, restore previous lighting state */
2168 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2169 if (isLightingOn) glEnable(GL_LIGHTING);
2170 else glDisable(GL_LIGHTING);
2171 TRACE("Restored lighting to original state\n");
2174 #if 0 /* TODO: vertex and pixel shaders */
2175 if (pixel_shader)
2177 #if 0
2178 GLint errPos;
2179 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2180 if (errPos != -1)
2181 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2182 #endif
2183 glDisable(GL_FRAGMENT_PROGRAM_ARB);
2185 #endif
2187 /* Finshed updating the screen, restore lock */
2188 LEAVE_GL();
2189 TRACE("Done all gl drawing\n");
2191 /* Diagnostics */
2192 #ifdef SHOW_FRAME_MAKEUP
2194 static long int primCounter = 0;
2195 /* NOTE: set primCounter to the value reported by drawprim
2196 before you want to to write frame makeup to /tmp */
2197 if (primCounter >= 0) {
2198 D3DLOCKED_RECT r;
2199 char buffer[80];
2200 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2201 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2202 TRACE("Saving screenshot %s\n", buffer);
2203 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2204 IWineD3DSurface_UnlockRect(This->renderTarget);
2206 #ifdef SHOW_TEXTURE_MAKEUP
2208 IWineD3DSurface *pSur;
2209 int textureNo;
2210 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2211 if (This->stateBlock->textures[textureNo] != NULL) {
2212 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2213 TRACE("Saving texture %s\n", buffer);
2214 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2215 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2216 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2217 IWineD3DSurface_Release(pSur);
2218 } else {
2219 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2224 #endif
2226 TRACE("drawprim #%ld\n", primCounter);
2227 ++primCounter;
2229 #endif