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
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 #include "d3d8_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
39 extern IDirect3DVertexShaderImpl* VertexShaders[64];
40 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
41 extern IDirect3DPixelShaderImpl* PixelShaders[64];
43 /* Useful holding place for 4 floats */
44 typedef struct _D3DVECTOR_4 {
51 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
53 /* Returns bits for what is expected from the fixed function pipeline, and whether
54 a vertex shader will be in use. Note the fvf bits returned may be split over
55 multiple streams only if the vertex shader was created, otherwise it all relates
57 BOOL initializeFVF(LPDIRECT3DDEVICE8 iface,
58 DWORD *FVFbits, /* What to expect in the FVF across all streams */
59 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
62 ICOM_THIS(IDirect3DDevice8Impl,iface);
64 /* The first thing to work out is if we are using the fixed function pipeline
65 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
66 is the FVF, or with a shader which was created with no function - in which
67 case there is an FVF per declared stream. If this occurs, we also maintain
68 an 'OR' of all the FVF's together so we know what to expect across all the
71 if (This->UpdateStateBlock->VertexShader <= VS_HIGHESTFIXEDFXF) {
73 /* Use this as the FVF */
74 *FVFbits = This->UpdateStateBlock->VertexShader;
75 *useVertexShaderFunction = FALSE;
76 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
80 /* Use created shader */
81 IDirect3DVertexShaderImpl* vertex_shader = NULL;
82 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
84 if (vertex_shader == NULL) {
86 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
87 ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
92 *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
94 if (vertex_shader->function == NULL) {
95 /* No function, so many streams supplied plus FVF definition pre stream */
96 *useVertexShaderFunction = FALSE;
97 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
98 This->StateBlock->VertexShader, *FVFbits);
100 /* Vertex shader needs calling */
101 *useVertexShaderFunction = TRUE;
102 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
109 /* Issues the glBegin call for gl given the primitive type and count */
110 DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
114 DWORD NumVertexes = NumPrimitives;
116 switch (PrimitiveType) {
117 case D3DPT_POINTLIST:
119 *primType = GL_POINTS;
120 NumVertexes = NumPrimitives;
125 *primType = GL_LINES;
126 NumVertexes = NumPrimitives * 2;
129 case D3DPT_LINESTRIP:
130 TRACE("LINE_STRIP\n");
131 *primType = GL_LINE_STRIP;
132 NumVertexes = NumPrimitives + 1;
135 case D3DPT_TRIANGLELIST:
136 TRACE("TRIANGLES\n");
137 *primType = GL_TRIANGLES;
138 NumVertexes = NumPrimitives * 3;
141 case D3DPT_TRIANGLESTRIP:
142 TRACE("TRIANGLE_STRIP\n");
143 *primType = GL_TRIANGLE_STRIP;
144 NumVertexes = NumPrimitives + 2;
147 case D3DPT_TRIANGLEFAN:
148 TRACE("TRIANGLE_FAN\n");
149 *primType = GL_TRIANGLE_FAN;
150 NumVertexes = NumPrimitives + 2;
154 FIXME("Unhandled primitive\n");
155 *primType = GL_POINTS;
161 /* Setup views - Transformed & lit if RHW, else untransformed.
162 Only unlit if Normals are supplied
163 Returns: Whether to restore lighting afterwards */
164 BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_lit) {
166 BOOL isLightingOn = FALSE;
167 ICOM_THIS(IDirect3DDevice8Impl,iface);
169 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
170 set by the appropriate render state */
172 isLightingOn = glIsEnabled(GL_LIGHTING);
173 glDisable(GL_LIGHTING);
174 checkGLcall("glDisable(GL_LIGHTING);");
175 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
178 if (vtx_transformed) {
180 /* If the last draw was transformed as well, no need to reapply all the matrixes */
181 if (!This->last_was_rhw) {
183 double X, Y, height, width, minZ, maxZ;
184 This->last_was_rhw = TRUE;
186 /* Transformed already into viewport coordinates, so we do not need transform
187 matrices. Reset all matrices to identity and leave the default matrix in world
189 glMatrixMode(GL_MODELVIEW);
190 checkGLcall("glMatrixMode");
192 checkGLcall("glLoadIdentity");
194 glMatrixMode(GL_PROJECTION);
195 checkGLcall("glMatrixMode");
197 checkGLcall("glLoadIdentity");
199 /* Set up the viewport to be full viewport */
200 X = This->StateBlock->viewport.X;
201 Y = This->StateBlock->viewport.Y;
202 height = This->StateBlock->viewport.Height;
203 width = This->StateBlock->viewport.Width;
204 minZ = This->StateBlock->viewport.MinZ;
205 maxZ = This->StateBlock->viewport.MaxZ;
206 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
207 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
208 checkGLcall("glOrtho");
210 /* Window Coord 0 is the middle of the first pixel, so translate by half
211 a pixel (See comment above glTranslate below) */
212 glTranslatef(0.5, 0.5, 0);
213 checkGLcall("glTranslatef(0.5, 0.5, 0)");
218 /* Untransformed, so relies on the view and projection matrices */
220 if (This->last_was_rhw || !This->modelview_valid) {
221 /* Only reapply when have to */
222 This->modelview_valid = TRUE;
223 glMatrixMode(GL_MODELVIEW);
224 checkGLcall("glMatrixMode");
226 /* In the general case, the view matrix is the identity matrix */
227 if (This->view_ident) {
228 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
229 checkGLcall("glLoadMatrixf");
231 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
232 checkGLcall("glLoadMatrixf");
233 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
234 checkGLcall("glMultMatrixf");
238 if (This->last_was_rhw || !This->proj_valid) {
239 /* Only reapply when have to */
240 This->proj_valid = TRUE;
241 glMatrixMode(GL_PROJECTION);
242 checkGLcall("glMatrixMode");
244 /* The rule is that the window coordinate 0 does not correspond to the
245 beginning of the first pixel, but the center of the first pixel.
246 As a consequence if you want to correctly draw one line exactly from
247 the left to the right end of the viewport (with all matrices set to
248 be identity), the x coords of both ends of the line would be not
249 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
252 glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
253 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
254 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
255 checkGLcall("glLoadMatrixf");
258 This->last_was_rhw = FALSE;
263 void primitiveConvertToStridedData(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
265 short LoopThroughTo = 0;
267 BOOL canDoViaGLPointers = TRUE;
271 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
272 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
274 ICOM_THIS(IDirect3DDevice8Impl,iface);
276 /* OK, Now to setup the data locations
277 For the non-created vertex shaders, the VertexShader var holds the real
278 FVF and only stream 0 matters
279 For the created vertex shaders, there is an FVF per stream */
280 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
281 LoopThroughTo = MAX_STREAMS;
286 /* Work through stream by stream */
287 for (nStream=0; nStream<LoopThroughTo; nStream++) {
288 DWORD stride = This->StateBlock->stream_stride[nStream];
292 /* Skip empty streams */
293 if (This->StateBlock->stream_source[nStream] == NULL) continue;
295 /* Retrieve appropriate FVF */
296 if (LoopThroughTo == 1) { /* VertexShader is FVF */
297 thisFVF = This->UpdateStateBlock->VertexShader;
298 /* Handle memory passed directly as well as vertex buffers */
299 if (This->StateBlock->streamIsUP == TRUE) {
300 data = (BYTE *)This->StateBlock->stream_source[nStream];
302 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
305 thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
306 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
308 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
309 if (thisFVF == 0) continue;
311 /* Now convert the stream into pointers */
313 /* Shuffle to the beginning of the vertexes to render and index from there */
314 data = data + (BaseVertexIndex * stride);
316 /* Either 3 or 4 floats depending on the FVF */
317 /* FIXME: Can blending data be in a different stream to the position data?
318 and if so using the fixed pipeline how do we handle it */
319 if (thisFVF & D3DFVF_POSITION_MASK) {
320 strided->u.s.position.lpData = data;
321 strided->u.s.position.dwType = D3DVSDT_FLOAT3;
322 strided->u.s.position.dwStride = stride;
323 data += 3 * sizeof(float);
324 if (thisFVF & D3DFVF_XYZRHW) {
325 strided->u.s.position.dwType = D3DVSDT_FLOAT4;
326 data += sizeof(float);
330 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
331 /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
332 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
333 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
335 canDoViaGLPointers = FALSE;
336 strided->u.s.blendWeights.lpData = data;
337 strided->u.s.blendWeights.dwType = D3DVSDT_FLOAT1 + (numBlends - 1);
338 strided->u.s.blendWeights.dwStride = stride;
339 data += numBlends * sizeof(FLOAT);
341 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
342 strided->u.s.blendMatrixIndices.lpData = data;
343 strided->u.s.blendMatrixIndices.dwType = D3DVSDT_UBYTE4;
344 strided->u.s.blendMatrixIndices.dwStride= stride;
345 data += sizeof(DWORD);
349 /* Normal is always 3 floats */
350 if (thisFVF & D3DFVF_NORMAL) {
351 strided->u.s.normal.lpData = data;
352 strided->u.s.normal.dwType = D3DVSDT_FLOAT3;
353 strided->u.s.normal.dwStride = stride;
354 data += 3 * sizeof(FLOAT);
357 /* Pointsize is a single float */
358 if (thisFVF & D3DFVF_PSIZE) {
359 strided->u.s.pSize.lpData = data;
360 strided->u.s.pSize.dwType = D3DVSDT_FLOAT1;
361 strided->u.s.pSize.dwStride = stride;
362 data += sizeof(FLOAT);
365 /* Diffuse is 4 unsigned bytes */
366 if (thisFVF & D3DFVF_DIFFUSE) {
367 strided->u.s.diffuse.lpData = data;
368 strided->u.s.diffuse.dwType = D3DVSDT_SHORT4;
369 strided->u.s.diffuse.dwStride = stride;
370 data += sizeof(DWORD);
373 /* Specular is 4 unsigned bytes */
374 if (thisFVF & D3DFVF_SPECULAR) {
375 strided->u.s.specular.lpData = data;
376 strided->u.s.specular.dwType = D3DVSDT_SHORT4;
377 strided->u.s.specular.dwStride = stride;
378 data += sizeof(DWORD);
382 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
383 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
385 /* numTextures indicates the number of texture coordinates supplied */
386 /* However, the first set may not be for stage 0 texture - it all */
387 /* depends on D3DTSS_TEXCOORDINDEX. */
388 /* The number of bytes for each coordinate set is based off */
389 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
391 /* So, for each supplied texture extract the coords */
392 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
394 strided->u.s.texCoords[textureNo].lpData = data;
395 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT1;
396 strided->u.s.texCoords[textureNo].dwStride = stride;
397 numCoords[textureNo] = coordIdxInfo & 0x03;
400 data += sizeof(float);
401 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
402 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
403 data += sizeof(float);
404 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
405 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
406 data += sizeof(float);
407 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
408 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
409 data += sizeof(float);
413 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
418 /* Draw a single vertex using this information */
419 void draw_vertex(LPDIRECT3DDEVICE8 iface, /* interface */
420 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
421 BOOL isNormal, float nx, float ny, float nz, /* normal */
422 BOOL isDiffuse, float *dRGBA, /* 1st colors */
423 BOOL isSpecular, float *sRGB, /* 2ndry colors */
424 BOOL isPtSize, float ptSize, /* pointSize */
425 D3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
429 ICOM_THIS(IDirect3DDevice8Impl,iface);
431 /* Diffuse -------------------------------- */
432 if (isDiffuse == TRUE) {
434 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
437 /* Specular Colour ------------------------------------------*/
438 if (isSpecular == TRUE) {
439 #if defined(GL_EXT_secondary_color)
440 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
441 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
442 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
447 /* Normal -------------------------------- */
448 if (isNormal == TRUE) {
449 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
450 glNormal3f(nx, ny, nz);
453 /* Point Size ----------------------------------------------*/
454 if (isPtSize == TRUE) {
456 /* no such functionality in the fixed function GL pipeline */
457 FIXME("Cannot change ptSize here in openGl\n");
460 /* Texture coords --------------------------- */
461 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
463 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
464 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
468 /* Query tex coords */
469 if (This->StateBlock->textures[textureNo] != NULL) {
471 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
473 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
475 } else if (numcoords[coordIdx] == 0) {
476 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
480 /* Initialize vars */
486 switch (numcoords[coordIdx]) {
487 case 4: q = texcoords[coordIdx].w; /* drop through */
488 case 3: r = texcoords[coordIdx].z; /* drop through */
489 case 2: t = texcoords[coordIdx].y; /* drop through */
490 case 1: s = texcoords[coordIdx].x;
493 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
495 VTRACE(("tex:%d, s=%f\n", textureNo, s));
496 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
497 #if defined(GL_VERSION_1_3)
498 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
500 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
507 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
508 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
509 #if defined(GL_VERSION_1_3)
510 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
512 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
519 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
520 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
521 #if defined(GL_VERSION_1_3)
522 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
524 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
527 glTexCoord3f(s, t, r);
531 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
532 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
533 #if defined(GL_VERSION_1_3)
534 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
536 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
539 glTexCoord4f(s, t, r, q);
543 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
547 } /* End of textures */
549 /* Position -------------------------------- */
551 if (1.0f == rhw || rhw < 0.01f) {
552 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
555 GLfloat w = 1.0f / rhw;
556 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
557 glVertex4f(x * w, y * w, z * w, 1.0f);
563 * Actually draw using the supplied information.
564 * Faster GL version using pointers to data, harder to debug though
565 * Note does not handle vertex shaders yet
567 void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
568 int PrimitiveType, ULONG NumPrimitives,
569 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
571 GLenum glPrimType = GL_POINTS;
572 int NumVertexes = NumPrimitives;
573 ICOM_THIS(IDirect3DDevice8Impl,iface);
575 TRACE("Using fast vertex array code\n");
577 /* Vertex Pointers -----------------------------------------*/
578 if (sd->u.s.position.lpData != NULL) {
580 /* Note dwType == float3 or float4 == 2 or 3 */
581 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
582 sd->u.s.position.dwStride,
583 sd->u.s.position.dwType + 1,
584 sd->u.s.position.lpData));
585 glVertexPointer(sd->u.s.position.dwType + 1, GL_FLOAT,
586 sd->u.s.position.dwStride,
587 sd->u.s.position.lpData);
588 checkGLcall("glVertexPointer(...)");
589 glEnableClientState(GL_VERTEX_ARRAY);
590 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
594 glDisableClientState(GL_VERTEX_ARRAY);
595 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
598 /* Blend Data ----------------------------------------------*/
599 if ((sd->u.s.blendWeights.lpData != NULL) ||
600 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
601 /* FIXME: Wont get here as will drop to slow method */
602 FIXME("Blending not supported in fast draw routine\n");
604 #if 0 /* Vertex blend support needs to be added */
605 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
607 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
610 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
611 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
612 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
613 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
616 FIXME("unsupported blending in openGl\n");
619 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
621 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
624 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
625 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
631 /* Normals -------------------------------------------------*/
632 if (sd->u.s.normal.lpData != NULL) {
634 /* Note dwType == float3 or float4 == 2 or 3 */
635 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
636 sd->u.s.normal.dwStride,
637 sd->u.s.normal.lpData));
638 glNormalPointer(GL_FLOAT,
639 sd->u.s.normal.dwStride,
640 sd->u.s.normal.lpData);
641 checkGLcall("glNormalPointer(...)");
642 glEnableClientState(GL_NORMAL_ARRAY);
643 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
647 glDisableClientState(GL_NORMAL_ARRAY);
648 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
650 checkGLcall("glNormal3f(0, 0, 1)");
653 /* Point Size ----------------------------------------------*/
654 if (sd->u.s.pSize.lpData != NULL) {
656 /* no such functionality in the fixed function GL pipeline */
657 /* FIXME: Wont get here as will drop to slow method */
658 FIXME("Cannot change ptSize here in openGl\n");
661 /* Diffuse Colour ------------------------------------------*/
662 /* WARNING: Data here MUST be in RGBA format, so cannot */
663 /* go directly into fast mode from app pgm, because */
664 /* directx requires data in BGRA format. */
665 if (sd->u.s.diffuse.lpData != NULL) {
667 /* Note dwType == float3 or float4 == 2 or 3 */
668 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
669 sd->u.s.diffuse.dwStride,
670 sd->u.s.diffuse.lpData));
671 glColorPointer(4, GL_UNSIGNED_BYTE,
672 sd->u.s.diffuse.dwStride,
673 sd->u.s.diffuse.lpData);
674 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
675 glEnableClientState(GL_COLOR_ARRAY);
676 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
680 glDisableClientState(GL_COLOR_ARRAY);
681 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
684 /* Specular Colour ------------------------------------------*/
685 if (sd->u.s.specular.lpData != NULL) {
687 /* Note dwType == float3 or float4 == 2 or 3 */
688 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
689 sd->u.s.specular.dwStride,
690 sd->u.s.specular.lpData));
692 #if defined(GL_VERSION_1_4)
693 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE,
694 sd->u.s.specular.dwStride,
695 sd->u.s.specular.lpData);
696 vcheckGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, ...)");
697 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
698 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
699 #elif defined(GL_EXT_secondary_color)
700 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
701 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
702 sd->u.s.specular.dwStride,
703 sd->u.s.specular.lpData);
704 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
705 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
706 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
709 /* Missing specular color is not critical, no warnings */
710 VTRACE(("Specular colour is not supported in this GL implementation\n"));
715 #if defined(GL_VERSION_1_4)
716 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
717 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
718 glSecondaryColor3f(0, 0, 0);
719 checkGLcall("glSecondaryColor3f(0, 0, 0)");
720 #elif defined(GL_EXT_secondary_color)
721 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
722 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
723 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
724 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
725 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
728 /* Do not worry if specular colour missing and disable request */
732 /* Texture coords -------------------------------------------*/
733 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
735 /* Select the correct texture stage */
736 #if defined(GL_VERSION_1_3)
737 glClientActiveTexture(GL_TEXTURE0 + textureNo);
739 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
742 /* Query tex coords */
743 if (This->StateBlock->textures[textureNo] != NULL) {
744 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
746 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
747 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
748 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
749 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
754 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
755 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
756 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
757 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
758 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
759 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
760 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
763 /* The coords to supply depend completely on the fvf / vertex shader */
767 switch (sd->u.s.texCoords[coordIdx].dwType) {
768 case D3DVSDT_FLOAT1: size = 1, type = GL_FLOAT; break;
769 case D3DVSDT_FLOAT2: size = 2, type = GL_FLOAT; break;
770 case D3DVSDT_FLOAT3: size = 3, type = GL_FLOAT; break;
771 case D3DVSDT_FLOAT4: size = 4, type = GL_FLOAT; break;
772 case D3DVSDT_SHORT2: size = 2, type = GL_SHORT; break;
773 case D3DVSDT_SHORT4: size = 4, type = GL_SHORT; break;
774 case D3DVSDT_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
775 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
776 size = 4; type = GL_UNSIGNED_BYTE;
779 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
780 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
783 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
784 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
788 /* Ok, Work out which primitive is requested and how many vertexes that
790 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
792 /* Finally do the drawing */
793 if (idxData != NULL) {
795 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
796 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
797 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
798 (char *)idxData+(idxSize * startIdx));
800 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
801 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
802 (char *)idxData+(idxSize * startIdx));
804 checkGLcall("glDrawRangeElements");
808 /* Note first is now zero as we shuffled along earlier */
809 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
810 glDrawArrays(glPrimType, 0, NumVertexes);
811 checkGLcall("glDrawArrays");
817 * Actually draw using the supplied information.
818 * Slower GL version which extracts info about each vertex in turn
820 void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
821 int PrimitiveType, ULONG NumPrimitives,
822 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
825 GLenum glPrimType = GL_POINTS;
826 int NumVertexes = NumPrimitives;
827 const short *pIdxBufS = NULL;
828 const long *pIdxBufL = NULL;
829 LONG SkipnStrides = 0;
831 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
832 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
833 float rhw = 0.0f; /* rhw */
834 float ptSize = 0.0f; /* Point size */
835 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
836 DWORD specularColor = 0; /* Specular Color */
837 ICOM_THIS(IDirect3DDevice8Impl,iface);
839 TRACE("Using slow vertex array code\n");
841 /* Variable Initialization */
842 if (idxData != NULL) {
843 if (idxSize == 2) pIdxBufS = (short *) idxData;
844 else pIdxBufL = (long *) idxData;
847 /* Ok, Work out which primitive is requested and how many vertexes that will be */
848 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
850 /* Start drawing in GL */
851 VTRACE(("glBegin(%x)\n", glPrimType));
854 /* For each primitive */
855 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
857 /* Initialize diffuse color */
858 diffuseColor = 0xFFFFFFFF;
860 /* For indexed data, we need to go a few more strides in */
861 if (idxData != NULL) {
863 /* Indexed so work out the number of strides to skip */
865 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
866 SkipnStrides = pIdxBufS[startIdx+vx_index];
868 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
869 SkipnStrides = pIdxBufL[startIdx+vx_index];
873 /* Position Information ------------------ */
874 if (sd->u.s.position.lpData != NULL) {
876 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
881 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
883 /* RHW follows, only if transformed, ie 4 floats were provided */
884 if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
885 rhw = ptrToCoords[3];
886 VTRACE(("rhw=%f\n", rhw));
890 /* Blending data -------------------------- */
891 if (sd->u.s.blendWeights.lpData != NULL) {
892 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
893 FIXME("Blending not supported yet\n");
895 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
896 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
900 /* Vertex Normal Data (untransformed only)- */
901 if (sd->u.s.normal.lpData != NULL) {
903 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
907 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
910 /* Point Size ----------------------------- */
911 if (sd->u.s.pSize.lpData != NULL) {
913 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
914 ptSize = ptrToCoords[0];
915 VTRACE(("ptSize=%f\n", ptSize));
916 FIXME("No support for ptSize yet\n");
919 /* Diffuse -------------------------------- */
920 if (sd->u.s.diffuse.lpData != NULL) {
922 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
923 diffuseColor = ptrToCoords[0];
924 VTRACE(("diffuseColor=%lx\n", diffuseColor));
927 /* Specular -------------------------------- */
928 if (sd->u.s.specular.lpData != NULL) {
930 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
931 specularColor = ptrToCoords[0];
932 VTRACE(("specularColor=%lx\n", specularColor));
935 /* Texture coords --------------------------- */
936 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
938 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
939 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
943 /* Query tex coords */
944 if (This->StateBlock->textures[textureNo] != NULL) {
946 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
947 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
948 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
951 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
953 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
954 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
958 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
960 /* The coords to supply depend completely on the fvf / vertex shader */
961 switch (coordsToUse) {
962 case 4: q = ptrToCoords[3]; /* drop through */
963 case 3: r = ptrToCoords[2]; /* drop through */
964 case 2: t = ptrToCoords[1]; /* drop through */
965 case 1: s = ptrToCoords[0];
968 /* Projected is more 'fun' - Move the last coord to the 'q'
969 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
970 if ((This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
971 (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
973 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
974 switch (coordsToUse) {
975 case 0: /* Drop Through */
977 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
989 case 4: /* Nop here */
992 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
993 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
998 switch (coordsToUse) { /* Supply the provided texture coords */
1000 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1001 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1002 #if defined(GL_VERSION_1_3)
1003 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1005 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1011 case D3DTTFF_COUNT2:
1012 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1013 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1014 #if defined(GL_VERSION_1_3)
1015 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1017 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1023 case D3DTTFF_COUNT3:
1024 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1025 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1026 #if defined(GL_VERSION_1_3)
1027 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1029 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1032 glTexCoord3f(s, t, r);
1035 case D3DTTFF_COUNT4:
1036 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1037 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1038 #if defined(GL_VERSION_1_3)
1039 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1041 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1044 glTexCoord4f(s, t, r, q);
1048 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1052 } /* End of textures */
1054 /* Diffuse -------------------------------- */
1055 if (sd->u.s.diffuse.lpData != NULL) {
1056 glColor4ub((diffuseColor >> 16) & 0xFF,
1057 (diffuseColor >> 8) & 0xFF,
1058 (diffuseColor >> 0) & 0xFF,
1059 (diffuseColor >> 24) & 0xFF);
1060 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1061 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1062 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1063 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1064 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1067 /* Normal -------------------------------- */
1068 if (sd->u.s.normal.lpData != NULL) {
1069 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1070 glNormal3f(nx, ny, nz);
1073 /* Position -------------------------------- */
1074 if (sd->u.s.position.lpData != NULL) {
1075 if (1.0f == rhw || rhw < 0.01f) {
1076 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1077 glVertex3f(x, y, z);
1079 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1080 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
1084 /* For non indexed mode, step onto next parts */
1085 if (idxData == NULL) {
1091 checkGLcall("glEnd and previous calls");
1095 * Draw with emulated vertex shaders
1096 * Note: strided data is uninitialized, as we need to pass the vertex
1097 * shader directly as ordering irs yet
1099 void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
1100 int PrimitiveType, ULONG NumPrimitives,
1101 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1104 GLenum glPrimType = GL_POINTS;
1105 int NumVertexes = NumPrimitives;
1106 const short *pIdxBufS = NULL;
1107 const long *pIdxBufL = NULL;
1108 LONG SkipnStrides = 0;
1110 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1111 float rhw = 0.0f; /* rhw */
1112 float ptSize = 0.0f; /* Point size */
1113 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1114 int numcoords[8]; /* Number of coords */
1115 ICOM_THIS(IDirect3DDevice8Impl,iface);
1117 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1119 TRACE("Using slow software vertex shader code\n");
1121 /* Variable Initialization */
1122 if (idxData != NULL) {
1123 if (idxSize == 2) pIdxBufS = (short *) idxData;
1124 else pIdxBufL = (long *) idxData;
1127 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1128 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1130 /* Retrieve the VS information */
1131 vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1133 /* Start drawing in GL */
1134 VTRACE(("glBegin(%x)\n", glPrimType));
1135 glBegin(glPrimType);
1137 /* For each primitive */
1138 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1140 /* For indexed data, we need to go a few more strides in */
1141 if (idxData != NULL) {
1143 /* Indexed so work out the number of strides to skip */
1145 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1146 SkipnStrides = pIdxBufS[startIdx+vx_index];
1148 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1149 SkipnStrides = pIdxBufL[startIdx+vx_index];
1153 /* Fill the vertex shader input */
1154 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, SkipnStrides);
1156 /* Now execute the vertex shader */
1157 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1158 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1161 TRACE_VECTOR(vertex_shader->output.oPos);
1162 TRACE_VECTOR(vertex_shader->output.oD[0]);
1163 TRACE_VECTOR(vertex_shader->output.oD[1]);
1164 TRACE_VECTOR(vertex_shader->output.oT[0]);
1165 TRACE_VECTOR(vertex_shader->output.oT[1]);
1166 TRACE_VECTOR(vertex_shader->input.V[0]);
1167 TRACE_VECTOR(vertex_shader->data->C[0]);
1168 TRACE_VECTOR(vertex_shader->data->C[1]);
1169 TRACE_VECTOR(vertex_shader->data->C[2]);
1170 TRACE_VECTOR(vertex_shader->data->C[3]);
1171 TRACE_VECTOR(vertex_shader->data->C[4]);
1172 TRACE_VECTOR(vertex_shader->data->C[5]);
1173 TRACE_VECTOR(vertex_shader->data->C[6]);
1174 TRACE_VECTOR(vertex_shader->data->C[7]);
1177 /* Extract out the output */
1178 /*FIXME: Fog coords? */
1179 x = vertex_shader->output.oPos.x;
1180 y = vertex_shader->output.oPos.y;
1181 z = vertex_shader->output.oPos.z;
1182 rhw = vertex_shader->output.oPos.w;
1183 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1185 /** Update textures coords using vertex_shader->output.oT[0->7] */
1186 memset(texcoords, 0x00, sizeof(texcoords));
1187 memset(numcoords, 0x00, sizeof(numcoords));
1188 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1189 if (This->StateBlock->textures[textureNo] != NULL) {
1190 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1191 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1192 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1193 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1194 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1195 numcoords[textureNo] = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1197 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
1198 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1199 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1200 default: numcoords[textureNo] = 4;
1204 numcoords[textureNo] = 0;
1208 /* Draw using this information */
1211 FALSE, 0.0f, 0.0f, 0.0f,
1212 TRUE, (float*) &vertex_shader->output.oD[0],
1213 TRUE, (float*) &vertex_shader->output.oD[1],
1214 FALSE, ptSize, /* FIXME: Change back when supported */
1215 texcoords, numcoords);
1217 /* For non indexed mode, step onto next parts */
1218 if (idxData == NULL) {
1222 } /* for each vertex */
1225 checkGLcall("glEnd and previous calls");
1228 /* Routine common to the draw primitive and draw indexed primitive routines */
1229 void drawPrimitive(LPDIRECT3DDEVICE8 iface,
1230 int PrimitiveType, long NumPrimitives,
1233 long StartVertexIndex,
1236 const void *idxData,
1241 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1242 BOOL useVertexShaderFunction = FALSE;
1243 BOOL isLightingOn = FALSE;
1244 Direct3DVertexStridedData dataLocations;
1245 ICOM_THIS(IDirect3DDevice8Impl,iface);
1248 /* Work out what the FVF should look like */
1249 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1252 /* If we will be using a vertex shader, do some initialization for it */
1253 if (useVertexShaderFunction == TRUE) {
1254 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
1255 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1257 /** init Constants */
1258 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
1259 TRACE_(d3d_shader)("vertex shader init Constant\n");
1260 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
1264 /* Ok, we will be updating the screen from here onwards so grab the lock */
1267 /* Setup transform matrices and sort out */
1268 isLightingOn = primitiveInitState(iface,
1269 fvf & D3DFVF_XYZRHW,
1270 !(fvf & D3DFVF_NORMAL));
1272 /* Initialize all values to null */
1273 if (useVertexShaderFunction == FALSE) {
1274 memset(&dataLocations, 0x00, sizeof(dataLocations));
1276 /* Convert to strided data */
1277 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1279 /* Dump out what parts we have supplied */
1280 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1281 TRACE_STRIDED((&dataLocations), position);
1282 TRACE_STRIDED((&dataLocations), blendWeights);
1283 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1284 TRACE_STRIDED((&dataLocations), normal);
1285 TRACE_STRIDED((&dataLocations), pSize);
1286 TRACE_STRIDED((&dataLocations), diffuse);
1287 TRACE_STRIDED((&dataLocations), specular);
1288 TRACE_STRIDED((&dataLocations), texCoords[0]);
1289 TRACE_STRIDED((&dataLocations), texCoords[1]);
1290 TRACE_STRIDED((&dataLocations), texCoords[2]);
1291 TRACE_STRIDED((&dataLocations), texCoords[3]);
1292 TRACE_STRIDED((&dataLocations), texCoords[4]);
1293 TRACE_STRIDED((&dataLocations), texCoords[5]);
1294 TRACE_STRIDED((&dataLocations), texCoords[6]);
1295 TRACE_STRIDED((&dataLocations), texCoords[7]);
1298 /* Now draw the graphics to the screen */
1299 if (useVertexShaderFunction == TRUE) {
1301 /* Ideally, we should have software FV and hardware VS, possibly
1302 depending on the device type? */
1304 /* We will have to use the very, very slow emulation layer */
1305 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1306 idxData, idxSize, minIndex, StartIdx);
1308 } else if ((dataLocations.u.s.pSize.lpData != NULL) ||
1309 (dataLocations.u.s.diffuse.lpData != NULL) ||
1310 (dataLocations.u.s.blendWeights.lpData != NULL)) {
1312 /* Fixme, Ideally, only use the per-vertex code for software HAL
1313 but until opengl supports all the functions returned to setup
1314 vertex arrays, we need to drop down to the slow mechanism for
1315 certain functions */
1317 /* We will have to use the slow version of GL per vertex setup */
1318 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1319 idxData, idxSize, minIndex, StartIdx);
1323 /* We can use the fast version of GL pointers */
1324 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1325 idxData, idxSize, minIndex, StartIdx);
1328 /* If no normals, restore previous lighting state */
1329 if (!(fvf & D3DFVF_NORMAL)) {
1330 if (isLightingOn) glEnable(GL_LIGHTING);
1331 else glDisable(GL_LIGHTING);
1332 TRACE("Restored lighting to original state\n");
1335 /* Finshed updating the screen, restore lock */
1337 TRACE("Done all gl drawing\n");
1340 #if defined(SHOW_FRAME_MAKEUP)
1342 if (isDumpingFrames == TRUE) {
1345 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->backBuffer, &r, NULL, D3DLOCK_READONLY);
1346 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1347 TRACE("Saving screenshot %s\n", buffer);
1348 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
1349 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
1351 #if defined(SHOW_TEXTURE_MAKEUP)
1353 LPDIRECT3DSURFACE8 pSur;
1355 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1356 if (This->StateBlock->textures[textureNo] != NULL) {
1357 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1358 TRACE("Saving texture %s\n", buffer);
1359 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->StateBlock->textures[textureNo], 0, &pSur);
1360 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1365 primCounter = primCounter + 1;