2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
32 extern IDirect3DVertexShaderImpl* VertexShaders[64];
33 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
34 extern IDirect3DPixelShaderImpl* PixelShaders[64];
36 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
39 /* Returns bits for what is expected from the fixed function pipeline, and whether
40 a vertex shader will be in use. Note the fvf bits returned may be split over
41 multiple streams only if the vertex shader was created, otherwise it all relates
43 static BOOL initializeFVF(IWineD3DDevice *iface,
44 DWORD *FVFbits, /* What to expect in the FVF across all streams */
45 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
48 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
50 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
51 /* The first thing to work out is if we are using the fixed function pipeline
52 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
53 is the FVF, or with a shader which was created with no function - in which
54 case there is an FVF per declared stream. If this occurs, we also maintain
55 an 'OR' of all the FVF's together so we know what to expect across all the
59 if (This->stateBlock->vertexShader == NULL) {
61 /* Use this as the FVF */
62 *FVFbits = This->stateBlock->fvf;
63 *useVertexShaderFunction = FALSE;
64 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
69 /* Use created shader */
70 IDirect3DVertexShaderImpl* vertex_shader = NULL;
71 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
73 if (vertex_shader == NULL) {
75 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
76 ERR("trying to use unitialised vertex shader: %lu\n", This->stateBlock->VertexShader);
81 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
83 if (vertex_shader->function == NULL) {
84 /* No function, so many streams supplied plus FVF definition pre stream */
85 *useVertexShaderFunction = FALSE;
86 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
87 This->stateBlock->VertexShader, *FVFbits);
89 /* Vertex shader needs calling */
90 *useVertexShaderFunction = TRUE;
91 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
95 FIXME("Vertex Shaders not moved into wined3d yet\n");
101 /* Issues the glBegin call for gl given the primitive type and count */
102 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
106 DWORD NumVertexes = NumPrimitives;
108 switch (PrimitiveType) {
109 case D3DPT_POINTLIST:
111 *primType = GL_POINTS;
112 NumVertexes = NumPrimitives;
117 *primType = GL_LINES;
118 NumVertexes = NumPrimitives * 2;
121 case D3DPT_LINESTRIP:
122 TRACE("LINE_STRIP\n");
123 *primType = GL_LINE_STRIP;
124 NumVertexes = NumPrimitives + 1;
127 case D3DPT_TRIANGLELIST:
128 TRACE("TRIANGLES\n");
129 *primType = GL_TRIANGLES;
130 NumVertexes = NumPrimitives * 3;
133 case D3DPT_TRIANGLESTRIP:
134 TRACE("TRIANGLE_STRIP\n");
135 *primType = GL_TRIANGLE_STRIP;
136 NumVertexes = NumPrimitives + 2;
139 case D3DPT_TRIANGLEFAN:
140 TRACE("TRIANGLE_FAN\n");
141 *primType = GL_TRIANGLE_FAN;
142 NumVertexes = NumPrimitives + 2;
146 FIXME("Unhandled primitive\n");
147 *primType = GL_POINTS;
153 /* Ensure the appropriate material states are set up - only change
154 state if really required */
155 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
157 BOOL requires_material_reset = FALSE;
158 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
160 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
161 /* If we have not set up the material color tracking, do it now as required */
162 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
163 checkGLcall("glDisable GL_COLOR_MATERIAL");
164 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
165 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
166 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
167 glEnable(GL_COLOR_MATERIAL);
168 checkGLcall("glEnable GL_COLOR_MATERIAL");
169 This->tracking_color = IS_TRACKING;
170 requires_material_reset = TRUE; /* Restore material settings as will be used */
172 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
173 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
174 /* If we are tracking the current color but one isn't supplied, don't! */
175 glDisable(GL_COLOR_MATERIAL);
176 checkGLcall("glDisable GL_COLOR_MATERIAL");
177 This->tracking_color = NEEDS_TRACKING;
178 requires_material_reset = TRUE; /* Restore material settings as will be used */
180 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
181 /* No need to reset material colors since no change to gl_color_material */
182 requires_material_reset = FALSE;
184 } else if (This->tracking_color == NEEDS_DISABLE) {
185 glDisable(GL_COLOR_MATERIAL);
186 checkGLcall("glDisable GL_COLOR_MATERIAL");
187 This->tracking_color = DISABLED_TRACKING;
188 requires_material_reset = TRUE; /* Restore material settings as will be used */
191 /* Reset the material colors which may have been tracking the color*/
192 if (requires_material_reset) {
193 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
194 checkGLcall("glMaterialfv");
195 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
196 checkGLcall("glMaterialfv");
197 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
198 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
199 checkGLcall("glMaterialfv");
201 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
202 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
203 checkGLcall("glMaterialfv");
205 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
206 checkGLcall("glMaterialfv");
211 static GLfloat invymat[16]={
212 1.0f, 0.0f, 0.0f, 0.0f,
213 0.0f, -1.0f, 0.0f, 0.0f,
214 0.0f, 0.0f, 1.0f, 0.0f,
215 0.0f, 0.0f, 0.0f, 1.0f};
217 /* Setup views - Transformed & lit if RHW, else untransformed.
218 Only unlit if Normals are supplied
219 Returns: Whether to restore lighting afterwards */
220 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
222 BOOL isLightingOn = FALSE;
223 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
225 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
226 set by the appropriate render state. Note Vertex Shader output is already lit */
227 if (vtx_lit || useVS) {
228 isLightingOn = glIsEnabled(GL_LIGHTING);
229 glDisable(GL_LIGHTING);
230 checkGLcall("glDisable(GL_LIGHTING);");
231 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
234 if (!useVS && vtx_transformed) {
236 /* If the last draw was transformed as well, no need to reapply all the matrixes */
237 if (!This->last_was_rhw) {
239 double X, Y, height, width, minZ, maxZ;
240 This->last_was_rhw = TRUE;
242 /* Transformed already into viewport coordinates, so we do not need transform
243 matrices. Reset all matrices to identity and leave the default matrix in world
245 glMatrixMode(GL_MODELVIEW);
246 checkGLcall("glMatrixMode");
248 checkGLcall("glLoadIdentity");
250 glMatrixMode(GL_PROJECTION);
251 checkGLcall("glMatrixMode");
253 checkGLcall("glLoadIdentity");
255 /* Set up the viewport to be full viewport */
256 X = This->stateBlock->viewport.X;
257 Y = This->stateBlock->viewport.Y;
258 height = This->stateBlock->viewport.Height;
259 width = This->stateBlock->viewport.Width;
260 minZ = This->stateBlock->viewport.MinZ;
261 maxZ = This->stateBlock->viewport.MaxZ;
262 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
263 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
264 checkGLcall("glOrtho");
266 /* Window Coord 0 is the middle of the first pixel, so translate by half
267 a pixel (See comment above glTranslate below) */
268 glTranslatef(0.5, 0.5, 0);
269 checkGLcall("glTranslatef(0.5, 0.5, 0)");
270 if (This->renderUpsideDown) {
271 glMultMatrixf(invymat);
272 checkGLcall("glMultMatrixf(invymat)");
278 /* Untransformed, so relies on the view and projection matrices */
280 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
281 /* Only reapply when have to */
282 This->modelview_valid = TRUE;
283 glMatrixMode(GL_MODELVIEW);
284 checkGLcall("glMatrixMode");
286 /* In the general case, the view matrix is the identity matrix */
287 if (This->view_ident) {
288 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
289 checkGLcall("glLoadMatrixf");
291 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
292 checkGLcall("glLoadMatrixf");
293 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
294 checkGLcall("glMultMatrixf");
298 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
299 /* Only reapply when have to */
300 This->proj_valid = TRUE;
301 glMatrixMode(GL_PROJECTION);
302 checkGLcall("glMatrixMode");
304 /* The rule is that the window coordinate 0 does not correspond to the
305 beginning of the first pixel, but the center of the first pixel.
306 As a consequence if you want to correctly draw one line exactly from
307 the left to the right end of the viewport (with all matrices set to
308 be identity), the x coords of both ends of the line would be not
309 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
312 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
313 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
315 if (This->renderUpsideDown) {
316 glMultMatrixf(invymat);
317 checkGLcall("glMultMatrixf(invymat)");
319 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
320 checkGLcall("glLoadMatrixf");
323 /* Vertex Shader output is already transformed, so set up identity matrices */
324 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
325 come along this needs to take into account whether s/w ones were
328 glMatrixMode(GL_MODELVIEW);
329 checkGLcall("glMatrixMode");
331 glMatrixMode(GL_PROJECTION);
332 checkGLcall("glMatrixMode");
334 /* Window Coord 0 is the middle of the first pixel, so translate by half
335 a pixel (See comment above glTranslate above) */
336 glTranslatef(1.0/This->stateBlock->viewport.Width, -1.0/This->stateBlock->viewport.Height, 0);
337 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
338 if (This->renderUpsideDown) {
339 glMultMatrixf(invymat);
340 checkGLcall("glMultMatrixf(invymat)");
342 This->modelview_valid = FALSE;
343 This->proj_valid = FALSE;
345 This->last_was_rhw = FALSE;
350 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
351 /* We need to deal with frequency data!*/
355 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
356 IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
358 D3DVERTEXELEMENT9 *element;
360 for(i = 0 ; i < vertexDeclaration->declaration9NumElements -1; i++){
362 element = vertexDeclaration->pDeclaration9 + i;
363 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclaration9, element, i, vertexDeclaration->declaration9NumElements);
364 if (This->stateBlock->streamIsUP) {
365 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
366 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
368 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
369 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory;
371 stride = This->stateBlock->streamStride[element->Stream];
372 data += (BaseVertexIndex * stride);
373 data += element->Offset;
374 /* Why can't I just use a lookup table instead of a switch statment? */
375 switch(element->Usage){
376 case D3DDECLUSAGE_POSITION:
377 switch(element->UsageIndex){
378 case 0: /* N-patch */
379 strided->u.s.position.lpData = data;
380 strided->u.s.position.dwType = element->Type;
381 strided->u.s.position.dwStride = stride;
383 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
384 FIXME("Tweened positions\n");
388 case D3DDECLUSAGE_NORMAL:
389 switch(element->UsageIndex){
390 case 0: /* N-patch */
391 strided->u.s.normal.lpData = data;
392 strided->u.s.normal.dwType = element->Type;
393 strided->u.s.normal.dwStride = stride;
395 case 1: /* skinning */
396 FIXME("Skinning normals\n");
399 *fvf |= D3DFVF_NORMAL;
401 case D3DDECLUSAGE_BLENDINDICES:
402 /* demo @http://www.ati.com/developer/vertexblend.html
403 and http://www.flipcode.com/articles/article_dx8shaders.shtml
405 strided->u.s.blendMatrixIndices.lpData = data;
406 strided->u.s.blendMatrixIndices.dwType = element->Type;
407 strided->u.s.blendMatrixIndices.dwStride= stride;
409 case D3DDECLUSAGE_BLENDWEIGHT:
410 strided->u.s.blendWeights.lpData = data;
411 strided->u.s.blendWeights.dwType = element->Type;
412 strided->u.s.blendWeights.dwStride = stride;
414 case D3DDECLUSAGE_PSIZE:
415 strided->u.s.pSize.lpData = data;
416 strided->u.s.pSize.dwType = element->Type;
417 strided->u.s.pSize.dwStride = stride;
419 case D3DDECLUSAGE_COLOR:
420 switch(element->UsageIndex){
422 strided->u.s.diffuse.lpData = data;
423 strided->u.s.diffuse.dwType = element->Type;
424 strided->u.s.diffuse.dwStride = stride;
426 case 1: /* specular */
427 strided->u.s.specular.lpData = data;
428 strided->u.s.specular.dwType = element->Type;
429 strided->u.s.specular.dwStride = stride;
433 case D3DDECLUSAGE_TEXCOORD:
434 /* For some odd reason Microsoft decided to sum usage accross all the streams,
435 which means we need to do a count and not just use the usage number */
437 strided->u.s.texCoords[textureNo].lpData = data;
438 strided->u.s.texCoords[textureNo].dwType = element->Type;
439 strided->u.s.texCoords[textureNo].dwStride = stride;
443 case D3DDECLUSAGE_TANGENT:
444 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
445 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
446 normal using tangents where no normal data has been provided */
448 strided->u.s.tangent.lpData = data;
449 strided->u.s.tangent.dwType = element->type;
450 strided->u.s.tangent.dsString = stride;
454 case D3DDECLUSAGE_BINORMAL:
455 /* Binormals are really bitangents perpendicular to the normal but s-aligned to the tangent, basically they are the vectors of any two lines on the plain at right angles to the normal and at right angles to each other, like the x,y,z axis.
456 tangent data makes it easier to perform some calculations (a bit like using 2d graph paper instead of the normal of the piece of paper)
457 The only thing they are useful for in fixed function would be working out normals when none are given.
460 strided->u.s.binormal.lpData = data;
461 strided->u.s.binormal.dwType = element->type;
462 strided->u.s.binormal.dsString = stride;
464 /* Don't bother showing fixme's tangents aren't that interesting */
465 TRACE("BI-Normal\n");
467 case D3DDECLUSAGE_TESSFACTOR:
468 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
471 strided->u.s.tessFacrot.lpData = data;
472 strided->u.s.tessFactor.dwType = element->type;
473 strided->u.s.tessFactor.dsString = stride;
475 FIXME("Tess Factor\n");
478 case D3DDECLUSAGE_POSITIONT:
480 switch(element->UsageIndex){
481 case 0: /* N-patch */
482 strided->u.s.position.lpData = data;
483 strided->u.s.position.dwType = element->Type;
484 strided->u.s.position.dwStride = stride;
486 case 1: /* skinning */
487 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
488 http://xface.blogspot.com/2004_08_01_xface_archive.html
490 FIXME("Skinning positionsT\n");
493 /* TODO: change fvf usage to a plain boolean flag */
494 *fvf |= D3DFVF_XYZRHW;
495 /* FIXME: were faking this flag so that we don't transform the data again */
497 case D3DDECLUSAGE_FOG:
498 /* maybe GL_EXT_fog_coord ?
499 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
500 * This extension allows specifying an explicit per-vertex fog
501 * coordinate to be used in fog computations, rather than using a
502 * fragment depth-based fog equation.
506 strided->u.s.fog.lpData = data;
507 strided->u.s.fog.dwType = element->type;
508 strided->u.s.fog.dsString = stride;
513 case D3DDECLUSAGE_DEPTH:
516 strided->u.s.depth.lpData = data;
517 strided->u.s.depth.dwType = element->type;
518 strided->u.s.depth.dsString = stride;
522 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
524 strided->u.s.sample.lpData = data;
525 strided->u.s.sample.dwType = element->type;
526 strided->u.s.sample.dsString = stride;
536 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
538 short LoopThroughTo = 0;
540 BOOL canDoViaGLPointers = TRUE;
544 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
545 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
547 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
549 /* OK, Now to setup the data locations
550 For the non-created vertex shaders, the VertexShader var holds the real
551 FVF and only stream 0 matters
552 For the created vertex shaders, there is an FVF per stream */
553 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
554 LoopThroughTo = MAX_STREAMS;
559 /* Work through stream by stream */
560 for (nStream=0; nStream<LoopThroughTo; nStream++) {
561 DWORD stride = This->stateBlock->streamStride[nStream];
565 /* Skip empty streams */
566 if (This->stateBlock->streamSource[nStream] == NULL) continue;
568 /* Retrieve appropriate FVF */
569 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
570 thisFVF = This->stateBlock->fvf;
571 /* Handle memory passed directly as well as vertex buffers */
572 if (This->stateBlock->streamIsUP) {
573 data = (BYTE *)This->stateBlock->streamSource[nStream];
575 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->streamSource[nStream])->resource.allocatedMemory;
578 #if 0 /* TODO: Vertex shader support */
579 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
580 data = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->streamSource[nStream])->allocatedMemory;
583 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
584 if (thisFVF == 0) continue;
586 /* Now convert the stream into pointers */
588 /* Shuffle to the beginning of the vertexes to render and index from there */
589 data = data + (BaseVertexIndex * stride);
591 /* Either 3 or 4 floats depending on the FVF */
592 /* FIXME: Can blending data be in a different stream to the position data?
593 and if so using the fixed pipeline how do we handle it */
594 if (thisFVF & D3DFVF_POSITION_MASK) {
595 strided->u.s.position.lpData = data;
596 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
597 strided->u.s.position.dwStride = stride;
598 data += 3 * sizeof(float);
599 if (thisFVF & D3DFVF_XYZRHW) {
600 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
601 data += sizeof(float);
605 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
606 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
607 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
608 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
610 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
611 TRACE("Setting blend Weights to %p \n", data);
612 strided->u.s.blendWeights.lpData = data;
613 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
614 strided->u.s.blendWeights.dwStride = stride;
615 data += numBlends * sizeof(FLOAT);
617 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
618 strided->u.s.blendMatrixIndices.lpData = data;
619 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
620 strided->u.s.blendMatrixIndices.dwStride= stride;
621 data += sizeof(DWORD);
625 /* Normal is always 3 floats */
626 if (thisFVF & D3DFVF_NORMAL) {
627 strided->u.s.normal.lpData = data;
628 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
629 strided->u.s.normal.dwStride = stride;
630 data += 3 * sizeof(FLOAT);
633 /* Pointsize is a single float */
634 if (thisFVF & D3DFVF_PSIZE) {
635 strided->u.s.pSize.lpData = data;
636 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
637 strided->u.s.pSize.dwStride = stride;
638 data += sizeof(FLOAT);
641 /* Diffuse is 4 unsigned bytes */
642 if (thisFVF & D3DFVF_DIFFUSE) {
643 strided->u.s.diffuse.lpData = data;
644 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
645 strided->u.s.diffuse.dwStride = stride;
646 data += sizeof(DWORD);
649 /* Specular is 4 unsigned bytes */
650 if (thisFVF & D3DFVF_SPECULAR) {
651 strided->u.s.specular.lpData = data;
652 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
653 strided->u.s.specular.dwStride = stride;
654 data += sizeof(DWORD);
658 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
659 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
661 /* numTextures indicates the number of texture coordinates supplied */
662 /* However, the first set may not be for stage 0 texture - it all */
663 /* depends on D3DTSS_TEXCOORDINDEX. */
664 /* The number of bytes for each coordinate set is based off */
665 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
667 /* So, for each supplied texture extract the coords */
668 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
670 strided->u.s.texCoords[textureNo].lpData = data;
671 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
672 strided->u.s.texCoords[textureNo].dwStride = stride;
673 numCoords[textureNo] = coordIdxInfo & 0x03;
676 data += sizeof(float);
677 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
678 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
679 data += sizeof(float);
680 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
681 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
682 data += sizeof(float);
683 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
684 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
685 data += sizeof(float);
689 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
694 /* Draw a single vertex using this information */
695 static void draw_vertex(IWineD3DDevice *iface, /* interface */
696 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
697 BOOL isNormal, float nx, float ny, float nz, /* normal */
698 BOOL isDiffuse, float *dRGBA, /* 1st colors */
699 BOOL isSpecular, float *sRGB, /* 2ndry colors */
700 BOOL isPtSize, float ptSize, /* pointSize */
701 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
703 unsigned int textureNo;
705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
707 /* Diffuse -------------------------------- */
710 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
713 /* Specular Colour ------------------------------------------*/
715 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
716 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
717 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
719 VTRACE(("Specular color extensions not supplied\n"));
723 /* Normal -------------------------------- */
725 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
726 glNormal3f(nx, ny, nz);
729 /* Point Size ----------------------------------------------*/
732 /* no such functionality in the fixed function GL pipeline */
733 FIXME("Cannot change ptSize here in openGl\n");
736 /* Texture coords --------------------------- */
737 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
739 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
740 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
744 /* Query tex coords */
745 if (This->stateBlock->textures[textureNo] != NULL) {
747 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
749 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
751 } else if (numcoords[coordIdx] == 0) {
752 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
756 /* Initialize vars */
762 switch (numcoords[coordIdx]) {
763 case 4: q = texcoords[coordIdx].w; /* drop through */
764 case 3: r = texcoords[coordIdx].z; /* drop through */
765 case 2: t = texcoords[coordIdx].y; /* drop through */
766 case 1: s = texcoords[coordIdx].x;
769 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
771 VTRACE(("tex:%d, s=%f\n", textureNo, s));
772 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
773 GLMULTITEXCOORD1F(textureNo, s);
779 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
780 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
781 GLMULTITEXCOORD2F(textureNo, s, t);
787 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
788 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
789 GLMULTITEXCOORD3F(textureNo, s, t, r);
791 glTexCoord3f(s, t, r);
795 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
796 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
797 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
799 glTexCoord4f(s, t, r, q);
803 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
807 } /* End of textures */
809 /* Position -------------------------------- */
811 if (1.0f == rhw || rhw < 0.00001f) {
812 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
815 /* Cannot optimize by dividing through by rhw as rhw is required
816 later for perspective in the GL pipeline for vertex shaders */
817 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
818 glVertex4f(x,y,z,rhw);
824 * Actually draw using the supplied information.
825 * Faster GL version using pointers to data, harder to debug though
826 * Note does not handle vertex shaders yet
828 static void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
829 int PrimitiveType, ULONG NumPrimitives,
830 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
831 unsigned int textureNo = 0;
832 GLenum glPrimType = GL_POINTS;
833 int NumVertexes = NumPrimitives;
834 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
836 TRACE("Using fast vertex array code\n");
838 /* Vertex Pointers -----------------------------------------*/
839 if (sd->u.s.position.lpData != NULL) {
841 /* Note dwType == float3 or float4 == 2 or 3 */
842 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
843 sd->u.s.position.dwStride,
844 sd->u.s.position.dwType + 1,
845 sd->u.s.position.lpData));
847 /* Disable RHW mode as 'w' coord handling for rhw mode should
848 not impact screen position whereas in GL it does. This may
849 result in very slightly distored textures in rhw mode, but
850 a very minimal different */
851 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
852 sd->u.s.position.dwStride,
853 sd->u.s.position.lpData);
854 checkGLcall("glVertexPointer(...)");
855 glEnableClientState(GL_VERTEX_ARRAY);
856 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
860 glDisableClientState(GL_VERTEX_ARRAY);
861 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
864 /* Blend Data ----------------------------------------------*/
865 if ((sd->u.s.blendWeights.lpData != NULL) ||
866 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
867 #if 1 /* Vertex blend support needs to be added */
868 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
869 DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
870 int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
872 /* Note dwType == float3 or float4 == 2 or 3 */
873 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
875 sd->u.s.blendWeights.dwStride,
876 sd->u.s.blendWeights.lpData));
877 GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
878 sd->u.s.blendWeights.dwStride,
879 sd->u.s.blendWeights.lpData);
880 checkGLcall("glWeightPointerARB(...)");
881 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
882 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
883 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
886 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
887 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
888 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
889 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
892 FIXME("unsupported blending in openGl\n");
895 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
896 TRACE("TODO ARB_VERTEX_BLEND\n");
897 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
898 TRACE("TODO EXT_VERTEX_WEIGHTING\n");
900 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
901 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
905 /* FIXME: Won't get here as will drop to slow method */
906 FIXME("Blending not supported in fast draw routine\n");
910 /* Normals -------------------------------------------------*/
911 if (sd->u.s.normal.lpData != NULL) {
913 /* Note dwType == float3 or float4 == 2 or 3 */
914 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
915 sd->u.s.normal.dwStride,
916 sd->u.s.normal.lpData));
917 glNormalPointer(GL_FLOAT,
918 sd->u.s.normal.dwStride,
919 sd->u.s.normal.lpData);
920 checkGLcall("glNormalPointer(...)");
921 glEnableClientState(GL_NORMAL_ARRAY);
922 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
926 glDisableClientState(GL_NORMAL_ARRAY);
927 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
929 checkGLcall("glNormal3f(0, 0, 1)");
932 /* Point Size ----------------------------------------------*/
933 if (sd->u.s.pSize.lpData != NULL) {
935 /* no such functionality in the fixed function GL pipeline */
936 /* FIXME: Won't get here as will drop to slow method */
937 FIXME("Cannot change ptSize here in openGl\n");
940 /* Diffuse Colour ------------------------------------------*/
941 /* WARNING: Data here MUST be in RGBA format, so cannot */
942 /* go directly into fast mode from app pgm, because */
943 /* directx requires data in BGRA format. */
944 if (sd->u.s.diffuse.lpData != NULL) {
946 /* Note dwType == float3 or float4 == 2 or 3 */
947 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
948 sd->u.s.diffuse.dwStride,
949 sd->u.s.diffuse.lpData));
950 glColorPointer(4, GL_UNSIGNED_BYTE,
951 sd->u.s.diffuse.dwStride,
952 sd->u.s.diffuse.lpData);
953 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
954 glEnableClientState(GL_COLOR_ARRAY);
955 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
959 glDisableClientState(GL_COLOR_ARRAY);
960 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
961 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
962 checkGLcall("glColor4f(1, 1, 1, 1)");
965 /* Specular Colour ------------------------------------------*/
966 if (sd->u.s.specular.lpData != NULL) {
968 /* Note dwType == float3 or float4 == 2 or 3 */
969 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
970 sd->u.s.specular.dwStride,
971 sd->u.s.specular.lpData));
973 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
974 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
975 sd->u.s.specular.dwStride,
976 sd->u.s.specular.lpData);
977 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
978 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
979 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
981 /* Missing specular color is not critical, no warnings */
982 VTRACE(("Specular colour is not supported in this GL implementation\n"));
987 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
988 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
989 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
990 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
991 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
993 /* Missing specular color is not critical, no warnings */
994 VTRACE(("Specular colour is not supported in this GL implementation\n"));
998 /* Texture coords -------------------------------------------*/
999 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1001 /* Select the correct texture stage */
1002 GLCLIENTACTIVETEXTURE(textureNo);
1004 /* Query tex coords */
1005 if (This->stateBlock->textures[textureNo] != NULL) {
1006 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1008 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1009 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1010 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1011 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1016 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1017 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1018 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1020 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1021 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1022 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1023 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1027 /* The coords to supply depend completely on the fvf / vertex shader */
1031 switch (sd->u.s.texCoords[coordIdx].dwType) {
1032 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
1033 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
1034 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
1035 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
1036 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
1037 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
1038 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
1039 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
1040 size = 4; type = GL_UNSIGNED_BYTE;
1043 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1044 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1047 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1048 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1052 /* Ok, Work out which primitive is requested and how many vertexes that
1054 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1056 /* Finally do the drawing */
1057 if (idxData != NULL) {
1059 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1060 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1061 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1062 (const char *)idxData+(idxSize * startIdx));
1064 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1065 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1066 (const char *)idxData+(idxSize * startIdx));
1068 checkGLcall("glDrawRangeElements");
1072 /* Note first is now zero as we shuffled along earlier */
1073 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1074 glDrawArrays(glPrimType, 0, NumVertexes);
1075 checkGLcall("glDrawArrays");
1081 * Actually draw using the supplied information.
1082 * Slower GL version which extracts info about each vertex in turn
1084 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1085 int PrimitiveType, ULONG NumPrimitives,
1086 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1088 unsigned int textureNo = 0;
1089 GLenum glPrimType = GL_POINTS;
1090 int NumVertexes = NumPrimitives;
1091 const short *pIdxBufS = NULL;
1092 const long *pIdxBufL = NULL;
1093 LONG SkipnStrides = 0;
1095 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1096 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1097 float rhw = 0.0f; /* rhw */
1098 float ptSize = 0.0f; /* Point size */
1099 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1100 DWORD specularColor = 0; /* Specular Color */
1101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1103 TRACE("Using slow vertex array code\n");
1105 /* Variable Initialization */
1106 if (idxData != NULL) {
1107 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1108 else pIdxBufL = (const long *) idxData;
1111 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1112 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1114 /* Start drawing in GL */
1115 VTRACE(("glBegin(%x)\n", glPrimType));
1116 glBegin(glPrimType);
1118 /* For each primitive */
1119 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1121 /* Initialize diffuse color */
1122 diffuseColor = 0xFFFFFFFF;
1124 /* For indexed data, we need to go a few more strides in */
1125 if (idxData != NULL) {
1127 /* Indexed so work out the number of strides to skip */
1129 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1130 SkipnStrides = pIdxBufS[startIdx+vx_index];
1132 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1133 SkipnStrides = pIdxBufL[startIdx+vx_index];
1137 /* Position Information ------------------ */
1138 if (sd->u.s.position.lpData != NULL) {
1140 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1145 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1147 /* RHW follows, only if transformed, ie 4 floats were provided */
1148 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1149 rhw = ptrToCoords[3];
1150 VTRACE(("rhw=%f\n", rhw));
1154 /* Blending data -------------------------- */
1155 if (sd->u.s.blendWeights.lpData != NULL) {
1156 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1157 FIXME("Blending not supported yet\n");
1159 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1160 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1164 /* Vertex Normal Data (untransformed only)- */
1165 if (sd->u.s.normal.lpData != NULL) {
1167 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1168 nx = ptrToCoords[0];
1169 ny = ptrToCoords[1];
1170 nz = ptrToCoords[2];
1171 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1174 /* Point Size ----------------------------- */
1175 if (sd->u.s.pSize.lpData != NULL) {
1177 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1178 ptSize = ptrToCoords[0];
1179 VTRACE(("ptSize=%f\n", ptSize));
1180 FIXME("No support for ptSize yet\n");
1183 /* Diffuse -------------------------------- */
1184 if (sd->u.s.diffuse.lpData != NULL) {
1186 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1187 diffuseColor = ptrToCoords[0];
1188 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1191 /* Specular -------------------------------- */
1192 if (sd->u.s.specular.lpData != NULL) {
1194 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1195 specularColor = ptrToCoords[0];
1196 VTRACE(("specularColor=%lx\n", specularColor));
1199 /* Texture coords --------------------------- */
1200 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1202 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1203 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1207 /* Query tex coords */
1208 if (This->stateBlock->textures[textureNo] != NULL) {
1210 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1211 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1212 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1215 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1217 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1218 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1222 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1224 /* The coords to supply depend completely on the fvf / vertex shader */
1225 switch (coordsToUse) {
1226 case 4: q = ptrToCoords[3]; /* drop through */
1227 case 3: r = ptrToCoords[2]; /* drop through */
1228 case 2: t = ptrToCoords[1]; /* drop through */
1229 case 1: s = ptrToCoords[0];
1232 /* Projected is more 'fun' - Move the last coord to the 'q'
1233 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1234 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1235 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1237 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1238 switch (coordsToUse) {
1239 case 0: /* Drop Through */
1241 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1253 case 4: /* Nop here */
1256 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1257 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1262 /* crude support for non-power2 textures */
1263 if(((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2){
1264 t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
1265 s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
1268 switch (coordsToUse) { /* Supply the provided texture coords */
1269 case D3DTTFF_COUNT1:
1270 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1271 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1272 GLMULTITEXCOORD1F(textureNo, s);
1277 case D3DTTFF_COUNT2:
1278 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1279 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1280 GLMULTITEXCOORD2F(textureNo, s, t);
1285 case D3DTTFF_COUNT3:
1286 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1287 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1288 GLMULTITEXCOORD3F(textureNo, s, t, r);
1290 glTexCoord3f(s, t, r);
1293 case D3DTTFF_COUNT4:
1294 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1295 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1296 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1298 glTexCoord4f(s, t, r, q);
1302 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1306 } /* End of textures */
1308 /* Diffuse -------------------------------- */
1309 if (sd->u.s.diffuse.lpData != NULL) {
1310 glColor4ub((diffuseColor >> 16) & 0xFF,
1311 (diffuseColor >> 8) & 0xFF,
1312 (diffuseColor >> 0) & 0xFF,
1313 (diffuseColor >> 24) & 0xFF);
1314 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1315 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1316 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1317 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1318 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1320 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1323 /* Specular ------------------------------- */
1324 if (sd->u.s.diffuse.lpData != NULL) {
1325 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1326 ((specularColor >> 16) & 0xFF) / 255.0f,
1327 ((specularColor >> 8) & 0xFF) / 255.0f,
1328 ((specularColor >> 0) & 0xFF) / 255.0f));
1329 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1330 GL_EXTCALL(glSecondaryColor3ubEXT)(
1331 (specularColor >> 16) & 0xFF,
1332 (specularColor >> 8) & 0xFF,
1333 (specularColor >> 0) & 0xFF);
1335 /* Do not worry if specular colour missing and disable request */
1336 VTRACE(("Specular color extensions not supplied\n"));
1339 if (vx_index == 0) {
1340 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1341 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1343 /* Do not worry if specular colour missing and disable request */
1344 VTRACE(("Specular color extensions not supplied\n"));
1349 /* Normal -------------------------------- */
1350 if (sd->u.s.normal.lpData != NULL) {
1351 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1352 glNormal3f(nx, ny, nz);
1354 if (vx_index == 0) glNormal3f(0, 0, 1);
1357 /* Position -------------------------------- */
1358 if (sd->u.s.position.lpData != NULL) {
1359 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1360 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1361 glVertex3f(x, y, z);
1363 GLfloat w = 1.0 / rhw;
1364 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1365 glVertex4f(x*w, y*w, z*w, w);
1369 /* For non indexed mode, step onto next parts */
1370 if (idxData == NULL) {
1376 checkGLcall("glEnd and previous calls");
1379 #if 0 /* TODO: Software/Hardware vertex blending support */
1381 * Draw with emulated vertex shaders
1382 * Note: strided data is uninitialized, as we need to pass the vertex
1383 * shader directly as ordering irs yet
1385 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1386 int PrimitiveType, ULONG NumPrimitives,
1387 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1389 unsigned int textureNo = 0;
1390 GLenum glPrimType = GL_POINTS;
1391 int NumVertexes = NumPrimitives;
1392 const short *pIdxBufS = NULL;
1393 const long *pIdxBufL = NULL;
1394 LONG SkipnStrides = 0;
1396 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1397 float rhw = 0.0f; /* rhw */
1398 float ptSize = 0.0f; /* Point size */
1399 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1400 int numcoords[8]; /* Number of coords */
1401 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1403 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1405 TRACE("Using slow software vertex shader code\n");
1407 /* Variable Initialization */
1408 if (idxData != NULL) {
1409 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1410 else pIdxBufL = (const long *) idxData;
1413 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1414 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1416 /* Retrieve the VS information */
1417 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1419 /* Start drawing in GL */
1420 VTRACE(("glBegin(%x)\n", glPrimType));
1421 glBegin(glPrimType);
1423 /* For each primitive */
1424 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1426 /* For indexed data, we need to go a few more strides in */
1427 if (idxData != NULL) {
1429 /* Indexed so work out the number of strides to skip */
1431 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1432 SkipnStrides = pIdxBufS[startIdx+vx_index];
1434 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1435 SkipnStrides = pIdxBufL[startIdx+vx_index];
1439 /* Fill the vertex shader input */
1440 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1442 /* Initialize the output fields to the same defaults as it would normally have */
1443 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1444 vertex_shader->output.oD[0].x = 1.0;
1445 vertex_shader->output.oD[0].y = 1.0;
1446 vertex_shader->output.oD[0].z = 1.0;
1447 vertex_shader->output.oD[0].w = 1.0;
1449 /* Now execute the vertex shader */
1450 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1453 TRACE_VECTOR(vertex_shader->output.oPos);
1454 TRACE_VECTOR(vertex_shader->output.oD[0]);
1455 TRACE_VECTOR(vertex_shader->output.oD[1]);
1456 TRACE_VECTOR(vertex_shader->output.oT[0]);
1457 TRACE_VECTOR(vertex_shader->output.oT[1]);
1458 TRACE_VECTOR(vertex_shader->input.V[0]);
1459 TRACE_VECTOR(vertex_shader->data->C[0]);
1460 TRACE_VECTOR(vertex_shader->data->C[1]);
1461 TRACE_VECTOR(vertex_shader->data->C[2]);
1462 TRACE_VECTOR(vertex_shader->data->C[3]);
1463 TRACE_VECTOR(vertex_shader->data->C[4]);
1464 TRACE_VECTOR(vertex_shader->data->C[5]);
1465 TRACE_VECTOR(vertex_shader->data->C[6]);
1466 TRACE_VECTOR(vertex_shader->data->C[7]);
1469 /* Extract out the output */
1470 /*FIXME: Fog coords? */
1471 x = vertex_shader->output.oPos.x;
1472 y = vertex_shader->output.oPos.y;
1473 z = vertex_shader->output.oPos.z;
1474 rhw = vertex_shader->output.oPos.w;
1475 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1477 /** Update textures coords using vertex_shader->output.oT[0->7] */
1478 memset(texcoords, 0x00, sizeof(texcoords));
1479 memset(numcoords, 0x00, sizeof(numcoords));
1480 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1481 if (This->stateBlock->textures[textureNo] != NULL) {
1482 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1483 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1484 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1485 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1486 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1487 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1489 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1490 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1491 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1492 default: numcoords[textureNo] = 4;
1496 numcoords[textureNo] = 0;
1500 /* Draw using this information */
1503 TRUE, 0.0f, 0.0f, 1.0f,
1504 TRUE, (float*) &vertex_shader->output.oD[0],
1505 TRUE, (float*) &vertex_shader->output.oD[1],
1506 FALSE, ptSize, /* FIXME: Change back when supported */
1507 texcoords, numcoords);
1509 /* For non indexed mode, step onto next parts */
1510 if (idxData == NULL) {
1514 } /* for each vertex */
1517 checkGLcall("glEnd and previous calls");
1520 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1521 int PrimitiveType, ULONG NumPrimitives,
1522 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1524 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1531 TRACE("Drawing with hardware vertex shaders\n");
1533 /* Retrieve the VS information */
1534 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1536 /* Enable the Vertex Shader */
1537 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1538 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1539 glEnable(GL_VERTEX_PROGRAM_ARB);
1540 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1542 /* Update the constants */
1543 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1544 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1545 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1548 /* Set up the vertex.attr[n] inputs */
1549 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1551 /* Ok, Work out which primitive is requested and how many vertexes that
1553 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1555 /* Finally do the drawing */
1556 if (idxData != NULL) {
1558 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1559 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1560 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1561 (const char *)idxData+(idxSize * startIdx));
1563 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1564 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1565 (const char *)idxData+(idxSize * startIdx));
1567 checkGLcall("glDrawRangeElements");
1571 /* Note first is now zero as we shuffled along earlier */
1572 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1573 glDrawArrays(glPrimType, 0, NumVertexes);
1574 checkGLcall("glDrawArrays");
1580 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1582 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1586 /* Leave all the attribs disabled */
1587 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1588 /* MESA does not support it right not */
1589 if (glGetError() != GL_NO_ERROR)
1591 for (i=0; i<maxAttribs; i++) {
1592 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1593 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1597 glDisable(GL_VERTEX_PROGRAM_ARB);
1601 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf){
1603 /* Dump out what parts we have supplied */
1604 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1605 TRACE_STRIDED((dataLocations), position);
1606 TRACE_STRIDED((dataLocations), blendWeights);
1607 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1608 TRACE_STRIDED((dataLocations), normal);
1609 TRACE_STRIDED((dataLocations), pSize);
1610 TRACE_STRIDED((dataLocations), diffuse);
1611 TRACE_STRIDED((dataLocations), specular);
1612 TRACE_STRIDED((dataLocations), texCoords[0]);
1613 TRACE_STRIDED((dataLocations), texCoords[1]);
1614 TRACE_STRIDED((dataLocations), texCoords[2]);
1615 TRACE_STRIDED((dataLocations), texCoords[3]);
1616 TRACE_STRIDED((dataLocations), texCoords[4]);
1617 TRACE_STRIDED((dataLocations), texCoords[5]);
1618 TRACE_STRIDED((dataLocations), texCoords[6]);
1619 TRACE_STRIDED((dataLocations), texCoords[7]);
1624 /* loads any dirty textures and returns true if any of the textures are nonpower2 */
1625 BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
1626 BOOL nonPower2 = FALSE;
1628 register IWineD3DBaseTexture *texture;
1629 /* And re-upload any dirty textures */
1630 for (i = 0; i<GL_LIMITS(textures); ++i) {
1631 texture = This->stateBlock->textures[i];
1632 if (texture != NULL) {
1633 if(IWineD3DBaseTexture_GetDirty(texture)) {
1634 /* Load up the texture now */
1635 IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
1637 if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
1638 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1639 IWineD3DSurface *surface;
1640 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
1641 if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
1650 /* Routine common to the draw primitive and draw indexed primitive routines */
1651 void drawPrimitive(IWineD3DDevice *iface,
1652 int PrimitiveType, long NumPrimitives,
1655 long StartVertexIndex,
1658 const void *idxData,
1663 #if 0 /* TODO: vertex and pixel shaders */
1664 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1665 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1668 BOOL useVertexShaderFunction = FALSE;
1669 BOOL isLightingOn = FALSE;
1670 Direct3DVertexStridedData dataLocations;
1672 BOOL nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
1674 if (This->stateBlock->vertexDecl == NULL) {
1675 /* Work out what the FVF should look like */
1676 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1679 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1682 /* If we will be using a vertex shader, do some initialization for it */
1683 if (useVertexShaderFunction) {
1684 #if 0 /* TODO: vertex and pixel shaders */
1685 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1686 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1688 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1689 This->devType != D3DDEVTYPE_REF &&
1690 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1691 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1693 /** init Constants */
1694 if (This->stateBlock->Changed.vertexShaderConstant) {
1695 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1696 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1698 #endif /* TODO: vertex and pixel shaders */
1701 /* Ok, we will be updating the screen from here onwards so grab the lock */
1704 #if 0 /* TODO: vertex and pixel shaders */
1705 /* If we will be using a pixel, do some initialization for it */
1706 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1707 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1708 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1710 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1711 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1712 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1713 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1715 /* init Constants */
1716 if (This->stateBlock->Changed.pixelShaderConstant) {
1717 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1718 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1720 /* Update the constants */
1721 for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1722 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1723 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1726 #endif /* TODO: vertex and pixel shaders */
1728 /* Initialize all values to null */
1729 if (useVertexShaderFunction == FALSE) {
1730 memset(&dataLocations, 0x00, sizeof(dataLocations));
1732 /* Convert to strided data */
1733 if(This->stateBlock->vertexDecl != NULL){
1734 TRACE("================ Vertex Declaration ===================\n");
1735 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1737 TRACE("================ FVF ===================\n");
1738 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1741 /* write out some debug information*/
1742 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1744 FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1747 /* Setup transform matrices and sort out */
1749 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1750 So make sure lighting is disabled. */
1751 isLightingOn = glIsEnabled(GL_LIGHTING);
1752 glDisable(GL_LIGHTING);
1753 checkGLcall("glDisable(GL_LIGHTING);");
1754 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1756 isLightingOn = primitiveInitState(iface,
1757 fvf & D3DFVF_XYZRHW,
1758 !(fvf & D3DFVF_NORMAL),
1759 useVertexShaderFunction);
1762 /* Now initialize the materials state */
1763 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1765 nonPower2 = drawPrimitiveUploadDirtyTextures(This);
1767 /* Now draw the graphics to the screen */
1768 if (useVertexShaderFunction) {
1770 /* Ideally, we should have software FV and hardware VS, possibly
1771 depending on the device type? */
1774 TRACE("Swap HW vertex shader\n");
1775 #if 0 /* TODO: vertex and pixel shaders */
1776 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1777 idxData, idxSize, minIndex, StartIdx);
1780 /* We will have to use the very, very slow emulation layer */
1781 TRACE("Swap SW vertex shader\n");
1782 #if 0 /* TODO: vertex and pixel shaders */
1783 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1784 idxData, idxSize, minIndex, StartIdx);
1788 } else if ((dataLocations.u.s.pSize.lpData != NULL)
1789 || (dataLocations.u.s.diffuse.lpData != NULL)
1791 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1793 /* Fixme, Ideally, only use the per-vertex code for software HAL
1794 but until opengl supports all the functions returned to setup
1795 vertex arrays, we need to drop down to the slow mechanism for
1796 certain functions */
1798 /* We will have to use the slow version of GL per vertex setup */
1799 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1800 idxData, idxSize, minIndex, StartIdx);
1804 /* We can use the fast version of GL pointers */
1805 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1806 idxData, idxSize, minIndex, StartIdx);
1809 /* If vertex shaders or no normals, restore previous lighting state */
1810 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1811 if (isLightingOn) glEnable(GL_LIGHTING);
1812 else glDisable(GL_LIGHTING);
1813 TRACE("Restored lighting to original state\n");
1816 #if 0 /* TODO: vertex and pixel shaders */
1821 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1823 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1825 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1829 /* Finshed updating the screen, restore lock */
1831 TRACE("Done all gl drawing\n");
1834 #if defined(SHOW_FRAME_MAKEUP)
1836 if (isDumpingFrames) {
1839 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1840 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1841 TRACE("Saving screenshot %s\n", buffer);
1842 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1843 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1845 #if defined(SHOW_TEXTURE_MAKEUP)
1847 LPDIRECT3DSURFACE8 pSur;
1849 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1850 if (This->stateBlock->textures[textureNo] != NULL) {
1851 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1852 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1853 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1854 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1855 IDirect3DSurface8Impl_Release(pSur);
1860 primCounter = primCounter + 1;