Remove unused variable in primitiveConvertToStridedData().
[wine/wine64.git] / dlls / wined3d / drawprim.c
blobc4b159fd2b0463e5ae91c7ec7f118500d6c65f29
1 /*
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
24 #include "config.h"
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
31 #if 0 /* TODO */
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 */
37 #endif
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
42 to stream 0 */
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
56 streams */
57 #endif
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);
66 } else {
68 #if 0 /* TODO */
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);
77 return TRUE;
79 } else {
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);
88 } else {
89 /* Vertex shader needs calling */
90 *useVertexShaderFunction = TRUE;
91 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
94 #else
95 FIXME("Vertex Shaders not moved into wined3d yet\n");
96 #endif
98 return FALSE;
101 /* Issues the glBegin call for gl given the primitive type and count */
102 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
103 DWORD NumPrimitives,
104 GLenum *primType)
106 DWORD NumVertexes = NumPrimitives;
108 switch (PrimitiveType) {
109 case D3DPT_POINTLIST:
110 TRACE("POINTS\n");
111 *primType = GL_POINTS;
112 NumVertexes = NumPrimitives;
113 break;
115 case D3DPT_LINELIST:
116 TRACE("LINES\n");
117 *primType = GL_LINES;
118 NumVertexes = NumPrimitives * 2;
119 break;
121 case D3DPT_LINESTRIP:
122 TRACE("LINE_STRIP\n");
123 *primType = GL_LINE_STRIP;
124 NumVertexes = NumPrimitives + 1;
125 break;
127 case D3DPT_TRIANGLELIST:
128 TRACE("TRIANGLES\n");
129 *primType = GL_TRIANGLES;
130 NumVertexes = NumPrimitives * 3;
131 break;
133 case D3DPT_TRIANGLESTRIP:
134 TRACE("TRIANGLE_STRIP\n");
135 *primType = GL_TRIANGLE_STRIP;
136 NumVertexes = NumPrimitives + 2;
137 break;
139 case D3DPT_TRIANGLEFAN:
140 TRACE("TRIANGLE_FAN\n");
141 *primType = GL_TRIANGLE_FAN;
142 NumVertexes = NumPrimitives + 2;
143 break;
145 default:
146 FIXME("Unhandled primitive\n");
147 *primType = GL_POINTS;
148 break;
150 return NumVertexes;
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");
200 } else {
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
244 mode. */
245 glMatrixMode(GL_MODELVIEW);
246 checkGLcall("glMatrixMode");
247 glLoadIdentity();
248 checkGLcall("glLoadIdentity");
250 glMatrixMode(GL_PROJECTION);
251 checkGLcall("glMatrixMode");
252 glLoadIdentity();
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)");
276 } else {
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");
290 } else {
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)
310 instead. */
311 glLoadIdentity();
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
326 requested or not */
327 if (useVS) {
328 glMatrixMode(GL_MODELVIEW);
329 checkGLcall("glMatrixMode");
330 glLoadIdentity();
331 glMatrixMode(GL_PROJECTION);
332 checkGLcall("glMatrixMode");
333 glLoadIdentity();
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;
347 return isLightingOn;
350 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
351 /* We need to deal with frequency data!*/
353 int textureNo =0;
354 BYTE *data = NULL;
355 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
356 IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
357 int i;
358 D3DVERTEXELEMENT9 *element;
359 DWORD stride;
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];
367 } else {
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;
382 break;
383 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
384 FIXME("Tweened positions\n");
385 break;
387 break;
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;
394 break;
395 case 1: /* skinning */
396 FIXME("Skinning normals\n");
397 break;
399 *fvf |= D3DFVF_NORMAL;
400 break;
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;
408 break;
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;
413 break;
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;
418 break;
419 case D3DDECLUSAGE_COLOR:
420 switch(element->UsageIndex){
421 case 0:/* diffuse */
422 strided->u.s.diffuse.lpData = data;
423 strided->u.s.diffuse.dwType = element->Type;
424 strided->u.s.diffuse.dwStride = stride;
425 break;
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;
432 break;
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;
441 textureNo++;
442 break;
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 */
447 #if 0
448 strided->u.s.tangent.lpData = data;
449 strided->u.s.tangent.dwType = element->type;
450 strided->u.s.tangent.dsString = stride;
451 #endif
452 TRACE("Tangents\n");
453 break;
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.
459 #if 0
460 strided->u.s.binormal.lpData = data;
461 strided->u.s.binormal.dwType = element->type;
462 strided->u.s.binormal.dsString = stride;
463 #endif
464 /* Don't bother showing fixme's tangents aren't that interesting */
465 TRACE("BI-Normal\n");
466 break;
467 case D3DDECLUSAGE_TESSFACTOR:
468 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
470 #if 0
471 strided->u.s.tessFacrot.lpData = data;
472 strided->u.s.tessFactor.dwType = element->type;
473 strided->u.s.tessFactor.dsString = stride;
474 #else
475 FIXME("Tess Factor\n");
476 #endif
477 break;
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;
485 break;
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");
491 break;
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 */
496 break;
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.
504 * */
505 #if 0
506 strided->u.s.fog.lpData = data;
507 strided->u.s.fog.dwType = element->type;
508 strided->u.s.fog.dsString = stride;
509 #else
510 FIXME("Fog\n");
511 #endif
512 break;
513 case D3DDECLUSAGE_DEPTH:
514 FIXME("depth\n");
515 #if 0
516 strided->u.s.depth.lpData = data;
517 strided->u.s.depth.dwType = element->type;
518 strided->u.s.depth.dsString = stride;
519 #endif
521 break;
522 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
523 #if 0
524 strided->u.s.sample.lpData = data;
525 strided->u.s.sample.dwType = element->type;
526 strided->u.s.sample.dsString = stride;
527 #endif
528 FIXME("depth\n");
529 break;
536 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
538 short LoopThroughTo = 0;
539 short nStream;
540 int numBlends;
541 int numTextures;
542 int textureNo;
543 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
544 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
546 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
548 /* OK, Now to setup the data locations
549 For the non-created vertex shaders, the VertexShader var holds the real
550 FVF and only stream 0 matters
551 For the created vertex shaders, there is an FVF per stream */
552 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
553 LoopThroughTo = MAX_STREAMS;
554 } else {
555 LoopThroughTo = 1;
558 /* Work through stream by stream */
559 for (nStream=0; nStream<LoopThroughTo; nStream++) {
560 DWORD stride = This->stateBlock->streamStride[nStream];
561 BYTE *data = NULL;
562 DWORD thisFVF = 0;
564 /* Skip empty streams */
565 if (This->stateBlock->streamSource[nStream] == NULL) continue;
567 /* Retrieve appropriate FVF */
568 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
569 thisFVF = This->stateBlock->fvf;
570 /* Handle memory passed directly as well as vertex buffers */
571 if (This->stateBlock->streamIsUP) {
572 data = (BYTE *)This->stateBlock->streamSource[nStream];
573 } else {
574 data = ((IWineD3DVertexBufferImpl *)This->stateBlock->streamSource[nStream])->resource.allocatedMemory;
576 } else {
577 #if 0 /* TODO: Vertex shader support */
578 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
579 data = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->streamSource[nStream])->allocatedMemory;
580 #endif
582 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
583 if (thisFVF == 0) continue;
585 /* Now convert the stream into pointers */
587 /* Shuffle to the beginning of the vertexes to render and index from there */
588 data = data + (BaseVertexIndex * stride);
590 /* Either 3 or 4 floats depending on the FVF */
591 /* FIXME: Can blending data be in a different stream to the position data?
592 and if so using the fixed pipeline how do we handle it */
593 if (thisFVF & D3DFVF_POSITION_MASK) {
594 strided->u.s.position.lpData = data;
595 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
596 strided->u.s.position.dwStride = stride;
597 data += 3 * sizeof(float);
598 if (thisFVF & D3DFVF_XYZRHW) {
599 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
600 data += sizeof(float);
604 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
605 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
606 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
607 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
609 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
610 TRACE("Setting blend Weights to %p \n", data);
611 strided->u.s.blendWeights.lpData = data;
612 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
613 strided->u.s.blendWeights.dwStride = stride;
614 data += numBlends * sizeof(FLOAT);
616 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
617 strided->u.s.blendMatrixIndices.lpData = data;
618 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
619 strided->u.s.blendMatrixIndices.dwStride= stride;
620 data += sizeof(DWORD);
624 /* Normal is always 3 floats */
625 if (thisFVF & D3DFVF_NORMAL) {
626 strided->u.s.normal.lpData = data;
627 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
628 strided->u.s.normal.dwStride = stride;
629 data += 3 * sizeof(FLOAT);
632 /* Pointsize is a single float */
633 if (thisFVF & D3DFVF_PSIZE) {
634 strided->u.s.pSize.lpData = data;
635 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
636 strided->u.s.pSize.dwStride = stride;
637 data += sizeof(FLOAT);
640 /* Diffuse is 4 unsigned bytes */
641 if (thisFVF & D3DFVF_DIFFUSE) {
642 strided->u.s.diffuse.lpData = data;
643 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
644 strided->u.s.diffuse.dwStride = stride;
645 data += sizeof(DWORD);
648 /* Specular is 4 unsigned bytes */
649 if (thisFVF & D3DFVF_SPECULAR) {
650 strided->u.s.specular.lpData = data;
651 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
652 strided->u.s.specular.dwStride = stride;
653 data += sizeof(DWORD);
656 /* Texture coords */
657 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
658 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
660 /* numTextures indicates the number of texture coordinates supplied */
661 /* However, the first set may not be for stage 0 texture - it all */
662 /* depends on D3DTSS_TEXCOORDINDEX. */
663 /* The number of bytes for each coordinate set is based off */
664 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
666 /* So, for each supplied texture extract the coords */
667 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
669 strided->u.s.texCoords[textureNo].lpData = data;
670 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
671 strided->u.s.texCoords[textureNo].dwStride = stride;
672 numCoords[textureNo] = coordIdxInfo & 0x03;
674 /* Always one set */
675 data += sizeof(float);
676 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
677 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
678 data += sizeof(float);
679 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
680 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
681 data += sizeof(float);
682 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
683 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
684 data += sizeof(float);
688 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
693 /* Draw a single vertex using this information */
694 static void draw_vertex(IWineD3DDevice *iface, /* interface */
695 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
696 BOOL isNormal, float nx, float ny, float nz, /* normal */
697 BOOL isDiffuse, float *dRGBA, /* 1st colors */
698 BOOL isSpecular, float *sRGB, /* 2ndry colors */
699 BOOL isPtSize, float ptSize, /* pointSize */
700 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
702 unsigned int textureNo;
703 float s, t, r, q;
704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
706 /* Diffuse -------------------------------- */
707 if (isDiffuse) {
708 glColor4fv(dRGBA);
709 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
712 /* Specular Colour ------------------------------------------*/
713 if (isSpecular) {
714 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
715 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
716 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
717 } else {
718 VTRACE(("Specular color extensions not supplied\n"));
722 /* Normal -------------------------------- */
723 if (isNormal) {
724 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
725 glNormal3f(nx, ny, nz);
728 /* Point Size ----------------------------------------------*/
729 if (isPtSize) {
731 /* no such functionality in the fixed function GL pipeline */
732 FIXME("Cannot change ptSize here in openGl\n");
735 /* Texture coords --------------------------- */
736 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
738 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
739 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
740 continue ;
743 /* Query tex coords */
744 if (This->stateBlock->textures[textureNo] != NULL) {
746 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
747 if (coordIdx > 7) {
748 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
749 continue;
750 } else if (numcoords[coordIdx] == 0) {
751 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
752 continue;
753 } else {
755 /* Initialize vars */
756 s = 0.0f;
757 t = 0.0f;
758 r = 0.0f;
759 q = 0.0f;
761 switch (numcoords[coordIdx]) {
762 case 4: q = texcoords[coordIdx].w; /* drop through */
763 case 3: r = texcoords[coordIdx].z; /* drop through */
764 case 2: t = texcoords[coordIdx].y; /* drop through */
765 case 1: s = texcoords[coordIdx].x;
768 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
769 case D3DTTFF_COUNT1:
770 VTRACE(("tex:%d, s=%f\n", textureNo, s));
771 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
772 GLMULTITEXCOORD1F(textureNo, s);
773 } else {
774 glTexCoord1f(s);
776 break;
777 case D3DTTFF_COUNT2:
778 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
779 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
780 GLMULTITEXCOORD2F(textureNo, s, t);
781 } else {
782 glTexCoord2f(s, t);
784 break;
785 case D3DTTFF_COUNT3:
786 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
787 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
788 GLMULTITEXCOORD3F(textureNo, s, t, r);
789 } else {
790 glTexCoord3f(s, t, r);
792 break;
793 case D3DTTFF_COUNT4:
794 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
795 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
796 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
797 } else {
798 glTexCoord4f(s, t, r, q);
800 break;
801 default:
802 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
806 } /* End of textures */
808 /* Position -------------------------------- */
809 if (isXYZ) {
810 if (1.0f == rhw || rhw < 0.00001f) {
811 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
812 glVertex3f(x, y, z);
813 } else {
814 /* Cannot optimize by dividing through by rhw as rhw is required
815 later for perspective in the GL pipeline for vertex shaders */
816 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
817 glVertex4f(x,y,z,rhw);
823 * Actually draw using the supplied information.
824 * Faster GL version using pointers to data, harder to debug though
825 * Note does not handle vertex shaders yet
827 static void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
828 int PrimitiveType, ULONG NumPrimitives,
829 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
830 unsigned int textureNo = 0;
831 GLenum glPrimType = GL_POINTS;
832 int NumVertexes = NumPrimitives;
833 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
835 TRACE("Using fast vertex array code\n");
837 /* Vertex Pointers -----------------------------------------*/
838 if (sd->u.s.position.lpData != NULL) {
840 /* Note dwType == float3 or float4 == 2 or 3 */
841 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
842 sd->u.s.position.dwStride,
843 sd->u.s.position.dwType + 1,
844 sd->u.s.position.lpData));
846 /* Disable RHW mode as 'w' coord handling for rhw mode should
847 not impact screen position whereas in GL it does. This may
848 result in very slightly distored textures in rhw mode, but
849 a very minimal different */
850 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
851 sd->u.s.position.dwStride,
852 sd->u.s.position.lpData);
853 checkGLcall("glVertexPointer(...)");
854 glEnableClientState(GL_VERTEX_ARRAY);
855 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
857 } else {
859 glDisableClientState(GL_VERTEX_ARRAY);
860 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
863 /* Blend Data ----------------------------------------------*/
864 if ((sd->u.s.blendWeights.lpData != NULL) ||
865 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
866 #if 1 /* Vertex blend support needs to be added */
867 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
868 DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
869 int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
871 /* Note dwType == float3 or float4 == 2 or 3 */
872 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
873 numBlends,
874 sd->u.s.blendWeights.dwStride,
875 sd->u.s.blendWeights.lpData));
876 GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
877 sd->u.s.blendWeights.dwStride,
878 sd->u.s.blendWeights.lpData);
879 checkGLcall("glWeightPointerARB(...)");
880 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
881 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
882 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
883 /*FIXME("TODO\n");*/
885 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
886 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
887 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
888 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
890 } else {
891 FIXME("unsupported blending in openGl\n");
893 } else {
894 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
895 TRACE("TODO ARB_VERTEX_BLEND\n");
896 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
897 TRACE("TODO EXT_VERTEX_WEIGHTING\n");
899 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
900 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
903 #else
904 /* FIXME: Won't get here as will drop to slow method */
905 FIXME("Blending not supported in fast draw routine\n");
906 #endif
909 /* Normals -------------------------------------------------*/
910 if (sd->u.s.normal.lpData != NULL) {
912 /* Note dwType == float3 or float4 == 2 or 3 */
913 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
914 sd->u.s.normal.dwStride,
915 sd->u.s.normal.lpData));
916 glNormalPointer(GL_FLOAT,
917 sd->u.s.normal.dwStride,
918 sd->u.s.normal.lpData);
919 checkGLcall("glNormalPointer(...)");
920 glEnableClientState(GL_NORMAL_ARRAY);
921 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
923 } else {
925 glDisableClientState(GL_NORMAL_ARRAY);
926 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
927 glNormal3f(0, 0, 1);
928 checkGLcall("glNormal3f(0, 0, 1)");
931 /* Point Size ----------------------------------------------*/
932 if (sd->u.s.pSize.lpData != NULL) {
934 /* no such functionality in the fixed function GL pipeline */
935 /* FIXME: Won't get here as will drop to slow method */
936 FIXME("Cannot change ptSize here in openGl\n");
939 /* Diffuse Colour ------------------------------------------*/
940 /* WARNING: Data here MUST be in RGBA format, so cannot */
941 /* go directly into fast mode from app pgm, because */
942 /* directx requires data in BGRA format. */
943 if (sd->u.s.diffuse.lpData != NULL) {
945 /* Note dwType == float3 or float4 == 2 or 3 */
946 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
947 sd->u.s.diffuse.dwStride,
948 sd->u.s.diffuse.lpData));
949 glColorPointer(4, GL_UNSIGNED_BYTE,
950 sd->u.s.diffuse.dwStride,
951 sd->u.s.diffuse.lpData);
952 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
953 glEnableClientState(GL_COLOR_ARRAY);
954 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
956 } else {
958 glDisableClientState(GL_COLOR_ARRAY);
959 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
960 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
961 checkGLcall("glColor4f(1, 1, 1, 1)");
964 /* Specular Colour ------------------------------------------*/
965 if (sd->u.s.specular.lpData != NULL) {
967 /* Note dwType == float3 or float4 == 2 or 3 */
968 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
969 sd->u.s.specular.dwStride,
970 sd->u.s.specular.lpData));
972 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
973 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
974 sd->u.s.specular.dwStride,
975 sd->u.s.specular.lpData);
976 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
977 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
978 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
979 } else {
980 /* Missing specular color is not critical, no warnings */
981 VTRACE(("Specular colour is not supported in this GL implementation\n"));
984 } else {
986 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
987 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
988 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
989 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
990 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
991 } else {
992 /* Missing specular color is not critical, no warnings */
993 VTRACE(("Specular colour is not supported in this GL implementation\n"));
997 /* Texture coords -------------------------------------------*/
998 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1000 /* Select the correct texture stage */
1001 GLCLIENTACTIVETEXTURE(textureNo);
1003 /* Query tex coords */
1004 if (This->stateBlock->textures[textureNo] != NULL) {
1005 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1007 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1008 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1009 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1010 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1011 continue;
1014 if (coordIdx > 7) {
1015 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1016 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1017 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1019 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1020 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1021 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1022 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1024 } else {
1026 /* The coords to supply depend completely on the fvf / vertex shader */
1027 GLint size;
1028 GLenum type;
1030 switch (sd->u.s.texCoords[coordIdx].dwType) {
1031 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
1032 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
1033 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
1034 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
1035 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
1036 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
1037 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
1038 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
1039 size = 4; type = GL_UNSIGNED_BYTE;
1042 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1043 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1045 } else {
1046 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1047 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1051 /* Ok, Work out which primitive is requested and how many vertexes that
1052 will be */
1053 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1055 /* Finally do the drawing */
1056 if (idxData != NULL) {
1058 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1059 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1060 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1061 (const char *)idxData+(idxSize * startIdx));
1062 #else
1063 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1064 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1065 (const char *)idxData+(idxSize * startIdx));
1066 #endif
1067 checkGLcall("glDrawRangeElements");
1069 } else {
1071 /* Note first is now zero as we shuffled along earlier */
1072 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1073 glDrawArrays(glPrimType, 0, NumVertexes);
1074 checkGLcall("glDrawArrays");
1080 * Actually draw using the supplied information.
1081 * Slower GL version which extracts info about each vertex in turn
1083 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1084 int PrimitiveType, ULONG NumPrimitives,
1085 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1087 unsigned int textureNo = 0;
1088 GLenum glPrimType = GL_POINTS;
1089 int NumVertexes = NumPrimitives;
1090 const short *pIdxBufS = NULL;
1091 const long *pIdxBufL = NULL;
1092 LONG SkipnStrides = 0;
1093 LONG vx_index;
1094 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1095 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1096 float rhw = 0.0f; /* rhw */
1097 float ptSize = 0.0f; /* Point size */
1098 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1099 DWORD specularColor = 0; /* Specular Color */
1100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1102 TRACE("Using slow vertex array code\n");
1104 /* Variable Initialization */
1105 if (idxData != NULL) {
1106 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1107 else pIdxBufL = (const long *) idxData;
1110 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1111 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1113 /* Start drawing in GL */
1114 VTRACE(("glBegin(%x)\n", glPrimType));
1115 glBegin(glPrimType);
1117 /* For each primitive */
1118 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1120 /* Initialize diffuse color */
1121 diffuseColor = 0xFFFFFFFF;
1123 /* For indexed data, we need to go a few more strides in */
1124 if (idxData != NULL) {
1126 /* Indexed so work out the number of strides to skip */
1127 if (idxSize == 2) {
1128 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1129 SkipnStrides = pIdxBufS[startIdx+vx_index];
1130 } else {
1131 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1132 SkipnStrides = pIdxBufL[startIdx+vx_index];
1136 /* Position Information ------------------ */
1137 if (sd->u.s.position.lpData != NULL) {
1139 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1140 x = ptrToCoords[0];
1141 y = ptrToCoords[1];
1142 z = ptrToCoords[2];
1143 rhw = 1.0;
1144 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1146 /* RHW follows, only if transformed, ie 4 floats were provided */
1147 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1148 rhw = ptrToCoords[3];
1149 VTRACE(("rhw=%f\n", rhw));
1153 /* Blending data -------------------------- */
1154 if (sd->u.s.blendWeights.lpData != NULL) {
1155 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1156 FIXME("Blending not supported yet\n");
1158 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1159 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1163 /* Vertex Normal Data (untransformed only)- */
1164 if (sd->u.s.normal.lpData != NULL) {
1166 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1167 nx = ptrToCoords[0];
1168 ny = ptrToCoords[1];
1169 nz = ptrToCoords[2];
1170 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1173 /* Point Size ----------------------------- */
1174 if (sd->u.s.pSize.lpData != NULL) {
1176 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1177 ptSize = ptrToCoords[0];
1178 VTRACE(("ptSize=%f\n", ptSize));
1179 FIXME("No support for ptSize yet\n");
1182 /* Diffuse -------------------------------- */
1183 if (sd->u.s.diffuse.lpData != NULL) {
1185 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1186 diffuseColor = ptrToCoords[0];
1187 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1190 /* Specular -------------------------------- */
1191 if (sd->u.s.specular.lpData != NULL) {
1193 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1194 specularColor = ptrToCoords[0];
1195 VTRACE(("specularColor=%lx\n", specularColor));
1198 /* Texture coords --------------------------- */
1199 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1201 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1202 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1203 continue ;
1206 /* Query tex coords */
1207 if (This->stateBlock->textures[textureNo] != NULL) {
1209 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1210 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1211 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1213 if (coordIdx > 7) {
1214 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1215 continue;
1216 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1217 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1218 continue;
1219 } else {
1221 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1223 /* The coords to supply depend completely on the fvf / vertex shader */
1224 switch (coordsToUse) {
1225 case 4: q = ptrToCoords[3]; /* drop through */
1226 case 3: r = ptrToCoords[2]; /* drop through */
1227 case 2: t = ptrToCoords[1]; /* drop through */
1228 case 1: s = ptrToCoords[0];
1231 /* Projected is more 'fun' - Move the last coord to the 'q'
1232 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1233 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1234 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1236 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1237 switch (coordsToUse) {
1238 case 0: /* Drop Through */
1239 case 1:
1240 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1241 break;
1242 case 2:
1243 q = t;
1244 t = 0.0;
1245 coordsToUse = 4;
1246 break;
1247 case 3:
1248 q = r;
1249 r = 0.0;
1250 coordsToUse = 4;
1251 break;
1252 case 4: /* Nop here */
1253 break;
1254 default:
1255 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1256 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1261 /* crude support for non-power2 textures */
1262 if(((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2){
1263 t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
1264 s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
1267 switch (coordsToUse) { /* Supply the provided texture coords */
1268 case D3DTTFF_COUNT1:
1269 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1270 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1271 GLMULTITEXCOORD1F(textureNo, s);
1272 } else {
1273 glTexCoord1f(s);
1275 break;
1276 case D3DTTFF_COUNT2:
1277 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1278 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1279 GLMULTITEXCOORD2F(textureNo, s, t);
1280 } else {
1281 glTexCoord2f(s, t);
1283 break;
1284 case D3DTTFF_COUNT3:
1285 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1286 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1287 GLMULTITEXCOORD3F(textureNo, s, t, r);
1288 } else {
1289 glTexCoord3f(s, t, r);
1291 break;
1292 case D3DTTFF_COUNT4:
1293 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1294 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1295 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1296 } else {
1297 glTexCoord4f(s, t, r, q);
1299 break;
1300 default:
1301 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1305 } /* End of textures */
1307 /* Diffuse -------------------------------- */
1308 if (sd->u.s.diffuse.lpData != NULL) {
1309 glColor4ub((diffuseColor >> 16) & 0xFF,
1310 (diffuseColor >> 8) & 0xFF,
1311 (diffuseColor >> 0) & 0xFF,
1312 (diffuseColor >> 24) & 0xFF);
1313 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1314 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1315 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1316 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1317 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1318 } else {
1319 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1322 /* Specular ------------------------------- */
1323 if (sd->u.s.diffuse.lpData != NULL) {
1324 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1325 ((specularColor >> 16) & 0xFF) / 255.0f,
1326 ((specularColor >> 8) & 0xFF) / 255.0f,
1327 ((specularColor >> 0) & 0xFF) / 255.0f));
1328 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1329 GL_EXTCALL(glSecondaryColor3ubEXT)(
1330 (specularColor >> 16) & 0xFF,
1331 (specularColor >> 8) & 0xFF,
1332 (specularColor >> 0) & 0xFF);
1333 } else {
1334 /* Do not worry if specular colour missing and disable request */
1335 VTRACE(("Specular color extensions not supplied\n"));
1337 } else {
1338 if (vx_index == 0) {
1339 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1340 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1341 } else {
1342 /* Do not worry if specular colour missing and disable request */
1343 VTRACE(("Specular color extensions not supplied\n"));
1348 /* Normal -------------------------------- */
1349 if (sd->u.s.normal.lpData != NULL) {
1350 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1351 glNormal3f(nx, ny, nz);
1352 } else {
1353 if (vx_index == 0) glNormal3f(0, 0, 1);
1356 /* Position -------------------------------- */
1357 if (sd->u.s.position.lpData != NULL) {
1358 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1359 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1360 glVertex3f(x, y, z);
1361 } else {
1362 GLfloat w = 1.0 / rhw;
1363 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1364 glVertex4f(x*w, y*w, z*w, w);
1368 /* For non indexed mode, step onto next parts */
1369 if (idxData == NULL) {
1370 SkipnStrides += 1;
1374 glEnd();
1375 checkGLcall("glEnd and previous calls");
1378 #if 0 /* TODO: Software/Hardware vertex blending support */
1380 * Draw with emulated vertex shaders
1381 * Note: strided data is uninitialized, as we need to pass the vertex
1382 * shader directly as ordering irs yet
1384 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1385 int PrimitiveType, ULONG NumPrimitives,
1386 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1388 unsigned int textureNo = 0;
1389 GLenum glPrimType = GL_POINTS;
1390 int NumVertexes = NumPrimitives;
1391 const short *pIdxBufS = NULL;
1392 const long *pIdxBufL = NULL;
1393 LONG SkipnStrides = 0;
1394 LONG vx_index;
1395 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1396 float rhw = 0.0f; /* rhw */
1397 float ptSize = 0.0f; /* Point size */
1398 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1399 int numcoords[8]; /* Number of coords */
1400 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1402 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1404 TRACE("Using slow software vertex shader code\n");
1406 /* Variable Initialization */
1407 if (idxData != NULL) {
1408 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1409 else pIdxBufL = (const long *) idxData;
1412 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1413 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1415 /* Retrieve the VS information */
1416 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1418 /* Start drawing in GL */
1419 VTRACE(("glBegin(%x)\n", glPrimType));
1420 glBegin(glPrimType);
1422 /* For each primitive */
1423 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1425 /* For indexed data, we need to go a few more strides in */
1426 if (idxData != NULL) {
1428 /* Indexed so work out the number of strides to skip */
1429 if (idxSize == 2) {
1430 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1431 SkipnStrides = pIdxBufS[startIdx+vx_index];
1432 } else {
1433 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1434 SkipnStrides = pIdxBufL[startIdx+vx_index];
1438 /* Fill the vertex shader input */
1439 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1441 /* Initialize the output fields to the same defaults as it would normally have */
1442 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1443 vertex_shader->output.oD[0].x = 1.0;
1444 vertex_shader->output.oD[0].y = 1.0;
1445 vertex_shader->output.oD[0].z = 1.0;
1446 vertex_shader->output.oD[0].w = 1.0;
1448 /* Now execute the vertex shader */
1449 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1452 TRACE_VECTOR(vertex_shader->output.oPos);
1453 TRACE_VECTOR(vertex_shader->output.oD[0]);
1454 TRACE_VECTOR(vertex_shader->output.oD[1]);
1455 TRACE_VECTOR(vertex_shader->output.oT[0]);
1456 TRACE_VECTOR(vertex_shader->output.oT[1]);
1457 TRACE_VECTOR(vertex_shader->input.V[0]);
1458 TRACE_VECTOR(vertex_shader->data->C[0]);
1459 TRACE_VECTOR(vertex_shader->data->C[1]);
1460 TRACE_VECTOR(vertex_shader->data->C[2]);
1461 TRACE_VECTOR(vertex_shader->data->C[3]);
1462 TRACE_VECTOR(vertex_shader->data->C[4]);
1463 TRACE_VECTOR(vertex_shader->data->C[5]);
1464 TRACE_VECTOR(vertex_shader->data->C[6]);
1465 TRACE_VECTOR(vertex_shader->data->C[7]);
1468 /* Extract out the output */
1469 /*FIXME: Fog coords? */
1470 x = vertex_shader->output.oPos.x;
1471 y = vertex_shader->output.oPos.y;
1472 z = vertex_shader->output.oPos.z;
1473 rhw = vertex_shader->output.oPos.w;
1474 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1476 /** Update textures coords using vertex_shader->output.oT[0->7] */
1477 memset(texcoords, 0x00, sizeof(texcoords));
1478 memset(numcoords, 0x00, sizeof(numcoords));
1479 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1480 if (This->stateBlock->textures[textureNo] != NULL) {
1481 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1482 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1483 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1484 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1485 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1486 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1487 } else {
1488 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1489 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1490 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1491 default: numcoords[textureNo] = 4;
1494 } else {
1495 numcoords[textureNo] = 0;
1499 /* Draw using this information */
1500 draw_vertex(iface,
1501 TRUE, x, y, z, rhw,
1502 TRUE, 0.0f, 0.0f, 1.0f,
1503 TRUE, (float*) &vertex_shader->output.oD[0],
1504 TRUE, (float*) &vertex_shader->output.oD[1],
1505 FALSE, ptSize, /* FIXME: Change back when supported */
1506 texcoords, numcoords);
1508 /* For non indexed mode, step onto next parts */
1509 if (idxData == NULL) {
1510 SkipnStrides += 1;
1513 } /* for each vertex */
1515 glEnd();
1516 checkGLcall("glEnd and previous calls");
1519 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1520 int PrimitiveType, ULONG NumPrimitives,
1521 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1523 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1524 int i;
1525 int NumVertexes;
1526 int glPrimType;
1527 int maxAttribs;
1529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1530 TRACE("Drawing with hardware vertex shaders\n");
1532 /* Retrieve the VS information */
1533 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1535 /* Enable the Vertex Shader */
1536 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1537 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1538 glEnable(GL_VERTEX_PROGRAM_ARB);
1539 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1541 /* Update the constants */
1542 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1543 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1544 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1547 /* Set up the vertex.attr[n] inputs */
1548 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1550 /* Ok, Work out which primitive is requested and how many vertexes that
1551 will be */
1552 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1554 /* Finally do the drawing */
1555 if (idxData != NULL) {
1557 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1558 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1559 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1560 (const char *)idxData+(idxSize * startIdx));
1561 #else
1562 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1563 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1564 (const char *)idxData+(idxSize * startIdx));
1565 #endif
1566 checkGLcall("glDrawRangeElements");
1568 } else {
1570 /* Note first is now zero as we shuffled along earlier */
1571 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1572 glDrawArrays(glPrimType, 0, NumVertexes);
1573 checkGLcall("glDrawArrays");
1578 GLint errPos;
1579 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1580 if (errPos != -1)
1581 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1585 /* Leave all the attribs disabled */
1586 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1587 /* MESA does not support it right not */
1588 if (glGetError() != GL_NO_ERROR)
1589 maxAttribs = 16;
1590 for (i=0; i<maxAttribs; i++) {
1591 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1592 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1595 /* Done */
1596 glDisable(GL_VERTEX_PROGRAM_ARB);
1598 #endif
1600 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf){
1602 /* Dump out what parts we have supplied */
1603 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1604 TRACE_STRIDED((dataLocations), position);
1605 TRACE_STRIDED((dataLocations), blendWeights);
1606 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1607 TRACE_STRIDED((dataLocations), normal);
1608 TRACE_STRIDED((dataLocations), pSize);
1609 TRACE_STRIDED((dataLocations), diffuse);
1610 TRACE_STRIDED((dataLocations), specular);
1611 TRACE_STRIDED((dataLocations), texCoords[0]);
1612 TRACE_STRIDED((dataLocations), texCoords[1]);
1613 TRACE_STRIDED((dataLocations), texCoords[2]);
1614 TRACE_STRIDED((dataLocations), texCoords[3]);
1615 TRACE_STRIDED((dataLocations), texCoords[4]);
1616 TRACE_STRIDED((dataLocations), texCoords[5]);
1617 TRACE_STRIDED((dataLocations), texCoords[6]);
1618 TRACE_STRIDED((dataLocations), texCoords[7]);
1619 return;
1623 /* loads any dirty textures and returns true if any of the textures are nonpower2 */
1624 BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
1625 BOOL nonPower2 = FALSE;
1626 unsigned int i;
1627 register IWineD3DBaseTexture *texture;
1628 /* And re-upload any dirty textures */
1629 for (i = 0; i<GL_LIMITS(textures); ++i) {
1630 texture = This->stateBlock->textures[i];
1631 if (texture != NULL) {
1632 if(IWineD3DBaseTexture_GetDirty(texture)) {
1633 /* Load up the texture now */
1634 IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
1636 if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
1637 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1638 IWineD3DSurface *surface;
1639 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
1640 if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
1641 nonPower2 = TRUE;
1646 return nonPower2;
1649 /* Routine common to the draw primitive and draw indexed primitive routines */
1650 void drawPrimitive(IWineD3DDevice *iface,
1651 int PrimitiveType, long NumPrimitives,
1653 /* for Indexed: */
1654 long StartVertexIndex,
1655 long StartIdx,
1656 short idxSize,
1657 const void *idxData,
1658 int minIndex) {
1660 BOOL rc = FALSE;
1661 DWORD fvf = 0;
1662 #if 0 /* TODO: vertex and pixel shaders */
1663 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1664 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1665 #endif
1666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1667 BOOL useVertexShaderFunction = FALSE;
1668 BOOL isLightingOn = FALSE;
1669 Direct3DVertexStridedData dataLocations;
1670 int useHW = FALSE;
1671 BOOL nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
1673 if (This->stateBlock->vertexDecl == NULL) {
1674 /* Work out what the FVF should look like */
1675 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1676 if (rc) return;
1677 } else {
1678 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1681 /* If we will be using a vertex shader, do some initialization for it */
1682 if (useVertexShaderFunction) {
1683 #if 0 /* TODO: vertex and pixel shaders */
1684 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1685 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1687 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1688 This->devType != D3DDEVTYPE_REF &&
1689 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1690 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1692 /** init Constants */
1693 if (This->stateBlock->Changed.vertexShaderConstant) {
1694 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1695 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1697 #endif /* TODO: vertex and pixel shaders */
1700 /* Ok, we will be updating the screen from here onwards so grab the lock */
1701 ENTER_GL();
1703 #if 0 /* TODO: vertex and pixel shaders */
1704 /* If we will be using a pixel, do some initialization for it */
1705 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1706 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1707 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1709 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1710 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1711 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1712 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1714 /* init Constants */
1715 if (This->stateBlock->Changed.pixelShaderConstant) {
1716 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1717 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1719 /* Update the constants */
1720 for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1721 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1722 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1725 #endif /* TODO: vertex and pixel shaders */
1727 /* Initialize all values to null */
1728 if (useVertexShaderFunction == FALSE) {
1729 memset(&dataLocations, 0x00, sizeof(dataLocations));
1731 /* Convert to strided data */
1732 if(This->stateBlock->vertexDecl != NULL){
1733 TRACE("================ Vertex Declaration ===================\n");
1734 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1735 }else{
1736 TRACE("================ FVF ===================\n");
1737 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1740 /* write out some debug information*/
1741 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1742 } else {
1743 FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1746 /* Setup transform matrices and sort out */
1747 if (useHW) {
1748 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1749 So make sure lighting is disabled. */
1750 isLightingOn = glIsEnabled(GL_LIGHTING);
1751 glDisable(GL_LIGHTING);
1752 checkGLcall("glDisable(GL_LIGHTING);");
1753 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1754 } else {
1755 isLightingOn = primitiveInitState(iface,
1756 fvf & D3DFVF_XYZRHW,
1757 !(fvf & D3DFVF_NORMAL),
1758 useVertexShaderFunction);
1761 /* Now initialize the materials state */
1762 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1764 nonPower2 = drawPrimitiveUploadDirtyTextures(This);
1766 /* Now draw the graphics to the screen */
1767 if (useVertexShaderFunction) {
1769 /* Ideally, we should have software FV and hardware VS, possibly
1770 depending on the device type? */
1772 if (useHW) {
1773 TRACE("Swap HW vertex shader\n");
1774 #if 0 /* TODO: vertex and pixel shaders */
1775 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1776 idxData, idxSize, minIndex, StartIdx);
1777 #endif
1778 } else {
1779 /* We will have to use the very, very slow emulation layer */
1780 TRACE("Swap SW vertex shader\n");
1781 #if 0 /* TODO: vertex and pixel shaders */
1782 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1783 idxData, idxSize, minIndex, StartIdx);
1784 #endif
1787 } else if ((dataLocations.u.s.pSize.lpData != NULL)
1788 || (dataLocations.u.s.diffuse.lpData != NULL)
1789 || nonPower2
1790 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1792 /* Fixme, Ideally, only use the per-vertex code for software HAL
1793 but until opengl supports all the functions returned to setup
1794 vertex arrays, we need to drop down to the slow mechanism for
1795 certain functions */
1797 /* We will have to use the slow version of GL per vertex setup */
1798 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1799 idxData, idxSize, minIndex, StartIdx);
1801 } else {
1803 /* We can use the fast version of GL pointers */
1804 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1805 idxData, idxSize, minIndex, StartIdx);
1808 /* If vertex shaders or no normals, restore previous lighting state */
1809 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1810 if (isLightingOn) glEnable(GL_LIGHTING);
1811 else glDisable(GL_LIGHTING);
1812 TRACE("Restored lighting to original state\n");
1815 #if 0 /* TODO: vertex and pixel shaders */
1816 if (pixel_shader)
1818 #if 0
1819 GLint errPos;
1820 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1821 if (errPos != -1)
1822 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1823 #endif
1824 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1826 #endif
1828 /* Finshed updating the screen, restore lock */
1829 LEAVE_GL();
1830 TRACE("Done all gl drawing\n");
1832 /* Diagnostics */
1833 #if defined(SHOW_FRAME_MAKEUP)
1835 if (isDumpingFrames) {
1836 D3DLOCKED_RECT r;
1837 char buffer[80];
1838 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1839 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1840 TRACE("Saving screenshot %s\n", buffer);
1841 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1842 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1844 #if defined(SHOW_TEXTURE_MAKEUP)
1846 LPDIRECT3DSURFACE8 pSur;
1847 int textureNo;
1848 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1849 if (This->stateBlock->textures[textureNo] != NULL) {
1850 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1851 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1852 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1853 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1854 IDirect3DSurface8Impl_Release(pSur);
1858 #endif
1859 primCounter = primCounter + 1;
1862 #endif