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