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
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
34 extern IWineD3DVertexShaderImpl
* VertexShaders
[64];
35 extern IWineD3DVertexDeclarationImpl
* VertexShaderDeclarations
[64];
36 extern IWineD3DPixelShaderImpl
* PixelShaders
[64];
38 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
41 /* Returns bits for what is expected from the fixed function pipeline, and whether
42 a vertex shader will be in use. Note the fvf bits returned may be split over
43 multiple streams only if the vertex shader was created, otherwise it all relates
45 static BOOL
initializeFVF(IWineD3DDevice
*iface
, DWORD
*FVFbits
)
48 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
50 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
51 /* The first thing to work out is if we are using the fixed function pipeline
52 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
53 is the FVF, or with a shader which was created with no function - in which
54 case there is an FVF per declared stream. If this occurs, we also maintain
55 an 'OR' of all the FVF's together so we know what to expect across all the
58 *FVFbits
= This
->stateBlock
->fvf
;
60 *FVFbits
= This
->stateBlock
->vertexShaderDecl
->allFVF
;
65 /* Issues the glBegin call for gl given the primitive type and count */
66 static DWORD
primitiveToGl(D3DPRIMITIVETYPE PrimitiveType
,
70 DWORD NumVertexes
= NumPrimitives
;
72 switch (PrimitiveType
) {
75 *primType
= GL_POINTS
;
76 NumVertexes
= NumPrimitives
;
82 NumVertexes
= NumPrimitives
* 2;
86 TRACE("LINE_STRIP\n");
87 *primType
= GL_LINE_STRIP
;
88 NumVertexes
= NumPrimitives
+ 1;
91 case D3DPT_TRIANGLELIST
:
93 *primType
= GL_TRIANGLES
;
94 NumVertexes
= NumPrimitives
* 3;
97 case D3DPT_TRIANGLESTRIP
:
98 TRACE("TRIANGLE_STRIP\n");
99 *primType
= GL_TRIANGLE_STRIP
;
100 NumVertexes
= NumPrimitives
+ 2;
103 case D3DPT_TRIANGLEFAN
:
104 TRACE("TRIANGLE_FAN\n");
105 *primType
= GL_TRIANGLE_FAN
;
106 NumVertexes
= NumPrimitives
+ 2;
110 FIXME("Unhandled primitive\n");
111 *primType
= GL_POINTS
;
117 /* Ensure the appropriate material states are set up - only change
118 state if really required */
119 static void init_materials(IWineD3DDevice
*iface
, BOOL isDiffuseSupplied
) {
121 BOOL requires_material_reset
= FALSE
;
122 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
124 if (This
->tracking_color
== NEEDS_TRACKING
&& isDiffuseSupplied
) {
125 /* If we have not set up the material color tracking, do it now as required */
126 glDisable(GL_COLOR_MATERIAL
); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
127 checkGLcall("glDisable GL_COLOR_MATERIAL");
128 TRACE("glColorMaterial Parm=%x\n", This
->tracking_parm
);
129 glColorMaterial(GL_FRONT_AND_BACK
, This
->tracking_parm
);
130 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
131 glEnable(GL_COLOR_MATERIAL
);
132 checkGLcall("glEnable GL_COLOR_MATERIAL");
133 This
->tracking_color
= IS_TRACKING
;
134 requires_material_reset
= TRUE
; /* Restore material settings as will be used */
136 } else if ((This
->tracking_color
== IS_TRACKING
&& isDiffuseSupplied
== FALSE
) ||
137 (This
->tracking_color
== NEEDS_TRACKING
&& isDiffuseSupplied
== FALSE
)) {
138 /* If we are tracking the current color but one isn't supplied, don't! */
139 glDisable(GL_COLOR_MATERIAL
);
140 checkGLcall("glDisable GL_COLOR_MATERIAL");
141 This
->tracking_color
= NEEDS_TRACKING
;
142 requires_material_reset
= TRUE
; /* Restore material settings as will be used */
144 } else if (This
->tracking_color
== IS_TRACKING
&& isDiffuseSupplied
) {
145 /* No need to reset material colors since no change to gl_color_material */
146 requires_material_reset
= FALSE
;
148 } else if (This
->tracking_color
== NEEDS_DISABLE
) {
149 glDisable(GL_COLOR_MATERIAL
);
150 checkGLcall("glDisable GL_COLOR_MATERIAL");
151 This
->tracking_color
= DISABLED_TRACKING
;
152 requires_material_reset
= TRUE
; /* Restore material settings as will be used */
155 /* Reset the material colors which may have been tracking the color*/
156 if (requires_material_reset
) {
157 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, (float*) &This
->stateBlock
->material
.Ambient
);
158 checkGLcall("glMaterialfv");
159 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, (float*) &This
->stateBlock
->material
.Diffuse
);
160 checkGLcall("glMaterialfv");
161 if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARENABLE
]) {
162 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->stateBlock
->material
.Specular
);
163 checkGLcall("glMaterialfv");
165 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
166 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
167 checkGLcall("glMaterialfv");
169 glMaterialfv(GL_FRONT_AND_BACK
, GL_EMISSION
, (float*) &This
->stateBlock
->material
.Emissive
);
170 checkGLcall("glMaterialfv");
175 static GLfloat invymat
[16] = {
176 1.0f
, 0.0f
, 0.0f
, 0.0f
,
177 0.0f
, -1.0f
, 0.0f
, 0.0f
,
178 0.0f
, 0.0f
, 1.0f
, 0.0f
,
179 0.0f
, 0.0f
, 0.0f
, 1.0f
};
181 void d3ddevice_set_ortho(IWineD3DDeviceImpl
*This
) {
182 /* If the last draw was transformed as well, no need to reapply all the matrixes */
183 if ( (!This
->last_was_rhw
) || (This
->viewport_changed
) ) {
185 double X
, Y
, height
, width
, minZ
, maxZ
;
186 This
->last_was_rhw
= TRUE
;
187 This
->viewport_changed
= FALSE
;
189 /* Transformed already into viewport coordinates, so we do not need transform
190 matrices. Reset all matrices to identity and leave the default matrix in world
192 glMatrixMode(GL_MODELVIEW
);
193 checkGLcall("glMatrixMode(GL_MODELVIEW)");
195 checkGLcall("glLoadIdentity");
197 glMatrixMode(GL_PROJECTION
);
198 checkGLcall("glMatrixMode(GL_PROJECTION)");
200 checkGLcall("glLoadIdentity");
202 /* Set up the viewport to be full viewport */
203 X
= This
->stateBlock
->viewport
.X
;
204 Y
= This
->stateBlock
->viewport
.Y
;
205 height
= This
->stateBlock
->viewport
.Height
;
206 width
= This
->stateBlock
->viewport
.Width
;
207 minZ
= This
->stateBlock
->viewport
.MinZ
;
208 maxZ
= This
->stateBlock
->viewport
.MaxZ
;
209 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width
, height
, -minZ
, -maxZ
);
210 glOrtho(X
, X
+ width
, Y
+ height
, Y
, -minZ
, -maxZ
);
211 checkGLcall("glOrtho");
213 /* Window Coord 0 is the middle of the first pixel, so translate by half
214 a pixel (See comment above glTranslate below) */
215 glTranslatef(0.375, 0.375, 0);
216 checkGLcall("glTranslatef(0.375, 0.375, 0)");
217 if (This
->renderUpsideDown
) {
218 glMultMatrixf(invymat
);
219 checkGLcall("glMultMatrixf(invymat)");
224 /* Setup views - Transformed & lit if RHW, else untransformed.
225 Only unlit if Normals are supplied
226 Returns: Whether to restore lighting afterwards */
227 static BOOL
primitiveInitState(IWineD3DDevice
*iface
, BOOL vtx_transformed
, BOOL vtx_lit
, BOOL useVS
) {
229 BOOL isLightingOn
= FALSE
;
230 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
232 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
233 set by the appropriate render state. Note Vertex Shader output is already lit */
234 if (vtx_lit
|| useVS
) {
235 isLightingOn
= glIsEnabled(GL_LIGHTING
);
236 glDisable(GL_LIGHTING
);
237 checkGLcall("glDisable(GL_LIGHTING);");
238 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn
);
241 if (!useVS
&& vtx_transformed
) {
242 d3ddevice_set_ortho(This
);
245 /* Untransformed, so relies on the view and projection matrices */
247 if (!useVS
&& (This
->last_was_rhw
|| !This
->modelview_valid
)) {
248 /* Only reapply when have to */
249 This
->modelview_valid
= TRUE
;
250 glMatrixMode(GL_MODELVIEW
);
251 checkGLcall("glMatrixMode");
253 /* In the general case, the view matrix is the identity matrix */
254 if (This
->view_ident
) {
255 glLoadMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_WORLDMATRIX(0)].u
.m
[0][0]);
256 checkGLcall("glLoadMatrixf");
258 glLoadMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_VIEW
].u
.m
[0][0]);
259 checkGLcall("glLoadMatrixf");
260 glMultMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_WORLDMATRIX(0)].u
.m
[0][0]);
261 checkGLcall("glMultMatrixf");
265 if (!useVS
&& (This
->last_was_rhw
|| !This
->proj_valid
)) {
266 /* Only reapply when have to */
267 This
->proj_valid
= TRUE
;
268 glMatrixMode(GL_PROJECTION
);
269 checkGLcall("glMatrixMode");
271 /* The rule is that the window coordinate 0 does not correspond to the
272 beginning of the first pixel, but the center of the first pixel.
273 As a consequence if you want to correctly draw one line exactly from
274 the left to the right end of the viewport (with all matrices set to
275 be identity), the x coords of both ends of the line would be not
276 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
280 glTranslatef(0.9 / This
->stateBlock
->viewport
.Width
, -0.9 / This
->stateBlock
->viewport
.Height
, 0);
281 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
283 if (This
->renderUpsideDown
) {
284 glMultMatrixf(invymat
);
285 checkGLcall("glMultMatrixf(invymat)");
287 glMultMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_PROJECTION
].u
.m
[0][0]);
288 checkGLcall("glLoadMatrixf");
291 /* Vertex Shader output is already transformed, so set up identity matrices */
292 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
293 come along this needs to take into account whether s/w ones were
296 glMatrixMode(GL_MODELVIEW
);
297 checkGLcall("glMatrixMode");
299 glMatrixMode(GL_PROJECTION
);
300 checkGLcall("glMatrixMode");
302 /* Window Coord 0 is the middle of the first pixel, so translate by half
303 a pixel (See comment above glTranslate above) */
304 glTranslatef(0.9 / This
->stateBlock
->viewport
.Width
, -0.9 / This
->stateBlock
->viewport
.Height
, 0);
305 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
306 if (This
->renderUpsideDown
) {
307 glMultMatrixf(invymat
);
308 checkGLcall("glMultMatrixf(invymat)");
310 This
->modelview_valid
= FALSE
;
311 This
->proj_valid
= FALSE
;
313 This
->last_was_rhw
= FALSE
;
318 void primitiveDeclarationConvertToStridedData(
319 IWineD3DDevice
*iface
,
320 BOOL useVertexShaderFunction
,
321 WineDirect3DVertexStridedData
*strided
,
322 LONG BaseVertexIndex
,
325 /* We need to deal with frequency data!*/
329 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
330 IWineD3DVertexDeclarationImpl
* vertexDeclaration
= NULL
;
332 WINED3DVERTEXELEMENT
*element
;
336 /* Locate the vertex declaration */
337 if (useVertexShaderFunction
&& ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->vertexDeclaration
) {
338 TRACE("Using vertex declaration from shader\n");
339 vertexDeclaration
= (IWineD3DVertexDeclarationImpl
*)((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->vertexDeclaration
;
341 TRACE("Using vertex declaration\n");
342 vertexDeclaration
= (IWineD3DVertexDeclarationImpl
*)This
->stateBlock
->vertexDecl
;
345 /* Translate the declaration into strided data */
346 for (i
= 0 ; i
< vertexDeclaration
->declarationWNumElements
- 1; ++i
) {
348 element
= vertexDeclaration
->pDeclarationWine
+ i
;
349 TRACE("%p Elements %p %d or %d\n", vertexDeclaration
->pDeclarationWine
, element
, i
, vertexDeclaration
->declarationWNumElements
);
350 if (This
->stateBlock
->streamIsUP
) {
351 TRACE("Stream is up %d, %p\n", element
->Stream
, This
->stateBlock
->streamSource
[element
->Stream
]);
352 data
= (BYTE
*)This
->stateBlock
->streamSource
[element
->Stream
];
354 TRACE("Stream isn't up %d, %p\n", element
->Stream
, This
->stateBlock
->streamSource
[element
->Stream
]);
355 data
= IWineD3DVertexBufferImpl_GetMemory(This
->stateBlock
->streamSource
[element
->Stream
], 0);
357 stride
= This
->stateBlock
->streamStride
[element
->Stream
];
358 data
+= (BaseVertexIndex
* stride
);
359 data
+= element
->Offset
;
362 TRACE("Offset %d Stream %d UsageIndex %d\n", element
->Offset
, element
->Stream
, element
->UsageIndex
);
364 if (useVertexShaderFunction
&& reg
!= -1 && data
) {
365 WINED3DGLTYPE glType
= glTypeLookup
[element
->Type
];
367 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
);
369 GL_EXTCALL(glVertexAttribPointerARB(reg
, glType
.size
, glType
.glType
, glType
.normalized
, stride
, data
));
370 checkGLcall("glVertexAttribPointerARB");
371 GL_EXTCALL(glEnableVertexAttribArrayARB(reg
));
372 checkGLcall("glEnableVertexAttribArrayARB");
375 switch (element
->Usage
) {
376 case D3DDECLUSAGE_POSITION
:
377 switch (element
->UsageIndex
) {
378 case 0: /* N-patch */
379 strided
->u
.s
.position
.lpData
= data
;
380 strided
->u
.s
.position
.dwType
= element
->Type
;
381 strided
->u
.s
.position
.dwStride
= stride
;
382 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position", data
, element
->Type
, stride
);
384 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
385 TRACE("Tweened positions\n");
386 strided
->u
.s
.position2
.lpData
= data
;
387 strided
->u
.s
.position2
.dwType
= element
->Type
;
388 strided
->u
.s
.position2
.dwStride
= stride
;
389 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2", data
, element
->Type
, stride
);
393 case D3DDECLUSAGE_NORMAL
:
394 switch (element
->UsageIndex
) {
395 case 0: /* N-patch */
396 strided
->u
.s
.normal
.lpData
= data
;
397 strided
->u
.s
.normal
.dwType
= element
->Type
;
398 strided
->u
.s
.normal
.dwStride
= stride
;
399 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal", data
, element
->Type
, stride
);
401 case 1: /* skinning */
402 TRACE("Skinning / tween normals\n");
403 strided
->u
.s
.normal2
.lpData
= data
;
404 strided
->u
.s
.normal2
.dwType
= element
->Type
;
405 strided
->u
.s
.normal2
.dwStride
= stride
;
406 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "normal2", data
, element
->Type
, stride
);
409 *fvf
|= D3DFVF_NORMAL
;
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
);
420 case D3DDECLUSAGE_BLENDWEIGHT
:
421 strided
->u
.s
.blendWeights
.lpData
= data
;
422 strided
->u
.s
.blendWeights
.dwType
= element
->Type
;
423 strided
->u
.s
.blendWeights
.dwStride
= stride
;
424 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "blendWeights", data
, element
->Type
, stride
);
426 case D3DDECLUSAGE_PSIZE
:
427 strided
->u
.s
.pSize
.lpData
= data
;
428 strided
->u
.s
.pSize
.dwType
= element
->Type
;
429 strided
->u
.s
.pSize
.dwStride
= stride
;
430 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "pSize", data
, element
->Type
, stride
);
432 case D3DDECLUSAGE_COLOR
:
433 switch (element
->UsageIndex
) {
435 strided
->u
.s
.diffuse
.lpData
= data
;
436 strided
->u
.s
.diffuse
.dwType
= element
->Type
;
437 strided
->u
.s
.diffuse
.dwStride
= stride
;
438 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "diffuse", data
, element
->Type
, stride
);
440 case 1: /* specular */
441 strided
->u
.s
.specular
.lpData
= data
;
442 strided
->u
.s
.specular
.dwType
= element
->Type
;
443 strided
->u
.s
.specular
.dwStride
= stride
;
444 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "specular", data
, element
->Type
, stride
);
449 case D3DDECLUSAGE_TEXCOORD
:
450 /* For some odd reason Microsoft decided to sum usage accross all the streams,
451 which means we need to do a count and not just use the usage number */
453 strided
->u
.s
.texCoords
[textureNo
].lpData
= data
;
454 strided
->u
.s
.texCoords
[textureNo
].dwType
= element
->Type
;
455 strided
->u
.s
.texCoords
[textureNo
].dwStride
= stride
;
456 TRACE("Set strided %s.%d data %p, type %d. stride %ld\n", "texCoords", textureNo
, data
, element
->Type
, stride
);
460 case D3DDECLUSAGE_TANGENT
:
461 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
462 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
463 normal using tangents where no normal data has been provided */
465 strided
->u
.s
.tangent
.lpData
= data
;
466 strided
->u
.s
.tangent
.dwType
= element
->Type
;
467 strided
->u
.s
.tangent
.dwStride
= stride
;
468 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tangent", data
, element
->Type
, stride
);
470 case D3DDECLUSAGE_BINORMAL
:
471 /* 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.
472 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)
473 The only thing they are useful for in fixed function would be working out normals when none are given.
475 TRACE("BI-Normal\n");
476 strided
->u
.s
.binormal
.lpData
= data
;
477 strided
->u
.s
.binormal
.dwType
= element
->Type
;
478 strided
->u
.s
.binormal
.dwStride
= stride
;
479 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "binormal", data
, element
->Type
, stride
);
481 case D3DDECLUSAGE_TESSFACTOR
:
482 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
484 TRACE("Tess Factor\n");
485 strided
->u
.s
.tessFactor
.lpData
= data
;
486 strided
->u
.s
.tessFactor
.dwType
= element
->Type
;
487 strided
->u
.s
.tessFactor
.dwStride
= stride
;
488 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "tessFactor", data
, element
->Type
, stride
);
490 case D3DDECLUSAGE_POSITIONT
:
492 switch (element
->UsageIndex
) {
493 case 0: /* N-patch */
494 strided
->u
.s
.position
.lpData
= data
;
495 strided
->u
.s
.position
.dwType
= element
->Type
;
496 strided
->u
.s
.position
.dwStride
= stride
;
497 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "positionT", data
, element
->Type
, stride
);
499 case 1: /* skinning */
500 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
501 http://xface.blogspot.com/2004_08_01_xface_archive.html
503 TRACE("Skinning positionsT\n");
504 strided
->u
.s
.position2
.lpData
= data
;
505 strided
->u
.s
.position2
.dwType
= element
->Type
;
506 strided
->u
.s
.position2
.dwStride
= stride
;
507 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "position2T", data
, element
->Type
, stride
);
510 /* TODO: change fvf usage to a plain boolean flag */
511 *fvf
|= D3DFVF_XYZRHW
;
512 /* FIXME: were faking this flag so that we don't transform the data again */
514 case D3DDECLUSAGE_FOG
:
515 /* maybe GL_EXT_fog_coord ?
516 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
517 * This extension allows specifying an explicit per-vertex fog
518 * coordinate to be used in fog computations, rather than using a
519 * fragment depth-based fog equation.
523 strided
->u
.s
.fog
.lpData
= data
;
524 strided
->u
.s
.fog
.dwType
= element
->Type
;
525 strided
->u
.s
.fog
.dwStride
= stride
;
526 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "fog", data
, element
->Type
, stride
);
528 case D3DDECLUSAGE_DEPTH
:
530 strided
->u
.s
.depth
.lpData
= data
;
531 strided
->u
.s
.depth
.dwType
= element
->Type
;
532 strided
->u
.s
.depth
.dwStride
= stride
;
533 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "depth", data
, element
->Type
, stride
);
535 case D3DDECLUSAGE_SAMPLE
: /* VertexShader textures */
537 strided
->u
.s
.sample
.lpData
= data
;
538 strided
->u
.s
.sample
.dwType
= element
->Type
;
539 strided
->u
.s
.sample
.dwStride
= stride
;
540 TRACE("Set strided %s. data %p, type %d. stride %ld\n", "sample", data
, element
->Type
, stride
);
548 void primitiveConvertToStridedData(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*strided
, LONG BaseVertexIndex
) {
550 short LoopThroughTo
= 0;
555 int coordIdxInfo
= 0x00; /* Information on number of coords supplied */
556 int numCoords
[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
558 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
560 /* OK, Now to setup the data locations
561 For the non-created vertex shaders, the VertexShader var holds the real
562 FVF and only stream 0 matters
563 For the created vertex shaders, there is an FVF per stream */
564 if (!This
->stateBlock
->streamIsUP
&& !(This
->stateBlock
->vertexShader
== NULL
)) {
565 LoopThroughTo
= MAX_STREAMS
;
570 /* Work through stream by stream */
571 for (nStream
=0; nStream
<LoopThroughTo
; ++nStream
) {
572 DWORD stride
= This
->stateBlock
->streamStride
[nStream
];
576 /* Skip empty streams */
577 if (This
->stateBlock
->streamSource
[nStream
] == NULL
) continue;
579 /* Retrieve appropriate FVF */
580 if (LoopThroughTo
== 1) { /* Use FVF, not vertex shader */
581 thisFVF
= This
->stateBlock
->fvf
;
582 /* Handle memory passed directly as well as vertex buffers */
583 if (This
->stateBlock
->streamIsUP
) {
584 data
= (BYTE
*)This
->stateBlock
->streamSource
[nStream
];
586 data
= IWineD3DVertexBufferImpl_GetMemory(This
->stateBlock
->streamSource
[nStream
], 0);
589 #if 0 /* TODO: Vertex shader support */
590 thisFVF
= This
->stateBlock
->vertexShaderDecl
->fvf
[nStream
];
591 data
= IWineD3DVertexBufferImpl_GetMemory(This
->stateBlock
->streamSource
[nStream
], 0);
594 VTRACE(("FVF for stream %d is %lx\n", nStream
, thisFVF
));
595 if (thisFVF
== 0) continue;
597 /* Now convert the stream into pointers */
599 /* Shuffle to the beginning of the vertexes to render and index from there */
600 data
= data
+ (BaseVertexIndex
* stride
);
602 /* Either 3 or 4 floats depending on the FVF */
603 /* FIXME: Can blending data be in a different stream to the position data?
604 and if so using the fixed pipeline how do we handle it */
605 if (thisFVF
& D3DFVF_POSITION_MASK
) {
606 strided
->u
.s
.position
.lpData
= data
;
607 strided
->u
.s
.position
.dwType
= D3DDECLTYPE_FLOAT3
;
608 strided
->u
.s
.position
.dwStride
= stride
;
609 data
+= 3 * sizeof(float);
610 if (thisFVF
& D3DFVF_XYZRHW
) {
611 strided
->u
.s
.position
.dwType
= D3DDECLTYPE_FLOAT4
;
612 data
+= sizeof(float);
616 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
617 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
618 numBlends
= 1 + (((thisFVF
& D3DFVF_XYZB5
) - D3DFVF_XYZB1
) >> 1);
619 if(thisFVF
& D3DFVF_LASTBETA_UBYTE4
) numBlends
--;
621 if ((thisFVF
& D3DFVF_XYZB5
) > D3DFVF_XYZRHW
) {
622 TRACE("Setting blend Weights to %p\n", data
);
623 strided
->u
.s
.blendWeights
.lpData
= data
;
624 strided
->u
.s
.blendWeights
.dwType
= D3DDECLTYPE_FLOAT1
+ numBlends
- 1;
625 strided
->u
.s
.blendWeights
.dwStride
= stride
;
626 data
+= numBlends
* sizeof(FLOAT
);
628 if (thisFVF
& D3DFVF_LASTBETA_UBYTE4
) {
629 strided
->u
.s
.blendMatrixIndices
.lpData
= data
;
630 strided
->u
.s
.blendMatrixIndices
.dwType
= D3DDECLTYPE_UBYTE4
;
631 strided
->u
.s
.blendMatrixIndices
.dwStride
= stride
;
632 data
+= sizeof(DWORD
);
636 /* Normal is always 3 floats */
637 if (thisFVF
& D3DFVF_NORMAL
) {
638 strided
->u
.s
.normal
.lpData
= data
;
639 strided
->u
.s
.normal
.dwType
= D3DDECLTYPE_FLOAT3
;
640 strided
->u
.s
.normal
.dwStride
= stride
;
641 data
+= 3 * sizeof(FLOAT
);
644 /* Pointsize is a single float */
645 if (thisFVF
& D3DFVF_PSIZE
) {
646 strided
->u
.s
.pSize
.lpData
= data
;
647 strided
->u
.s
.pSize
.dwType
= D3DDECLTYPE_FLOAT1
;
648 strided
->u
.s
.pSize
.dwStride
= stride
;
649 data
+= sizeof(FLOAT
);
652 /* Diffuse is 4 unsigned bytes */
653 if (thisFVF
& D3DFVF_DIFFUSE
) {
654 strided
->u
.s
.diffuse
.lpData
= data
;
655 strided
->u
.s
.diffuse
.dwType
= D3DDECLTYPE_SHORT4
;
656 strided
->u
.s
.diffuse
.dwStride
= stride
;
657 data
+= sizeof(DWORD
);
660 /* Specular is 4 unsigned bytes */
661 if (thisFVF
& D3DFVF_SPECULAR
) {
662 strided
->u
.s
.specular
.lpData
= data
;
663 strided
->u
.s
.specular
.dwType
= D3DDECLTYPE_SHORT4
;
664 strided
->u
.s
.specular
.dwStride
= stride
;
665 data
+= sizeof(DWORD
);
669 numTextures
= (thisFVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
670 coordIdxInfo
= (thisFVF
& 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
672 /* numTextures indicates the number of texture coordinates supplied */
673 /* However, the first set may not be for stage 0 texture - it all */
674 /* depends on D3DTSS_TEXCOORDINDEX. */
675 /* The number of bytes for each coordinate set is based off */
676 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
678 /* So, for each supplied texture extract the coords */
679 for (textureNo
= 0; textureNo
< numTextures
; ++textureNo
) {
681 strided
->u
.s
.texCoords
[textureNo
].lpData
= data
;
682 strided
->u
.s
.texCoords
[textureNo
].dwType
= D3DDECLTYPE_FLOAT1
;
683 strided
->u
.s
.texCoords
[textureNo
].dwStride
= stride
;
684 numCoords
[textureNo
] = coordIdxInfo
& 0x03;
687 data
+= sizeof(float);
688 if (numCoords
[textureNo
] != D3DFVF_TEXTUREFORMAT1
) {
689 strided
->u
.s
.texCoords
[textureNo
].dwType
= D3DDECLTYPE_FLOAT2
;
690 data
+= sizeof(float);
691 if (numCoords
[textureNo
] != D3DFVF_TEXTUREFORMAT2
) {
692 strided
->u
.s
.texCoords
[textureNo
].dwType
= D3DDECLTYPE_FLOAT3
;
693 data
+= sizeof(float);
694 if (numCoords
[textureNo
] != D3DFVF_TEXTUREFORMAT3
) {
695 strided
->u
.s
.texCoords
[textureNo
].dwType
= D3DDECLTYPE_FLOAT4
;
696 data
+= sizeof(float);
700 coordIdxInfo
= coordIdxInfo
>> 2; /* Drop bottom two bits */
705 #if 0 /* TODO: Software Shaders */
706 /* Draw a single vertex using this information */
707 static void draw_vertex(IWineD3DDevice
*iface
, /* interface */
708 BOOL isXYZ
, float x
, float y
, float z
, float rhw
, /* xyzn position*/
709 BOOL isNormal
, float nx
, float ny
, float nz
, /* normal */
710 BOOL isDiffuse
, float *dRGBA
, /* 1st colors */
711 BOOL isSpecular
, float *sRGB
, /* 2ndry colors */
712 BOOL isPtSize
, float ptSize
, /* pointSize */
713 WINED3DVECTOR_4
*texcoords
, int *numcoords
) /* texture info */
715 unsigned int textureNo
;
717 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
719 /* Diffuse -------------------------------- */
722 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA
[0], dRGBA
[1], dRGBA
[2], dRGBA
[3]));
725 /* Specular Colour ------------------------------------------*/
727 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
728 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB
));
729 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB
[0], sRGB
[1], sRGB
[2]));
731 VTRACE(("Specular color extensions not supplied\n"));
735 /* Normal -------------------------------- */
737 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx
,ny
,nz
));
738 glNormal3f(nx
, ny
, nz
);
741 /* Point Size ----------------------------------------------*/
744 /* no such functionality in the fixed function GL pipeline */
745 FIXME("Cannot change ptSize here in openGl\n");
748 /* Texture coords --------------------------- */
749 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
751 if (!GL_SUPPORT(ARB_MULTITEXTURE
) && textureNo
> 0) {
752 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
756 /* Query tex coords */
757 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
759 int coordIdx
= This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXCOORDINDEX
];
760 if (coordIdx
>= MAX_TEXTURES
) {
761 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo
));
763 } else if (numcoords
[coordIdx
] == 0) {
764 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo
);
768 /* Initialize vars */
774 switch (numcoords
[coordIdx
]) {
775 case 4: q
= texcoords
[coordIdx
].w
; /* drop through */
776 case 3: r
= texcoords
[coordIdx
].z
; /* drop through */
777 case 2: t
= texcoords
[coordIdx
].y
; /* drop through */
778 case 1: s
= texcoords
[coordIdx
].x
;
781 switch (numcoords
[coordIdx
]) { /* Supply the provided texture coords */
783 VTRACE(("tex:%d, s=%f\n", textureNo
, s
));
784 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
785 GLMULTITEXCOORD1F(textureNo
, s
);
791 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo
, s
, t
));
792 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
793 GLMULTITEXCOORD2F(textureNo
, s
, t
);
799 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo
, s
, t
, r
));
800 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
801 GLMULTITEXCOORD3F(textureNo
, s
, t
, r
);
803 glTexCoord3f(s
, t
, r
);
807 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo
, s
, t
, r
, q
));
808 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
809 GLMULTITEXCOORD4F(textureNo
, s
, t
, r
, q
);
811 glTexCoord4f(s
, t
, r
, q
);
815 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords
[coordIdx
]);
819 } /* End of textures */
821 /* Position -------------------------------- */
823 if (1.0f
== rhw
|| rhw
< 0.00001f
) {
824 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x
,y
,z
));
827 /* Cannot optimize by dividing through by rhw as rhw is required
828 later for perspective in the GL pipeline for vertex shaders */
829 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x
,y
,z
,rhw
));
830 glVertex4f(x
,y
,z
,rhw
);
834 #endif /* TODO: Software shaders */
836 void loadNumberedArrays(
837 IWineD3DDevice
*iface
,
838 WineDirect3DVertexStridedData
*sd
,
839 DWORD arrayUsageMap
[WINED3DSHADERDECLUSAGE_MAX_USAGE
]) {
841 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
843 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
844 if (sd->u.s._arrayName.lpData != NULL && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \
845 unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & D3DSP_REGNUM_MASK; \
846 TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, #_arrayName); \
847 GL_EXTCALL(glVertexAttribPointerARB(idx, \
848 WINED3D_ATR_SIZE(_arrayName), \
849 WINED3D_ATR_GLTYPE(_arrayName), \
850 WINED3D_ATR_NORMALIZED(_arrayName), \
851 sd->u.s._arrayName.dwStride, \
852 sd->u.s._arrayName.lpData)); \
853 GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
857 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
858 if (sd->u.s.position2.lpData != NULL && arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \
859 unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & D3DSP_REGNUM_MASK; \
860 TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, "position2"); \
861 GL_EXTCALL(glVertexAttribPointerARB(idx, \
862 WINED3D_ATR_SIZE(position2), \
863 WINED3D_ATR_GLTYPE(position2), \
864 WINED3D_ATR_NORMALIZED(position2), \
865 sd->u.s.position2.dwStride, \
866 ((char *)sd->u.s.position2.lpData) + \
867 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
868 GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
871 /* Generate some lookup tables */
872 /* drop the RHW coord, there must be a nicer way of doing this. */
873 sd
->u
.s
.position
.dwType
= min(D3DDECLTYPE_FLOAT3
, sd
->u
.s
.position
.dwType
);
874 sd
->u
.s
.position2
.dwType
= min(D3DDECLTYPE_FLOAT3
, sd
->u
.s
.position
.dwType
);
876 LOAD_NUMBERED_ARRAY(blendWeights
,BLENDWEIGHT
);
877 LOAD_NUMBERED_ARRAY(blendMatrixIndices
,BLENDINDICES
);
878 LOAD_NUMBERED_ARRAY(position
,POSITION
);
879 LOAD_NUMBERED_ARRAY(normal
,NORMAL
);
880 LOAD_NUMBERED_ARRAY(pSize
,PSIZE
);
881 LOAD_NUMBERED_ARRAY(diffuse
,DIFFUSE
);
882 LOAD_NUMBERED_ARRAY(specular
,SPECULAR
);
883 LOAD_NUMBERED_ARRAY(texCoords
[0],TEXCOORD0
);
884 LOAD_NUMBERED_ARRAY(texCoords
[1],TEXCOORD1
);
885 LOAD_NUMBERED_ARRAY(texCoords
[2],TEXCOORD2
);
886 LOAD_NUMBERED_ARRAY(texCoords
[3],TEXCOORD3
);
887 LOAD_NUMBERED_ARRAY(texCoords
[4],TEXCOORD4
);
888 LOAD_NUMBERED_ARRAY(texCoords
[5],TEXCOORD5
);
889 LOAD_NUMBERED_ARRAY(texCoords
[6],TEXCOORD6
);
890 LOAD_NUMBERED_ARRAY(texCoords
[7],TEXCOORD7
);
891 #if 0 /* TODO: Samplers may allow for more texture coords */
892 LOAD_NUMBERED_ARRAY(texCoords
[8],TEXCOORD8
);
893 LOAD_NUMBERED_ARRAY(texCoords
[9],TEXCOORD9
);
894 LOAD_NUMBERED_ARRAY(texCoords
[10],TEXCOORD10
);
895 LOAD_NUMBERED_ARRAY(texCoords
[11],TEXCOORD11
);
896 LOAD_NUMBERED_ARRAY(texCoords
[12],TEXCOORD12
);
897 LOAD_NUMBERED_ARRAY(texCoords
[13],TEXCOORD13
);
898 LOAD_NUMBERED_ARRAY(texCoords
[14],TEXCOORD14
);
899 LOAD_NUMBERED_ARRAY(texCoords
[15],TEXCOORD15
);
901 LOAD_NUMBERED_ARRAY(position
,POSITIONT
);
903 LOAD_NUMBERED_ARRAY(tangent
,TANGENT
);
904 LOAD_NUMBERED_ARRAY(binormal
,BINORMAL
);
905 LOAD_NUMBERED_ARRAY(tessFactor
,TESSFACTOR
);
906 LOAD_NUMBERED_ARRAY(position2
,POSITION2
);
907 /* there can be lots of position arrays */
908 LOAD_NUMBERED_POSITION_ARRAY(0);
909 LOAD_NUMBERED_POSITION_ARRAY(1);
910 LOAD_NUMBERED_POSITION_ARRAY(2);
911 LOAD_NUMBERED_POSITION_ARRAY(3);
912 LOAD_NUMBERED_POSITION_ARRAY(4);
913 LOAD_NUMBERED_POSITION_ARRAY(5);
914 LOAD_NUMBERED_POSITION_ARRAY(6);
915 LOAD_NUMBERED_POSITION_ARRAY(7);
916 LOAD_NUMBERED_ARRAY(position2
,POSITIONT2
);
917 LOAD_NUMBERED_ARRAY(normal2
,NORMAL2
);
918 LOAD_NUMBERED_ARRAY(fog
,FOG
);
919 LOAD_NUMBERED_ARRAY(depth
,DEPTH
);
920 LOAD_NUMBERED_ARRAY(sample
,SAMPLE
);
922 #undef LOAD_NUMBERED_ARRAY
925 static void loadVertexData(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*sd
) {
926 unsigned int textureNo
= 0;
927 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
929 TRACE("Using fast vertex array code\n");
930 /* Blend Data ---------------------------------------------- */
931 if ((sd
->u
.s
.blendWeights
.lpData
!= NULL
) ||
932 (sd
->u
.s
.blendMatrixIndices
.lpData
!= NULL
)) {
935 if (GL_SUPPORT(ARB_VERTEX_BLEND
)) {
938 glEnableClientState(GL_WEIGHT_ARRAY_ARB
);
939 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
942 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights
), sd
->u
.s
.blendWeights
.lpData
, sd
->u
.s
.blendWeights
.dwStride
);
943 /* FIXME("TODO\n");*/
944 /* Note dwType == float3 or float4 == 2 or 3 */
947 /* with this on, the normals appear to be being modified,
948 but the vertices aren't being translated as they should be
949 Maybe the world matrix aren't being setup properly? */
950 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights
) + 1);
954 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
955 WINED3D_ATR_SIZE(blendWeights
) ,
956 sd
->u
.s
.blendWeights
.dwStride
,
957 sd
->u
.s
.blendWeights
.lpData
));
959 GL_EXTCALL(glWeightPointerARB
)(WINED3D_ATR_SIZE(blendWeights
), WINED3D_ATR_GLTYPE(blendWeights
),
960 sd
->u
.s
.blendWeights
.dwStride
,
961 sd
->u
.s
.blendWeights
.lpData
);
963 checkGLcall("glWeightPointerARB");
965 if(sd
->u
.s
.blendMatrixIndices
.lpData
!= NULL
){
966 static BOOL showfixme
= TRUE
;
968 FIXME("blendMatrixIndices support\n");
975 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING
)) {
976 /* FIXME("TODO\n");*/
979 GL_EXTCALL(glVertexWeightPointerEXT
)(WINED3D_ATR_SIZE(blendWeights
), WINED3D_ATR_GLTYPE(blendWeights
),
980 sd
->u
.s
.blendWeights
.dwStride
,
981 sd
->u
.s
.blendWeights
.lpData
);
982 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
983 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT
);
984 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
988 /* TODO: support blends in fixupVertices */
989 FIXME("unsupported blending in openGl\n");
992 if (GL_SUPPORT(ARB_VERTEX_BLEND
)) {
993 #if 0 /* TODO: Vertex blending */
994 glDisable(GL_VERTEX_BLEND_ARB
);
996 TRACE("ARB_VERTEX_BLEND\n");
997 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING
)) {
998 TRACE(" EXT_VERTEX_WEIGHTING\n");
999 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT
);
1000 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
1005 #if 0 /* FOG ----------------------------------------------*/
1006 if (sd
->u
.s
.fog
.lpData
!= NULL
) {
1008 if (GL_SUPPORT(EXT_FOG_COORD
) {
1009 glEnableClientState(GL_FOG_COORD_EXT
);
1010 (GL_EXTCALL
)(FogCoordPointerEXT
)(WINED3D_ATR_GLTYPE(fog
),
1011 sd
->u
.s
.fog
.dwStride
,
1012 sd
->u
.s
.fog
.lpData
);
1014 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1015 /* FIXME: fixme once */
1016 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1019 if (GL_SUPPRT(EXT_FOR_COORD
) {
1020 /* make sure fog is disabled */
1021 glDisableClientState(GL_FOG_COORD_EXT
);
1026 #if 0 /* tangents ----------------------------------------------*/
1027 if (sd
->u
.s
.tangent
.lpData
!= NULL
|| sd
->u
.s
.binormal
.lpData
!= NULL
) {
1029 if (GL_SUPPORT(EXT_COORDINATE_FRAME
) {
1030 if (sd
->u
.s
.tangent
.lpData
!= NULL
) {
1031 glEnable(GL_TANGENT_ARRAY_EXT
);
1032 (GL_EXTCALL
)(TangentPointerEXT
)(WINED3D_ATR_GLTYPE(tangent
),
1033 sd
->u
.s
.tangent
.dwStride
,
1034 sd
->u
.s
.tangent
.lpData
);
1036 glDisable(GL_TANGENT_ARRAY_EXT
);
1038 if (sd
->u
.s
.binormal
.lpData
!= NULL
) {
1039 glEnable(GL_BINORMAL_ARRAY_EXT
);
1040 (GL_EXTCALL
)(BinormalPointerEXT
)(WINED3D_ATR_GLTYPE(binormal
),
1041 sd
->u
.s
.binormal
.dwStride
,
1042 sd
->u
.s
.binormal
.lpData
);
1044 glDisable(GL_BINORMAL_ARRAY_EXT
);
1048 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1049 /* FIXME: fixme once */
1050 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1053 if (GL_SUPPORT(EXT_COORDINATE_FRAME
) {
1054 /* make sure fog is disabled */
1055 glDisable(GL_TANGENT_ARRAY_EXT
);
1056 glDisable(GL_BINORMAL_ARRAY_EXT
);
1061 /* Point Size ----------------------------------------------*/
1062 if (sd
->u
.s
.pSize
.lpData
!= NULL
) {
1064 /* no such functionality in the fixed function GL pipeline */
1065 TRACE("Cannot change ptSize here in openGl\n");
1066 /* TODO: Implement this function in using shaders if they are available */
1070 /* Vertex Pointers -----------------------------------------*/
1071 if (sd
->u
.s
.position
.lpData
!= NULL
) {
1072 /* Note dwType == float3 or float4 == 2 or 3 */
1073 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1074 sd
->u
.s
.position
.dwStride
,
1075 sd
->u
.s
.position
.dwType
+ 1,
1076 sd
->u
.s
.position
.lpData
));
1078 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1079 handling for rhw mode should not impact screen position whereas in GL it does.
1080 This may result in very slightly distored textures in rhw mode, but
1081 a very minimal different. There's always the other option of
1082 fixing the view matrix to prevent w from having any effect */
1083 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position
),
1084 sd
->u
.s
.position
.dwStride
, sd
->u
.s
.position
.lpData
);
1085 checkGLcall("glVertexPointer(...)");
1086 glEnableClientState(GL_VERTEX_ARRAY
);
1087 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1090 glDisableClientState(GL_VERTEX_ARRAY
);
1091 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1094 /* Normals -------------------------------------------------*/
1095 if (sd
->u
.s
.normal
.lpData
!= NULL
) {
1096 /* Note dwType == float3 or float4 == 2 or 3 */
1097 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1098 sd
->u
.s
.normal
.dwStride
,
1099 sd
->u
.s
.normal
.lpData
));
1100 glNormalPointer(WINED3D_ATR_GLTYPE(normal
),
1101 sd
->u
.s
.normal
.dwStride
,
1102 sd
->u
.s
.normal
.lpData
);
1103 checkGLcall("glNormalPointer(...)");
1104 glEnableClientState(GL_NORMAL_ARRAY
);
1105 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1108 glDisableClientState(GL_NORMAL_ARRAY
);
1109 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1110 glNormal3f(0, 0, 1);
1111 checkGLcall("glNormal3f(0, 0, 1)");
1114 /* Diffuse Colour --------------------------------------------*/
1115 /* WARNING: Data here MUST be in RGBA format, so cannot */
1116 /* go directly into fast mode from app pgm, because */
1117 /* directx requires data in BGRA format. */
1118 /* currently fixupVertices swizels the format, but this isn't */
1119 /* very practical when using VBOS */
1120 /* NOTE: Unless we write a vertex shader to swizel the colour */
1121 /* , or the user doesn't care and wants the speed advantage */
1123 if (sd
->u
.s
.diffuse
.lpData
!= NULL
) {
1124 /* Note dwType == float3 or float4 == 2 or 3 */
1125 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1126 sd
->u
.s
.diffuse
.dwStride
,
1127 sd
->u
.s
.diffuse
.lpData
));
1129 glColorPointer(4, GL_UNSIGNED_BYTE
,
1130 sd
->u
.s
.diffuse
.dwStride
,
1131 sd
->u
.s
.diffuse
.lpData
);
1132 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1133 glEnableClientState(GL_COLOR_ARRAY
);
1134 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1137 glDisableClientState(GL_COLOR_ARRAY
);
1138 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1139 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
1140 checkGLcall("glColor4f(1, 1, 1, 1)");
1143 /* Specular Colour ------------------------------------------*/
1144 if (sd
->u
.s
.specular
.lpData
!= NULL
) {
1145 TRACE("setting specular colour\n");
1146 /* Note dwType == float3 or float4 == 2 or 3 */
1147 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1148 sd
->u
.s
.specular
.dwStride
,
1149 sd
->u
.s
.specular
.lpData
));
1150 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
1151 GL_EXTCALL(glSecondaryColorPointerEXT
)(4, GL_UNSIGNED_BYTE
,
1152 sd
->u
.s
.specular
.dwStride
,
1153 sd
->u
.s
.specular
.lpData
);
1154 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1155 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT
);
1156 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1159 /* Missing specular color is not critical, no warnings */
1160 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1164 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
1166 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT
);
1167 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1168 GL_EXTCALL(glSecondaryColor3fEXT
)(0, 0, 0);
1169 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1172 /* Missing specular color is not critical, no warnings */
1173 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1177 /* Texture coords -------------------------------------------*/
1179 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
1180 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1181 /* Abort if we don't support the extension. */
1182 if (!GL_SUPPORT(ARB_MULTITEXTURE
)) {
1183 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1187 /* Select the correct texture stage */
1188 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB
+ textureNo
));
1189 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
1190 int coordIdx
= This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXCOORDINDEX
];
1191 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo
, coordIdx
, sd
->u
.s
.texCoords
[coordIdx
].lpData
);
1193 if (coordIdx
>= MAX_TEXTURES
) {
1194 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo
));
1195 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
1196 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB
+ textureNo
, 0, 0, 0, 1));
1198 } else if (sd
->u
.s
.texCoords
[coordIdx
].lpData
== NULL
) {
1199 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1200 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
1201 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB
+ textureNo
, 0, 0, 0, 1));
1205 /* The coords to supply depend completely on the fvf / vertex shader */
1206 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords
[coordIdx
]), WINED3D_ATR_GLTYPE(texCoords
[coordIdx
]), sd
->u
.s
.texCoords
[coordIdx
].dwStride
, sd
->u
.s
.texCoords
[coordIdx
].lpData
);
1207 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
1211 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
1212 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB
+ textureNo
, 0, 0, 0, 1));
1217 static void drawStridedFast(IWineD3DDevice
*iface
,UINT numberOfVertices
, GLenum glPrimitiveType
,
1218 const void *idxData
, short idxSize
, ULONG minIndex
, ULONG startIdx
) {
1219 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1221 if (idxData
!= NULL
/* This crashes sometimes!*/) {
1222 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This
, glPrimitiveType
, numberOfVertices
, minIndex
);
1223 idxData
= idxData
== (void *)-1 ? NULL
: idxData
;
1226 glIndexPointer(idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
, idxSize
, startIdx
);
1227 glEnableClientState(GL_INDEX_ARRAY
);
1229 glDrawElements(glPrimitiveType
, numberOfVertices
, idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
,
1230 (const char *)idxData
+(idxSize
* startIdx
));
1231 #else /* using drawRangeElements may be faster */
1233 glDrawRangeElements(glPrimitiveType
, minIndex
, minIndex
+ numberOfVertices
- 1, numberOfVertices
,
1234 idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
,
1235 (const char *)idxData
+(idxSize
* startIdx
));
1237 checkGLcall("glDrawRangeElements");
1241 /* Note first is now zero as we shuffled along earlier */
1242 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This
, glPrimitiveType
, numberOfVertices
);
1243 glDrawArrays(glPrimitiveType
, 0, numberOfVertices
);
1244 checkGLcall("glDrawArrays");
1252 * Actually draw using the supplied information.
1253 * Slower GL version which extracts info about each vertex in turn
1256 static void drawStridedSlow(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*sd
,
1257 UINT NumVertexes
, GLenum glPrimType
,
1258 const void *idxData
, short idxSize
, ULONG minIndex
, ULONG startIdx
) {
1260 unsigned int textureNo
= 0;
1261 const short *pIdxBufS
= NULL
;
1262 const long *pIdxBufL
= NULL
;
1263 LONG SkipnStrides
= 0;
1265 float x
= 0.0f
, y
= 0.0f
, z
= 0.0f
; /* x,y,z coordinates */
1266 float nx
= 0.0f
, ny
= 0.0, nz
= 0.0f
; /* normal x,y,z coordinates */
1267 float rhw
= 0.0f
; /* rhw */
1268 float ptSize
= 0.0f
; /* Point size */
1269 DWORD diffuseColor
= 0xFFFFFFFF; /* Diffuse Color */
1270 DWORD specularColor
= 0; /* Specular Color */
1271 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1273 TRACE("Using slow vertex array code\n");
1275 /* Variable Initialization */
1276 if (idxData
!= NULL
) {
1277 if (idxSize
== 2) pIdxBufS
= (const short *) idxData
;
1278 else pIdxBufL
= (const long *) idxData
;
1281 /* Start drawing in GL */
1282 VTRACE(("glBegin(%x)\n", glPrimType
));
1283 glBegin(glPrimType
);
1285 /* For each primitive */
1286 for (vx_index
= 0; vx_index
< NumVertexes
; ++vx_index
) {
1288 /* Initialize diffuse color */
1289 diffuseColor
= 0xFFFFFFFF;
1291 /* For indexed data, we need to go a few more strides in */
1292 if (idxData
!= NULL
) {
1294 /* Indexed so work out the number of strides to skip */
1296 VTRACE(("Idx for vertex %ld = %d\n", vx_index
, pIdxBufS
[startIdx
+vx_index
]));
1297 SkipnStrides
= pIdxBufS
[startIdx
+ vx_index
];
1299 VTRACE(("Idx for vertex %ld = %ld\n", vx_index
, pIdxBufL
[startIdx
+vx_index
]));
1300 SkipnStrides
= pIdxBufL
[startIdx
+ vx_index
];
1304 /* Position Information ------------------ */
1305 if (sd
->u
.s
.position
.lpData
!= NULL
) {
1307 float *ptrToCoords
= (float *)(sd
->u
.s
.position
.lpData
+ (SkipnStrides
* sd
->u
.s
.position
.dwStride
));
1312 VTRACE(("x,y,z=%f,%f,%f\n", x
,y
,z
));
1314 /* RHW follows, only if transformed, ie 4 floats were provided */
1315 if (sd
->u
.s
.position
.dwType
== D3DDECLTYPE_FLOAT4
) {
1316 rhw
= ptrToCoords
[3];
1317 VTRACE(("rhw=%f\n", rhw
));
1321 /* Blending data -------------------------- */
1322 if (sd
->u
.s
.blendWeights
.lpData
!= NULL
) {
1323 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1324 FIXME("Blending not supported yet\n");
1326 if (sd
->u
.s
.blendMatrixIndices
.lpData
!= NULL
) {
1327 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1331 /* Vertex Normal Data (untransformed only)- */
1332 if (sd
->u
.s
.normal
.lpData
!= NULL
) {
1334 float *ptrToCoords
= (float *)(sd
->u
.s
.normal
.lpData
+ (SkipnStrides
* sd
->u
.s
.normal
.dwStride
));
1335 nx
= ptrToCoords
[0];
1336 ny
= ptrToCoords
[1];
1337 nz
= ptrToCoords
[2];
1338 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx
, ny
, nz
));
1341 /* Point Size ----------------------------- */
1342 if (sd
->u
.s
.pSize
.lpData
!= NULL
) {
1344 float *ptrToCoords
= (float *)(sd
->u
.s
.pSize
.lpData
+ (SkipnStrides
* sd
->u
.s
.pSize
.dwStride
));
1345 ptSize
= ptrToCoords
[0];
1346 VTRACE(("ptSize=%f\n", ptSize
));
1347 FIXME("No support for ptSize yet\n");
1350 /* Diffuse -------------------------------- */
1351 if (sd
->u
.s
.diffuse
.lpData
!= NULL
) {
1353 DWORD
*ptrToCoords
= (DWORD
*)(sd
->u
.s
.diffuse
.lpData
+ (SkipnStrides
* sd
->u
.s
.diffuse
.dwStride
));
1354 diffuseColor
= ptrToCoords
[0];
1355 VTRACE(("diffuseColor=%lx\n", diffuseColor
));
1358 /* Specular -------------------------------- */
1359 if (sd
->u
.s
.specular
.lpData
!= NULL
) {
1361 DWORD
*ptrToCoords
= (DWORD
*)(sd
->u
.s
.specular
.lpData
+ (SkipnStrides
* sd
->u
.s
.specular
.dwStride
));
1362 specularColor
= ptrToCoords
[0];
1363 VTRACE(("specularColor=%lx\n", specularColor
));
1366 /* Texture coords --------------------------- */
1367 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
1369 if (!GL_SUPPORT(ARB_MULTITEXTURE
) && textureNo
> 0) {
1370 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1374 /* Query tex coords */
1375 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
1377 int coordIdx
= This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXCOORDINDEX
];
1378 float *ptrToCoords
= NULL
;
1379 float s
= 0.0, t
= 0.0, r
= 0.0, q
= 0.0;
1382 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo
));
1384 } else if (coordIdx
< 0) {
1385 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo
, coordIdx
);
1389 ptrToCoords
= (float *)(sd
->u
.s
.texCoords
[coordIdx
].lpData
+ (SkipnStrides
* sd
->u
.s
.texCoords
[coordIdx
].dwStride
));
1390 if (sd
->u
.s
.texCoords
[coordIdx
].lpData
== NULL
) {
1391 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo
);
1395 int coordsToUse
= sd
->u
.s
.texCoords
[coordIdx
].dwType
+ 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1397 /* The coords to supply depend completely on the fvf / vertex shader */
1398 switch (coordsToUse
) {
1399 case 4: q
= ptrToCoords
[3]; /* drop through */
1400 case 3: r
= ptrToCoords
[2]; /* drop through */
1401 case 2: t
= ptrToCoords
[1]; /* drop through */
1402 case 1: s
= ptrToCoords
[0];
1405 /* Projected is more 'fun' - Move the last coord to the 'q'
1406 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1407 if ((This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] != D3DTTFF_DISABLE
) &&
1408 (This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] & D3DTTFF_PROJECTED
)) {
1410 if (This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] & D3DTTFF_PROJECTED
) {
1411 switch (coordsToUse
) {
1412 case 0: /* Drop Through */
1414 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1426 case 4: /* Nop here */
1429 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1430 This
->stateBlock
->textureState
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] & D3DTTFF_PROJECTED
);
1435 switch (coordsToUse
) { /* Supply the provided texture coords */
1436 case D3DTTFF_COUNT1
:
1437 VTRACE(("tex:%d, s=%f\n", textureNo
, s
));
1438 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1439 GL_EXTCALL(glMultiTexCoord1fARB(textureNo
, s
));
1444 case D3DTTFF_COUNT2
:
1445 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo
, s
, t
));
1446 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1447 GL_EXTCALL(glMultiTexCoord2fARB(textureNo
, s
, t
));
1452 case D3DTTFF_COUNT3
:
1453 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo
, s
, t
, r
));
1454 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1455 GL_EXTCALL(glMultiTexCoord3fARB(textureNo
, s
, t
, r
));
1457 glTexCoord3f(s
, t
, r
);
1460 case D3DTTFF_COUNT4
:
1461 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo
, s
, t
, r
, q
));
1462 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1463 GL_EXTCALL(glMultiTexCoord4fARB(textureNo
, s
, t
, r
, q
));
1465 glTexCoord4f(s
, t
, r
, q
);
1469 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse
);
1473 } /* End of textures */
1475 /* Diffuse -------------------------------- */
1476 if (sd
->u
.s
.diffuse
.lpData
!= NULL
) {
1477 glColor4ub(D3DCOLOR_B_R(diffuseColor
),
1478 D3DCOLOR_B_G(diffuseColor
),
1479 D3DCOLOR_B_B(diffuseColor
),
1480 D3DCOLOR_B_A(diffuseColor
));
1481 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1482 D3DCOLOR_B_R(diffuseColor
),
1483 D3DCOLOR_B_G(diffuseColor
),
1484 D3DCOLOR_B_B(diffuseColor
),
1485 D3DCOLOR_B_A(diffuseColor
)));
1487 if (vx_index
== 0) glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
1490 /* Specular ------------------------------- */
1491 if (sd
->u
.s
.specular
.lpData
!= NULL
) {
1492 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1493 D3DCOLOR_B_R(specularColor
),
1494 D3DCOLOR_B_G(specularColor
),
1495 D3DCOLOR_B_B(specularColor
)));
1496 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
1497 GL_EXTCALL(glSecondaryColor3ubEXT
)(
1498 D3DCOLOR_B_R(specularColor
),
1499 D3DCOLOR_B_G(specularColor
),
1500 D3DCOLOR_B_B(specularColor
));
1502 /* Do not worry if specular colour missing and disable request */
1503 VTRACE(("Specular color extensions not supplied\n"));
1506 if (vx_index
== 0) {
1507 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
1508 GL_EXTCALL(glSecondaryColor3fEXT
)(0, 0, 0);
1510 /* Do not worry if specular colour missing and disable request */
1511 VTRACE(("Specular color extensions not supplied\n"));
1516 /* Normal -------------------------------- */
1517 if (sd
->u
.s
.normal
.lpData
!= NULL
) {
1518 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx
,ny
,nz
));
1519 glNormal3f(nx
, ny
, nz
);
1521 if (vx_index
== 0) glNormal3f(0, 0, 1);
1524 /* Position -------------------------------- */
1525 if (sd
->u
.s
.position
.lpData
!= NULL
) {
1526 if (1.0f
== rhw
|| ((rhw
< eps
) && (rhw
> -eps
))) {
1527 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x
,y
,z
));
1528 glVertex3f(x
, y
, z
);
1530 GLfloat w
= 1.0 / rhw
;
1531 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x
,y
,z
,rhw
));
1532 glVertex4f(x
*w
, y
*w
, z
*w
, w
);
1536 /* For non indexed mode, step onto next parts */
1537 if (idxData
== NULL
) {
1543 checkGLcall("glEnd and previous calls");
1546 #if 0 /* TODO: Software/Hardware vertex blending support */
1548 * Draw with emulated vertex shaders
1549 * Note: strided data is uninitialized, as we need to pass the vertex
1550 * shader directly as ordering irs yet
1552 void drawStridedSoftwareVS(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*sd
,
1553 int PrimitiveType
, ULONG NumPrimitives
,
1554 const void *idxData
, short idxSize
, ULONG minIndex
, ULONG startIdx
) {
1556 unsigned int textureNo
= 0;
1557 GLenum glPrimType
= GL_POINTS
;
1558 int NumVertexes
= NumPrimitives
;
1559 const short *pIdxBufS
= NULL
;
1560 const long *pIdxBufL
= NULL
;
1561 LONG SkipnStrides
= 0;
1563 float x
= 0.0f
, y
= 0.0f
, z
= 0.0f
; /* x,y,z coordinates */
1564 float rhw
= 0.0f
; /* rhw */
1565 float ptSize
= 0.0f
; /* Point size */
1566 D3DVECTOR_4 texcoords
[8]; /* Texture Coords */
1567 int numcoords
[8]; /* Number of coords */
1568 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1570 IDirect3DVertexShaderImpl
* vertexShader
= NULL
;
1572 TRACE("Using slow software vertex shader code\n");
1574 /* Variable Initialization */
1575 if (idxData
!= NULL
) {
1576 if (idxSize
== 2) pIdxBufS
= (const short *) idxData
;
1577 else pIdxBufL
= (const long *) idxData
;
1580 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1581 NumVertexes
= primitiveToGl(PrimitiveType
, NumPrimitives
, &glPrimType
);
1583 /* Retrieve the VS information */
1584 vertexShader
= (IWineD3DVertexShaderImp
*)This
->stateBlock
->VertexShader
;
1586 /* Start drawing in GL */
1587 VTRACE(("glBegin(%x)\n", glPrimType
));
1588 glBegin(glPrimType
);
1590 /* For each primitive */
1591 for (vx_index
= 0; vx_index
< NumVertexes
; ++vx_index
) {
1593 /* For indexed data, we need to go a few more strides in */
1594 if (idxData
!= NULL
) {
1596 /* Indexed so work out the number of strides to skip */
1598 VTRACE(("Idx for vertex %ld = %d\n", vx_index
, pIdxBufS
[startIdx
+vx_index
]));
1599 SkipnStrides
= pIdxBufS
[startIdx
+vx_index
];
1601 VTRACE(("Idx for vertex %ld = %ld\n", vx_index
, pIdxBufL
[startIdx
+vx_index
]));
1602 SkipnStrides
= pIdxBufL
[startIdx
+vx_index
];
1606 /* Fill the vertex shader input */
1607 IDirect3DDeviceImpl_FillVertexShaderInputSW(This
, vertexShader
, SkipnStrides
);
1609 /* Initialize the output fields to the same defaults as it would normally have */
1610 memset(&vertexShader
->output
, 0, sizeof(VSHADEROUTPUTDATA8
));
1611 vertexShader
->output
.oD
[0].x
= 1.0;
1612 vertexShader
->output
.oD
[0].y
= 1.0;
1613 vertexShader
->output
.oD
[0].z
= 1.0;
1614 vertexShader
->output
.oD
[0].w
= 1.0;
1616 /* Now execute the vertex shader */
1617 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader
, &vertexShader
->input
, &vertexShader
->output
);
1620 TRACE_VECTOR(vertexShader->output.oPos);
1621 TRACE_VECTOR(vertexShader->output.oD[0]);
1622 TRACE_VECTOR(vertexShader->output.oD[1]);
1623 TRACE_VECTOR(vertexShader->output.oT[0]);
1624 TRACE_VECTOR(vertexShader->output.oT[1]);
1625 TRACE_VECTOR(vertexShader->input.V[0]);
1626 TRACE_VECTOR(vertexShader->data->C[0]);
1627 TRACE_VECTOR(vertexShader->data->C[1]);
1628 TRACE_VECTOR(vertexShader->data->C[2]);
1629 TRACE_VECTOR(vertexShader->data->C[3]);
1630 TRACE_VECTOR(vertexShader->data->C[4]);
1631 TRACE_VECTOR(vertexShader->data->C[5]);
1632 TRACE_VECTOR(vertexShader->data->C[6]);
1633 TRACE_VECTOR(vertexShader->data->C[7]);
1636 /* Extract out the output */
1637 /* FIXME: Fog coords? */
1638 x
= vertexShader
->output
.oPos
.x
;
1639 y
= vertexShader
->output
.oPos
.y
;
1640 z
= vertexShader
->output
.oPos
.z
;
1641 rhw
= vertexShader
->output
.oPos
.w
;
1642 ptSize
= vertexShader
->output
.oPts
.x
; /* Fixme - Is this right? */
1644 /** Update textures coords using vertexShader->output.oT[0->7] */
1645 memset(texcoords
, 0x00, sizeof(texcoords
));
1646 memset(numcoords
, 0x00, sizeof(numcoords
));
1647 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
1648 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
1649 texcoords
[textureNo
].x
= vertexShader
->output
.oT
[textureNo
].x
;
1650 texcoords
[textureNo
].y
= vertexShader
->output
.oT
[textureNo
].y
;
1651 texcoords
[textureNo
].z
= vertexShader
->output
.oT
[textureNo
].z
;
1652 texcoords
[textureNo
].w
= vertexShader
->output
.oT
[textureNo
].w
;
1653 if (This
->stateBlock
->texture_state
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] != D3DTTFF_DISABLE
) {
1654 numcoords
[textureNo
] = This
->stateBlock
->texture_state
[textureNo
][D3DTSS_TEXTURETRANSFORMFLAGS
] & ~D3DTTFF_PROJECTED
;
1656 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8
) This
->stateBlock
->textures
[textureNo
])) {
1657 case WINED3DRTYPE_TEXTURE
: numcoords
[textureNo
] = 2; break;
1658 case WINED3DRTYPE_VOLUMETEXTURE
: numcoords
[textureNo
] = 3; break;
1659 default: numcoords
[textureNo
] = 4;
1663 numcoords
[textureNo
] = 0;
1667 /* Draw using this information */
1670 TRUE
, 0.0f
, 0.0f
, 1.0f
,
1671 TRUE
, (float*) &vertexShader
->output
.oD
[0],
1672 TRUE
, (float*) &vertexShader
->output
.oD
[1],
1673 FALSE
, ptSize
, /* FIXME: Change back when supported */
1674 texcoords
, numcoords
);
1676 /* For non indexed mode, step onto next parts */
1677 if (idxData
== NULL
) {
1681 } /* for each vertex */
1684 checkGLcall("glEnd and previous calls");
1690 * Loads (pixel shader) samplers
1692 void drawPrimLoadPSamplersGLSL(
1693 IWineD3DDevice
* iface
) {
1695 IWineD3DDeviceImpl
* This
= (IWineD3DDeviceImpl
*)iface
;
1696 GLhandleARB programId
= This
->stateBlock
->shaderPrgId
;
1697 GLhandleARB name_loc
;
1699 char sampler_name
[20];
1701 if (programId
== 0) {
1702 /* No GLSL program set - nothing to do. */
1706 for (i
=0; i
< GL_LIMITS(textures
); ++i
) {
1707 if (This
->stateBlock
->textures
[i
] != NULL
) {
1708 snprintf(sampler_name
, sizeof(sampler_name
), "psampler%d", i
);
1709 name_loc
= GL_EXTCALL(glGetUniformLocationARB(programId
, sampler_name
));
1710 if (name_loc
!= -1) {
1711 TRACE_(d3d_shader
)("Loading %s for texture %d\n", sampler_name
, i
);
1712 GL_EXTCALL(glUniform1iARB(name_loc
, i
));
1713 checkGLcall("glUniform1iARB");
1720 * Loads floating point constants (aka uniforms) into the currently set GLSL program.
1721 * When @constants_set == NULL, it will load all the constants.
1723 void drawPrimLoadConstantsGLSL_F(IWineD3DDevice
* iface
,
1724 unsigned max_constants
,
1726 BOOL
* constants_set
,
1729 IWineD3DDeviceImpl
* This
= (IWineD3DDeviceImpl
*)iface
;
1730 GLhandleARB programId
= This
->stateBlock
->shaderPrgId
;
1731 GLhandleARB tmp_loc
;
1735 if (programId
== 0) {
1736 /* No GLSL program set - nothing to do. */
1740 for (i
=0; i
<max_constants
; ++i
) {
1741 if (NULL
== constants_set
|| constants_set
[i
]) {
1743 const char* prefix
= is_pshader
? "PC":"VC";
1745 TRACE_(d3d_shader
)("Loading constants %i: %f, %f, %f, %f\n",
1746 i
, constants
[i
*4], constants
[i
*4+1], constants
[i
*4+2], constants
[i
*4+3]);
1748 /* TODO: Benchmark and see if it would be beneficial to store the
1749 * locations of the constants to avoid looking up each time */
1750 snprintf(tmp_name
, sizeof(tmp_name
), "%s[%i]", prefix
, i
);
1751 tmp_loc
= GL_EXTCALL(glGetUniformLocationARB(programId
, tmp_name
));
1752 if (tmp_loc
!= -1) {
1753 /* We found this uniform name in the program - go ahead and send the data */
1754 GL_EXTCALL(glUniform4fvARB(tmp_loc
, 1, &constants
[i
*4]));
1755 checkGLcall("glUniform4fvARB");
1762 * Loads floating point constants into the currently set ARB_vertex/fragment_program.
1763 * When @constants_set == NULL, it will load all the constants.
1765 * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
1766 * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
1768 void drawPrimLoadConstantsARB_F(IWineD3DDevice
* iface
,
1770 unsigned max_constants
,
1772 BOOL
* constants_set
) {
1774 IWineD3DDeviceImpl
* This
= (IWineD3DDeviceImpl
*)iface
;
1777 for (i
=0; i
<max_constants
; ++i
) {
1778 if (NULL
== constants_set
|| constants_set
[i
]) {
1779 TRACE_(d3d_shader
)("Loading constants %i: %f, %f, %f, %f\n",
1780 i
, constants
[i
*4], constants
[i
*4+1], constants
[i
*4+2], constants
[i
*4+3]);
1782 GL_EXTCALL(glProgramEnvParameter4fvARB(target_type
, i
, &constants
[i
*4]));
1783 checkGLcall("glProgramEnvParameter4fvARB");
1788 /* Load the constants/uniforms which were passed by the application into either GLSL or ARB shader programs. */
1789 void drawPrimLoadConstants(IWineD3DDevice
*iface
,
1790 BOOL useVertexShader
,
1791 BOOL usePixelShader
) {
1793 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1794 IWineD3DVertexShaderImpl
*vshader
= (IWineD3DVertexShaderImpl
*) This
->stateBlock
->vertexShader
;
1796 if (wined3d_settings
.shader_mode
== SHADER_GLSL
) {
1798 if (useVertexShader
) {
1799 IWineD3DVertexDeclarationImpl
* vertexDeclaration
=
1800 (IWineD3DVertexDeclarationImpl
*) vshader
->vertexDeclaration
;
1802 if (NULL
!= vertexDeclaration
&& NULL
!= vertexDeclaration
->constants
) {
1803 /* Load DirectX 8 float constants/uniforms for vertex shader */
1804 drawPrimLoadConstantsGLSL_F(iface
, WINED3D_VSHADER_MAX_CONSTANTS
,
1805 vertexDeclaration
->constants
, NULL
, 0);
1808 /* Load DirectX 9 float constants/uniforms for vertex shader */
1809 drawPrimLoadConstantsGLSL_F(iface
, WINED3D_VSHADER_MAX_CONSTANTS
,
1810 This
->stateBlock
->vertexShaderConstantF
,
1811 This
->stateBlock
->set
.vertexShaderConstantsF
, 0);
1813 /* TODO: Load boolean & integer constants for vertex shader */
1815 if (usePixelShader
) {
1817 /* Load pixel shader samplers */
1818 drawPrimLoadPSamplersGLSL(iface
);
1820 /* Load DirectX 9 float constants/uniforms for pixel shader */
1821 drawPrimLoadConstantsGLSL_F(iface
, WINED3D_PSHADER_MAX_CONSTANTS
,
1822 This
->stateBlock
->pixelShaderConstantF
,
1823 This
->stateBlock
->set
.pixelShaderConstantsF
, 1);
1825 /* TODO: Load boolean & integer constants for pixel shader */
1827 } else if (wined3d_settings
.shader_mode
== SHADER_ARB
) {
1829 /* We only support float constants in ARB at the moment, so don't
1830 * worry about the Integers or Booleans */
1832 if (useVertexShader
) {
1833 IWineD3DVertexDeclarationImpl
* vertexDeclaration
=
1834 (IWineD3DVertexDeclarationImpl
*) vshader
->vertexDeclaration
;
1836 if (NULL
!= vertexDeclaration
&& NULL
!= vertexDeclaration
->constants
) {
1837 /* Load DirectX 8 float constants for vertex shader */
1838 drawPrimLoadConstantsARB_F(iface
, GL_VERTEX_PROGRAM_ARB
, WINED3D_VSHADER_MAX_CONSTANTS
,
1839 vertexDeclaration
->constants
, NULL
);
1842 /* Load DirectX 9 float constants for vertex shader */
1843 drawPrimLoadConstantsARB_F(iface
, GL_VERTEX_PROGRAM_ARB
, WINED3D_VSHADER_MAX_CONSTANTS
,
1844 This
->stateBlock
->vertexShaderConstantF
,
1845 This
->stateBlock
->set
.vertexShaderConstantsF
);
1847 if (usePixelShader
) {
1849 /* Load DirectX 9 float constants for pixel shader */
1850 drawPrimLoadConstantsARB_F(iface
, GL_FRAGMENT_PROGRAM_ARB
, WINED3D_PSHADER_MAX_CONSTANTS
,
1851 This
->stateBlock
->pixelShaderConstantF
,
1852 This
->stateBlock
->set
.pixelShaderConstantsF
);
1857 void inline drawPrimitiveDrawStrided(IWineD3DDevice
*iface
, BOOL useVertexShaderFunction
, BOOL usePixelShaderFunction
, int useHW
, WineDirect3DVertexStridedData
*dataLocations
,
1858 UINT numberOfvertices
, UINT numberOfIndicies
, GLenum glPrimType
, const void *idxData
, short idxSize
, int minIndex
, long StartIdx
) {
1859 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1861 /* Now draw the graphics to the screen */
1862 if (FALSE
/* disable software vs for now */ && useVertexShaderFunction
&& !useHW
) {
1863 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__
);
1864 /* Ideally, we should have software FV and hardware VS, possibly
1865 depending on the device type? */
1866 #if 0 /* TODO: vertex and pixel shaders */
1867 drawStridedSoftwareVS(iface
, dataLocations
, PrimitiveType
, NumPrimitives
,
1868 idxData
, idxSize
, minIndex
, StartIdx
);
1873 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1874 int startStride
= idxData
== NULL
? 0 : idxData
== (void *) -1 ? 0 :(idxSize
== 2 ? *(((const short *) idxData
) + StartIdx
) : *((const int *) idxData
) + StartIdx
);
1875 int endStride
= startStride
;
1876 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride
, endStride
, numberOfIndicies
, numberOfvertices
);
1878 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1879 if (idxData
!= NULL
) { /* index data isn't linear, so lookup the real start and end strides */
1882 unsigned short *index
= (unsigned short *)idxData
;
1884 for (t
= 0 ; t
< numberOfIndicies
; t
++) {
1885 if (startStride
> *index
)
1886 startStride
= *index
;
1887 if (endStride
< *index
)
1891 } else { /* idxSize == 4 */
1892 unsigned int *index
= (unsigned int *)idxData
;
1894 for (t
= 0 ; t
< numberOfIndicies
; t
++) {
1895 if (startStride
> *index
)
1896 startStride
= *index
;
1897 if (endStride
< *index
)
1903 endStride
+= numberOfvertices
-1;
1906 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride
, endStride
, numberOfIndicies
, numberOfvertices
);
1907 /* pre-transform verticex */
1908 /* TODO: Caching, VBO's etc.. */
1910 /* Generate some fixme's if unsupported functionality is being used */
1911 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1912 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1913 if (!useVertexShaderFunction
&& (BUFFER_OR_DATA(blendMatrixIndices
) || BUFFER_OR_DATA(blendWeights
))) {
1914 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations
->u
.s
.blendWeights
.lpData
,dataLocations
->u
.s
.blendWeights
.lpData
);
1916 if (!useVertexShaderFunction
&& (BUFFER_OR_DATA(position2
) || BUFFER_OR_DATA(normal2
))) {
1917 FIXME("Tweening is only valid with vertex shaders\n");
1919 if (!useVertexShaderFunction
&& (BUFFER_OR_DATA(tangent
) || BUFFER_OR_DATA(binormal
))) {
1920 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1922 if (!useVertexShaderFunction
&& (BUFFER_OR_DATA(tessFactor
) || BUFFER_OR_DATA(fog
) || BUFFER_OR_DATA(depth
) || BUFFER_OR_DATA(sample
))) {
1923 FIXME("Extended attributes are only valid with vertex shaders\n");
1925 #undef BUFFER_OR_DATA
1927 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1928 fixupVertices(This
, dataLocations
, &transformedDataLocations
, 1 + endStride
- startStride
, startStride
);
1931 /* If the only vertex data used by the shader is supported by OpenGL then*/
1932 if (!useVertexShaderFunction
&&
1933 dataLocations
->u
.s
.pSize
.lpData
== NULL
&&
1934 dataLocations
->u
.s
.diffuse
.lpData
== NULL
&&
1935 dataLocations
->u
.s
.specular
.lpData
== NULL
) {
1937 /* Load the vertex data using named arrays */
1938 TRACE("(%p) Loading vertex data\n", This
);
1939 loadVertexData(iface
, dataLocations
);
1941 } else if(useVertexShaderFunction
) {
1943 /* load the array data using ordinal mapping */
1944 loadNumberedArrays(iface
, dataLocations
,
1945 ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->arrayUsageMap
);
1947 } else { /* If this happens we must drawStridedSlow later on */
1948 TRACE("Not loading vertex data\n");
1951 TRACE("Loaded arrays\n");
1953 /* Bind the correct GLSL shader program based on the currently set vertex & pixel shaders. */
1954 if (wined3d_settings
.shader_mode
== SHADER_GLSL
) {
1955 set_glsl_shader_program(iface
);
1956 /* Start using this program ID (if it's 0, there is no shader program to use, so
1957 * glUseProgramObjectARB(0) will disable the use of any shaders) */
1958 if (This
->stateBlock
->shaderPrgId
) {
1959 TRACE_(d3d_shader
)("Using GLSL program %u\n", This
->stateBlock
->shaderPrgId
);
1961 GL_EXTCALL(glUseProgramObjectARB(This
->stateBlock
->shaderPrgId
));
1962 checkGLcall("glUseProgramObjectARB");
1965 if (useVertexShaderFunction
) {
1967 TRACE("Using vertex shader\n");
1969 if (wined3d_settings
.shader_mode
== SHADER_ARB
) {
1970 /* Bind the vertex program */
1971 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
,
1972 ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.prgId
));
1973 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1975 /* Enable OpenGL vertex programs */
1976 glEnable(GL_VERTEX_PROGRAM_ARB
);
1977 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1978 TRACE_(d3d_shader
)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1979 This
, ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.prgId
);
1983 if (usePixelShaderFunction
) {
1985 TRACE("Using pixel shader\n");
1987 if (wined3d_settings
.shader_mode
== SHADER_ARB
) {
1988 /* Bind the fragment program */
1989 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
,
1990 ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.prgId
));
1991 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1993 /* Enable OpenGL fragment programs */
1994 glEnable(GL_FRAGMENT_PROGRAM_ARB
);
1995 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1996 TRACE_(d3d_shader
)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1997 This
, ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.prgId
);
2001 /* Load any global constants/uniforms that may have been set by the application */
2002 drawPrimLoadConstants(iface
, useVertexShaderFunction
, usePixelShaderFunction
);
2004 /* DirectX colours are in a different format to opengl colours
2005 * so if diffuse or specular are used then we need to use drawStridedSlow
2006 * to correct the colours */
2007 if (!useVertexShaderFunction
&&
2008 ((dataLocations
->u
.s
.pSize
.lpData
!= NULL
)
2009 || (dataLocations
->u
.s
.diffuse
.lpData
!= NULL
)
2010 || (dataLocations
->u
.s
.specular
.lpData
!= NULL
))) {
2011 /* TODO: replace drawStridedSlow with vertex fixups */
2013 drawStridedSlow(iface
, dataLocations
, numberOfIndicies
, glPrimType
,
2014 idxData
, idxSize
, minIndex
, StartIdx
);
2017 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
2018 drawStridedFast(iface
, numberOfIndicies
, glPrimType
,
2019 idxData
, idxSize
, minIndex
, StartIdx
);
2022 /* Cleanup vertex program */
2023 if (useVertexShaderFunction
) {
2024 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2027 /* Leave all the attribs disabled */
2028 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB
, &maxAttribs
);
2029 /* MESA does not support it right not */
2030 if (glGetError() != GL_NO_ERROR
)
2032 for (i
= 0; i
< maxAttribs
; ++i
) {
2033 GL_EXTCALL(glDisableVertexAttribArrayARB(i
));
2034 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2037 if (wined3d_settings
.shader_mode
== SHADER_ARB
)
2038 glDisable(GL_VERTEX_PROGRAM_ARB
);
2041 /* Cleanup fragment program */
2042 if (usePixelShaderFunction
&& wined3d_settings
.shader_mode
== SHADER_ARB
) {
2043 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
2048 void inline drawPrimitiveTraceDataLocations(WineDirect3DVertexStridedData
*dataLocations
,DWORD fvf
) {
2050 /* Dump out what parts we have supplied */
2051 TRACE("Strided Data (from FVF/VS): %lx\n", fvf
);
2052 TRACE_STRIDED((dataLocations
), position
);
2053 TRACE_STRIDED((dataLocations
), blendWeights
);
2054 TRACE_STRIDED((dataLocations
), blendMatrixIndices
);
2055 TRACE_STRIDED((dataLocations
), normal
);
2056 TRACE_STRIDED((dataLocations
), pSize
);
2057 TRACE_STRIDED((dataLocations
), diffuse
);
2058 TRACE_STRIDED((dataLocations
), specular
);
2059 TRACE_STRIDED((dataLocations
), texCoords
[0]);
2060 TRACE_STRIDED((dataLocations
), texCoords
[1]);
2061 TRACE_STRIDED((dataLocations
), texCoords
[2]);
2062 TRACE_STRIDED((dataLocations
), texCoords
[3]);
2063 TRACE_STRIDED((dataLocations
), texCoords
[4]);
2064 TRACE_STRIDED((dataLocations
), texCoords
[5]);
2065 TRACE_STRIDED((dataLocations
), texCoords
[6]);
2066 TRACE_STRIDED((dataLocations
), texCoords
[7]);
2067 TRACE_STRIDED((dataLocations
), position2
);
2068 TRACE_STRIDED((dataLocations
), normal2
);
2069 TRACE_STRIDED((dataLocations
), tangent
);
2070 TRACE_STRIDED((dataLocations
), binormal
);
2071 TRACE_STRIDED((dataLocations
), tessFactor
);
2072 TRACE_STRIDED((dataLocations
), fog
);
2073 TRACE_STRIDED((dataLocations
), depth
);
2074 TRACE_STRIDED((dataLocations
), sample
);
2080 /* uploads textures and setup texture states ready for rendering */
2081 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl
* This
) {
2085 * OK, here we clear down any old junk iect in the context
2086 * enable the new texture and apply any state changes:
2088 * Loop through all textures
2089 * select texture unit
2090 * if there is a texture bound to that unit then..
2091 * disable all textures types on that unit
2092 * enable and bind the texture that is bound to that unit.
2093 * otherwise disable all texture types on that unit.
2095 /* upload the textures */
2096 for (i
= 0; i
< GL_LIMITS(textures
); ++i
) {
2097 /* Bind the texture to the stage here */
2098 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
2099 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
2100 checkGLcall("glActiveTextureARB");
2102 /* This isn't so much a warn as a message to the user about lack of hardware support */
2103 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2106 /* don't bother with textures that have a colorop of disable */
2107 if (This
->stateBlock
->textureState
[i
][WINED3DTSS_COLOROP
] != D3DTOP_DISABLE
) {
2108 if (This
->stateBlock
->textures
[i
] != NULL
) {
2110 glDisable(GL_TEXTURE_1D
);
2111 This
->stateBlock
->textureDimensions
[i
] = IWineD3DBaseTexture_GetTextureDimensions(This
->stateBlock
->textures
[i
]);
2112 /* disable all texture states that aren't the selected textures' dimension */
2113 switch(This
->stateBlock
->textureDimensions
[i
]) {
2115 glDisable(GL_TEXTURE_3D
);
2116 glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
2119 glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
2120 glDisable(GL_TEXTURE_2D
);
2122 case GLTEXTURECUBEMAP
:
2123 glDisable(GL_TEXTURE_2D
);
2124 glDisable(GL_TEXTURE_3D
);
2127 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2128 if (This
->texture_shader_active
&& This
->stateBlock
->textureDimensions
[i
] == GL_TEXTURE_2D
) {
2129 glTexEnvi(GL_TEXTURE_SHADER_NV
, GL_SHADER_OPERATION_NV
, GL_TEXTURE_2D
);
2131 glEnable(This
->stateBlock
->textureDimensions
[i
]);
2133 /* Load up the texture now */
2134 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture
*) This
->stateBlock
->textures
[i
]);
2135 IWineD3DDevice_SetupTextureStates((IWineD3DDevice
*)This
, i
, REAPPLY_ALPHAOP
);
2136 /* this is a stub function representing the state blocks
2137 * being separated here we are only updating the texture
2138 * state changes, other objects and units get updated when
2139 * they change (or need to be updated), e.g. states that
2140 * relate to a context member line the texture unit are
2141 * only updated when the context needs updating
2143 /* Tell the abse texture to sync it's states */
2144 IWineD3DBaseTexture_ApplyStateChanges(This
->stateBlock
->textures
[i
], This
->stateBlock
->textureState
[i
], This
->stateBlock
->samplerState
[i
]);
2147 /* Bind a default texture if no texture has been set, but colour-op is enabled */
2149 glDisable(GL_TEXTURE_2D
);
2150 glDisable(GL_TEXTURE_3D
);
2151 glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
2152 glEnable(GL_TEXTURE_1D
);
2153 This
->stateBlock
->textureDimensions
[i
] = GL_TEXTURE_1D
;
2154 glBindTexture(GL_TEXTURE_1D
, This
->dummyTextureName
[i
]);
2156 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2157 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2158 set_tex_op((IWineD3DDevice
*)This
, FALSE
, i
, This
->stateBlock
->textureState
[i
][WINED3DTSS_COLOROP
],
2159 This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG1
],
2160 This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG2
],
2161 This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG0
]);
2163 set_tex_op((IWineD3DDevice
*)This
, TRUE
, i
, This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAOP
],
2164 This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG1
],
2165 This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG2
],
2166 This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG0
]);
2169 /* no colorop so disable all the texture states */
2170 glDisable(GL_TEXTURE_1D
);
2171 glDisable(GL_TEXTURE_2D
);
2172 glDisable(GL_TEXTURE_3D
);
2173 glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
2180 /* Routine common to the draw primitive and draw indexed primitive routines */
2181 void drawPrimitive(IWineD3DDevice
*iface
,
2185 long StartVertexIndex
,
2186 UINT numberOfVertices
,
2189 const void *idxData
,
2191 WineDirect3DVertexStridedData
*DrawPrimStrideData
) {
2195 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2196 BOOL useVertexShaderFunction
= FALSE
;
2197 BOOL usePixelShaderFunction
= FALSE
;
2198 BOOL isLightingOn
= FALSE
;
2199 WineDirect3DVertexStridedData
*dataLocations
;
2200 IWineD3DSwapChainImpl
*swapchain
;
2201 int useHW
= FALSE
, i
;
2203 if (This
->stateBlock
->vertexShader
!= NULL
&& wined3d_settings
.vs_mode
!= VS_NONE
2204 &&((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.function
!= NULL
2205 && GL_SUPPORT(ARB_VERTEX_PROGRAM
)) {
2206 useVertexShaderFunction
= TRUE
;
2208 useVertexShaderFunction
= FALSE
;
2211 if (wined3d_settings
.ps_mode
!= PS_NONE
&& GL_SUPPORT(ARB_FRAGMENT_PROGRAM
)
2212 && This
->stateBlock
->pixelShader
2213 && ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.function
) {
2214 usePixelShaderFunction
= TRUE
;
2217 if (This
->stateBlock
->vertexDecl
== NULL
) {
2218 /* Work out what the FVF should look like */
2219 rc
= initializeFVF(iface
, &fvf
);
2222 TRACE("(%p) : using vertex declaration %p\n", iface
, This
->stateBlock
->vertexDecl
);
2225 /* Invalidate the back buffer memory so LockRect will read it the next time */
2226 for(i
= 0; i
< IWineD3DDevice_GetNumberOfSwapChains(iface
); i
++) {
2227 IWineD3DDevice_GetSwapChain(iface
, i
, (IWineD3DSwapChain
**) &swapchain
);
2229 if(swapchain
->backBuffer
) ((IWineD3DSurfaceImpl
*) swapchain
->backBuffer
)->Flags
|= SFLAG_GLDIRTY
;
2230 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
2234 /* Ok, we will be updating the screen from here onwards so grab the lock */
2237 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2239 if(DrawPrimStrideData
) {
2240 TRACE("================ Strided Input ===================\n");
2241 dataLocations
= DrawPrimStrideData
;
2243 else if (This
->stateBlock
->vertexDecl
!= NULL
|| (useVertexShaderFunction
&& NULL
!= ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->vertexDeclaration
)) {
2245 TRACE("================ Vertex Declaration ===================\n");
2246 dataLocations
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*dataLocations
));
2247 if(!dataLocations
) {
2248 ERR("Out of memory!\n");
2251 primitiveDeclarationConvertToStridedData(iface
, useVertexShaderFunction
, dataLocations
, StartVertexIndex
, &fvf
);
2254 TRACE("================ FVF ===================\n");
2255 dataLocations
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*dataLocations
));
2256 if(!dataLocations
) {
2257 ERR("Out of memory!\n");
2260 primitiveConvertToStridedData(iface
, dataLocations
, StartVertexIndex
);
2263 /* write out some debug information*/
2264 drawPrimitiveTraceDataLocations(dataLocations
, fvf
);
2266 /* Setup transform matrices and sort out */
2268 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2269 So make sure lighting is disabled. */
2270 isLightingOn
= glIsEnabled(GL_LIGHTING
);
2271 glDisable(GL_LIGHTING
);
2272 checkGLcall("glDisable(GL_LIGHTING);");
2273 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn
);
2275 isLightingOn
= primitiveInitState(iface
,
2276 fvf
& D3DFVF_XYZRHW
,
2277 !(fvf
& D3DFVF_NORMAL
),
2278 useVertexShaderFunction
);
2281 /* Now initialize the materials state */
2282 init_materials(iface
, (dataLocations
->u
.s
.diffuse
.lpData
!= NULL
));
2284 drawPrimitiveUploadTextures(This
);
2289 /* Ok, Work out which primitive is requested and how many vertexes that
2291 UINT calculatedNumberOfindices
= primitiveToGl(PrimitiveType
, NumPrimitives
, &glPrimType
);
2292 #if 0 /* debugging code... just information not an error */
2293 if(numberOfVertices
!= 0 && numberOfVertices
!= calculatedNumberOfindices
){
2294 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices
, calculatedNumberOfindices
);
2297 if (numberOfVertices
== 0 )
2298 numberOfVertices
= calculatedNumberOfindices
;
2299 drawPrimitiveDrawStrided(iface
, useVertexShaderFunction
, usePixelShaderFunction
, useHW
, dataLocations
, numberOfVertices
, calculatedNumberOfindices
, glPrimType
, idxData
, idxSize
, minIndex
, StartIdx
);
2302 if(!DrawPrimStrideData
) HeapFree(GetProcessHeap(), 0, dataLocations
);
2304 /* If vertex shaders or no normals, restore previous lighting state */
2305 if (useVertexShaderFunction
|| !(fvf
& D3DFVF_NORMAL
)) {
2306 if (isLightingOn
) glEnable(GL_LIGHTING
);
2307 else glDisable(GL_LIGHTING
);
2308 TRACE("Restored lighting to original state\n");
2311 /* Finshed updating the screen, restore lock */
2313 TRACE("Done all gl drawing\n");
2316 #ifdef SHOW_FRAME_MAKEUP
2318 static long int primCounter
= 0;
2319 /* NOTE: set primCounter to the value reported by drawprim
2320 before you want to to write frame makeup to /tmp */
2321 if (primCounter
>= 0) {
2322 WINED3DLOCKED_RECT r
;
2324 IWineD3DSurface_LockRect(This
->renderTarget
, &r
, NULL
, WINED3DLOCK_READONLY
);
2325 sprintf(buffer
, "/tmp/backbuffer_%ld.tga", primCounter
);
2326 TRACE("Saving screenshot %s\n", buffer
);
2327 IWineD3DSurface_SaveSnapshot(This
->renderTarget
, buffer
);
2328 IWineD3DSurface_UnlockRect(This
->renderTarget
);
2330 #ifdef SHOW_TEXTURE_MAKEUP
2332 IWineD3DSurface
*pSur
;
2334 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
2335 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
2336 sprintf(buffer
, "/tmp/texture_%p_%ld_%d.tga", This
->stateBlock
->textures
[textureNo
], primCounter
, textureNo
);
2337 TRACE("Saving texture %s\n", buffer
);
2338 if (IWineD3DBaseTexture_GetType(This
->stateBlock
->textures
[textureNo
]) == WINED3DRTYPE_TEXTURE
) {
2339 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)This
->stateBlock
->textures
[textureNo
], 0, &pSur
);
2340 IWineD3DSurface_SaveSnapshot(pSur
, buffer
);
2341 IWineD3DSurface_Release(pSur
);
2343 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This
->stateBlock
->textures
[textureNo
]));
2350 TRACE("drawprim #%ld\n", primCounter
);