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");
205 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
206 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
207 checkGLcall("glMaterialfv");
209 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
210 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
211 checkGLcall("glMaterialfv");
213 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
214 checkGLcall("glMaterialfv");
219 static GLfloat invymat[16]={
220 1.0f, 0.0f, 0.0f, 0.0f,
221 0.0f, -1.0f, 0.0f, 0.0f,
222 0.0f, 0.0f, 1.0f, 0.0f,
223 0.0f, 0.0f, 0.0f, 1.0f};
225 /* Setup views - Transformed & lit if RHW, else untransformed.
226 Only unlit if Normals are supplied
227 Returns: Whether to restore lighting afterwards */
228 BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
230 BOOL isLightingOn = FALSE;
231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
233 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
234 set by the appropriate render state. Note Vertex Shader output is already lit */
235 if (vtx_lit || useVS) {
236 isLightingOn = glIsEnabled(GL_LIGHTING);
237 glDisable(GL_LIGHTING);
238 checkGLcall("glDisable(GL_LIGHTING);");
239 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
242 if (!useVS && vtx_transformed) {
244 /* If the last draw was transformed as well, no need to reapply all the matrixes */
245 if (!This->last_was_rhw) {
247 double X, Y, height, width, minZ, maxZ;
248 This->last_was_rhw = TRUE;
250 /* Transformed already into viewport coordinates, so we do not need transform
251 matrices. Reset all matrices to identity and leave the default matrix in world
253 glMatrixMode(GL_MODELVIEW);
254 checkGLcall("glMatrixMode");
256 checkGLcall("glLoadIdentity");
258 glMatrixMode(GL_PROJECTION);
259 checkGLcall("glMatrixMode");
261 checkGLcall("glLoadIdentity");
263 /* Set up the viewport to be full viewport */
264 X = This->stateBlock->viewport.X;
265 Y = This->stateBlock->viewport.Y;
266 height = This->stateBlock->viewport.Height;
267 width = This->stateBlock->viewport.Width;
268 minZ = This->stateBlock->viewport.MinZ;
269 maxZ = This->stateBlock->viewport.MaxZ;
270 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
271 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
272 checkGLcall("glOrtho");
274 /* Window Coord 0 is the middle of the first pixel, so translate by half
275 a pixel (See comment above glTranslate below) */
276 glTranslatef(0.5, 0.5, 0);
277 checkGLcall("glTranslatef(0.5, 0.5, 0)");
278 if (This->renderUpsideDown) {
279 glMultMatrixf(invymat);
280 checkGLcall("glMultMatrixf(invymat)");
286 /* Untransformed, so relies on the view and projection matrices */
288 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
289 /* Only reapply when have to */
290 This->modelview_valid = TRUE;
291 glMatrixMode(GL_MODELVIEW);
292 checkGLcall("glMatrixMode");
294 /* In the general case, the view matrix is the identity matrix */
295 if (This->view_ident) {
296 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
297 checkGLcall("glLoadMatrixf");
299 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
300 checkGLcall("glLoadMatrixf");
301 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
302 checkGLcall("glMultMatrixf");
306 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
307 /* Only reapply when have to */
308 This->proj_valid = TRUE;
309 glMatrixMode(GL_PROJECTION);
310 checkGLcall("glMatrixMode");
312 /* The rule is that the window coordinate 0 does not correspond to the
313 beginning of the first pixel, but the center of the first pixel.
314 As a consequence if you want to correctly draw one line exactly from
315 the left to the right end of the viewport (with all matrices set to
316 be identity), the x coords of both ends of the line would be not
317 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
320 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
321 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
323 if (This->renderUpsideDown) {
324 glMultMatrixf(invymat);
325 checkGLcall("glMultMatrixf(invymat)");
327 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
328 checkGLcall("glLoadMatrixf");
331 /* Vertex Shader output is already transformed, so set up identity matrices */
332 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
333 come along this needs to take into account whether s/w ones were
336 glMatrixMode(GL_MODELVIEW);
337 checkGLcall("glMatrixMode");
339 glMatrixMode(GL_PROJECTION);
340 checkGLcall("glMatrixMode");
342 /* Window Coord 0 is the middle of the first pixel, so translate by half
343 a pixel (See comment above glTranslate above) */
344 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
345 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
346 if (This->renderUpsideDown) {
347 glMultMatrixf(invymat);
348 checkGLcall("glMultMatrixf(invymat)");
350 This->modelview_valid = FALSE;
351 This->proj_valid = FALSE;
353 This->last_was_rhw = FALSE;
358 void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
360 short LoopThroughTo = 0;
362 BOOL canDoViaGLPointers = TRUE;
366 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
367 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
371 /* OK, Now to setup the data locations
372 For the non-created vertex shaders, the VertexShader var holds the real
373 FVF and only stream 0 matters
374 For the created vertex shaders, there is an FVF per stream */
375 if (!This->stateBlock->streamIsUP && !(This->updateStateBlock->vertexShader == NULL)) {
376 LoopThroughTo = MAX_STREAMS;
381 /* Work through stream by stream */
382 for (nStream=0; nStream<LoopThroughTo; nStream++) {
383 DWORD stride = This->stateBlock->stream_stride[nStream];
387 /* Skip empty streams */
388 if (This->stateBlock->stream_source[nStream] == NULL) continue;
390 /* Retrieve appropriate FVF */
391 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
392 thisFVF = This->updateStateBlock->fvf;
393 /* Handle memory passed directly as well as vertex buffers */
394 if (This->stateBlock->streamIsUP) {
395 data = (BYTE *)This->stateBlock->stream_source[nStream];
397 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->stream_source[nStream])->allocatedMemory;
400 #if 0 /* TODO: Vertex shader support */
401 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
402 data = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->stream_source[nStream])->allocatedMemory;
405 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
406 if (thisFVF == 0) continue;
408 /* Now convert the stream into pointers */
410 /* Shuffle to the beginning of the vertexes to render and index from there */
411 data = data + (BaseVertexIndex * stride);
413 /* Either 3 or 4 floats depending on the FVF */
414 /* FIXME: Can blending data be in a different stream to the position data?
415 and if so using the fixed pipeline how do we handle it */
416 if (thisFVF & D3DFVF_POSITION_MASK) {
417 strided->u.s.position.lpData = data;
418 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
419 strided->u.s.position.dwStride = stride;
420 data += 3 * sizeof(float);
421 if (thisFVF & D3DFVF_XYZRHW) {
422 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
423 data += sizeof(float);
427 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
428 /** do we have to Check This->updateStateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
429 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
430 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
432 canDoViaGLPointers = FALSE;
433 strided->u.s.blendWeights.lpData = data;
434 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + (numBlends - 1);
435 strided->u.s.blendWeights.dwStride = stride;
436 data += numBlends * sizeof(FLOAT);
438 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
439 strided->u.s.blendMatrixIndices.lpData = data;
440 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
441 strided->u.s.blendMatrixIndices.dwStride= stride;
442 data += sizeof(DWORD);
446 /* Normal is always 3 floats */
447 if (thisFVF & D3DFVF_NORMAL) {
448 strided->u.s.normal.lpData = data;
449 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
450 strided->u.s.normal.dwStride = stride;
451 data += 3 * sizeof(FLOAT);
454 /* Pointsize is a single float */
455 if (thisFVF & D3DFVF_PSIZE) {
456 strided->u.s.pSize.lpData = data;
457 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
458 strided->u.s.pSize.dwStride = stride;
459 data += sizeof(FLOAT);
462 /* Diffuse is 4 unsigned bytes */
463 if (thisFVF & D3DFVF_DIFFUSE) {
464 strided->u.s.diffuse.lpData = data;
465 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
466 strided->u.s.diffuse.dwStride = stride;
467 data += sizeof(DWORD);
470 /* Specular is 4 unsigned bytes */
471 if (thisFVF & D3DFVF_SPECULAR) {
472 strided->u.s.specular.lpData = data;
473 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
474 strided->u.s.specular.dwStride = stride;
475 data += sizeof(DWORD);
479 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
480 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
482 /* numTextures indicates the number of texture coordinates supplied */
483 /* However, the first set may not be for stage 0 texture - it all */
484 /* depends on D3DTSS_TEXCOORDINDEX. */
485 /* The number of bytes for each coordinate set is based off */
486 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
488 /* So, for each supplied texture extract the coords */
489 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
491 strided->u.s.texCoords[textureNo].lpData = data;
492 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
493 strided->u.s.texCoords[textureNo].dwStride = stride;
494 numCoords[textureNo] = coordIdxInfo & 0x03;
497 data += sizeof(float);
498 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
499 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
500 data += sizeof(float);
501 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
502 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
503 data += sizeof(float);
504 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
505 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
506 data += sizeof(float);
510 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
515 /* Draw a single vertex using this information */
516 void draw_vertex(IWineD3DDevice *iface, /* interface */
517 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
518 BOOL isNormal, float nx, float ny, float nz, /* normal */
519 BOOL isDiffuse, float *dRGBA, /* 1st colors */
520 BOOL isSpecular, float *sRGB, /* 2ndry colors */
521 BOOL isPtSize, float ptSize, /* pointSize */
522 D3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
524 unsigned int textureNo;
526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
528 /* Diffuse -------------------------------- */
531 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
534 /* Specular Colour ------------------------------------------*/
536 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
537 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
538 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
540 VTRACE(("Specular color extensions not supplied\n"));
544 /* Normal -------------------------------- */
546 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
547 glNormal3f(nx, ny, nz);
550 /* Point Size ----------------------------------------------*/
553 /* no such functionality in the fixed function GL pipeline */
554 FIXME("Cannot change ptSize here in openGl\n");
557 /* Texture coords --------------------------- */
558 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
560 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
561 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
565 /* Query tex coords */
566 if (This->stateBlock->textures[textureNo] != NULL) {
568 int coordIdx = This->updateStateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
570 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
572 } else if (numcoords[coordIdx] == 0) {
573 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
577 /* Initialize vars */
583 switch (numcoords[coordIdx]) {
584 case 4: q = texcoords[coordIdx].w; /* drop through */
585 case 3: r = texcoords[coordIdx].z; /* drop through */
586 case 2: t = texcoords[coordIdx].y; /* drop through */
587 case 1: s = texcoords[coordIdx].x;
590 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
592 VTRACE(("tex:%d, s=%f\n", textureNo, s));
593 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
594 GLMULTITEXCOORD1F(textureNo, s);
600 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
601 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
602 GLMULTITEXCOORD2F(textureNo, s, t);
608 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
609 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
610 GLMULTITEXCOORD3F(textureNo, s, t, r);
612 glTexCoord3f(s, t, r);
616 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
617 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
618 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
620 glTexCoord4f(s, t, r, q);
624 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
628 } /* End of textures */
630 /* Position -------------------------------- */
632 if (1.0f == rhw || rhw < 0.00001f) {
633 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
636 /* Cannot optimize by dividing through by rhw as rhw is required
637 later for perspective in the GL pipeline for vertex shaders */
638 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
639 glVertex4f(x,y,z,rhw);
645 * Actually draw using the supplied information.
646 * Faster GL version using pointers to data, harder to debug though
647 * Note does not handle vertex shaders yet
649 void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
650 int PrimitiveType, ULONG NumPrimitives,
651 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
652 #if 0 /* TODO: Texture support */
653 unsigned int textureNo = 0;
655 GLenum glPrimType = GL_POINTS;
656 int NumVertexes = NumPrimitives;
657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
659 TRACE("Using fast vertex array code\n");
661 /* Vertex Pointers -----------------------------------------*/
662 if (sd->u.s.position.lpData != NULL) {
664 /* Note dwType == float3 or float4 == 2 or 3 */
665 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
666 sd->u.s.position.dwStride,
667 sd->u.s.position.dwType + 1,
668 sd->u.s.position.lpData));
670 /* Disable RHW mode as 'w' coord handling for rhw mode should
671 not impact screen position whereas in GL it does. This may
672 result in very slightly distored textures in rhw mode, but
673 a very minimal different */
674 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
675 sd->u.s.position.dwStride,
676 sd->u.s.position.lpData);
677 checkGLcall("glVertexPointer(...)");
678 glEnableClientState(GL_VERTEX_ARRAY);
679 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
683 glDisableClientState(GL_VERTEX_ARRAY);
684 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
687 /* Blend Data ----------------------------------------------*/
688 if ((sd->u.s.blendWeights.lpData != NULL) ||
689 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
690 /* FIXME: Won't get here as will drop to slow method */
691 FIXME("Blending not supported in fast draw routine\n");
693 #if 0 /* Vertex blend support needs to be added */
694 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
696 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
699 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
700 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
701 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
702 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
705 FIXME("unsupported blending in openGl\n");
708 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
710 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
713 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
714 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
720 /* Normals -------------------------------------------------*/
721 if (sd->u.s.normal.lpData != NULL) {
723 /* Note dwType == float3 or float4 == 2 or 3 */
724 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
725 sd->u.s.normal.dwStride,
726 sd->u.s.normal.lpData));
727 glNormalPointer(GL_FLOAT,
728 sd->u.s.normal.dwStride,
729 sd->u.s.normal.lpData);
730 checkGLcall("glNormalPointer(...)");
731 glEnableClientState(GL_NORMAL_ARRAY);
732 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
736 glDisableClientState(GL_NORMAL_ARRAY);
737 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
739 checkGLcall("glNormal3f(0, 0, 1)");
742 /* Point Size ----------------------------------------------*/
743 if (sd->u.s.pSize.lpData != NULL) {
745 /* no such functionality in the fixed function GL pipeline */
746 /* FIXME: Won't get here as will drop to slow method */
747 FIXME("Cannot change ptSize here in openGl\n");
750 /* Diffuse Colour ------------------------------------------*/
751 /* WARNING: Data here MUST be in RGBA format, so cannot */
752 /* go directly into fast mode from app pgm, because */
753 /* directx requires data in BGRA format. */
754 if (sd->u.s.diffuse.lpData != NULL) {
756 /* Note dwType == float3 or float4 == 2 or 3 */
757 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
758 sd->u.s.diffuse.dwStride,
759 sd->u.s.diffuse.lpData));
760 glColorPointer(4, GL_UNSIGNED_BYTE,
761 sd->u.s.diffuse.dwStride,
762 sd->u.s.diffuse.lpData);
763 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
764 glEnableClientState(GL_COLOR_ARRAY);
765 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
769 glDisableClientState(GL_COLOR_ARRAY);
770 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
771 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
772 checkGLcall("glColor4f(1, 1, 1, 1)");
775 /* Specular Colour ------------------------------------------*/
776 if (sd->u.s.specular.lpData != NULL) {
778 /* Note dwType == float3 or float4 == 2 or 3 */
779 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
780 sd->u.s.specular.dwStride,
781 sd->u.s.specular.lpData));
783 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
784 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
785 sd->u.s.specular.dwStride,
786 sd->u.s.specular.lpData);
787 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
788 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
789 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
791 /* Missing specular color is not critical, no warnings */
792 VTRACE(("Specular colour is not supported in this GL implementation\n"));
797 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
798 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
799 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
800 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
801 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
803 /* Missing specular color is not critical, no warnings */
804 VTRACE(("Specular colour is not supported in this GL implementation\n"));
808 /* Texture coords -------------------------------------------*/
809 #if 0 /* TODO: Texture support */
810 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
812 /* Select the correct texture stage */
813 #if defined(GL_VERSION_1_3)
814 glClientActiveTexture(GL_TEXTURE0 + textureNo);
816 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
819 /* Query tex coords */
820 if (This->stateBlock->textures[textureNo] != NULL) {
821 int coordIdx = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
823 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
824 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
825 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
826 #if defined(GL_VERSION_1_3)
827 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
829 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
835 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
836 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
837 #if defined(GL_VERSION_1_3)
838 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
840 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
842 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
843 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
844 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
845 #if defined(GL_VERSION_1_3)
846 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
848 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
852 /* The coords to supply depend completely on the fvf / vertex shader */
856 switch (sd->u.s.texCoords[coordIdx].dwType) {
857 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
858 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
859 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
860 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
861 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
862 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
863 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
864 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
865 size = 4; type = GL_UNSIGNED_BYTE;
868 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
869 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
872 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
873 #if defined(GL_VERSION_1_3)
874 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
876 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
880 #endif /* TODO: Texture support */
882 /* Ok, Work out which primitive is requested and how many vertexes that
884 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
886 /* Finally do the drawing */
887 if (idxData != NULL) {
889 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
890 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
891 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
892 (const char *)idxData+(idxSize * startIdx));
894 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
895 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
896 (const char *)idxData+(idxSize * startIdx));
898 checkGLcall("glDrawRangeElements");
902 /* Note first is now zero as we shuffled along earlier */
903 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
904 glDrawArrays(glPrimType, 0, NumVertexes);
905 checkGLcall("glDrawArrays");
911 * Actually draw using the supplied information.
912 * Slower GL version which extracts info about each vertex in turn
914 void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
915 int PrimitiveType, ULONG NumPrimitives,
916 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
918 #if 0 /* TODO: Texture support */
919 unsigned int textureNo = 0;
921 GLenum glPrimType = GL_POINTS;
922 int NumVertexes = NumPrimitives;
923 const short *pIdxBufS = NULL;
924 const long *pIdxBufL = NULL;
925 LONG SkipnStrides = 0;
927 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
928 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
929 float rhw = 0.0f; /* rhw */
930 float ptSize = 0.0f; /* Point size */
931 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
932 DWORD specularColor = 0; /* Specular Color */
933 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
935 TRACE("Using slow vertex array code\n");
937 /* Variable Initialization */
938 if (idxData != NULL) {
939 if (idxSize == 2) pIdxBufS = (const short *) idxData;
940 else pIdxBufL = (const long *) idxData;
943 /* Ok, Work out which primitive is requested and how many vertexes that will be */
944 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
946 /* Start drawing in GL */
947 VTRACE(("glBegin(%x)\n", glPrimType));
950 /* For each primitive */
951 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
953 /* Initialize diffuse color */
954 diffuseColor = 0xFFFFFFFF;
956 /* For indexed data, we need to go a few more strides in */
957 if (idxData != NULL) {
959 /* Indexed so work out the number of strides to skip */
961 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
962 SkipnStrides = pIdxBufS[startIdx+vx_index];
964 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
965 SkipnStrides = pIdxBufL[startIdx+vx_index];
969 /* Position Information ------------------ */
970 if (sd->u.s.position.lpData != NULL) {
972 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
977 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
979 /* RHW follows, only if transformed, ie 4 floats were provided */
980 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
981 rhw = ptrToCoords[3];
982 VTRACE(("rhw=%f\n", rhw));
986 /* Blending data -------------------------- */
987 if (sd->u.s.blendWeights.lpData != NULL) {
988 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
989 FIXME("Blending not supported yet\n");
991 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
992 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
996 /* Vertex Normal Data (untransformed only)- */
997 if (sd->u.s.normal.lpData != NULL) {
999 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1000 nx = ptrToCoords[0];
1001 ny = ptrToCoords[1];
1002 nz = ptrToCoords[2];
1003 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1006 /* Point Size ----------------------------- */
1007 if (sd->u.s.pSize.lpData != NULL) {
1009 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1010 ptSize = ptrToCoords[0];
1011 VTRACE(("ptSize=%f\n", ptSize));
1012 FIXME("No support for ptSize yet\n");
1015 /* Diffuse -------------------------------- */
1016 if (sd->u.s.diffuse.lpData != NULL) {
1018 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1019 diffuseColor = ptrToCoords[0];
1020 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1023 /* Specular -------------------------------- */
1024 if (sd->u.s.specular.lpData != NULL) {
1026 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1027 specularColor = ptrToCoords[0];
1028 VTRACE(("specularColor=%lx\n", specularColor));
1031 /* Texture coords --------------------------- */
1032 #if 0 /* TODO: Texture support */
1033 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1035 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1036 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1040 /* Query tex coords */
1041 if (This->stateBlock->textures[textureNo] != NULL) {
1043 int coordIdx = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1044 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1045 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1048 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1050 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1051 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1055 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1057 /* The coords to supply depend completely on the fvf / vertex shader */
1058 switch (coordsToUse) {
1059 case 4: q = ptrToCoords[3]; /* drop through */
1060 case 3: r = ptrToCoords[2]; /* drop through */
1061 case 2: t = ptrToCoords[1]; /* drop through */
1062 case 1: s = ptrToCoords[0];
1065 /* Projected is more 'fun' - Move the last coord to the 'q'
1066 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1067 if ((This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1068 (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1070 if (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1071 switch (coordsToUse) {
1072 case 0: /* Drop Through */
1074 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1086 case 4: /* Nop here */
1089 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1090 This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1095 switch (coordsToUse) { /* Supply the provided texture coords */
1096 case D3DTTFF_COUNT1:
1097 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1098 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1099 #if defined(GL_VERSION_1_3)
1100 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1102 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1108 case D3DTTFF_COUNT2:
1109 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1110 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1111 #if defined(GL_VERSION_1_3)
1112 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1114 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1120 case D3DTTFF_COUNT3:
1121 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1122 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1123 #if defined(GL_VERSION_1_3)
1124 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1126 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1129 glTexCoord3f(s, t, r);
1132 case D3DTTFF_COUNT4:
1133 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1134 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1135 #if defined(GL_VERSION_1_3)
1136 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1138 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1141 glTexCoord4f(s, t, r, q);
1145 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1149 } /* End of textures */
1150 #endif /* TODO: Texture support */
1152 /* Diffuse -------------------------------- */
1153 if (sd->u.s.diffuse.lpData != NULL) {
1154 glColor4ub((diffuseColor >> 16) & 0xFF,
1155 (diffuseColor >> 8) & 0xFF,
1156 (diffuseColor >> 0) & 0xFF,
1157 (diffuseColor >> 24) & 0xFF);
1158 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1159 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1160 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1161 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1162 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1164 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1167 /* Specular ------------------------------- */
1168 if (sd->u.s.diffuse.lpData != NULL) {
1169 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1170 ((specularColor >> 16) & 0xFF) / 255.0f,
1171 ((specularColor >> 8) & 0xFF) / 255.0f,
1172 ((specularColor >> 0) & 0xFF) / 255.0f));
1173 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1174 GL_EXTCALL(glSecondaryColor3ubEXT)(
1175 (specularColor >> 16) & 0xFF,
1176 (specularColor >> 8) & 0xFF,
1177 (specularColor >> 0) & 0xFF);
1179 /* Do not worry if specular colour missing and disable request */
1180 VTRACE(("Specular color extensions not supplied\n"));
1183 if (vx_index == 0) {
1184 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1185 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1187 /* Do not worry if specular colour missing and disable request */
1188 VTRACE(("Specular color extensions not supplied\n"));
1193 /* Normal -------------------------------- */
1194 if (sd->u.s.normal.lpData != NULL) {
1195 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1196 glNormal3f(nx, ny, nz);
1198 if (vx_index == 0) glNormal3f(0, 0, 1);
1201 /* Position -------------------------------- */
1202 if (sd->u.s.position.lpData != NULL) {
1203 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1204 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1205 glVertex3f(x, y, z);
1207 GLfloat w = 1.0 / rhw;
1208 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1209 glVertex4f(x*w, y*w, z*w, w);
1213 /* For non indexed mode, step onto next parts */
1214 if (idxData == NULL) {
1220 checkGLcall("glEnd and previous calls");
1223 #if 0 /* TODO: Software/Hardware vertex blending support */
1225 * Draw with emulated vertex shaders
1226 * Note: strided data is uninitialized, as we need to pass the vertex
1227 * shader directly as ordering irs yet
1229 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1230 int PrimitiveType, ULONG NumPrimitives,
1231 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1233 unsigned int textureNo = 0;
1234 GLenum glPrimType = GL_POINTS;
1235 int NumVertexes = NumPrimitives;
1236 const short *pIdxBufS = NULL;
1237 const long *pIdxBufL = NULL;
1238 LONG SkipnStrides = 0;
1240 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1241 float rhw = 0.0f; /* rhw */
1242 float ptSize = 0.0f; /* Point size */
1243 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1244 int numcoords[8]; /* Number of coords */
1245 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1247 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1249 TRACE("Using slow software vertex shader code\n");
1251 /* Variable Initialization */
1252 if (idxData != NULL) {
1253 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1254 else pIdxBufL = (const long *) idxData;
1257 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1258 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1260 /* Retrieve the VS information */
1261 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1263 /* Start drawing in GL */
1264 VTRACE(("glBegin(%x)\n", glPrimType));
1265 glBegin(glPrimType);
1267 /* For each primitive */
1268 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1270 /* For indexed data, we need to go a few more strides in */
1271 if (idxData != NULL) {
1273 /* Indexed so work out the number of strides to skip */
1275 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1276 SkipnStrides = pIdxBufS[startIdx+vx_index];
1278 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1279 SkipnStrides = pIdxBufL[startIdx+vx_index];
1283 /* Fill the vertex shader input */
1284 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1286 /* Initialize the output fields to the same defaults as it would normally have */
1287 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1288 vertex_shader->output.oD[0].x = 1.0;
1289 vertex_shader->output.oD[0].y = 1.0;
1290 vertex_shader->output.oD[0].z = 1.0;
1291 vertex_shader->output.oD[0].w = 1.0;
1293 /* Now execute the vertex shader */
1294 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1297 TRACE_VECTOR(vertex_shader->output.oPos);
1298 TRACE_VECTOR(vertex_shader->output.oD[0]);
1299 TRACE_VECTOR(vertex_shader->output.oD[1]);
1300 TRACE_VECTOR(vertex_shader->output.oT[0]);
1301 TRACE_VECTOR(vertex_shader->output.oT[1]);
1302 TRACE_VECTOR(vertex_shader->input.V[0]);
1303 TRACE_VECTOR(vertex_shader->data->C[0]);
1304 TRACE_VECTOR(vertex_shader->data->C[1]);
1305 TRACE_VECTOR(vertex_shader->data->C[2]);
1306 TRACE_VECTOR(vertex_shader->data->C[3]);
1307 TRACE_VECTOR(vertex_shader->data->C[4]);
1308 TRACE_VECTOR(vertex_shader->data->C[5]);
1309 TRACE_VECTOR(vertex_shader->data->C[6]);
1310 TRACE_VECTOR(vertex_shader->data->C[7]);
1313 /* Extract out the output */
1314 /*FIXME: Fog coords? */
1315 x = vertex_shader->output.oPos.x;
1316 y = vertex_shader->output.oPos.y;
1317 z = vertex_shader->output.oPos.z;
1318 rhw = vertex_shader->output.oPos.w;
1319 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1321 /** Update textures coords using vertex_shader->output.oT[0->7] */
1322 memset(texcoords, 0x00, sizeof(texcoords));
1323 memset(numcoords, 0x00, sizeof(numcoords));
1324 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1325 if (This->stateBlock->textures[textureNo] != NULL) {
1326 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1327 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1328 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1329 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1330 if (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1331 numcoords[textureNo] = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1333 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1334 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1335 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1336 default: numcoords[textureNo] = 4;
1340 numcoords[textureNo] = 0;
1344 /* Draw using this information */
1347 TRUE, 0.0f, 0.0f, 1.0f,
1348 TRUE, (float*) &vertex_shader->output.oD[0],
1349 TRUE, (float*) &vertex_shader->output.oD[1],
1350 FALSE, ptSize, /* FIXME: Change back when supported */
1351 texcoords, numcoords);
1353 /* For non indexed mode, step onto next parts */
1354 if (idxData == NULL) {
1358 } /* for each vertex */
1361 checkGLcall("glEnd and previous calls");
1364 void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1365 int PrimitiveType, ULONG NumPrimitives,
1366 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1368 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1374 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1375 TRACE("Drawing with hardware vertex shaders\n");
1377 /* Retrieve the VS information */
1378 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1380 /* Enable the Vertex Shader */
1381 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1382 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1383 glEnable(GL_VERTEX_PROGRAM_ARB);
1384 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1386 /* Update the constants */
1387 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1388 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1389 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1392 /* Set up the vertex.attr[n] inputs */
1393 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1395 /* Ok, Work out which primitive is requested and how many vertexes that
1397 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1399 /* Finally do the drawing */
1400 if (idxData != NULL) {
1402 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1403 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1404 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1405 (const char *)idxData+(idxSize * startIdx));
1407 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1408 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1409 (const char *)idxData+(idxSize * startIdx));
1411 checkGLcall("glDrawRangeElements");
1415 /* Note first is now zero as we shuffled along earlier */
1416 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1417 glDrawArrays(glPrimType, 0, NumVertexes);
1418 checkGLcall("glDrawArrays");
1424 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1426 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1430 /* Leave all the attribs disabled */
1431 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1432 /* MESA does not support it right not */
1433 if (glGetError() != GL_NO_ERROR)
1435 for (i=0; i<maxAttribs; i++) {
1436 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1437 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1441 glDisable(GL_VERTEX_PROGRAM_ARB);
1445 /* Routine common to the draw primitive and draw indexed primitive routines */
1446 void drawPrimitive(IWineD3DDevice *iface,
1447 int PrimitiveType, long NumPrimitives,
1450 long StartVertexIndex,
1453 const void *idxData,
1458 #if 0 /* TODO: vertex and pixel shaders */
1459 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1460 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1464 BOOL useVertexShaderFunction = FALSE;
1465 BOOL isLightingOn = FALSE;
1466 Direct3DVertexStridedData dataLocations;
1469 /* Work out what the FVF should look like */
1470 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1473 /* If we will be using a vertex shader, do some initialization for it */
1474 if (useVertexShaderFunction) {
1475 #if 0 /* TODO: vertex and pixel shaders */
1476 vertex_shader = VERTEX_SHADER(This->updateStateBlock->VertexShader);
1477 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1479 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1480 This->devType != D3DDEVTYPE_REF &&
1481 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1482 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1484 /** init Constants */
1485 if (This->updateStateBlock->Changed.vertexShaderConstant) {
1486 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1487 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->updateStateBlock->vertexShaderConstant[0], 96);
1489 #endif /* TODO: vertex and pixel shaders */
1492 /* Ok, we will be updating the screen from here onwards so grab the lock */
1495 #if 0 /* TODO: vertex and pixel shaders */
1496 /* If we will be using a pixel, do some initialization for it */
1497 if ((pixel_shader = PIXEL_SHADER(This->updateStateBlock->PixelShader))) {
1498 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1499 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1501 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1502 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1503 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1504 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1506 /* init Constants */
1507 if (This->updateStateBlock->Changed.pixelShaderConstant) {
1508 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1509 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->updateStateBlock->pixelShaderConstant[0], 8);
1511 /* Update the constants */
1512 for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1513 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1514 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1517 #endif /* TODO: vertex and pixel shaders */
1519 /* Setup transform matrices and sort out */
1521 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1522 So make sure lighting is disabled. */
1523 isLightingOn = glIsEnabled(GL_LIGHTING);
1524 glDisable(GL_LIGHTING);
1525 checkGLcall("glDisable(GL_LIGHTING);");
1526 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1528 isLightingOn = primitiveInitState(iface,
1529 fvf & D3DFVF_XYZRHW,
1530 !(fvf & D3DFVF_NORMAL),
1531 useVertexShaderFunction);
1533 /* Initialize all values to null */
1534 if (useVertexShaderFunction == FALSE) {
1535 memset(&dataLocations, 0x00, sizeof(dataLocations));
1537 /* Convert to strided data */
1538 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1540 /* Dump out what parts we have supplied */
1541 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1542 TRACE_STRIDED((&dataLocations), position);
1543 TRACE_STRIDED((&dataLocations), blendWeights);
1544 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1545 TRACE_STRIDED((&dataLocations), normal);
1546 TRACE_STRIDED((&dataLocations), pSize);
1547 TRACE_STRIDED((&dataLocations), diffuse);
1548 TRACE_STRIDED((&dataLocations), specular);
1549 TRACE_STRIDED((&dataLocations), texCoords[0]);
1550 TRACE_STRIDED((&dataLocations), texCoords[1]);
1551 TRACE_STRIDED((&dataLocations), texCoords[2]);
1552 TRACE_STRIDED((&dataLocations), texCoords[3]);
1553 TRACE_STRIDED((&dataLocations), texCoords[4]);
1554 TRACE_STRIDED((&dataLocations), texCoords[5]);
1555 TRACE_STRIDED((&dataLocations), texCoords[6]);
1556 TRACE_STRIDED((&dataLocations), texCoords[7]);
1559 /* Now initialize the materials state */
1560 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1563 #if 0 /* TODO: Texture support */
1564 /* And re-upload any dirty textures */
1565 for (i=0; i<GL_LIMITS(textures); i++) {
1567 if ((This->stateBlock->textures[i] != NULL) &&
1568 (IWineD3DBaseTextureImpl_IsDirty(This->stateBlock->textures[i])))
1570 /* Load up the texture now */
1571 IWineD3DTextureImpl_PreLoad((IWineD3DTexture8 *) This->stateBlock->textures[i]);
1572 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1577 /* Now draw the graphics to the screen */
1578 if (useVertexShaderFunction) {
1580 /* Ideally, we should have software FV and hardware VS, possibly
1581 depending on the device type? */
1584 TRACE("Swap HW vertex shader\n");
1585 #if 0 /* TODO: vertex and pixel shaders */
1586 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1587 idxData, idxSize, minIndex, StartIdx);
1590 /* We will have to use the very, very slow emulation layer */
1591 TRACE("Swap SW vertex shader\n");
1592 #if 0 /* TODO: vertex and pixel shaders */
1593 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1594 idxData, idxSize, minIndex, StartIdx);
1598 } else if ((dataLocations.u.s.pSize.lpData != NULL) ||
1599 (dataLocations.u.s.diffuse.lpData != NULL) ||
1600 (dataLocations.u.s.blendWeights.lpData != NULL)) {
1602 /* Fixme, Ideally, only use the per-vertex code for software HAL
1603 but until opengl supports all the functions returned to setup
1604 vertex arrays, we need to drop down to the slow mechanism for
1605 certain functions */
1607 /* We will have to use the slow version of GL per vertex setup */
1608 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1609 idxData, idxSize, minIndex, StartIdx);
1613 /* We can use the fast version of GL pointers */
1614 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1615 idxData, idxSize, minIndex, StartIdx);
1618 /* If vertex shaders or no normals, restore previous lighting state */
1619 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1620 if (isLightingOn) glEnable(GL_LIGHTING);
1621 else glDisable(GL_LIGHTING);
1622 TRACE("Restored lighting to original state\n");
1625 #if 0 /* TODO: vertex and pixel shaders */
1630 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1632 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1634 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1638 /* Finshed updating the screen, restore lock */
1640 TRACE("Done all gl drawing\n");
1643 #if defined(SHOW_FRAME_MAKEUP)
1645 if (isDumpingFrames) {
1648 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1649 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1650 TRACE("Saving screenshot %s\n", buffer);
1651 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1652 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1654 #if defined(SHOW_TEXTURE_MAKEUP)
1656 LPDIRECT3DSURFACE8 pSur;
1658 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1659 if (This->stateBlock->textures[textureNo] != NULL) {
1660 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1661 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1662 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1663 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1664 IDirect3DSurface8Impl_Release(pSur);
1669 primCounter = primCounter + 1;