4 * Copyright 2002-2003 Jason Edmeades
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
35 #include "d3d8_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
38 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
40 extern IDirect3DVertexShaderImpl* VertexShaders[64];
41 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
42 extern IDirect3DPixelShaderImpl* PixelShaders[64];
44 /* Useful holding place for 4 floats */
45 typedef struct _D3DVECTOR_4 {
52 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
54 /* Returns bits for what is expected from the fixed function pipeline, and whether
55 a vertex shader will be in use. Note the fvf bits returned may be split over
56 multiple streams only if the vertex shader was created, otherwise it all relates
58 BOOL initializeFVF(LPDIRECT3DDEVICE8 iface,
59 DWORD *FVFbits, /* What to expect in the FVF across all streams */
60 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
63 ICOM_THIS(IDirect3DDevice8Impl,iface);
65 /* The first thing to work out is if we are using the fixed function pipeline
66 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
67 is the FVF, or with a shader which was created with no function - in which
68 case there is an FVF per declared stream. If this occurs, we also maintain
69 an 'OR' of all the FVF's together so we know what to expect across all the
72 if (This->UpdateStateBlock->VertexShader <= VS_HIGHESTFIXEDFXF) {
74 /* Use this as the FVF */
75 *FVFbits = This->UpdateStateBlock->VertexShader;
76 *useVertexShaderFunction = FALSE;
77 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
81 /* Use created shader */
82 IDirect3DVertexShaderImpl* vertex_shader = NULL;
83 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
85 if (vertex_shader == NULL) {
87 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
88 ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
93 *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
95 if (vertex_shader->function == NULL) {
96 /* No function, so many streams supplied plus FVF definition pre stream */
97 *useVertexShaderFunction = FALSE;
98 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
99 This->StateBlock->VertexShader, *FVFbits);
101 /* Vertex shader needs calling */
102 *useVertexShaderFunction = TRUE;
103 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
110 /* Issues the glBegin call for gl given the primitive type and count */
111 DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
115 DWORD NumVertexes = NumPrimitives;
117 switch (PrimitiveType) {
118 case D3DPT_POINTLIST:
120 *primType = GL_POINTS;
121 NumVertexes = NumPrimitives;
126 *primType = GL_LINES;
127 NumVertexes = NumPrimitives * 2;
130 case D3DPT_LINESTRIP:
131 TRACE("LINE_STRIP\n");
132 *primType = GL_LINE_STRIP;
133 NumVertexes = NumPrimitives + 1;
136 case D3DPT_TRIANGLELIST:
137 TRACE("TRIANGLES\n");
138 *primType = GL_TRIANGLES;
139 NumVertexes = NumPrimitives * 3;
142 case D3DPT_TRIANGLESTRIP:
143 TRACE("TRIANGLE_STRIP\n");
144 *primType = GL_TRIANGLE_STRIP;
145 NumVertexes = NumPrimitives + 2;
148 case D3DPT_TRIANGLEFAN:
149 TRACE("TRIANGLE_FAN\n");
150 *primType = GL_TRIANGLE_FAN;
151 NumVertexes = NumPrimitives + 2;
155 FIXME("Unhandled primitive\n");
156 *primType = GL_POINTS;
162 /* Ensure the appropriate material states are set up - only change
163 state if really required */
164 void init_materials(LPDIRECT3DDEVICE8 iface, BOOL isDiffuseSupplied) {
166 BOOL requires_material_reset = FALSE;
167 ICOM_THIS(IDirect3DDevice8Impl,iface);
169 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == TRUE) {
170 /* If we have not set up the material color tracking, do it now as required */
171 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
172 checkGLcall("glDisable GL_COLOR_MATERIAL");
173 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
174 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
175 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
176 glEnable(GL_COLOR_MATERIAL);
177 checkGLcall("glEnable GL_COLOR_MATERIAL");
178 This->tracking_color = IS_TRACKING;
179 requires_material_reset = TRUE; /* Restore material settings as will be used */
181 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
182 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
183 /* If we are tracking the current color but one isnt supplied, dont! */
184 glDisable(GL_COLOR_MATERIAL);
185 checkGLcall("glDisable GL_COLOR_MATERIAL");
186 This->tracking_color = NEEDS_TRACKING;
187 requires_material_reset = TRUE; /* Restore material settings as will be used */
189 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied == TRUE) {
190 /* No need to reset material colors since no change to gl_color_material */
191 requires_material_reset = FALSE;
193 } else if (This->tracking_color == NEEDS_DISABLE) {
194 glDisable(GL_COLOR_MATERIAL);
195 checkGLcall("glDisable GL_COLOR_MATERIAL");
196 This->tracking_color = DISABLED_TRACKING;
197 requires_material_reset = TRUE; /* Restore material settings as will be used */
200 /* Reset the material colors which may have been tracking the color*/
201 if (requires_material_reset == TRUE) {
202 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->StateBlock->material.Ambient);
203 checkGLcall("glMaterialfv");
204 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->StateBlock->material.Diffuse);
205 checkGLcall("glMaterialfv");
206 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
207 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->StateBlock->material.Specular);
208 checkGLcall("glMaterialfv");
210 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
211 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
212 checkGLcall("glMaterialfv");
214 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->StateBlock->material.Emissive);
215 checkGLcall("glMaterialfv");
220 /* Setup views - Transformed & lit if RHW, else untransformed.
221 Only unlit if Normals are supplied
222 Returns: Whether to restore lighting afterwards */
223 BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
225 BOOL isLightingOn = FALSE;
226 ICOM_THIS(IDirect3DDevice8Impl,iface);
228 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
229 set by the appropriate render state. Note Vertex Shader output is already lit */
230 if (vtx_lit || useVS) {
231 isLightingOn = glIsEnabled(GL_LIGHTING);
232 glDisable(GL_LIGHTING);
233 checkGLcall("glDisable(GL_LIGHTING);");
234 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
237 if (!useVS && vtx_transformed) {
239 /* If the last draw was transformed as well, no need to reapply all the matrixes */
240 if (!This->last_was_rhw) {
242 double X, Y, height, width, minZ, maxZ;
243 This->last_was_rhw = TRUE;
245 /* Transformed already into viewport coordinates, so we do not need transform
246 matrices. Reset all matrices to identity and leave the default matrix in world
248 glMatrixMode(GL_MODELVIEW);
249 checkGLcall("glMatrixMode");
251 checkGLcall("glLoadIdentity");
253 glMatrixMode(GL_PROJECTION);
254 checkGLcall("glMatrixMode");
256 checkGLcall("glLoadIdentity");
258 /* Set up the viewport to be full viewport */
259 X = This->StateBlock->viewport.X;
260 Y = This->StateBlock->viewport.Y;
261 height = This->StateBlock->viewport.Height;
262 width = This->StateBlock->viewport.Width;
263 minZ = This->StateBlock->viewport.MinZ;
264 maxZ = This->StateBlock->viewport.MaxZ;
265 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
266 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
267 checkGLcall("glOrtho");
269 /* Window Coord 0 is the middle of the first pixel, so translate by half
270 a pixel (See comment above glTranslate below) */
271 glTranslatef(0.5, 0.5, 0);
272 checkGLcall("glTranslatef(0.5, 0.5, 0)");
277 /* Untransformed, so relies on the view and projection matrices */
279 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
280 /* Only reapply when have to */
281 This->modelview_valid = TRUE;
282 glMatrixMode(GL_MODELVIEW);
283 checkGLcall("glMatrixMode");
285 /* In the general case, the view matrix is the identity matrix */
286 if (This->view_ident) {
287 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
288 checkGLcall("glLoadMatrixf");
290 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
291 checkGLcall("glLoadMatrixf");
292 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
293 checkGLcall("glMultMatrixf");
297 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
298 /* Only reapply when have to */
299 This->proj_valid = TRUE;
300 glMatrixMode(GL_PROJECTION);
301 checkGLcall("glMatrixMode");
303 /* The rule is that the window coordinate 0 does not correspond to the
304 beginning of the first pixel, but the center of the first pixel.
305 As a consequence if you want to correctly draw one line exactly from
306 the left to the right end of the viewport (with all matrices set to
307 be identity), the x coords of both ends of the line would be not
308 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
311 glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
312 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
313 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
314 checkGLcall("glLoadMatrixf");
317 /* Vertex Shader output is already transformed, so set up identity matrices */
318 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
319 come along this needs to take into account whether s/w ones were
322 glMatrixMode(GL_MODELVIEW);
323 checkGLcall("glMatrixMode");
325 glMatrixMode(GL_PROJECTION);
326 checkGLcall("glMatrixMode");
328 /* Window Coord 0 is the middle of the first pixel, so translate by half
329 a pixel (See comment above glTranslate above) */
330 glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
331 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
332 This->modelview_valid = FALSE;
333 This->proj_valid = FALSE;
335 This->last_was_rhw = FALSE;
340 void primitiveConvertToStridedData(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
342 short LoopThroughTo = 0;
344 BOOL canDoViaGLPointers = TRUE;
348 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
349 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
351 ICOM_THIS(IDirect3DDevice8Impl,iface);
353 /* OK, Now to setup the data locations
354 For the non-created vertex shaders, the VertexShader var holds the real
355 FVF and only stream 0 matters
356 For the created vertex shaders, there is an FVF per stream */
357 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
358 LoopThroughTo = MAX_STREAMS;
363 /* Work through stream by stream */
364 for (nStream=0; nStream<LoopThroughTo; nStream++) {
365 DWORD stride = This->StateBlock->stream_stride[nStream];
369 /* Skip empty streams */
370 if (This->StateBlock->stream_source[nStream] == NULL) continue;
372 /* Retrieve appropriate FVF */
373 if (LoopThroughTo == 1) { /* VertexShader is FVF */
374 thisFVF = This->UpdateStateBlock->VertexShader;
375 /* Handle memory passed directly as well as vertex buffers */
376 if (This->StateBlock->streamIsUP == TRUE) {
377 data = (BYTE *)This->StateBlock->stream_source[nStream];
379 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
382 thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
383 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
385 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
386 if (thisFVF == 0) continue;
388 /* Now convert the stream into pointers */
390 /* Shuffle to the beginning of the vertexes to render and index from there */
391 data = data + (BaseVertexIndex * stride);
393 /* Either 3 or 4 floats depending on the FVF */
394 /* FIXME: Can blending data be in a different stream to the position data?
395 and if so using the fixed pipeline how do we handle it */
396 if (thisFVF & D3DFVF_POSITION_MASK) {
397 strided->u.s.position.lpData = data;
398 strided->u.s.position.dwType = D3DVSDT_FLOAT3;
399 strided->u.s.position.dwStride = stride;
400 data += 3 * sizeof(float);
401 if (thisFVF & D3DFVF_XYZRHW) {
402 strided->u.s.position.dwType = D3DVSDT_FLOAT4;
403 data += sizeof(float);
407 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
408 /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
409 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
410 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
412 canDoViaGLPointers = FALSE;
413 strided->u.s.blendWeights.lpData = data;
414 strided->u.s.blendWeights.dwType = D3DVSDT_FLOAT1 + (numBlends - 1);
415 strided->u.s.blendWeights.dwStride = stride;
416 data += numBlends * sizeof(FLOAT);
418 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
419 strided->u.s.blendMatrixIndices.lpData = data;
420 strided->u.s.blendMatrixIndices.dwType = D3DVSDT_UBYTE4;
421 strided->u.s.blendMatrixIndices.dwStride= stride;
422 data += sizeof(DWORD);
426 /* Normal is always 3 floats */
427 if (thisFVF & D3DFVF_NORMAL) {
428 strided->u.s.normal.lpData = data;
429 strided->u.s.normal.dwType = D3DVSDT_FLOAT3;
430 strided->u.s.normal.dwStride = stride;
431 data += 3 * sizeof(FLOAT);
434 /* Pointsize is a single float */
435 if (thisFVF & D3DFVF_PSIZE) {
436 strided->u.s.pSize.lpData = data;
437 strided->u.s.pSize.dwType = D3DVSDT_FLOAT1;
438 strided->u.s.pSize.dwStride = stride;
439 data += sizeof(FLOAT);
442 /* Diffuse is 4 unsigned bytes */
443 if (thisFVF & D3DFVF_DIFFUSE) {
444 strided->u.s.diffuse.lpData = data;
445 strided->u.s.diffuse.dwType = D3DVSDT_SHORT4;
446 strided->u.s.diffuse.dwStride = stride;
447 data += sizeof(DWORD);
450 /* Specular is 4 unsigned bytes */
451 if (thisFVF & D3DFVF_SPECULAR) {
452 strided->u.s.specular.lpData = data;
453 strided->u.s.specular.dwType = D3DVSDT_SHORT4;
454 strided->u.s.specular.dwStride = stride;
455 data += sizeof(DWORD);
459 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
460 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
462 /* numTextures indicates the number of texture coordinates supplied */
463 /* However, the first set may not be for stage 0 texture - it all */
464 /* depends on D3DTSS_TEXCOORDINDEX. */
465 /* The number of bytes for each coordinate set is based off */
466 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
468 /* So, for each supplied texture extract the coords */
469 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
471 strided->u.s.texCoords[textureNo].lpData = data;
472 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT1;
473 strided->u.s.texCoords[textureNo].dwStride = stride;
474 numCoords[textureNo] = coordIdxInfo & 0x03;
477 data += sizeof(float);
478 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
479 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
480 data += sizeof(float);
481 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
482 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
483 data += sizeof(float);
484 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
485 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
486 data += sizeof(float);
490 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
495 /* Draw a single vertex using this information */
496 void draw_vertex(LPDIRECT3DDEVICE8 iface, /* interface */
497 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
498 BOOL isNormal, float nx, float ny, float nz, /* normal */
499 BOOL isDiffuse, float *dRGBA, /* 1st colors */
500 BOOL isSpecular, float *sRGB, /* 2ndry colors */
501 BOOL isPtSize, float ptSize, /* pointSize */
502 D3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
506 ICOM_THIS(IDirect3DDevice8Impl,iface);
508 /* Diffuse -------------------------------- */
509 if (isDiffuse == TRUE) {
511 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
514 /* Specular Colour ------------------------------------------*/
515 if (isSpecular == TRUE) {
516 #if defined(GL_EXT_secondary_color)
517 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
518 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
519 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
524 /* Normal -------------------------------- */
525 if (isNormal == TRUE) {
526 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
527 glNormal3f(nx, ny, nz);
530 /* Point Size ----------------------------------------------*/
531 if (isPtSize == TRUE) {
533 /* no such functionality in the fixed function GL pipeline */
534 FIXME("Cannot change ptSize here in openGl\n");
537 /* Texture coords --------------------------- */
538 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
540 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
541 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
545 /* Query tex coords */
546 if (This->StateBlock->textures[textureNo] != NULL) {
548 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
550 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
552 } else if (numcoords[coordIdx] == 0) {
553 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
557 /* Initialize vars */
563 switch (numcoords[coordIdx]) {
564 case 4: q = texcoords[coordIdx].w; /* drop through */
565 case 3: r = texcoords[coordIdx].z; /* drop through */
566 case 2: t = texcoords[coordIdx].y; /* drop through */
567 case 1: s = texcoords[coordIdx].x;
570 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
572 VTRACE(("tex:%d, s=%f\n", textureNo, s));
573 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
574 #if defined(GL_VERSION_1_3)
575 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
577 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
584 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
585 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
586 #if defined(GL_VERSION_1_3)
587 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
589 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
596 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
597 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
598 #if defined(GL_VERSION_1_3)
599 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
601 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
604 glTexCoord3f(s, t, r);
608 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
609 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
610 #if defined(GL_VERSION_1_3)
611 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
613 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
616 glTexCoord4f(s, t, r, q);
620 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
624 } /* End of textures */
626 /* Position -------------------------------- */
628 if (1.0f == rhw || rhw < 0.00001f) {
629 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
632 /* Cannot optimize by dividing through by rhw as rhw is required
633 later for perspective in the GL pipeline for vertex shaders */
634 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
635 glVertex4f(x,y,z,rhw);
641 * Actually draw using the supplied information.
642 * Faster GL version using pointers to data, harder to debug though
643 * Note does not handle vertex shaders yet
645 void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
646 int PrimitiveType, ULONG NumPrimitives,
647 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
649 GLenum glPrimType = GL_POINTS;
650 int NumVertexes = NumPrimitives;
651 ICOM_THIS(IDirect3DDevice8Impl,iface);
653 TRACE("Using fast vertex array code\n");
655 /* Vertex Pointers -----------------------------------------*/
656 if (sd->u.s.position.lpData != NULL) {
658 /* Note dwType == float3 or float4 == 2 or 3 */
659 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
660 sd->u.s.position.dwStride,
661 sd->u.s.position.dwType + 1,
662 sd->u.s.position.lpData));
663 glVertexPointer(sd->u.s.position.dwType + 1, GL_FLOAT,
664 sd->u.s.position.dwStride,
665 sd->u.s.position.lpData);
666 checkGLcall("glVertexPointer(...)");
667 glEnableClientState(GL_VERTEX_ARRAY);
668 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
672 glDisableClientState(GL_VERTEX_ARRAY);
673 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
676 /* Blend Data ----------------------------------------------*/
677 if ((sd->u.s.blendWeights.lpData != NULL) ||
678 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
679 /* FIXME: Wont get here as will drop to slow method */
680 FIXME("Blending not supported in fast draw routine\n");
682 #if 0 /* Vertex blend support needs to be added */
683 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
685 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
688 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
689 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
690 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
691 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
694 FIXME("unsupported blending in openGl\n");
697 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
699 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
702 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
703 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
709 /* Normals -------------------------------------------------*/
710 if (sd->u.s.normal.lpData != NULL) {
712 /* Note dwType == float3 or float4 == 2 or 3 */
713 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
714 sd->u.s.normal.dwStride,
715 sd->u.s.normal.lpData));
716 glNormalPointer(GL_FLOAT,
717 sd->u.s.normal.dwStride,
718 sd->u.s.normal.lpData);
719 checkGLcall("glNormalPointer(...)");
720 glEnableClientState(GL_NORMAL_ARRAY);
721 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
725 glDisableClientState(GL_NORMAL_ARRAY);
726 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
728 checkGLcall("glNormal3f(0, 0, 1)");
731 /* Point Size ----------------------------------------------*/
732 if (sd->u.s.pSize.lpData != NULL) {
734 /* no such functionality in the fixed function GL pipeline */
735 /* FIXME: Wont get here as will drop to slow method */
736 FIXME("Cannot change ptSize here in openGl\n");
739 /* Diffuse Colour ------------------------------------------*/
740 /* WARNING: Data here MUST be in RGBA format, so cannot */
741 /* go directly into fast mode from app pgm, because */
742 /* directx requires data in BGRA format. */
743 if (sd->u.s.diffuse.lpData != NULL) {
745 /* Note dwType == float3 or float4 == 2 or 3 */
746 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
747 sd->u.s.diffuse.dwStride,
748 sd->u.s.diffuse.lpData));
749 glColorPointer(4, GL_UNSIGNED_BYTE,
750 sd->u.s.diffuse.dwStride,
751 sd->u.s.diffuse.lpData);
752 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
753 glEnableClientState(GL_COLOR_ARRAY);
754 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
758 glDisableClientState(GL_COLOR_ARRAY);
759 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
760 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
761 checkGLcall("glColor4f(1, 1, 1, 1)");
764 /* Specular Colour ------------------------------------------*/
765 if (sd->u.s.specular.lpData != NULL) {
767 /* Note dwType == float3 or float4 == 2 or 3 */
768 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
769 sd->u.s.specular.dwStride,
770 sd->u.s.specular.lpData));
772 #if defined(GL_VERSION_1_4)
773 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE,
774 sd->u.s.specular.dwStride,
775 sd->u.s.specular.lpData);
776 vcheckGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, ...)");
777 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
778 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
779 #elif defined(GL_EXT_secondary_color)
780 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
781 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
782 sd->u.s.specular.dwStride,
783 sd->u.s.specular.lpData);
784 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
785 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
786 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
789 /* Missing specular color is not critical, no warnings */
790 VTRACE(("Specular colour is not supported in this GL implementation\n"));
795 #if defined(GL_VERSION_1_4)
796 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
797 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
798 glSecondaryColor3f(0, 0, 0);
799 checkGLcall("glSecondaryColor3f(0, 0, 0)");
800 #elif defined(GL_EXT_secondary_color)
801 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
802 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
803 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
804 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
805 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
808 /* Do not worry if specular colour missing and disable request */
812 /* Texture coords -------------------------------------------*/
813 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
815 /* Select the correct texture stage */
816 #if defined(GL_VERSION_1_3)
817 glClientActiveTexture(GL_TEXTURE0 + textureNo);
819 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
822 /* Query tex coords */
823 if (This->StateBlock->textures[textureNo] != NULL) {
824 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
826 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
827 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
828 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
829 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
834 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
835 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
836 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
837 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
838 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
839 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
840 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
843 /* The coords to supply depend completely on the fvf / vertex shader */
847 switch (sd->u.s.texCoords[coordIdx].dwType) {
848 case D3DVSDT_FLOAT1: size = 1, type = GL_FLOAT; break;
849 case D3DVSDT_FLOAT2: size = 2, type = GL_FLOAT; break;
850 case D3DVSDT_FLOAT3: size = 3, type = GL_FLOAT; break;
851 case D3DVSDT_FLOAT4: size = 4, type = GL_FLOAT; break;
852 case D3DVSDT_SHORT2: size = 2, type = GL_SHORT; break;
853 case D3DVSDT_SHORT4: size = 4, type = GL_SHORT; break;
854 case D3DVSDT_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
855 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
856 size = 4; type = GL_UNSIGNED_BYTE;
859 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
860 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
863 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
864 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
868 /* Ok, Work out which primitive is requested and how many vertexes that
870 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
872 /* Finally do the drawing */
873 if (idxData != NULL) {
875 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
876 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
877 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
878 (char *)idxData+(idxSize * startIdx));
880 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
881 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
882 (char *)idxData+(idxSize * startIdx));
884 checkGLcall("glDrawRangeElements");
888 /* Note first is now zero as we shuffled along earlier */
889 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
890 glDrawArrays(glPrimType, 0, NumVertexes);
891 checkGLcall("glDrawArrays");
897 * Actually draw using the supplied information.
898 * Slower GL version which extracts info about each vertex in turn
900 void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
901 int PrimitiveType, ULONG NumPrimitives,
902 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
905 GLenum glPrimType = GL_POINTS;
906 int NumVertexes = NumPrimitives;
907 const short *pIdxBufS = NULL;
908 const long *pIdxBufL = NULL;
909 LONG SkipnStrides = 0;
911 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
912 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
913 float rhw = 0.0f; /* rhw */
914 float ptSize = 0.0f; /* Point size */
915 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
916 DWORD specularColor = 0; /* Specular Color */
917 ICOM_THIS(IDirect3DDevice8Impl,iface);
919 TRACE("Using slow vertex array code\n");
921 /* Variable Initialization */
922 if (idxData != NULL) {
923 if (idxSize == 2) pIdxBufS = (short *) idxData;
924 else pIdxBufL = (long *) idxData;
927 /* Ok, Work out which primitive is requested and how many vertexes that will be */
928 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
930 /* Start drawing in GL */
931 VTRACE(("glBegin(%x)\n", glPrimType));
934 /* For each primitive */
935 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
937 /* Initialize diffuse color */
938 diffuseColor = 0xFFFFFFFF;
940 /* For indexed data, we need to go a few more strides in */
941 if (idxData != NULL) {
943 /* Indexed so work out the number of strides to skip */
945 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
946 SkipnStrides = pIdxBufS[startIdx+vx_index];
948 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
949 SkipnStrides = pIdxBufL[startIdx+vx_index];
953 /* Position Information ------------------ */
954 if (sd->u.s.position.lpData != NULL) {
956 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
961 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
963 /* RHW follows, only if transformed, ie 4 floats were provided */
964 if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
965 rhw = ptrToCoords[3];
966 VTRACE(("rhw=%f\n", rhw));
970 /* Blending data -------------------------- */
971 if (sd->u.s.blendWeights.lpData != NULL) {
972 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
973 FIXME("Blending not supported yet\n");
975 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
976 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
980 /* Vertex Normal Data (untransformed only)- */
981 if (sd->u.s.normal.lpData != NULL) {
983 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
987 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
990 /* Point Size ----------------------------- */
991 if (sd->u.s.pSize.lpData != NULL) {
993 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
994 ptSize = ptrToCoords[0];
995 VTRACE(("ptSize=%f\n", ptSize));
996 FIXME("No support for ptSize yet\n");
999 /* Diffuse -------------------------------- */
1000 if (sd->u.s.diffuse.lpData != NULL) {
1002 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1003 diffuseColor = ptrToCoords[0];
1004 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1007 /* Specular -------------------------------- */
1008 if (sd->u.s.specular.lpData != NULL) {
1010 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1011 specularColor = ptrToCoords[0];
1012 VTRACE(("specularColor=%lx\n", specularColor));
1015 /* Texture coords --------------------------- */
1016 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1018 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1019 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1023 /* Query tex coords */
1024 if (This->StateBlock->textures[textureNo] != NULL) {
1026 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1027 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1028 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1031 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1033 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1034 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1038 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
1040 /* The coords to supply depend completely on the fvf / vertex shader */
1041 switch (coordsToUse) {
1042 case 4: q = ptrToCoords[3]; /* drop through */
1043 case 3: r = ptrToCoords[2]; /* drop through */
1044 case 2: t = ptrToCoords[1]; /* drop through */
1045 case 1: s = ptrToCoords[0];
1048 /* Projected is more 'fun' - Move the last coord to the 'q'
1049 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1050 if ((This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1051 (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1053 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1054 switch (coordsToUse) {
1055 case 0: /* Drop Through */
1057 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1069 case 4: /* Nop here */
1072 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1073 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1078 switch (coordsToUse) { /* Supply the provided texture coords */
1079 case D3DTTFF_COUNT1:
1080 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1081 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1082 #if defined(GL_VERSION_1_3)
1083 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1085 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1091 case D3DTTFF_COUNT2:
1092 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1093 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1094 #if defined(GL_VERSION_1_3)
1095 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1097 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1103 case D3DTTFF_COUNT3:
1104 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1105 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1106 #if defined(GL_VERSION_1_3)
1107 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1109 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1112 glTexCoord3f(s, t, r);
1115 case D3DTTFF_COUNT4:
1116 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1117 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1118 #if defined(GL_VERSION_1_3)
1119 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1121 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1124 glTexCoord4f(s, t, r, q);
1128 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1132 } /* End of textures */
1134 /* Diffuse -------------------------------- */
1135 if (sd->u.s.diffuse.lpData != NULL) {
1136 glColor4ub((diffuseColor >> 16) & 0xFF,
1137 (diffuseColor >> 8) & 0xFF,
1138 (diffuseColor >> 0) & 0xFF,
1139 (diffuseColor >> 24) & 0xFF);
1140 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1141 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1142 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1143 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1144 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1146 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1150 /* Specular ------------------------------- */
1151 if (sd->u.s.diffuse.lpData != NULL) {
1152 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1153 ((specularColor >> 16) & 0xFF) / 255.0f,
1154 ((specularColor >> 8) & 0xFF) / 255.0f,
1155 ((specularColor >> 0) & 0xFF) / 255.0f));
1156 #if defined(GL_VERSION_1_4)
1157 glSecondaryColor3ub((specularColor >> 16) & 0xFF,
1158 (specularColor >> 8) & 0xFF,
1159 (specularColor >> 0) & 0xFF);
1160 #elif defined(GL_EXT_secondary_color)
1161 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1162 GL_EXTCALL(glSecondaryColor3ubEXT)(
1163 (specularColor >> 16) & 0xFF,
1164 (specularColor >> 8) & 0xFF,
1165 (specularColor >> 0) & 0xFF);
1168 /* Do not worry if specular colour missing and disable request */
1169 VTRACE(("Specular color extensions not supplied\n"));
1172 #if defined(GL_VERSION_1_4)
1173 if (vx_index == 0) glSecondaryColor3f(0, 0, 0);
1174 #elif defined(GL_EXT_secondary_color)
1175 if (vx_index == 0 && GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1176 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1179 /* Do not worry if specular colour missing and disable request */
1184 /* Normal -------------------------------- */
1185 if (sd->u.s.normal.lpData != NULL) {
1186 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1187 glNormal3f(nx, ny, nz);
1189 if (vx_index == 0) glNormal3f(0, 0, 1);
1192 /* Position -------------------------------- */
1193 if (sd->u.s.position.lpData != NULL) {
1194 if (1.0f == rhw || rhw < 0.0001f) {
1195 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1196 glVertex3f(x, y, z);
1198 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1199 glVertex4f(x,y,z,rhw);
1203 /* For non indexed mode, step onto next parts */
1204 if (idxData == NULL) {
1210 checkGLcall("glEnd and previous calls");
1214 * Draw with emulated vertex shaders
1215 * Note: strided data is uninitialized, as we need to pass the vertex
1216 * shader directly as ordering irs yet
1218 void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
1219 int PrimitiveType, ULONG NumPrimitives,
1220 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1223 GLenum glPrimType = GL_POINTS;
1224 int NumVertexes = NumPrimitives;
1225 const short *pIdxBufS = NULL;
1226 const long *pIdxBufL = NULL;
1227 LONG SkipnStrides = 0;
1229 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1230 float rhw = 0.0f; /* rhw */
1231 float ptSize = 0.0f; /* Point size */
1232 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1233 int numcoords[8]; /* Number of coords */
1234 ICOM_THIS(IDirect3DDevice8Impl,iface);
1236 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1238 TRACE("Using slow software vertex shader code\n");
1240 /* Variable Initialization */
1241 if (idxData != NULL) {
1242 if (idxSize == 2) pIdxBufS = (short *) idxData;
1243 else pIdxBufL = (long *) idxData;
1246 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1247 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1249 /* Retrieve the VS information */
1250 vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1252 /* Start drawing in GL */
1253 VTRACE(("glBegin(%x)\n", glPrimType));
1254 glBegin(glPrimType);
1256 /* For each primitive */
1257 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1259 /* For indexed data, we need to go a few more strides in */
1260 if (idxData != NULL) {
1262 /* Indexed so work out the number of strides to skip */
1264 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1265 SkipnStrides = pIdxBufS[startIdx+vx_index];
1267 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1268 SkipnStrides = pIdxBufL[startIdx+vx_index];
1272 /* Fill the vertex shader input */
1273 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, SkipnStrides);
1275 /* Initialize the output fields to the same defaults as it would normally have */
1276 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1277 vertex_shader->output.oD[0].x = 1.0;
1278 vertex_shader->output.oD[0].y = 1.0;
1279 vertex_shader->output.oD[0].z = 1.0;
1280 vertex_shader->output.oD[0].w = 1.0;
1282 /* Now execute the vertex shader */
1283 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1286 TRACE_VECTOR(vertex_shader->output.oPos);
1287 TRACE_VECTOR(vertex_shader->output.oD[0]);
1288 TRACE_VECTOR(vertex_shader->output.oD[1]);
1289 TRACE_VECTOR(vertex_shader->output.oT[0]);
1290 TRACE_VECTOR(vertex_shader->output.oT[1]);
1291 TRACE_VECTOR(vertex_shader->input.V[0]);
1292 TRACE_VECTOR(vertex_shader->data->C[0]);
1293 TRACE_VECTOR(vertex_shader->data->C[1]);
1294 TRACE_VECTOR(vertex_shader->data->C[2]);
1295 TRACE_VECTOR(vertex_shader->data->C[3]);
1296 TRACE_VECTOR(vertex_shader->data->C[4]);
1297 TRACE_VECTOR(vertex_shader->data->C[5]);
1298 TRACE_VECTOR(vertex_shader->data->C[6]);
1299 TRACE_VECTOR(vertex_shader->data->C[7]);
1302 /* Extract out the output */
1303 /*FIXME: Fog coords? */
1304 x = vertex_shader->output.oPos.x;
1305 y = vertex_shader->output.oPos.y;
1306 z = vertex_shader->output.oPos.z;
1307 rhw = vertex_shader->output.oPos.w;
1308 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1310 /** Update textures coords using vertex_shader->output.oT[0->7] */
1311 memset(texcoords, 0x00, sizeof(texcoords));
1312 memset(numcoords, 0x00, sizeof(numcoords));
1313 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1314 if (This->StateBlock->textures[textureNo] != NULL) {
1315 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1316 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1317 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1318 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1319 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1320 numcoords[textureNo] = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1322 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
1323 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1324 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1325 default: numcoords[textureNo] = 4;
1329 numcoords[textureNo] = 0;
1333 /* Draw using this information */
1336 TRUE, 0.0f, 0.0f, 1.0f,
1337 TRUE, (float*) &vertex_shader->output.oD[0],
1338 TRUE, (float*) &vertex_shader->output.oD[1],
1339 FALSE, ptSize, /* FIXME: Change back when supported */
1340 texcoords, numcoords);
1342 /* For non indexed mode, step onto next parts */
1343 if (idxData == NULL) {
1347 } /* for each vertex */
1350 checkGLcall("glEnd and previous calls");
1353 /* Routine common to the draw primitive and draw indexed primitive routines */
1354 void drawPrimitive(LPDIRECT3DDEVICE8 iface,
1355 int PrimitiveType, long NumPrimitives,
1358 long StartVertexIndex,
1361 const void *idxData,
1366 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1367 BOOL useVertexShaderFunction = FALSE;
1368 BOOL isLightingOn = FALSE;
1369 Direct3DVertexStridedData dataLocations;
1370 ICOM_THIS(IDirect3DDevice8Impl,iface);
1373 /* Work out what the FVF should look like */
1374 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1377 /* If we will be using a vertex shader, do some initialization for it */
1378 if (useVertexShaderFunction == TRUE) {
1379 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
1380 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1382 /** init Constants */
1383 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
1384 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1385 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
1389 /* Ok, we will be updating the screen from here onwards so grab the lock */
1392 /* Setup transform matrices and sort out */
1393 isLightingOn = primitiveInitState(iface,
1394 fvf & D3DFVF_XYZRHW,
1395 !(fvf & D3DFVF_NORMAL),
1396 useVertexShaderFunction);
1398 /* Initialize all values to null */
1399 if (useVertexShaderFunction == FALSE) {
1400 memset(&dataLocations, 0x00, sizeof(dataLocations));
1402 /* Convert to strided data */
1403 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1405 /* Dump out what parts we have supplied */
1406 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1407 TRACE_STRIDED((&dataLocations), position);
1408 TRACE_STRIDED((&dataLocations), blendWeights);
1409 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1410 TRACE_STRIDED((&dataLocations), normal);
1411 TRACE_STRIDED((&dataLocations), pSize);
1412 TRACE_STRIDED((&dataLocations), diffuse);
1413 TRACE_STRIDED((&dataLocations), specular);
1414 TRACE_STRIDED((&dataLocations), texCoords[0]);
1415 TRACE_STRIDED((&dataLocations), texCoords[1]);
1416 TRACE_STRIDED((&dataLocations), texCoords[2]);
1417 TRACE_STRIDED((&dataLocations), texCoords[3]);
1418 TRACE_STRIDED((&dataLocations), texCoords[4]);
1419 TRACE_STRIDED((&dataLocations), texCoords[5]);
1420 TRACE_STRIDED((&dataLocations), texCoords[6]);
1421 TRACE_STRIDED((&dataLocations), texCoords[7]);
1424 /* Now initialize the materials state */
1425 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1427 /* Now draw the graphics to the screen */
1428 if (useVertexShaderFunction == TRUE) {
1430 /* Ideally, we should have software FV and hardware VS, possibly
1431 depending on the device type? */
1433 /* We will have to use the very, very slow emulation layer */
1434 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1435 idxData, idxSize, minIndex, StartIdx);
1437 } else if ((dataLocations.u.s.pSize.lpData != NULL) ||
1438 (dataLocations.u.s.diffuse.lpData != NULL) ||
1439 (dataLocations.u.s.blendWeights.lpData != NULL)) {
1441 /* Fixme, Ideally, only use the per-vertex code for software HAL
1442 but until opengl supports all the functions returned to setup
1443 vertex arrays, we need to drop down to the slow mechanism for
1444 certain functions */
1446 /* We will have to use the slow version of GL per vertex setup */
1447 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1448 idxData, idxSize, minIndex, StartIdx);
1452 /* We can use the fast version of GL pointers */
1453 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1454 idxData, idxSize, minIndex, StartIdx);
1457 /* If vertex shaders or no normals, restore previous lighting state */
1458 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1459 if (isLightingOn) glEnable(GL_LIGHTING);
1460 else glDisable(GL_LIGHTING);
1461 TRACE("Restored lighting to original state\n");
1464 /* Finshed updating the screen, restore lock */
1466 TRACE("Done all gl drawing\n");
1469 #if defined(SHOW_FRAME_MAKEUP)
1471 if (isDumpingFrames == TRUE) {
1474 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->backBuffer, &r, NULL, D3DLOCK_READONLY);
1475 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1476 TRACE("Saving screenshot %s\n", buffer);
1477 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
1478 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
1480 #if defined(SHOW_TEXTURE_MAKEUP)
1482 LPDIRECT3DSURFACE8 pSur;
1484 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1485 if (This->StateBlock->textures[textureNo] != NULL) {
1486 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1487 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->StateBlock->textures[textureNo])->format));
1488 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->StateBlock->textures[textureNo], 0, &pSur);
1489 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1490 IDirect3DSurface8Impl_Release(pSur);
1495 primCounter = primCounter + 1;