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