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 /* Returns bits for what is expected from the fixed function pipeline, and whether
39 a vertex shader will be in use. Note the fvf bits returned may be split over
40 multiple streams only if the vertex shader was created, otherwise it all relates
42 BOOL initializeFVF(IWineD3DDevice *iface,
43 DWORD *FVFbits, /* What to expect in the FVF across all streams */
44 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
47 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
49 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
50 /* The first thing to work out is if we are using the fixed function pipeline
51 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
52 is the FVF, or with a shader which was created with no function - in which
53 case there is an FVF per declared stream. If this occurs, we also maintain
54 an 'OR' of all the FVF's together so we know what to expect across all the
58 if (This->updateStateBlock->vertexShader == NULL) {
60 /* Use this as the FVF */
61 *FVFbits = This->updateStateBlock->fvf;
62 *useVertexShaderFunction = FALSE;
63 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
68 /* Use created shader */
69 IDirect3DVertexShaderImpl* vertex_shader = NULL;
70 vertex_shader = VERTEX_SHADER(This->updateStateBlock->VertexShader);
72 if (vertex_shader == NULL) {
74 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
75 ERR("trying to use unitialised vertex shader: %lu\n", This->updateStateBlock->VertexShader);
80 *FVFbits = This->updateStateBlock->vertexShaderDecl->allFVF;
82 if (vertex_shader->function == NULL) {
83 /* No function, so many streams supplied plus FVF definition pre stream */
84 *useVertexShaderFunction = FALSE;
85 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
86 This->stateBlock->VertexShader, *FVFbits);
88 /* Vertex shader needs calling */
89 *useVertexShaderFunction = TRUE;
90 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
94 FIXME("Vertex Shaders not moved into wined3d yet\n");
100 /* Issues the glBegin call for gl given the primitive type and count */
101 DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
105 DWORD NumVertexes = NumPrimitives;
107 switch (PrimitiveType) {
108 case D3DPT_POINTLIST:
110 *primType = GL_POINTS;
111 NumVertexes = NumPrimitives;
116 *primType = GL_LINES;
117 NumVertexes = NumPrimitives * 2;
120 case D3DPT_LINESTRIP:
121 TRACE("LINE_STRIP\n");
122 *primType = GL_LINE_STRIP;
123 NumVertexes = NumPrimitives + 1;
126 case D3DPT_TRIANGLELIST:
127 TRACE("TRIANGLES\n");
128 *primType = GL_TRIANGLES;
129 NumVertexes = NumPrimitives * 3;
132 case D3DPT_TRIANGLESTRIP:
133 TRACE("TRIANGLE_STRIP\n");
134 *primType = GL_TRIANGLE_STRIP;
135 NumVertexes = NumPrimitives + 2;
138 case D3DPT_TRIANGLEFAN:
139 TRACE("TRIANGLE_FAN\n");
140 *primType = GL_TRIANGLE_FAN;
141 NumVertexes = NumPrimitives + 2;
145 FIXME("Unhandled primitive\n");
146 *primType = GL_POINTS;
152 /* Ensure the appropriate material states are set up - only change
153 state if really required */
154 void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
156 BOOL requires_material_reset = FALSE;
157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
159 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
160 /* If we have not set up the material color tracking, do it now as required */
161 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
162 checkGLcall("glDisable GL_COLOR_MATERIAL");
163 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
164 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
165 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
166 glEnable(GL_COLOR_MATERIAL);
167 checkGLcall("glEnable GL_COLOR_MATERIAL");
168 This->tracking_color = IS_TRACKING;
169 requires_material_reset = TRUE; /* Restore material settings as will be used */
171 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
172 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
173 /* If we are tracking the current color but one isn't supplied, don't! */
174 glDisable(GL_COLOR_MATERIAL);
175 checkGLcall("glDisable GL_COLOR_MATERIAL");
176 This->tracking_color = NEEDS_TRACKING;
177 requires_material_reset = TRUE; /* Restore material settings as will be used */
179 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
180 /* No need to reset material colors since no change to gl_color_material */
181 requires_material_reset = FALSE;
183 } else if (This->tracking_color == NEEDS_DISABLE) {
184 glDisable(GL_COLOR_MATERIAL);
185 checkGLcall("glDisable GL_COLOR_MATERIAL");
186 This->tracking_color = DISABLED_TRACKING;
187 requires_material_reset = TRUE; /* Restore material settings as will be used */
190 /* Reset the material colors which may have been tracking the color*/
191 if (requires_material_reset) {
192 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
193 checkGLcall("glMaterialfv");
194 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
195 checkGLcall("glMaterialfv");
196 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
197 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
198 checkGLcall("glMaterialfv");
200 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
201 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
202 checkGLcall("glMaterialfv");
204 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
205 checkGLcall("glMaterialfv");
210 static GLfloat invymat[16]={
211 1.0f, 0.0f, 0.0f, 0.0f,
212 0.0f, -1.0f, 0.0f, 0.0f,
213 0.0f, 0.0f, 1.0f, 0.0f,
214 0.0f, 0.0f, 0.0f, 1.0f};
216 /* Setup views - Transformed & lit if RHW, else untransformed.
217 Only unlit if Normals are supplied
218 Returns: Whether to restore lighting afterwards */
219 BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
221 BOOL isLightingOn = FALSE;
222 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
224 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
225 set by the appropriate render state. Note Vertex Shader output is already lit */
226 if (vtx_lit || useVS) {
227 isLightingOn = glIsEnabled(GL_LIGHTING);
228 glDisable(GL_LIGHTING);
229 checkGLcall("glDisable(GL_LIGHTING);");
230 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
233 if (!useVS && vtx_transformed) {
235 /* If the last draw was transformed as well, no need to reapply all the matrixes */
236 if (!This->last_was_rhw) {
238 double X, Y, height, width, minZ, maxZ;
239 This->last_was_rhw = TRUE;
241 /* Transformed already into viewport coordinates, so we do not need transform
242 matrices. Reset all matrices to identity and leave the default matrix in world
244 glMatrixMode(GL_MODELVIEW);
245 checkGLcall("glMatrixMode");
247 checkGLcall("glLoadIdentity");
249 glMatrixMode(GL_PROJECTION);
250 checkGLcall("glMatrixMode");
252 checkGLcall("glLoadIdentity");
254 /* Set up the viewport to be full viewport */
255 X = This->stateBlock->viewport.X;
256 Y = This->stateBlock->viewport.Y;
257 height = This->stateBlock->viewport.Height;
258 width = This->stateBlock->viewport.Width;
259 minZ = This->stateBlock->viewport.MinZ;
260 maxZ = This->stateBlock->viewport.MaxZ;
261 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
262 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
263 checkGLcall("glOrtho");
265 /* Window Coord 0 is the middle of the first pixel, so translate by half
266 a pixel (See comment above glTranslate below) */
267 glTranslatef(0.5, 0.5, 0);
268 checkGLcall("glTranslatef(0.5, 0.5, 0)");
269 if (This->renderUpsideDown) {
270 glMultMatrixf(invymat);
271 checkGLcall("glMultMatrixf(invymat)");
277 /* Untransformed, so relies on the view and projection matrices */
279 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
280 /* Only reapply when have to */
281 This->modelview_valid = TRUE;
282 glMatrixMode(GL_MODELVIEW);
283 checkGLcall("glMatrixMode");
285 /* In the general case, the view matrix is the identity matrix */
286 if (This->view_ident) {
287 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
288 checkGLcall("glLoadMatrixf");
290 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
291 checkGLcall("glLoadMatrixf");
292 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
293 checkGLcall("glMultMatrixf");
297 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
298 /* Only reapply when have to */
299 This->proj_valid = TRUE;
300 glMatrixMode(GL_PROJECTION);
301 checkGLcall("glMatrixMode");
303 /* The rule is that the window coordinate 0 does not correspond to the
304 beginning of the first pixel, but the center of the first pixel.
305 As a consequence if you want to correctly draw one line exactly from
306 the left to the right end of the viewport (with all matrices set to
307 be identity), the x coords of both ends of the line would be not
308 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
311 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
312 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
314 if (This->renderUpsideDown) {
315 glMultMatrixf(invymat);
316 checkGLcall("glMultMatrixf(invymat)");
318 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
319 checkGLcall("glLoadMatrixf");
322 /* Vertex Shader output is already transformed, so set up identity matrices */
323 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
324 come along this needs to take into account whether s/w ones were
327 glMatrixMode(GL_MODELVIEW);
328 checkGLcall("glMatrixMode");
330 glMatrixMode(GL_PROJECTION);
331 checkGLcall("glMatrixMode");
333 /* Window Coord 0 is the middle of the first pixel, so translate by half
334 a pixel (See comment above glTranslate above) */
335 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
336 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
337 if (This->renderUpsideDown) {
338 glMultMatrixf(invymat);
339 checkGLcall("glMultMatrixf(invymat)");
341 This->modelview_valid = FALSE;
342 This->proj_valid = FALSE;
344 This->last_was_rhw = FALSE;
349 void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
351 short LoopThroughTo = 0;
353 BOOL canDoViaGLPointers = TRUE;
357 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
358 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
360 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
362 /* OK, Now to setup the data locations
363 For the non-created vertex shaders, the VertexShader var holds the real
364 FVF and only stream 0 matters
365 For the created vertex shaders, there is an FVF per stream */
366 if (!This->stateBlock->streamIsUP && !(This->updateStateBlock->vertexShader == NULL)) {
367 LoopThroughTo = MAX_STREAMS;
372 /* Work through stream by stream */
373 for (nStream=0; nStream<LoopThroughTo; nStream++) {
374 DWORD stride = This->stateBlock->stream_stride[nStream];
378 /* Skip empty streams */
379 if (This->stateBlock->stream_source[nStream] == NULL) continue;
381 /* Retrieve appropriate FVF */
382 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
383 thisFVF = This->updateStateBlock->fvf;
384 /* Handle memory passed directly as well as vertex buffers */
385 if (This->stateBlock->streamIsUP) {
386 data = (BYTE *)This->stateBlock->stream_source[nStream];
388 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->stream_source[nStream])->resource.allocatedMemory;
391 #if 0 /* TODO: Vertex shader support */
392 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
393 data = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->stream_source[nStream])->allocatedMemory;
396 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
397 if (thisFVF == 0) continue;
399 /* Now convert the stream into pointers */
401 /* Shuffle to the beginning of the vertexes to render and index from there */
402 data = data + (BaseVertexIndex * stride);
404 /* Either 3 or 4 floats depending on the FVF */
405 /* FIXME: Can blending data be in a different stream to the position data?
406 and if so using the fixed pipeline how do we handle it */
407 if (thisFVF & D3DFVF_POSITION_MASK) {
408 strided->u.s.position.lpData = data;
409 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
410 strided->u.s.position.dwStride = stride;
411 data += 3 * sizeof(float);
412 if (thisFVF & D3DFVF_XYZRHW) {
413 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
414 data += sizeof(float);
418 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
419 /** do we have to Check This->updateStateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
420 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
421 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
423 canDoViaGLPointers = FALSE;
424 strided->u.s.blendWeights.lpData = data;
425 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + (numBlends - 1);
426 strided->u.s.blendWeights.dwStride = stride;
427 data += numBlends * sizeof(FLOAT);
429 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
430 strided->u.s.blendMatrixIndices.lpData = data;
431 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
432 strided->u.s.blendMatrixIndices.dwStride= stride;
433 data += sizeof(DWORD);
437 /* Normal is always 3 floats */
438 if (thisFVF & D3DFVF_NORMAL) {
439 strided->u.s.normal.lpData = data;
440 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
441 strided->u.s.normal.dwStride = stride;
442 data += 3 * sizeof(FLOAT);
445 /* Pointsize is a single float */
446 if (thisFVF & D3DFVF_PSIZE) {
447 strided->u.s.pSize.lpData = data;
448 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
449 strided->u.s.pSize.dwStride = stride;
450 data += sizeof(FLOAT);
453 /* Diffuse is 4 unsigned bytes */
454 if (thisFVF & D3DFVF_DIFFUSE) {
455 strided->u.s.diffuse.lpData = data;
456 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
457 strided->u.s.diffuse.dwStride = stride;
458 data += sizeof(DWORD);
461 /* Specular is 4 unsigned bytes */
462 if (thisFVF & D3DFVF_SPECULAR) {
463 strided->u.s.specular.lpData = data;
464 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
465 strided->u.s.specular.dwStride = stride;
466 data += sizeof(DWORD);
470 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
471 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
473 /* numTextures indicates the number of texture coordinates supplied */
474 /* However, the first set may not be for stage 0 texture - it all */
475 /* depends on D3DTSS_TEXCOORDINDEX. */
476 /* The number of bytes for each coordinate set is based off */
477 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
479 /* So, for each supplied texture extract the coords */
480 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
482 strided->u.s.texCoords[textureNo].lpData = data;
483 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
484 strided->u.s.texCoords[textureNo].dwStride = stride;
485 numCoords[textureNo] = coordIdxInfo & 0x03;
488 data += sizeof(float);
489 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
490 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
491 data += sizeof(float);
492 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
493 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
494 data += sizeof(float);
495 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
496 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
497 data += sizeof(float);
501 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
506 /* Draw a single vertex using this information */
507 void draw_vertex(IWineD3DDevice *iface, /* interface */
508 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
509 BOOL isNormal, float nx, float ny, float nz, /* normal */
510 BOOL isDiffuse, float *dRGBA, /* 1st colors */
511 BOOL isSpecular, float *sRGB, /* 2ndry colors */
512 BOOL isPtSize, float ptSize, /* pointSize */
513 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
515 unsigned int textureNo;
517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
519 /* Diffuse -------------------------------- */
522 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
525 /* Specular Colour ------------------------------------------*/
527 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
528 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
529 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
531 VTRACE(("Specular color extensions not supplied\n"));
535 /* Normal -------------------------------- */
537 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
538 glNormal3f(nx, ny, nz);
541 /* Point Size ----------------------------------------------*/
544 /* no such functionality in the fixed function GL pipeline */
545 FIXME("Cannot change ptSize here in openGl\n");
548 /* Texture coords --------------------------- */
549 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
551 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
552 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
556 /* Query tex coords */
557 if (This->stateBlock->textures[textureNo] != NULL) {
559 int coordIdx = This->updateStateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
561 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
563 } else if (numcoords[coordIdx] == 0) {
564 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
568 /* Initialize vars */
574 switch (numcoords[coordIdx]) {
575 case 4: q = texcoords[coordIdx].w; /* drop through */
576 case 3: r = texcoords[coordIdx].z; /* drop through */
577 case 2: t = texcoords[coordIdx].y; /* drop through */
578 case 1: s = texcoords[coordIdx].x;
581 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
583 VTRACE(("tex:%d, s=%f\n", textureNo, s));
584 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
585 GLMULTITEXCOORD1F(textureNo, s);
591 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
592 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
593 GLMULTITEXCOORD2F(textureNo, s, t);
599 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
600 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
601 GLMULTITEXCOORD3F(textureNo, s, t, r);
603 glTexCoord3f(s, t, r);
607 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
608 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
609 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
611 glTexCoord4f(s, t, r, q);
615 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
619 } /* End of textures */
621 /* Position -------------------------------- */
623 if (1.0f == rhw || rhw < 0.00001f) {
624 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
627 /* Cannot optimize by dividing through by rhw as rhw is required
628 later for perspective in the GL pipeline for vertex shaders */
629 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
630 glVertex4f(x,y,z,rhw);
636 * Actually draw using the supplied information.
637 * Faster GL version using pointers to data, harder to debug though
638 * Note does not handle vertex shaders yet
640 void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
641 int PrimitiveType, ULONG NumPrimitives,
642 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
643 unsigned int textureNo = 0;
644 GLenum glPrimType = GL_POINTS;
645 int NumVertexes = NumPrimitives;
646 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
648 TRACE("Using fast vertex array code\n");
650 /* Vertex Pointers -----------------------------------------*/
651 if (sd->u.s.position.lpData != NULL) {
653 /* Note dwType == float3 or float4 == 2 or 3 */
654 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
655 sd->u.s.position.dwStride,
656 sd->u.s.position.dwType + 1,
657 sd->u.s.position.lpData));
659 /* Disable RHW mode as 'w' coord handling for rhw mode should
660 not impact screen position whereas in GL it does. This may
661 result in very slightly distored textures in rhw mode, but
662 a very minimal different */
663 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
664 sd->u.s.position.dwStride,
665 sd->u.s.position.lpData);
666 checkGLcall("glVertexPointer(...)");
667 glEnableClientState(GL_VERTEX_ARRAY);
668 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
672 glDisableClientState(GL_VERTEX_ARRAY);
673 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
676 /* Blend Data ----------------------------------------------*/
677 if ((sd->u.s.blendWeights.lpData != NULL) ||
678 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
679 #if 1 /* Vertex blend support needs to be added */
680 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
681 DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
682 int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
685 /* Note dwType == float3 or float4 == 2 or 3 */
686 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
688 sd->u.s.blendWeights.dwStride,
689 sd->u.s.blendWeights.lpData));
690 GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
691 sd->u.s.blendWeights.dwStride,
692 sd->u.s.blendWeights.lpData);
693 checkGLcall("glWeightPointerARB(...)");
694 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
695 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
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)");
718 /* FIXME: Won't get here as will drop to slow method */
719 FIXME("Blending not supported in fast draw routine\n");
723 /* Normals -------------------------------------------------*/
724 if (sd->u.s.normal.lpData != NULL) {
726 /* Note dwType == float3 or float4 == 2 or 3 */
727 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
728 sd->u.s.normal.dwStride,
729 sd->u.s.normal.lpData));
730 glNormalPointer(GL_FLOAT,
731 sd->u.s.normal.dwStride,
732 sd->u.s.normal.lpData);
733 checkGLcall("glNormalPointer(...)");
734 glEnableClientState(GL_NORMAL_ARRAY);
735 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
739 glDisableClientState(GL_NORMAL_ARRAY);
740 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
742 checkGLcall("glNormal3f(0, 0, 1)");
745 /* Point Size ----------------------------------------------*/
746 if (sd->u.s.pSize.lpData != NULL) {
748 /* no such functionality in the fixed function GL pipeline */
749 /* FIXME: Won't get here as will drop to slow method */
750 FIXME("Cannot change ptSize here in openGl\n");
753 /* Diffuse Colour ------------------------------------------*/
754 /* WARNING: Data here MUST be in RGBA format, so cannot */
755 /* go directly into fast mode from app pgm, because */
756 /* directx requires data in BGRA format. */
757 if (sd->u.s.diffuse.lpData != NULL) {
759 /* Note dwType == float3 or float4 == 2 or 3 */
760 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
761 sd->u.s.diffuse.dwStride,
762 sd->u.s.diffuse.lpData));
763 glColorPointer(4, GL_UNSIGNED_BYTE,
764 sd->u.s.diffuse.dwStride,
765 sd->u.s.diffuse.lpData);
766 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
767 glEnableClientState(GL_COLOR_ARRAY);
768 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
772 glDisableClientState(GL_COLOR_ARRAY);
773 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
774 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
775 checkGLcall("glColor4f(1, 1, 1, 1)");
778 /* Specular Colour ------------------------------------------*/
779 if (sd->u.s.specular.lpData != NULL) {
781 /* Note dwType == float3 or float4 == 2 or 3 */
782 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
783 sd->u.s.specular.dwStride,
784 sd->u.s.specular.lpData));
786 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
787 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
788 sd->u.s.specular.dwStride,
789 sd->u.s.specular.lpData);
790 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
791 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
792 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
794 /* Missing specular color is not critical, no warnings */
795 VTRACE(("Specular colour is not supported in this GL implementation\n"));
800 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
801 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
802 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
803 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
804 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
806 /* Missing specular color is not critical, no warnings */
807 VTRACE(("Specular colour is not supported in this GL implementation\n"));
811 /* Texture coords -------------------------------------------*/
812 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
814 /* Select the correct texture stage */
815 GLCLIENTACTIVETEXTURE(textureNo);
817 /* Query tex coords */
818 if (This->stateBlock->textures[textureNo] != NULL) {
819 int coordIdx = This->updateStateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
821 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
822 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
823 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
824 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
829 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
830 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
831 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
833 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
834 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
835 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
836 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
840 /* The coords to supply depend completely on the fvf / vertex shader */
844 switch (sd->u.s.texCoords[coordIdx].dwType) {
845 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
846 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
847 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
848 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
849 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
850 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
851 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
852 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
853 size = 4; type = GL_UNSIGNED_BYTE;
856 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
857 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
860 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
861 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
865 /* Ok, Work out which primitive is requested and how many vertexes that
867 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
869 /* Finally do the drawing */
870 if (idxData != NULL) {
872 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
873 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
874 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
875 (const char *)idxData+(idxSize * startIdx));
877 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
878 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
879 (const char *)idxData+(idxSize * startIdx));
881 checkGLcall("glDrawRangeElements");
885 /* Note first is now zero as we shuffled along earlier */
886 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
887 glDrawArrays(glPrimType, 0, NumVertexes);
888 checkGLcall("glDrawArrays");
894 * Actually draw using the supplied information.
895 * Slower GL version which extracts info about each vertex in turn
897 void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
898 int PrimitiveType, ULONG NumPrimitives,
899 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
901 unsigned int textureNo = 0;
902 GLenum glPrimType = GL_POINTS;
903 int NumVertexes = NumPrimitives;
904 const short *pIdxBufS = NULL;
905 const long *pIdxBufL = NULL;
906 LONG SkipnStrides = 0;
908 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
909 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
910 float rhw = 0.0f; /* rhw */
911 float ptSize = 0.0f; /* Point size */
912 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
913 DWORD specularColor = 0; /* Specular Color */
914 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
916 TRACE("Using slow vertex array code\n");
918 /* Variable Initialization */
919 if (idxData != NULL) {
920 if (idxSize == 2) pIdxBufS = (const short *) idxData;
921 else pIdxBufL = (const long *) idxData;
924 /* Ok, Work out which primitive is requested and how many vertexes that will be */
925 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
927 /* Start drawing in GL */
928 VTRACE(("glBegin(%x)\n", glPrimType));
931 /* For each primitive */
932 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
934 /* Initialize diffuse color */
935 diffuseColor = 0xFFFFFFFF;
937 /* For indexed data, we need to go a few more strides in */
938 if (idxData != NULL) {
940 /* Indexed so work out the number of strides to skip */
942 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
943 SkipnStrides = pIdxBufS[startIdx+vx_index];
945 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
946 SkipnStrides = pIdxBufL[startIdx+vx_index];
950 /* Position Information ------------------ */
951 if (sd->u.s.position.lpData != NULL) {
953 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
958 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
960 /* RHW follows, only if transformed, ie 4 floats were provided */
961 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
962 rhw = ptrToCoords[3];
963 VTRACE(("rhw=%f\n", rhw));
967 /* Blending data -------------------------- */
968 if (sd->u.s.blendWeights.lpData != NULL) {
969 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
970 FIXME("Blending not supported yet\n");
972 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
973 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
977 /* Vertex Normal Data (untransformed only)- */
978 if (sd->u.s.normal.lpData != NULL) {
980 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
984 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
987 /* Point Size ----------------------------- */
988 if (sd->u.s.pSize.lpData != NULL) {
990 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
991 ptSize = ptrToCoords[0];
992 VTRACE(("ptSize=%f\n", ptSize));
993 FIXME("No support for ptSize yet\n");
996 /* Diffuse -------------------------------- */
997 if (sd->u.s.diffuse.lpData != NULL) {
999 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1000 diffuseColor = ptrToCoords[0];
1001 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1004 /* Specular -------------------------------- */
1005 if (sd->u.s.specular.lpData != NULL) {
1007 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1008 specularColor = ptrToCoords[0];
1009 VTRACE(("specularColor=%lx\n", specularColor));
1012 /* Texture coords --------------------------- */
1013 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1015 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1016 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1020 /* Query tex coords */
1021 if (This->stateBlock->textures[textureNo] != NULL) {
1023 int coordIdx = This->updateStateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1024 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1025 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1028 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1030 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1031 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1035 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1037 /* The coords to supply depend completely on the fvf / vertex shader */
1038 switch (coordsToUse) {
1039 case 4: q = ptrToCoords[3]; /* drop through */
1040 case 3: r = ptrToCoords[2]; /* drop through */
1041 case 2: t = ptrToCoords[1]; /* drop through */
1042 case 1: s = ptrToCoords[0];
1045 /* Projected is more 'fun' - Move the last coord to the 'q'
1046 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1047 if ((This->updateStateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1048 (This->updateStateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1050 if (This->updateStateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1051 switch (coordsToUse) {
1052 case 0: /* Drop Through */
1054 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1066 case 4: /* Nop here */
1069 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1070 This->updateStateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1075 switch (coordsToUse) { /* Supply the provided texture coords */
1076 case D3DTTFF_COUNT1:
1077 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1078 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1079 GLMULTITEXCOORD1F(textureNo, s);
1084 case D3DTTFF_COUNT2:
1085 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1086 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1087 GLMULTITEXCOORD2F(textureNo, s, t);
1092 case D3DTTFF_COUNT3:
1093 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1094 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1095 GLMULTITEXCOORD3F(textureNo, s, t, r);
1097 glTexCoord3f(s, t, r);
1100 case D3DTTFF_COUNT4:
1101 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1102 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1103 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1105 glTexCoord4f(s, t, r, q);
1109 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1113 } /* End of textures */
1115 /* Diffuse -------------------------------- */
1116 if (sd->u.s.diffuse.lpData != NULL) {
1117 glColor4ub((diffuseColor >> 16) & 0xFF,
1118 (diffuseColor >> 8) & 0xFF,
1119 (diffuseColor >> 0) & 0xFF,
1120 (diffuseColor >> 24) & 0xFF);
1121 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1122 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1123 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1124 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1125 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1127 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1130 /* Specular ------------------------------- */
1131 if (sd->u.s.diffuse.lpData != NULL) {
1132 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1133 ((specularColor >> 16) & 0xFF) / 255.0f,
1134 ((specularColor >> 8) & 0xFF) / 255.0f,
1135 ((specularColor >> 0) & 0xFF) / 255.0f));
1136 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1137 GL_EXTCALL(glSecondaryColor3ubEXT)(
1138 (specularColor >> 16) & 0xFF,
1139 (specularColor >> 8) & 0xFF,
1140 (specularColor >> 0) & 0xFF);
1142 /* Do not worry if specular colour missing and disable request */
1143 VTRACE(("Specular color extensions not supplied\n"));
1146 if (vx_index == 0) {
1147 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1148 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1150 /* Do not worry if specular colour missing and disable request */
1151 VTRACE(("Specular color extensions not supplied\n"));
1156 /* Normal -------------------------------- */
1157 if (sd->u.s.normal.lpData != NULL) {
1158 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1159 glNormal3f(nx, ny, nz);
1161 if (vx_index == 0) glNormal3f(0, 0, 1);
1164 /* Position -------------------------------- */
1165 if (sd->u.s.position.lpData != NULL) {
1166 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1167 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1168 glVertex3f(x, y, z);
1170 GLfloat w = 1.0 / rhw;
1171 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1172 glVertex4f(x*w, y*w, z*w, w);
1176 /* For non indexed mode, step onto next parts */
1177 if (idxData == NULL) {
1183 checkGLcall("glEnd and previous calls");
1186 #if 0 /* TODO: Software/Hardware vertex blending support */
1188 * Draw with emulated vertex shaders
1189 * Note: strided data is uninitialized, as we need to pass the vertex
1190 * shader directly as ordering irs yet
1192 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1193 int PrimitiveType, ULONG NumPrimitives,
1194 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1196 unsigned int textureNo = 0;
1197 GLenum glPrimType = GL_POINTS;
1198 int NumVertexes = NumPrimitives;
1199 const short *pIdxBufS = NULL;
1200 const long *pIdxBufL = NULL;
1201 LONG SkipnStrides = 0;
1203 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1204 float rhw = 0.0f; /* rhw */
1205 float ptSize = 0.0f; /* Point size */
1206 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1207 int numcoords[8]; /* Number of coords */
1208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1210 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1212 TRACE("Using slow software vertex shader code\n");
1214 /* Variable Initialization */
1215 if (idxData != NULL) {
1216 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1217 else pIdxBufL = (const long *) idxData;
1220 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1221 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1223 /* Retrieve the VS information */
1224 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1226 /* Start drawing in GL */
1227 VTRACE(("glBegin(%x)\n", glPrimType));
1228 glBegin(glPrimType);
1230 /* For each primitive */
1231 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1233 /* For indexed data, we need to go a few more strides in */
1234 if (idxData != NULL) {
1236 /* Indexed so work out the number of strides to skip */
1238 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1239 SkipnStrides = pIdxBufS[startIdx+vx_index];
1241 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1242 SkipnStrides = pIdxBufL[startIdx+vx_index];
1246 /* Fill the vertex shader input */
1247 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1249 /* Initialize the output fields to the same defaults as it would normally have */
1250 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1251 vertex_shader->output.oD[0].x = 1.0;
1252 vertex_shader->output.oD[0].y = 1.0;
1253 vertex_shader->output.oD[0].z = 1.0;
1254 vertex_shader->output.oD[0].w = 1.0;
1256 /* Now execute the vertex shader */
1257 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1260 TRACE_VECTOR(vertex_shader->output.oPos);
1261 TRACE_VECTOR(vertex_shader->output.oD[0]);
1262 TRACE_VECTOR(vertex_shader->output.oD[1]);
1263 TRACE_VECTOR(vertex_shader->output.oT[0]);
1264 TRACE_VECTOR(vertex_shader->output.oT[1]);
1265 TRACE_VECTOR(vertex_shader->input.V[0]);
1266 TRACE_VECTOR(vertex_shader->data->C[0]);
1267 TRACE_VECTOR(vertex_shader->data->C[1]);
1268 TRACE_VECTOR(vertex_shader->data->C[2]);
1269 TRACE_VECTOR(vertex_shader->data->C[3]);
1270 TRACE_VECTOR(vertex_shader->data->C[4]);
1271 TRACE_VECTOR(vertex_shader->data->C[5]);
1272 TRACE_VECTOR(vertex_shader->data->C[6]);
1273 TRACE_VECTOR(vertex_shader->data->C[7]);
1276 /* Extract out the output */
1277 /*FIXME: Fog coords? */
1278 x = vertex_shader->output.oPos.x;
1279 y = vertex_shader->output.oPos.y;
1280 z = vertex_shader->output.oPos.z;
1281 rhw = vertex_shader->output.oPos.w;
1282 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1284 /** Update textures coords using vertex_shader->output.oT[0->7] */
1285 memset(texcoords, 0x00, sizeof(texcoords));
1286 memset(numcoords, 0x00, sizeof(numcoords));
1287 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1288 if (This->stateBlock->textures[textureNo] != NULL) {
1289 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1290 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1291 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1292 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1293 if (This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1294 numcoords[textureNo] = This->updateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1296 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1297 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1298 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1299 default: numcoords[textureNo] = 4;
1303 numcoords[textureNo] = 0;
1307 /* Draw using this information */
1310 TRUE, 0.0f, 0.0f, 1.0f,
1311 TRUE, (float*) &vertex_shader->output.oD[0],
1312 TRUE, (float*) &vertex_shader->output.oD[1],
1313 FALSE, ptSize, /* FIXME: Change back when supported */
1314 texcoords, numcoords);
1316 /* For non indexed mode, step onto next parts */
1317 if (idxData == NULL) {
1321 } /* for each vertex */
1324 checkGLcall("glEnd and previous calls");
1327 void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1328 int PrimitiveType, ULONG NumPrimitives,
1329 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1331 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1338 TRACE("Drawing with hardware vertex shaders\n");
1340 /* Retrieve the VS information */
1341 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1343 /* Enable the Vertex Shader */
1344 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1345 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1346 glEnable(GL_VERTEX_PROGRAM_ARB);
1347 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1349 /* Update the constants */
1350 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1351 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1352 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1355 /* Set up the vertex.attr[n] inputs */
1356 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1358 /* Ok, Work out which primitive is requested and how many vertexes that
1360 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1362 /* Finally do the drawing */
1363 if (idxData != NULL) {
1365 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1366 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1367 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1368 (const char *)idxData+(idxSize * startIdx));
1370 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1371 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1372 (const char *)idxData+(idxSize * startIdx));
1374 checkGLcall("glDrawRangeElements");
1378 /* Note first is now zero as we shuffled along earlier */
1379 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1380 glDrawArrays(glPrimType, 0, NumVertexes);
1381 checkGLcall("glDrawArrays");
1387 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1389 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1393 /* Leave all the attribs disabled */
1394 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1395 /* MESA does not support it right not */
1396 if (glGetError() != GL_NO_ERROR)
1398 for (i=0; i<maxAttribs; i++) {
1399 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1400 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1404 glDisable(GL_VERTEX_PROGRAM_ARB);
1408 /* Routine common to the draw primitive and draw indexed primitive routines */
1409 void drawPrimitive(IWineD3DDevice *iface,
1410 int PrimitiveType, long NumPrimitives,
1413 long StartVertexIndex,
1416 const void *idxData,
1421 #if 0 /* TODO: vertex and pixel shaders */
1422 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1423 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1425 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1427 BOOL useVertexShaderFunction = FALSE;
1428 BOOL isLightingOn = FALSE;
1429 Direct3DVertexStridedData dataLocations;
1432 /* Work out what the FVF should look like */
1433 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1436 /* If we will be using a vertex shader, do some initialization for it */
1437 if (useVertexShaderFunction) {
1438 #if 0 /* TODO: vertex and pixel shaders */
1439 vertex_shader = VERTEX_SHADER(This->updateStateBlock->VertexShader);
1440 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1442 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1443 This->devType != D3DDEVTYPE_REF &&
1444 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1445 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1447 /** init Constants */
1448 if (This->updateStateBlock->Changed.vertexShaderConstant) {
1449 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1450 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->updateStateBlock->vertexShaderConstant[0], 96);
1452 #endif /* TODO: vertex and pixel shaders */
1455 /* Ok, we will be updating the screen from here onwards so grab the lock */
1458 #if 0 /* TODO: vertex and pixel shaders */
1459 /* If we will be using a pixel, do some initialization for it */
1460 if ((pixel_shader = PIXEL_SHADER(This->updateStateBlock->PixelShader))) {
1461 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1462 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1464 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1465 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1466 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1467 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1469 /* init Constants */
1470 if (This->updateStateBlock->Changed.pixelShaderConstant) {
1471 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1472 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->updateStateBlock->pixelShaderConstant[0], 8);
1474 /* Update the constants */
1475 for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1476 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1477 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1480 #endif /* TODO: vertex and pixel shaders */
1482 /* Setup transform matrices and sort out */
1484 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1485 So make sure lighting is disabled. */
1486 isLightingOn = glIsEnabled(GL_LIGHTING);
1487 glDisable(GL_LIGHTING);
1488 checkGLcall("glDisable(GL_LIGHTING);");
1489 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1491 isLightingOn = primitiveInitState(iface,
1492 fvf & D3DFVF_XYZRHW,
1493 !(fvf & D3DFVF_NORMAL),
1494 useVertexShaderFunction);
1496 /* Initialize all values to null */
1497 if (useVertexShaderFunction == FALSE) {
1498 memset(&dataLocations, 0x00, sizeof(dataLocations));
1500 /* Convert to strided data */
1501 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1503 /* Dump out what parts we have supplied */
1504 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1505 TRACE_STRIDED((&dataLocations), position);
1506 TRACE_STRIDED((&dataLocations), blendWeights);
1507 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1508 TRACE_STRIDED((&dataLocations), normal);
1509 TRACE_STRIDED((&dataLocations), pSize);
1510 TRACE_STRIDED((&dataLocations), diffuse);
1511 TRACE_STRIDED((&dataLocations), specular);
1512 TRACE_STRIDED((&dataLocations), texCoords[0]);
1513 TRACE_STRIDED((&dataLocations), texCoords[1]);
1514 TRACE_STRIDED((&dataLocations), texCoords[2]);
1515 TRACE_STRIDED((&dataLocations), texCoords[3]);
1516 TRACE_STRIDED((&dataLocations), texCoords[4]);
1517 TRACE_STRIDED((&dataLocations), texCoords[5]);
1518 TRACE_STRIDED((&dataLocations), texCoords[6]);
1519 TRACE_STRIDED((&dataLocations), texCoords[7]);
1522 /* Now initialize the materials state */
1523 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1526 /* And re-upload any dirty textures */
1527 for (i=0; i<GL_LIMITS(textures); i++) {
1529 if ((This->stateBlock->textures[i] != NULL) &&
1530 (IWineD3DBaseTexture_GetDirty(This->stateBlock->textures[i])))
1532 /* Load up the texture now */
1533 IWineD3DTexture_PreLoad((IWineD3DTexture *) This->stateBlock->textures[i]);
1534 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1538 /* Now draw the graphics to the screen */
1539 if (useVertexShaderFunction) {
1541 /* Ideally, we should have software FV and hardware VS, possibly
1542 depending on the device type? */
1545 TRACE("Swap HW vertex shader\n");
1546 #if 0 /* TODO: vertex and pixel shaders */
1547 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1548 idxData, idxSize, minIndex, StartIdx);
1551 /* We will have to use the very, very slow emulation layer */
1552 TRACE("Swap SW vertex shader\n");
1553 #if 0 /* TODO: vertex and pixel shaders */
1554 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1555 idxData, idxSize, minIndex, StartIdx);
1559 } else if ((dataLocations.u.s.pSize.lpData != NULL)
1560 || (dataLocations.u.s.diffuse.lpData != NULL)
1561 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1563 /* Fixme, Ideally, only use the per-vertex code for software HAL
1564 but until opengl supports all the functions returned to setup
1565 vertex arrays, we need to drop down to the slow mechanism for
1566 certain functions */
1568 /* We will have to use the slow version of GL per vertex setup */
1569 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1570 idxData, idxSize, minIndex, StartIdx);
1574 /* We can use the fast version of GL pointers */
1575 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1576 idxData, idxSize, minIndex, StartIdx);
1579 /* If vertex shaders or no normals, restore previous lighting state */
1580 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1581 if (isLightingOn) glEnable(GL_LIGHTING);
1582 else glDisable(GL_LIGHTING);
1583 TRACE("Restored lighting to original state\n");
1586 #if 0 /* TODO: vertex and pixel shaders */
1591 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1593 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1595 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1599 /* Finshed updating the screen, restore lock */
1601 TRACE("Done all gl drawing\n");
1604 #if defined(SHOW_FRAME_MAKEUP)
1606 if (isDumpingFrames) {
1609 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1610 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1611 TRACE("Saving screenshot %s\n", buffer);
1612 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1613 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1615 #if defined(SHOW_TEXTURE_MAKEUP)
1617 LPDIRECT3DSURFACE8 pSur;
1619 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1620 if (This->stateBlock->textures[textureNo] != NULL) {
1621 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1622 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1623 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1624 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1625 IDirect3DSurface8Impl_Release(pSur);
1630 primCounter = primCounter + 1;