2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
28 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
31 extern IDirect3DVertexShaderImpl* VertexShaders[64];
32 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
33 extern IDirect3DPixelShaderImpl* PixelShaders[64];
35 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
38 /* Useful internal structure, holding place for 4 floats */
39 typedef struct _D3DVECTOR_4 {
47 /* Returns bits for what is expected from the fixed function pipeline, and whether
48 a vertex shader will be in use. Note the fvf bits returned may be split over
49 multiple streams only if the vertex shader was created, otherwise it all relates
51 BOOL initializeFVF(IWineD3DDevice *iface,
52 DWORD *FVFbits, /* What to expect in the FVF across all streams */
53 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
56 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
58 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
59 /* The first thing to work out is if we are using the fixed function pipeline
60 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
61 is the FVF, or with a shader which was created with no function - in which
62 case there is an FVF per declared stream. If this occurs, we also maintain
63 an 'OR' of all the FVF's together so we know what to expect across all the
67 if (This->updateStateBlock->vertexShader == NULL) {
69 /* Use this as the FVF */
70 *FVFbits = This->updateStateBlock->fvf;
71 *useVertexShaderFunction = FALSE;
72 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
77 /* Use created shader */
78 IDirect3DVertexShaderImpl* vertex_shader = NULL;
79 vertex_shader = VERTEX_SHADER(This->updateStateBlock->VertexShader);
81 if (vertex_shader == NULL) {
83 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
84 ERR("trying to use unitialised vertex shader: %lu\n", This->updateStateBlock->VertexShader);
89 *FVFbits = This->updateStateBlock->vertexShaderDecl->allFVF;
91 if (vertex_shader->function == NULL) {
92 /* No function, so many streams supplied plus FVF definition pre stream */
93 *useVertexShaderFunction = FALSE;
94 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
95 This->stateBlock->VertexShader, *FVFbits);
97 /* Vertex shader needs calling */
98 *useVertexShaderFunction = TRUE;
99 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
103 FIXME("Vertex Shaders not moved into wined3d yet\n");
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 /* Ensure the appropriate material states are set up - only change
162 state if really required */
163 void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
165 BOOL requires_material_reset = FALSE;
166 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
168 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
169 /* If we have not set up the material color tracking, do it now as required */
170 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
171 checkGLcall("glDisable GL_COLOR_MATERIAL");
172 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
173 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
174 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
175 glEnable(GL_COLOR_MATERIAL);
176 checkGLcall("glEnable GL_COLOR_MATERIAL");
177 This->tracking_color = IS_TRACKING;
178 requires_material_reset = TRUE; /* Restore material settings as will be used */
180 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
181 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
182 /* If we are tracking the current color but one isn't supplied, don't! */
183 glDisable(GL_COLOR_MATERIAL);
184 checkGLcall("glDisable GL_COLOR_MATERIAL");
185 This->tracking_color = NEEDS_TRACKING;
186 requires_material_reset = TRUE; /* Restore material settings as will be used */
188 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
189 /* No need to reset material colors since no change to gl_color_material */
190 requires_material_reset = FALSE;
192 } else if (This->tracking_color == NEEDS_DISABLE) {
193 glDisable(GL_COLOR_MATERIAL);
194 checkGLcall("glDisable GL_COLOR_MATERIAL");
195 This->tracking_color = DISABLED_TRACKING;
196 requires_material_reset = TRUE; /* Restore material settings as will be used */
199 /* Reset the material colors which may have been tracking the color*/
200 if (requires_material_reset) {
201 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
202 checkGLcall("glMaterialfv");
203 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
204 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");
213 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
214 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
215 checkGLcall("glMaterialfv");
217 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
218 checkGLcall("glMaterialfv");
223 static GLfloat invymat[16]={
224 1.0f, 0.0f, 0.0f, 0.0f,
225 0.0f, -1.0f, 0.0f, 0.0f,
226 0.0f, 0.0f, 1.0f, 0.0f,
227 0.0f, 0.0f, 0.0f, 1.0f};
229 /* Setup views - Transformed & lit if RHW, else untransformed.
230 Only unlit if Normals are supplied
231 Returns: Whether to restore lighting afterwards */
232 BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
234 BOOL isLightingOn = FALSE;
235 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
237 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
238 set by the appropriate render state. Note Vertex Shader output is already lit */
239 if (vtx_lit || useVS) {
240 isLightingOn = glIsEnabled(GL_LIGHTING);
241 glDisable(GL_LIGHTING);
242 checkGLcall("glDisable(GL_LIGHTING);");
243 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
246 if (!useVS && vtx_transformed) {
248 /* If the last draw was transformed as well, no need to reapply all the matrixes */
249 if (!This->last_was_rhw) {
251 double X, Y, height, width, minZ, maxZ;
252 This->last_was_rhw = TRUE;
254 /* Transformed already into viewport coordinates, so we do not need transform
255 matrices. Reset all matrices to identity and leave the default matrix in world
257 glMatrixMode(GL_MODELVIEW);
258 checkGLcall("glMatrixMode");
260 checkGLcall("glLoadIdentity");
262 glMatrixMode(GL_PROJECTION);
263 checkGLcall("glMatrixMode");
265 checkGLcall("glLoadIdentity");
267 /* Set up the viewport to be full viewport */
268 X = This->stateBlock->viewport.X;
269 Y = This->stateBlock->viewport.Y;
270 height = This->stateBlock->viewport.Height;
271 width = This->stateBlock->viewport.Width;
272 minZ = This->stateBlock->viewport.MinZ;
273 maxZ = This->stateBlock->viewport.MaxZ;
274 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
275 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
276 checkGLcall("glOrtho");
278 /* Window Coord 0 is the middle of the first pixel, so translate by half
279 a pixel (See comment above glTranslate below) */
280 glTranslatef(0.5, 0.5, 0);
281 checkGLcall("glTranslatef(0.5, 0.5, 0)");
282 if (This->renderUpsideDown) {
283 glMultMatrixf(invymat);
284 checkGLcall("glMultMatrixf(invymat)");
290 /* Untransformed, so relies on the view and projection matrices */
292 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
293 /* Only reapply when have to */
294 This->modelview_valid = TRUE;
295 glMatrixMode(GL_MODELVIEW);
296 checkGLcall("glMatrixMode");
298 /* In the general case, the view matrix is the identity matrix */
299 if (This->view_ident) {
300 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
301 checkGLcall("glLoadMatrixf");
303 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
304 checkGLcall("glLoadMatrixf");
305 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
306 checkGLcall("glMultMatrixf");
310 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
311 /* Only reapply when have to */
312 This->proj_valid = TRUE;
313 glMatrixMode(GL_PROJECTION);
314 checkGLcall("glMatrixMode");
316 /* The rule is that the window coordinate 0 does not correspond to the
317 beginning of the first pixel, but the center of the first pixel.
318 As a consequence if you want to correctly draw one line exactly from
319 the left to the right end of the viewport (with all matrices set to
320 be identity), the x coords of both ends of the line would be not
321 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
324 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
325 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
327 if (This->renderUpsideDown) {
328 glMultMatrixf(invymat);
329 checkGLcall("glMultMatrixf(invymat)");
331 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
332 checkGLcall("glLoadMatrixf");
335 /* Vertex Shader output is already transformed, so set up identity matrices */
336 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
337 come along this needs to take into account whether s/w ones were
340 glMatrixMode(GL_MODELVIEW);
341 checkGLcall("glMatrixMode");
343 glMatrixMode(GL_PROJECTION);
344 checkGLcall("glMatrixMode");
346 /* Window Coord 0 is the middle of the first pixel, so translate by half
347 a pixel (See comment above glTranslate above) */
348 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
349 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
350 if (This->renderUpsideDown) {
351 glMultMatrixf(invymat);
352 checkGLcall("glMultMatrixf(invymat)");
354 This->modelview_valid = FALSE;
355 This->proj_valid = FALSE;
357 This->last_was_rhw = FALSE;
362 void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
364 short LoopThroughTo = 0;
366 BOOL canDoViaGLPointers = TRUE;
370 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
371 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
375 /* OK, Now to setup the data locations
376 For the non-created vertex shaders, the VertexShader var holds the real
377 FVF and only stream 0 matters
378 For the created vertex shaders, there is an FVF per stream */
379 if (!This->stateBlock->streamIsUP && (This->updateStateBlock->vertexShader == NULL)) {
380 LoopThroughTo = MAX_STREAMS;
385 /* Work through stream by stream */
386 for (nStream=0; nStream<LoopThroughTo; nStream++) {
387 DWORD stride = This->stateBlock->stream_stride[nStream];
391 /* Skip empty streams */
392 if (This->stateBlock->stream_source[nStream] == NULL) continue;
394 /* Retrieve appropriate FVF */
395 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
396 thisFVF = This->updateStateBlock->fvf;
397 /* Handle memory passed directly as well as vertex buffers */
398 if (This->stateBlock->streamIsUP) {
399 data = (BYTE *)This->stateBlock->stream_source[nStream];
401 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->stream_source[nStream])->allocatedMemory;
404 #if 0 /* TODO: Vertex shader support */
405 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
406 data = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->stream_source[nStream])->allocatedMemory;
409 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
410 if (thisFVF == 0) continue;
412 /* Now convert the stream into pointers */
414 /* Shuffle to the beginning of the vertexes to render and index from there */
415 data = data + (BaseVertexIndex * stride);
417 /* Either 3 or 4 floats depending on the FVF */
418 /* FIXME: Can blending data be in a different stream to the position data?
419 and if so using the fixed pipeline how do we handle it */
420 if (thisFVF & D3DFVF_POSITION_MASK) {
421 strided->u.s.position.lpData = data;
422 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
423 strided->u.s.position.dwStride = stride;
424 data += 3 * sizeof(float);
425 if (thisFVF & D3DFVF_XYZRHW) {
426 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
427 data += sizeof(float);
431 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
432 /** do we have to Check This->updateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
433 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
434 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
436 canDoViaGLPointers = FALSE;
437 strided->u.s.blendWeights.lpData = data;
438 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + (numBlends - 1);
439 strided->u.s.blendWeights.dwStride = stride;
440 data += numBlends * sizeof(FLOAT);
442 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
443 strided->u.s.blendMatrixIndices.lpData = data;
444 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
445 strided->u.s.blendMatrixIndices.dwStride= stride;
446 data += sizeof(DWORD);
450 /* Normal is always 3 floats */
451 if (thisFVF & D3DFVF_NORMAL) {
452 strided->u.s.normal.lpData = data;
453 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
454 strided->u.s.normal.dwStride = stride;
455 data += 3 * sizeof(FLOAT);
458 /* Pointsize is a single float */
459 if (thisFVF & D3DFVF_PSIZE) {
460 strided->u.s.pSize.lpData = data;
461 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
462 strided->u.s.pSize.dwStride = stride;
463 data += sizeof(FLOAT);
466 /* Diffuse is 4 unsigned bytes */
467 if (thisFVF & D3DFVF_DIFFUSE) {
468 strided->u.s.diffuse.lpData = data;
469 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
470 strided->u.s.diffuse.dwStride = stride;
471 data += sizeof(DWORD);
474 /* Specular is 4 unsigned bytes */
475 if (thisFVF & D3DFVF_SPECULAR) {
476 strided->u.s.specular.lpData = data;
477 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
478 strided->u.s.specular.dwStride = stride;
479 data += sizeof(DWORD);
483 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
484 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
486 /* numTextures indicates the number of texture coordinates supplied */
487 /* However, the first set may not be for stage 0 texture - it all */
488 /* depends on D3DTSS_TEXCOORDINDEX. */
489 /* The number of bytes for each coordinate set is based off */
490 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
492 /* So, for each supplied texture extract the coords */
493 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
495 strided->u.s.texCoords[textureNo].lpData = data;
496 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
497 strided->u.s.texCoords[textureNo].dwStride = stride;
498 numCoords[textureNo] = coordIdxInfo & 0x03;
501 data += sizeof(float);
502 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
503 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
504 data += sizeof(float);
505 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
506 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
507 data += sizeof(float);
508 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
509 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
510 data += sizeof(float);
514 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
519 /* Draw a single vertex using this information */
520 void draw_vertex(IWineD3DDevice *iface, /* interface */
521 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
522 BOOL isNormal, float nx, float ny, float nz, /* normal */
523 BOOL isDiffuse, float *dRGBA, /* 1st colors */
524 BOOL isSpecular, float *sRGB, /* 2ndry colors */
525 BOOL isPtSize, float ptSize, /* pointSize */
526 D3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
528 #if 0 /* TODO: Texture support */
529 unsigned int textureNo;
532 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
534 /* Diffuse -------------------------------- */
537 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
540 /* Specular Colour ------------------------------------------*/
542 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
543 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
544 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
546 VTRACE(("Specular color extensions not supplied\n"));
550 /* Normal -------------------------------- */
552 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
553 glNormal3f(nx, ny, nz);
556 /* Point Size ----------------------------------------------*/
559 /* no such functionality in the fixed function GL pipeline */
560 FIXME("Cannot change ptSize here in openGl\n");
563 /* Texture coords --------------------------- */
564 #if 0 /* TODO: Texture support */
565 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
567 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
568 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
572 /* Query tex coords */
573 if (This->stateBlock->textures[textureNo] != NULL) {
575 int coordIdx = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
577 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
579 } else if (numcoords[coordIdx] == 0) {
580 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
584 /* Initialize vars */
590 switch (numcoords[coordIdx]) {
591 case 4: q = texcoords[coordIdx].w; /* drop through */
592 case 3: r = texcoords[coordIdx].z; /* drop through */
593 case 2: t = texcoords[coordIdx].y; /* drop through */
594 case 1: s = texcoords[coordIdx].x;
597 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
599 VTRACE(("tex:%d, s=%f\n", textureNo, s));
600 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
601 #if defined(GL_VERSION_1_3)
602 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
604 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
611 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
612 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
613 #if defined(GL_VERSION_1_3)
614 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
616 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
623 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
624 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
625 #if defined(GL_VERSION_1_3)
626 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
628 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
631 glTexCoord3f(s, t, r);
635 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
636 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
637 #if defined(GL_VERSION_1_3)
638 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
640 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
643 glTexCoord4f(s, t, r, q);
647 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
651 } /* End of textures */
654 /* Position -------------------------------- */
656 if (1.0f == rhw || rhw < 0.00001f) {
657 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
660 /* Cannot optimize by dividing through by rhw as rhw is required
661 later for perspective in the GL pipeline for vertex shaders */
662 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
663 glVertex4f(x,y,z,rhw);
669 * Actually draw using the supplied information.
670 * Faster GL version using pointers to data, harder to debug though
671 * Note does not handle vertex shaders yet
673 void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
674 int PrimitiveType, ULONG NumPrimitives,
675 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
676 #if 0 /* TODO: Texture support */
677 unsigned int textureNo = 0;
679 GLenum glPrimType = GL_POINTS;
680 int NumVertexes = NumPrimitives;
681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
683 TRACE("Using fast vertex array code\n");
685 /* Vertex Pointers -----------------------------------------*/
686 if (sd->u.s.position.lpData != NULL) {
688 /* Note dwType == float3 or float4 == 2 or 3 */
689 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
690 sd->u.s.position.dwStride,
691 sd->u.s.position.dwType + 1,
692 sd->u.s.position.lpData));
694 /* Disable RHW mode as 'w' coord handling for rhw mode should
695 not impact screen position whereas in GL it does. This may
696 result in very slightly distored textures in rhw mode, but
697 a very minimal different */
698 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
699 sd->u.s.position.dwStride,
700 sd->u.s.position.lpData);
701 checkGLcall("glVertexPointer(...)");
702 glEnableClientState(GL_VERTEX_ARRAY);
703 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
707 glDisableClientState(GL_VERTEX_ARRAY);
708 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
711 /* Blend Data ----------------------------------------------*/
712 if ((sd->u.s.blendWeights.lpData != NULL) ||
713 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
714 /* FIXME: Won't get here as will drop to slow method */
715 FIXME("Blending not supported in fast draw routine\n");
717 #if 0 /* Vertex blend support needs to be added */
718 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
720 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
723 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
724 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
725 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
726 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
729 FIXME("unsupported blending in openGl\n");
732 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
734 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
737 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
738 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
744 /* Normals -------------------------------------------------*/
745 if (sd->u.s.normal.lpData != NULL) {
747 /* Note dwType == float3 or float4 == 2 or 3 */
748 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
749 sd->u.s.normal.dwStride,
750 sd->u.s.normal.lpData));
751 glNormalPointer(GL_FLOAT,
752 sd->u.s.normal.dwStride,
753 sd->u.s.normal.lpData);
754 checkGLcall("glNormalPointer(...)");
755 glEnableClientState(GL_NORMAL_ARRAY);
756 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
760 glDisableClientState(GL_NORMAL_ARRAY);
761 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
763 checkGLcall("glNormal3f(0, 0, 1)");
766 /* Point Size ----------------------------------------------*/
767 if (sd->u.s.pSize.lpData != NULL) {
769 /* no such functionality in the fixed function GL pipeline */
770 /* FIXME: Won't get here as will drop to slow method */
771 FIXME("Cannot change ptSize here in openGl\n");
774 /* Diffuse Colour ------------------------------------------*/
775 /* WARNING: Data here MUST be in RGBA format, so cannot */
776 /* go directly into fast mode from app pgm, because */
777 /* directx requires data in BGRA format. */
778 if (sd->u.s.diffuse.lpData != NULL) {
780 /* Note dwType == float3 or float4 == 2 or 3 */
781 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
782 sd->u.s.diffuse.dwStride,
783 sd->u.s.diffuse.lpData));
784 glColorPointer(4, GL_UNSIGNED_BYTE,
785 sd->u.s.diffuse.dwStride,
786 sd->u.s.diffuse.lpData);
787 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
788 glEnableClientState(GL_COLOR_ARRAY);
789 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
793 glDisableClientState(GL_COLOR_ARRAY);
794 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
795 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
796 checkGLcall("glColor4f(1, 1, 1, 1)");
799 /* Specular Colour ------------------------------------------*/
800 if (sd->u.s.specular.lpData != NULL) {
802 /* Note dwType == float3 or float4 == 2 or 3 */
803 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
804 sd->u.s.specular.dwStride,
805 sd->u.s.specular.lpData));
807 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
808 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
809 sd->u.s.specular.dwStride,
810 sd->u.s.specular.lpData);
811 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
812 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
813 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
815 /* Missing specular color is not critical, no warnings */
816 VTRACE(("Specular colour is not supported in this GL implementation\n"));
821 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
822 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
823 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
824 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
825 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
827 /* Missing specular color is not critical, no warnings */
828 VTRACE(("Specular colour is not supported in this GL implementation\n"));
832 /* Texture coords -------------------------------------------*/
833 #if 0 /* TODO: Texture support */
834 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
836 /* Select the correct texture stage */
837 #if defined(GL_VERSION_1_3)
838 glClientActiveTexture(GL_TEXTURE0 + textureNo);
840 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
843 /* Query tex coords */
844 if (This->stateBlock->textures[textureNo] != NULL) {
845 int coordIdx = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
847 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
848 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
849 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
850 #if defined(GL_VERSION_1_3)
851 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
853 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
859 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
860 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
861 #if defined(GL_VERSION_1_3)
862 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
864 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
866 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
867 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
868 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
869 #if defined(GL_VERSION_1_3)
870 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
872 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
876 /* The coords to supply depend completely on the fvf / vertex shader */
880 switch (sd->u.s.texCoords[coordIdx].dwType) {
881 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
882 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
883 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
884 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
885 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
886 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
887 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
888 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
889 size = 4; type = GL_UNSIGNED_BYTE;
892 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
893 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
896 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
897 #if defined(GL_VERSION_1_3)
898 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
900 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
904 #endif /* TODO: Texture support */
906 /* Ok, Work out which primitive is requested and how many vertexes that
908 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
910 /* Finally do the drawing */
911 if (idxData != NULL) {
913 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
914 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
915 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
916 (const char *)idxData+(idxSize * startIdx));
918 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
919 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
920 (const char *)idxData+(idxSize * startIdx));
922 checkGLcall("glDrawRangeElements");
926 /* Note first is now zero as we shuffled along earlier */
927 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
928 glDrawArrays(glPrimType, 0, NumVertexes);
929 checkGLcall("glDrawArrays");
935 * Actually draw using the supplied information.
936 * Slower GL version which extracts info about each vertex in turn
938 void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
939 int PrimitiveType, ULONG NumPrimitives,
940 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
942 #if 0 /* TODO: Texture support */
943 unsigned int textureNo = 0;
945 GLenum glPrimType = GL_POINTS;
946 int NumVertexes = NumPrimitives;
947 const short *pIdxBufS = NULL;
948 const long *pIdxBufL = NULL;
949 LONG SkipnStrides = 0;
951 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
952 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
953 float rhw = 0.0f; /* rhw */
954 float ptSize = 0.0f; /* Point size */
955 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
956 DWORD specularColor = 0; /* Specular Color */
957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
959 TRACE("Using slow vertex array code\n");
961 /* Variable Initialization */
962 if (idxData != NULL) {
963 if (idxSize == 2) pIdxBufS = (const short *) idxData;
964 else pIdxBufL = (const long *) idxData;
967 /* Ok, Work out which primitive is requested and how many vertexes that will be */
968 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
970 /* Start drawing in GL */
971 VTRACE(("glBegin(%x)\n", glPrimType));
974 /* For each primitive */
975 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
977 /* Initialize diffuse color */
978 diffuseColor = 0xFFFFFFFF;
980 /* For indexed data, we need to go a few more strides in */
981 if (idxData != NULL) {
983 /* Indexed so work out the number of strides to skip */
985 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
986 SkipnStrides = pIdxBufS[startIdx+vx_index];
988 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
989 SkipnStrides = pIdxBufL[startIdx+vx_index];
993 /* Position Information ------------------ */
994 if (sd->u.s.position.lpData != NULL) {
996 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1001 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1003 /* RHW follows, only if transformed, ie 4 floats were provided */
1004 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1005 rhw = ptrToCoords[3];
1006 VTRACE(("rhw=%f\n", rhw));
1010 /* Blending data -------------------------- */
1011 if (sd->u.s.blendWeights.lpData != NULL) {
1012 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1013 FIXME("Blending not supported yet\n");
1015 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1016 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1020 /* Vertex Normal Data (untransformed only)- */
1021 if (sd->u.s.normal.lpData != NULL) {
1023 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1024 nx = ptrToCoords[0];
1025 ny = ptrToCoords[1];
1026 nz = ptrToCoords[2];
1027 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1030 /* Point Size ----------------------------- */
1031 if (sd->u.s.pSize.lpData != NULL) {
1033 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1034 ptSize = ptrToCoords[0];
1035 VTRACE(("ptSize=%f\n", ptSize));
1036 FIXME("No support for ptSize yet\n");
1039 /* Diffuse -------------------------------- */
1040 if (sd->u.s.diffuse.lpData != NULL) {
1042 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1043 diffuseColor = ptrToCoords[0];
1044 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1047 /* Specular -------------------------------- */
1048 if (sd->u.s.specular.lpData != NULL) {
1050 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1051 specularColor = ptrToCoords[0];
1052 VTRACE(("specularColor=%lx\n", specularColor));
1055 /* Texture coords --------------------------- */
1056 #if 0 /* TODO: Texture support */
1057 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1059 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1060 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1064 /* Query tex coords */
1065 if (This->stateBlock->textures[textureNo] != NULL) {
1067 int coordIdx = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1068 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1069 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1072 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1074 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1075 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1079 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1081 /* The coords to supply depend completely on the fvf / vertex shader */
1082 switch (coordsToUse) {
1083 case 4: q = ptrToCoords[3]; /* drop through */
1084 case 3: r = ptrToCoords[2]; /* drop through */
1085 case 2: t = ptrToCoords[1]; /* drop through */
1086 case 1: s = ptrToCoords[0];
1089 /* Projected is more 'fun' - Move the last coord to the 'q'
1090 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1091 if ((This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1092 (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1094 if (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1095 switch (coordsToUse) {
1096 case 0: /* Drop Through */
1098 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1110 case 4: /* Nop here */
1113 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1114 This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1119 switch (coordsToUse) { /* Supply the provided texture coords */
1120 case D3DTTFF_COUNT1:
1121 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1122 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1123 #if defined(GL_VERSION_1_3)
1124 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1126 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1132 case D3DTTFF_COUNT2:
1133 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1134 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1135 #if defined(GL_VERSION_1_3)
1136 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1138 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1144 case D3DTTFF_COUNT3:
1145 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1146 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1147 #if defined(GL_VERSION_1_3)
1148 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1150 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1153 glTexCoord3f(s, t, r);
1156 case D3DTTFF_COUNT4:
1157 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1158 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1159 #if defined(GL_VERSION_1_3)
1160 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1162 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1165 glTexCoord4f(s, t, r, q);
1169 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1173 } /* End of textures */
1174 #endif /* TODO: Texture support */
1176 /* Diffuse -------------------------------- */
1177 if (sd->u.s.diffuse.lpData != NULL) {
1178 glColor4ub((diffuseColor >> 16) & 0xFF,
1179 (diffuseColor >> 8) & 0xFF,
1180 (diffuseColor >> 0) & 0xFF,
1181 (diffuseColor >> 24) & 0xFF);
1182 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1183 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1184 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1185 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1186 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1188 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1191 /* Specular ------------------------------- */
1192 if (sd->u.s.diffuse.lpData != NULL) {
1193 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1194 ((specularColor >> 16) & 0xFF) / 255.0f,
1195 ((specularColor >> 8) & 0xFF) / 255.0f,
1196 ((specularColor >> 0) & 0xFF) / 255.0f));
1197 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1198 GL_EXTCALL(glSecondaryColor3ubEXT)(
1199 (specularColor >> 16) & 0xFF,
1200 (specularColor >> 8) & 0xFF,
1201 (specularColor >> 0) & 0xFF);
1203 /* Do not worry if specular colour missing and disable request */
1204 VTRACE(("Specular color extensions not supplied\n"));
1207 if (vx_index == 0) {
1208 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1209 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1211 /* Do not worry if specular colour missing and disable request */
1212 VTRACE(("Specular color extensions not supplied\n"));
1217 /* Normal -------------------------------- */
1218 if (sd->u.s.normal.lpData != NULL) {
1219 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1220 glNormal3f(nx, ny, nz);
1222 if (vx_index == 0) glNormal3f(0, 0, 1);
1225 /* Position -------------------------------- */
1226 if (sd->u.s.position.lpData != NULL) {
1227 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1228 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1229 glVertex3f(x, y, z);
1231 GLfloat w = 1.0 / rhw;
1232 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1233 glVertex4f(x*w, y*w, z*w, w);
1237 /* For non indexed mode, step onto next parts */
1238 if (idxData == NULL) {
1244 checkGLcall("glEnd and previous calls");
1247 #if 0 /* TODO: Software/Hardware vertex blending support */
1249 * Draw with emulated vertex shaders
1250 * Note: strided data is uninitialized, as we need to pass the vertex
1251 * shader directly as ordering irs yet
1253 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1254 int PrimitiveType, ULONG NumPrimitives,
1255 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1257 unsigned int textureNo = 0;
1258 GLenum glPrimType = GL_POINTS;
1259 int NumVertexes = NumPrimitives;
1260 const short *pIdxBufS = NULL;
1261 const long *pIdxBufL = NULL;
1262 LONG SkipnStrides = 0;
1264 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1265 float rhw = 0.0f; /* rhw */
1266 float ptSize = 0.0f; /* Point size */
1267 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1268 int numcoords[8]; /* Number of coords */
1269 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1271 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1273 TRACE("Using slow software vertex shader code\n");
1275 /* Variable Initialization */
1276 if (idxData != NULL) {
1277 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1278 else pIdxBufL = (const long *) idxData;
1281 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1282 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1284 /* Retrieve the VS information */
1285 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1287 /* Start drawing in GL */
1288 VTRACE(("glBegin(%x)\n", glPrimType));
1289 glBegin(glPrimType);
1291 /* For each primitive */
1292 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1294 /* For indexed data, we need to go a few more strides in */
1295 if (idxData != NULL) {
1297 /* Indexed so work out the number of strides to skip */
1299 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1300 SkipnStrides = pIdxBufS[startIdx+vx_index];
1302 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1303 SkipnStrides = pIdxBufL[startIdx+vx_index];
1307 /* Fill the vertex shader input */
1308 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1310 /* Initialize the output fields to the same defaults as it would normally have */
1311 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1312 vertex_shader->output.oD[0].x = 1.0;
1313 vertex_shader->output.oD[0].y = 1.0;
1314 vertex_shader->output.oD[0].z = 1.0;
1315 vertex_shader->output.oD[0].w = 1.0;
1317 /* Now execute the vertex shader */
1318 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1321 TRACE_VECTOR(vertex_shader->output.oPos);
1322 TRACE_VECTOR(vertex_shader->output.oD[0]);
1323 TRACE_VECTOR(vertex_shader->output.oD[1]);
1324 TRACE_VECTOR(vertex_shader->output.oT[0]);
1325 TRACE_VECTOR(vertex_shader->output.oT[1]);
1326 TRACE_VECTOR(vertex_shader->input.V[0]);
1327 TRACE_VECTOR(vertex_shader->data->C[0]);
1328 TRACE_VECTOR(vertex_shader->data->C[1]);
1329 TRACE_VECTOR(vertex_shader->data->C[2]);
1330 TRACE_VECTOR(vertex_shader->data->C[3]);
1331 TRACE_VECTOR(vertex_shader->data->C[4]);
1332 TRACE_VECTOR(vertex_shader->data->C[5]);
1333 TRACE_VECTOR(vertex_shader->data->C[6]);
1334 TRACE_VECTOR(vertex_shader->data->C[7]);
1337 /* Extract out the output */
1338 /*FIXME: Fog coords? */
1339 x = vertex_shader->output.oPos.x;
1340 y = vertex_shader->output.oPos.y;
1341 z = vertex_shader->output.oPos.z;
1342 rhw = vertex_shader->output.oPos.w;
1343 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1345 /** Update textures coords using vertex_shader->output.oT[0->7] */
1346 memset(texcoords, 0x00, sizeof(texcoords));
1347 memset(numcoords, 0x00, sizeof(numcoords));
1348 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1349 if (This->stateBlock->textures[textureNo] != NULL) {
1350 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1351 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1352 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1353 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1354 if (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1355 numcoords[textureNo] = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1357 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1358 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1359 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1360 default: numcoords[textureNo] = 4;
1364 numcoords[textureNo] = 0;
1368 /* Draw using this information */
1371 TRUE, 0.0f, 0.0f, 1.0f,
1372 TRUE, (float*) &vertex_shader->output.oD[0],
1373 TRUE, (float*) &vertex_shader->output.oD[1],
1374 FALSE, ptSize, /* FIXME: Change back when supported */
1375 texcoords, numcoords);
1377 /* For non indexed mode, step onto next parts */
1378 if (idxData == NULL) {
1382 } /* for each vertex */
1385 checkGLcall("glEnd and previous calls");
1388 void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1389 int PrimitiveType, ULONG NumPrimitives,
1390 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1392 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1399 TRACE("Drawing with hardware vertex shaders\n");
1401 /* Retrieve the VS information */
1402 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1404 /* Enable the Vertex Shader */
1405 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1406 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1407 glEnable(GL_VERTEX_PROGRAM_ARB);
1408 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1410 /* Update the constants */
1411 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1412 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1413 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1416 /* Set up the vertex.attr[n] inputs */
1417 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1419 /* Ok, Work out which primitive is requested and how many vertexes that
1421 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1423 /* Finally do the drawing */
1424 if (idxData != NULL) {
1426 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1427 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1428 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1429 (const char *)idxData+(idxSize * startIdx));
1431 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1432 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1433 (const char *)idxData+(idxSize * startIdx));
1435 checkGLcall("glDrawRangeElements");
1439 /* Note first is now zero as we shuffled along earlier */
1440 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1441 glDrawArrays(glPrimType, 0, NumVertexes);
1442 checkGLcall("glDrawArrays");
1448 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1450 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1454 /* Leave all the attribs disabled */
1455 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1456 /* MESA does not support it right not */
1457 if (glGetError() != GL_NO_ERROR)
1459 for (i=0; i<maxAttribs; i++) {
1460 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1461 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1465 glDisable(GL_VERTEX_PROGRAM_ARB);
1469 /* Routine common to the draw primitive and draw indexed primitive routines */
1470 void drawPrimitive(IWineD3DDevice *iface,
1471 int PrimitiveType, long NumPrimitives,
1474 long StartVertexIndex,
1477 const void *idxData,
1482 #if 0 /* TODO: vertex and pixel shaders */
1483 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1484 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1488 BOOL useVertexShaderFunction = FALSE;
1489 BOOL isLightingOn = FALSE;
1490 Direct3DVertexStridedData dataLocations;
1493 /* Work out what the FVF should look like */
1494 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1497 /* If we will be using a vertex shader, do some initialization for it */
1498 if (useVertexShaderFunction) {
1499 #if 0 /* TODO: vertex and pixel shaders */
1500 vertex_shader = VERTEX_SHADER(This->updateStateBlock->VertexShader);
1501 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1503 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1504 This->devType != D3DDEVTYPE_REF &&
1505 !This->stateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1506 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1508 /** init Constants */
1509 if (This->updateStateBlock->Changed.vertexShaderConstant) {
1510 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1511 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->updateStateBlock->vertexShaderConstant[0], 96);
1513 #endif /* TODO: vertex and pixel shaders */
1516 /* Ok, we will be updating the screen from here onwards so grab the lock */
1519 #if 0 /* TODO: vertex and pixel shaders */
1520 /* If we will be using a pixel, do some initialization for it */
1521 if ((pixel_shader = PIXEL_SHADER(This->updateStateBlock->PixelShader))) {
1522 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1523 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1525 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1526 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1527 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1528 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1530 /* init Constants */
1531 if (This->updateStateBlock->Changed.pixelShaderConstant) {
1532 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1533 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->updateStateBlock->pixelShaderConstant[0], 8);
1535 /* Update the constants */
1536 for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1537 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1538 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1541 #endif /* TODO: vertex and pixel shaders */
1543 /* Setup transform matrices and sort out */
1545 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1546 So make sure lighting is disabled. */
1547 isLightingOn = glIsEnabled(GL_LIGHTING);
1548 glDisable(GL_LIGHTING);
1549 checkGLcall("glDisable(GL_LIGHTING);");
1550 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1552 isLightingOn = primitiveInitState(iface,
1553 fvf & D3DFVF_XYZRHW,
1554 !(fvf & D3DFVF_NORMAL),
1555 useVertexShaderFunction);
1557 /* Initialize all values to null */
1558 if (useVertexShaderFunction == FALSE) {
1559 memset(&dataLocations, 0x00, sizeof(dataLocations));
1561 /* Convert to strided data */
1562 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1564 /* Dump out what parts we have supplied */
1565 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1566 TRACE_STRIDED((&dataLocations), position);
1567 TRACE_STRIDED((&dataLocations), blendWeights);
1568 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1569 TRACE_STRIDED((&dataLocations), normal);
1570 TRACE_STRIDED((&dataLocations), pSize);
1571 TRACE_STRIDED((&dataLocations), diffuse);
1572 TRACE_STRIDED((&dataLocations), specular);
1573 TRACE_STRIDED((&dataLocations), texCoords[0]);
1574 TRACE_STRIDED((&dataLocations), texCoords[1]);
1575 TRACE_STRIDED((&dataLocations), texCoords[2]);
1576 TRACE_STRIDED((&dataLocations), texCoords[3]);
1577 TRACE_STRIDED((&dataLocations), texCoords[4]);
1578 TRACE_STRIDED((&dataLocations), texCoords[5]);
1579 TRACE_STRIDED((&dataLocations), texCoords[6]);
1580 TRACE_STRIDED((&dataLocations), texCoords[7]);
1583 /* Now initialize the materials state */
1584 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1587 #if 0 /* TODO: Texture support */
1588 /* And re-upload any dirty textures */
1589 for (i=0; i<GL_LIMITS(textures); i++) {
1591 if ((This->stateBlock->textures[i] != NULL) &&
1592 (IWineD3DBaseTextureImpl_IsDirty(This->stateBlock->textures[i])))
1594 /* Load up the texture now */
1595 IWineD3DTextureImpl_PreLoad((IWineD3DTexture8 *) This->stateBlock->textures[i]);
1596 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1601 /* Now draw the graphics to the screen */
1602 if (useVertexShaderFunction) {
1604 /* Ideally, we should have software FV and hardware VS, possibly
1605 depending on the device type? */
1608 TRACE("Swap HW vertex shader\n");
1609 #if 0 /* TODO: vertex and pixel shaders */
1610 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1611 idxData, idxSize, minIndex, StartIdx);
1614 /* We will have to use the very, very slow emulation layer */
1615 TRACE("Swap SW vertex shader\n");
1616 #if 0 /* TODO: vertex and pixel shaders */
1617 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1618 idxData, idxSize, minIndex, StartIdx);
1622 } else if ((dataLocations.u.s.pSize.lpData != NULL) ||
1623 (dataLocations.u.s.diffuse.lpData != NULL) ||
1624 (dataLocations.u.s.blendWeights.lpData != NULL)) {
1626 /* Fixme, Ideally, only use the per-vertex code for software HAL
1627 but until opengl supports all the functions returned to setup
1628 vertex arrays, we need to drop down to the slow mechanism for
1629 certain functions */
1631 /* We will have to use the slow version of GL per vertex setup */
1632 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1633 idxData, idxSize, minIndex, StartIdx);
1637 /* We can use the fast version of GL pointers */
1638 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1639 idxData, idxSize, minIndex, StartIdx);
1642 /* If vertex shaders or no normals, restore previous lighting state */
1643 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1644 if (isLightingOn) glEnable(GL_LIGHTING);
1645 else glDisable(GL_LIGHTING);
1646 TRACE("Restored lighting to original state\n");
1649 #if 0 /* TODO: vertex and pixel shaders */
1654 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1656 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1658 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1662 /* Finshed updating the screen, restore lock */
1664 TRACE("Done all gl drawing\n");
1667 #if defined(SHOW_FRAME_MAKEUP)
1669 if (isDumpingFrames) {
1672 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1673 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1674 TRACE("Saving screenshot %s\n", buffer);
1675 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1676 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1678 #if defined(SHOW_TEXTURE_MAKEUP)
1680 LPDIRECT3DSURFACE8 pSur;
1682 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1683 if (This->stateBlock->textures[textureNo] != NULL) {
1684 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1685 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1686 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1687 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1688 IDirect3DSurface8Impl_Release(pSur);
1693 primCounter = primCounter + 1;