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
8 * Copyright 2006 Henri Verbeet
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
30 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
35 extern IWineD3DVertexShaderImpl* VertexShaders[64];
36 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
37 extern IWineD3DPixelShaderImpl* PixelShaders[64];
39 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
42 /* Issues the glBegin call for gl given the primitive type and count */
43 static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType,
47 DWORD NumVertexes = NumPrimitives;
49 switch (PrimitiveType) {
50 case WINED3DPT_POINTLIST:
52 *primType = GL_POINTS;
53 NumVertexes = NumPrimitives;
56 case WINED3DPT_LINELIST:
59 NumVertexes = NumPrimitives * 2;
62 case WINED3DPT_LINESTRIP:
63 TRACE("LINE_STRIP\n");
64 *primType = GL_LINE_STRIP;
65 NumVertexes = NumPrimitives + 1;
68 case WINED3DPT_TRIANGLELIST:
70 *primType = GL_TRIANGLES;
71 NumVertexes = NumPrimitives * 3;
74 case WINED3DPT_TRIANGLESTRIP:
75 TRACE("TRIANGLE_STRIP\n");
76 *primType = GL_TRIANGLE_STRIP;
77 NumVertexes = NumPrimitives + 2;
80 case WINED3DPT_TRIANGLEFAN:
81 TRACE("TRIANGLE_FAN\n");
82 *primType = GL_TRIANGLE_FAN;
83 NumVertexes = NumPrimitives + 2;
87 FIXME("Unhandled primitive\n");
88 *primType = GL_POINTS;
94 /* Ensure the appropriate material states are set up - only change
95 state if really required */
96 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
98 BOOL requires_material_reset = FALSE;
99 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
101 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
102 /* If we have not set up the material color tracking, do it now as required */
103 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
104 checkGLcall("glDisable GL_COLOR_MATERIAL");
105 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
106 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
107 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
108 glEnable(GL_COLOR_MATERIAL);
109 checkGLcall("glEnable GL_COLOR_MATERIAL");
110 This->tracking_color = IS_TRACKING;
111 requires_material_reset = TRUE; /* Restore material settings as will be used */
113 } else if ((This->tracking_color == IS_TRACKING && !isDiffuseSupplied) ||
114 (This->tracking_color == NEEDS_TRACKING && !isDiffuseSupplied)) {
115 /* If we are tracking the current color but one isn't supplied, don't! */
116 glDisable(GL_COLOR_MATERIAL);
117 checkGLcall("glDisable GL_COLOR_MATERIAL");
118 This->tracking_color = NEEDS_TRACKING;
119 requires_material_reset = TRUE; /* Restore material settings as will be used */
121 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
122 /* No need to reset material colors since no change to gl_color_material */
123 requires_material_reset = FALSE;
125 } else if (This->tracking_color == NEEDS_DISABLE) {
126 glDisable(GL_COLOR_MATERIAL);
127 checkGLcall("glDisable GL_COLOR_MATERIAL");
128 This->tracking_color = DISABLED_TRACKING;
129 requires_material_reset = TRUE; /* Restore material settings as will be used */
132 /* Reset the material colors which may have been tracking the color*/
133 if (requires_material_reset) {
134 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
135 checkGLcall("glMaterialfv");
136 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
137 checkGLcall("glMaterialfv");
138 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
139 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
140 checkGLcall("glMaterialfv");
142 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
143 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
144 checkGLcall("glMaterialfv");
146 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
147 checkGLcall("glMaterialfv");
152 static const GLfloat invymat[16] = {
153 1.0f, 0.0f, 0.0f, 0.0f,
154 0.0f, -1.0f, 0.0f, 0.0f,
155 0.0f, 0.0f, 1.0f, 0.0f,
156 0.0f, 0.0f, 0.0f, 1.0f};
158 static BOOL fixed_get_input(
159 BYTE usage, BYTE usage_idx,
160 unsigned int* regnum) {
164 /* Those positions must have the order in the
165 * named part of the strided data */
167 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
169 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
171 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
173 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
175 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
177 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
179 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
181 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
182 *regnum = 7 + usage_idx;
183 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
184 *regnum = 7 + WINED3DDP_MAXTEXCOORD;
185 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
186 *regnum = 8 + WINED3DDP_MAXTEXCOORD;
187 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
188 *regnum = 9 + WINED3DDP_MAXTEXCOORD;
189 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
190 *regnum = 10 + WINED3DDP_MAXTEXCOORD;
191 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
192 *regnum = 11 + WINED3DDP_MAXTEXCOORD;
193 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
194 *regnum = 12 + WINED3DDP_MAXTEXCOORD;
195 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
196 *regnum = 13 + WINED3DDP_MAXTEXCOORD;
197 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
198 *regnum = 14 + WINED3DDP_MAXTEXCOORD;
201 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
202 debug_d3ddeclusage(usage), usage_idx);
208 void primitiveDeclarationConvertToStridedData(
209 IWineD3DDevice *iface,
210 BOOL useVertexShaderFunction,
211 WineDirect3DVertexStridedData *strided,
214 /* We need to deal with frequency data!*/
217 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
218 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
220 WINED3DVERTEXELEMENT *element;
224 /* Locate the vertex declaration */
225 if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
226 TRACE("Using vertex declaration from shader\n");
227 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
229 TRACE("Using vertex declaration\n");
230 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
233 /* Translate the declaration into strided data */
234 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
239 element = vertexDeclaration->pDeclarationWine + i;
240 TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
241 element, i + 1, vertexDeclaration->declarationWNumElements - 1);
243 if (This->stateBlock->streamSource[element->Stream] == NULL)
246 if (This->stateBlock->streamIsUP) {
247 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
249 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
250 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
252 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
253 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
254 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
256 if( streamVBO != 0) *fixup = TRUE;
257 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
260 stride = This->stateBlock->streamStride[element->Stream];
261 data += element->Offset;
264 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
266 if (useVertexShaderFunction)
267 stride_used = vshader_get_input(This->stateBlock->vertexShader,
268 element->Usage, element->UsageIndex, &idx);
270 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
273 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
274 "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
275 useVertexShaderFunction? "shader": "fixed function", idx,
276 debug_d3ddeclusage(element->Usage), element->UsageIndex,
277 element->Stream, element->Offset, stride, streamVBO);
279 strided->u.input[idx].lpData = data;
280 strided->u.input[idx].dwType = element->Type;
281 strided->u.input[idx].dwStride = stride;
282 strided->u.input[idx].VBO = streamVBO;
283 if (!useVertexShaderFunction) {
284 if (element->Usage == D3DDECLUSAGE_POSITION)
285 strided->u.s.position_transformed = FALSE;
286 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
287 strided->u.s.position_transformed = TRUE;
293 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
297 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
298 int numCoords[8]; /* Holding place for WINED3DFVF_TEXTUREFORMATx */
300 /* Either 3 or 4 floats depending on the FVF */
301 /* FIXME: Can blending data be in a different stream to the position data?
302 and if so using the fixed pipeline how do we handle it */
303 if (thisFVF & WINED3DFVF_POSITION_MASK) {
304 strided->u.s.position.lpData = data;
305 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
306 strided->u.s.position.dwStride = stride;
307 strided->u.s.position.VBO = streamVBO;
308 data += 3 * sizeof(float);
309 if (thisFVF & WINED3DFVF_XYZRHW) {
310 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
311 strided->u.s.position_transformed = TRUE;
312 data += sizeof(float);
314 strided->u.s.position_transformed = FALSE;
317 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
318 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
319 numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
320 if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
322 if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
323 TRACE("Setting blend Weights to %p\n", data);
324 strided->u.s.blendWeights.lpData = data;
325 strided->u.s.blendWeights.dwType = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
326 strided->u.s.blendWeights.dwStride = stride;
327 strided->u.s.blendWeights.VBO = streamVBO;
328 data += numBlends * sizeof(FLOAT);
330 if (thisFVF & WINED3DFVF_LASTBETA_UBYTE4) {
331 strided->u.s.blendMatrixIndices.lpData = data;
332 strided->u.s.blendMatrixIndices.dwType = WINED3DDECLTYPE_UBYTE4;
333 strided->u.s.blendMatrixIndices.dwStride= stride;
334 strided->u.s.blendMatrixIndices.VBO = streamVBO;
335 data += sizeof(DWORD);
339 /* Normal is always 3 floats */
340 if (thisFVF & WINED3DFVF_NORMAL) {
341 strided->u.s.normal.lpData = data;
342 strided->u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
343 strided->u.s.normal.dwStride = stride;
344 strided->u.s.normal.VBO = streamVBO;
345 data += 3 * sizeof(FLOAT);
348 /* Pointsize is a single float */
349 if (thisFVF & WINED3DFVF_PSIZE) {
350 strided->u.s.pSize.lpData = data;
351 strided->u.s.pSize.dwType = WINED3DDECLTYPE_FLOAT1;
352 strided->u.s.pSize.dwStride = stride;
353 strided->u.s.pSize.VBO = streamVBO;
354 data += sizeof(FLOAT);
357 /* Diffuse is 4 unsigned bytes */
358 if (thisFVF & WINED3DFVF_DIFFUSE) {
359 strided->u.s.diffuse.lpData = data;
360 strided->u.s.diffuse.dwType = WINED3DDECLTYPE_SHORT4;
361 strided->u.s.diffuse.dwStride = stride;
362 strided->u.s.diffuse.VBO = streamVBO;
363 data += sizeof(DWORD);
366 /* Specular is 4 unsigned bytes */
367 if (thisFVF & WINED3DFVF_SPECULAR) {
368 strided->u.s.specular.lpData = data;
369 strided->u.s.specular.dwType = WINED3DDECLTYPE_SHORT4;
370 strided->u.s.specular.dwStride = stride;
371 strided->u.s.specular.VBO = streamVBO;
372 data += sizeof(DWORD);
376 numTextures = (thisFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
377 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
379 /* numTextures indicates the number of texture coordinates supplied */
380 /* However, the first set may not be for stage 0 texture - it all */
381 /* depends on WINED3DTSS_TEXCOORDINDEX. */
382 /* The number of bytes for each coordinate set is based off */
383 /* WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
385 /* So, for each supplied texture extract the coords */
386 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
388 strided->u.s.texCoords[textureNo].lpData = data;
389 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT1;
390 strided->u.s.texCoords[textureNo].dwStride = stride;
391 strided->u.s.texCoords[textureNo].VBO = streamVBO;
392 numCoords[textureNo] = coordIdxInfo & 0x03;
395 data += sizeof(float);
396 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT1) {
397 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
398 data += sizeof(float);
399 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT2) {
400 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
401 data += sizeof(float);
402 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT3) {
403 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
404 data += sizeof(float);
408 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
412 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, BOOL *fixup) {
414 short LoopThroughTo = 0;
418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
420 /* OK, Now to setup the data locations
421 For the non-created vertex shaders, the VertexShader var holds the real
422 FVF and only stream 0 matters
423 For the created vertex shaders, there is an FVF per stream */
424 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
425 LoopThroughTo = MAX_STREAMS;
430 /* Work through stream by stream */
431 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
432 DWORD stride = This->stateBlock->streamStride[nStream];
436 /* Skip empty streams */
437 if (This->stateBlock->streamSource[nStream] == NULL) continue;
439 /* Retrieve appropriate FVF */
440 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
441 thisFVF = This->stateBlock->fvf;
442 /* Handle memory passed directly as well as vertex buffers */
443 if (This->stateBlock->streamIsUP) {
445 data = (BYTE *)This->stateBlock->streamSource[nStream];
447 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
448 /* GetMemory binds the VBO */
449 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
451 if(streamVBO != 0 ) *fixup = TRUE;
455 #if 0 /* TODO: Vertex shader support */
456 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
457 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
460 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
461 if (thisFVF == 0) continue;
463 /* Now convert the stream into pointers */
464 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
468 #if 0 /* TODO: Software Shaders */
469 /* Draw a single vertex using this information */
470 static void draw_vertex(IWineD3DDevice *iface, /* interface */
471 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
472 BOOL isNormal, float nx, float ny, float nz, /* normal */
473 BOOL isDiffuse, float *dRGBA, /* 1st colors */
474 BOOL isSpecular, float *sRGB, /* 2ndry colors */
475 BOOL isPtSize, float ptSize, /* pointSize */
476 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
478 unsigned int textureNo;
480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
482 /* Diffuse -------------------------------- */
485 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
488 /* Specular Colour ------------------------------------------*/
490 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
491 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
492 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
494 VTRACE(("Specular color extensions not supplied\n"));
498 /* Normal -------------------------------- */
500 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
501 glNormal3f(nx, ny, nz);
504 /* Point Size ----------------------------------------------*/
507 /* no such functionality in the fixed function GL pipeline */
508 FIXME("Cannot change ptSize here in openGl\n");
511 /* Texture coords --------------------------- */
512 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
514 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
515 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
519 /* Query tex coords */
520 if (This->stateBlock->textures[textureNo] != NULL) {
522 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
523 if (coordIdx >= MAX_TEXTURES) {
524 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
526 } else if (numcoords[coordIdx] == 0) {
527 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
531 /* Initialize vars */
537 switch (numcoords[coordIdx]) {
538 case 4: q = texcoords[coordIdx].w; /* drop through */
539 case 3: r = texcoords[coordIdx].z; /* drop through */
540 case 2: t = texcoords[coordIdx].y; /* drop through */
541 case 1: s = texcoords[coordIdx].x;
544 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
545 case WINED3DTTFF_COUNT1:
546 VTRACE(("tex:%d, s=%f\n", textureNo, s));
547 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
548 GLMULTITEXCOORD1F(textureNo, s);
553 case WINED3DTTFF_COUNT2:
554 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
555 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
556 GLMULTITEXCOORD2F(textureNo, s, t);
561 case WINED3DTTFF_COUNT3:
562 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
563 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
564 GLMULTITEXCOORD3F(textureNo, s, t, r);
566 glTexCoord3f(s, t, r);
569 case WINED3DTTFF_COUNT4:
570 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
571 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
572 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
574 glTexCoord4f(s, t, r, q);
578 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
582 } /* End of textures */
584 /* Position -------------------------------- */
586 if (1.0f == rhw || rhw < 0.00001f) {
587 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
590 /* Cannot optimize by dividing through by rhw as rhw is required
591 later for perspective in the GL pipeline for vertex shaders */
592 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
593 glVertex4f(x,y,z,rhw);
597 #endif /* TODO: Software shaders */
599 /* This should match any arrays loaded in loadNumberedArrays. */
600 /* TODO: Only load / unload arrays if we have to. */
601 static void unloadNumberedArrays(IWineD3DDevice *iface) {
602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
604 /* disable any attribs (this is the same for both GLSL and ARB modes) */
608 /* Leave all the attribs disabled */
609 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
610 /* MESA does not support it right not */
611 if (glGetError() != GL_NO_ERROR)
613 for (i = 0; i < maxAttribs; ++i) {
614 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
615 checkGLcall("glDisableVertexAttribArrayARB(reg);");
619 /* TODO: Only load / unload arrays if we have to. */
620 static void loadNumberedArrays(
621 IWineD3DDevice *iface,
622 IWineD3DVertexShader *shader,
623 WineDirect3DVertexStridedData *strided) {
625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
626 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
629 for (i = 0; i < MAX_ATTRIBS; i++) {
631 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
634 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
636 if(curVBO != strided->u.input[i].VBO) {
637 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
638 checkGLcall("glBindBufferARB");
639 curVBO = strided->u.input[i].VBO;
641 GL_EXTCALL(glVertexAttribPointerARB(i,
642 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
643 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
644 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
645 strided->u.input[i].dwStride,
646 strided->u.input[i].lpData + This->stateBlock->baseVertexIndex * strided->u.input[i].dwStride));
647 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
651 /* This should match any arrays loaded in loadVertexData. */
652 /* TODO: Only load / unload arrays if we have to. */
653 static void unloadVertexData(IWineD3DDevice *iface) {
654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
657 glDisableClientState(GL_VERTEX_ARRAY);
658 glDisableClientState(GL_NORMAL_ARRAY);
659 glDisableClientState(GL_COLOR_ARRAY);
660 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
661 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
663 for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
664 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
665 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
669 /* TODO: Only load / unload arrays if we have to. */
670 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
671 unsigned int textureNo = 0;
672 unsigned int texture_idx = 0;
673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
674 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
676 TRACE("Using fast vertex array code\n");
677 /* Blend Data ---------------------------------------------- */
678 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
679 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
682 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
685 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
686 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
689 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
690 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride);
691 /* FIXME("TODO\n");*/
692 /* Note dwType == float3 or float4 == 2 or 3 */
695 /* with this on, the normals appear to be being modified,
696 but the vertices aren't being translated as they should be
697 Maybe the world matrix aren't being setup properly? */
698 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
702 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
703 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
704 sd->u.s.blendWeights.dwStride,
705 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride));
707 if(curVBO != sd->u.s.blendWeights.VBO) {
708 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
709 checkGLcall("glBindBufferARB");
710 curVBO = sd->u.s.blendWeights.VBO;
713 GL_EXTCALL(glWeightPointerARB)(
714 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
715 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
716 sd->u.s.blendWeights.dwStride,
717 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride);
719 checkGLcall("glWeightPointerARB");
721 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
722 static BOOL showfixme = TRUE;
724 FIXME("blendMatrixIndices support\n");
729 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
730 /* FIXME("TODO\n");*/
733 GL_EXTCALL(glVertexWeightPointerEXT)(
734 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
735 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
736 sd->u.s.blendWeights.dwStride,
737 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride);
738 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
739 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
740 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
744 /* TODO: support blends in fixupVertices */
745 FIXME("unsupported blending in openGl\n");
748 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
749 #if 0 /* TODO: Vertex blending */
750 glDisable(GL_VERTEX_BLEND_ARB);
752 TRACE("ARB_VERTEX_BLEND\n");
753 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
754 TRACE(" EXT_VERTEX_WEIGHTING\n");
755 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
756 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
761 #if 0 /* FOG ----------------------------------------------*/
762 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
764 if (GL_SUPPORT(EXT_FOG_COORD) {
765 glEnableClientState(GL_FOG_COORDINATE_EXT);
766 (GL_EXTCALL)(FogCoordPointerEXT)(
767 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
768 sd->u.s.fog.dwStride,
769 sd->u.s.fog.lpData + This->stateBlock->baseVertexIndex * sd->u.s.fog.dwStride);
771 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
772 /* FIXME: fixme once */
773 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
776 if (GL_SUPPRT(EXT_FOR_COORD) {
777 /* make sure fog is disabled */
778 glDisableClientState(GL_FOG_COORDINATE_EXT);
783 #if 0 /* tangents ----------------------------------------------*/
784 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
785 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
787 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
788 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
789 glEnable(GL_TANGENT_ARRAY_EXT);
790 (GL_EXTCALL)(TangentPointerEXT)(
791 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
792 sd->u.s.tangent.dwStride,
793 sd->u.s.tangent.lpData + This->stateBlock->baseVertexIndex * sd->u.s.tangent.dwStride);
795 glDisable(GL_TANGENT_ARRAY_EXT);
797 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
798 glEnable(GL_BINORMAL_ARRAY_EXT);
799 (GL_EXTCALL)(BinormalPointerEXT)(
800 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
801 sd->u.s.binormal.dwStride,
802 sd->u.s.binormal.lpData + This->stateBlock->baseVertexIndex * sd->u.s.binormal.dwStride);
804 glDisable(GL_BINORMAL_ARRAY_EXT);
808 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
809 /* FIXME: fixme once */
810 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
813 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
814 /* make sure fog is disabled */
815 glDisable(GL_TANGENT_ARRAY_EXT);
816 glDisable(GL_BINORMAL_ARRAY_EXT);
821 /* Point Size ----------------------------------------------*/
822 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
824 /* no such functionality in the fixed function GL pipeline */
825 TRACE("Cannot change ptSize here in openGl\n");
826 /* TODO: Implement this function in using shaders if they are available */
830 /* Vertex Pointers -----------------------------------------*/
831 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
832 /* Note dwType == float3 or float4 == 2 or 3 */
833 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
834 sd->u.s.position.dwStride,
835 sd->u.s.position.dwType + 1,
836 sd->u.s.position.lpData));
838 if(curVBO != sd->u.s.position.VBO) {
839 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
840 checkGLcall("glBindBufferARB");
841 curVBO = sd->u.s.position.VBO;
844 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
845 handling for rhw mode should not impact screen position whereas in GL it does.
846 This may result in very slightly distored textures in rhw mode, but
847 a very minimal different. There's always the other option of
848 fixing the view matrix to prevent w from having any effect
850 This only applies to user pointer sources, in VBOs the vertices are fixed up
852 if(sd->u.s.position.VBO == 0) {
853 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
854 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
855 sd->u.s.position.dwStride, sd->u.s.position.lpData + This->stateBlock->baseVertexIndex * sd->u.s.position.dwStride);
858 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
859 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
860 sd->u.s.position.dwStride, sd->u.s.position.lpData + This->stateBlock->baseVertexIndex * sd->u.s.position.dwStride);
862 checkGLcall("glVertexPointer(...)");
863 glEnableClientState(GL_VERTEX_ARRAY);
864 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
867 glDisableClientState(GL_VERTEX_ARRAY);
868 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
871 /* Normals -------------------------------------------------*/
872 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
873 /* Note dwType == float3 or float4 == 2 or 3 */
874 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
875 sd->u.s.normal.dwStride,
876 sd->u.s.normal.lpData));
877 if(curVBO != sd->u.s.normal.VBO) {
878 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
879 checkGLcall("glBindBufferARB");
880 curVBO = sd->u.s.normal.VBO;
883 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
884 sd->u.s.normal.dwStride,
885 sd->u.s.normal.lpData + This->stateBlock->baseVertexIndex * sd->u.s.normal.dwStride);
886 checkGLcall("glNormalPointer(...)");
887 glEnableClientState(GL_NORMAL_ARRAY);
888 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
891 glDisableClientState(GL_NORMAL_ARRAY);
892 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
894 checkGLcall("glNormal3f(0, 0, 1)");
897 /* Diffuse Colour --------------------------------------------*/
898 /* WARNING: Data here MUST be in RGBA format, so cannot */
899 /* go directly into fast mode from app pgm, because */
900 /* directx requires data in BGRA format. */
901 /* currently fixupVertices swizels the format, but this isn't */
902 /* very practical when using VBOS */
903 /* NOTE: Unless we write a vertex shader to swizel the colour */
904 /* , or the user doesn't care and wants the speed advantage */
906 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
907 /* Note dwType == float3 or float4 == 2 or 3 */
908 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
909 sd->u.s.diffuse.dwStride,
910 sd->u.s.diffuse.lpData));
912 if(curVBO != sd->u.s.diffuse.VBO) {
913 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
914 checkGLcall("glBindBufferARB");
915 curVBO = sd->u.s.diffuse.VBO;
917 glColorPointer(4, GL_UNSIGNED_BYTE,
918 sd->u.s.diffuse.dwStride,
919 sd->u.s.diffuse.lpData + This->stateBlock->baseVertexIndex * sd->u.s.diffuse.dwStride);
920 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
921 glEnableClientState(GL_COLOR_ARRAY);
922 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
925 glDisableClientState(GL_COLOR_ARRAY);
926 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
927 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
928 checkGLcall("glColor4f(1, 1, 1, 1)");
931 /* Specular Colour ------------------------------------------*/
932 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
933 TRACE("setting specular colour\n");
934 /* Note dwType == float3 or float4 == 2 or 3 */
935 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
936 sd->u.s.specular.dwStride,
937 sd->u.s.specular.lpData));
938 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
939 if(curVBO != sd->u.s.specular.VBO) {
940 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
941 checkGLcall("glBindBufferARB");
942 curVBO = sd->u.s.specular.VBO;
944 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
945 sd->u.s.specular.dwStride,
946 sd->u.s.specular.lpData + This->stateBlock->baseVertexIndex * sd->u.s.specular.dwStride);
947 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
948 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
949 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
952 /* Missing specular color is not critical, no warnings */
953 VTRACE(("Specular colour is not supported in this GL implementation\n"));
957 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
959 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
960 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
961 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
962 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
965 /* Missing specular color is not critical, no warnings */
966 VTRACE(("Specular colour is not supported in this GL implementation\n"));
970 /* Texture coords -------------------------------------------*/
972 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
973 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
974 /* Abort if we don't support the extension. */
975 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
976 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
980 if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/ TRUE) {
981 /* Select the correct texture stage */
982 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
985 if (This->stateBlock->textures[textureNo] != NULL) {
986 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
988 if (coordIdx >= MAX_TEXTURES) {
989 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
990 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
991 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
993 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
994 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
995 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
996 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
999 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1000 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1001 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1002 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1003 checkGLcall("glBindBufferARB");
1004 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1006 /* The coords to supply depend completely on the fvf / vertex shader */
1008 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1009 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1010 sd->u.s.texCoords[coordIdx].dwStride,
1011 sd->u.s.texCoords[coordIdx].lpData + This->stateBlock->baseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride);
1012 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1014 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1015 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1016 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1018 if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/ TRUE) ++texture_idx;
1020 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1021 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1022 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1023 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1024 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1029 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1030 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
1031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1033 if (idxData != NULL /* This crashes sometimes!*/) {
1034 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1035 idxData = idxData == (void *)-1 ? NULL : idxData;
1038 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1039 glEnableClientState(GL_INDEX_ARRAY);
1041 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1042 (const char *)idxData+(idxSize * startIdx));
1043 #else /* using drawRangeElements may be faster */
1045 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1046 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1047 (const char *)idxData+(idxSize * startIdx));
1049 checkGLcall("glDrawRangeElements");
1053 /* Note first is now zero as we shuffled along earlier */
1054 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1055 glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
1056 checkGLcall("glDrawArrays");
1064 * Actually draw using the supplied information.
1065 * Slower GL version which extracts info about each vertex in turn
1068 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1069 UINT NumVertexes, GLenum glPrimType,
1070 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
1072 unsigned int textureNo = 0;
1073 unsigned int texture_idx = 0;
1074 const short *pIdxBufS = NULL;
1075 const long *pIdxBufL = NULL;
1077 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1078 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1079 float rhw = 0.0f; /* rhw */
1080 float ptSize = 0.0f; /* Point size */
1081 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1082 DWORD specularColor = 0; /* Specular Color */
1083 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1084 LONG SkipnStrides = startVertex + This->stateBlock->baseVertexIndex;
1086 TRACE("Using slow vertex array code\n");
1088 /* Variable Initialization */
1089 if (idxData != NULL) {
1090 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1091 else pIdxBufL = (const long *) idxData;
1094 /* Start drawing in GL */
1095 VTRACE(("glBegin(%x)\n", glPrimType));
1096 glBegin(glPrimType);
1098 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1099 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1102 /* For each primitive */
1103 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1105 /* Initialize diffuse color */
1106 diffuseColor = 0xFFFFFFFF;
1108 /* For indexed data, we need to go a few more strides in */
1109 if (idxData != NULL) {
1111 /* Indexed so work out the number of strides to skip */
1113 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1114 SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->baseVertexIndex;
1116 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1117 SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->baseVertexIndex;
1121 /* Position Information ------------------ */
1122 if (sd->u.s.position.lpData != NULL) {
1124 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1129 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1131 /* RHW follows, only if transformed, ie 4 floats were provided */
1132 if (sd->u.s.position_transformed) {
1133 rhw = ptrToCoords[3];
1134 VTRACE(("rhw=%f\n", rhw));
1138 /* Blending data -------------------------- */
1139 if (sd->u.s.blendWeights.lpData != NULL) {
1140 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1141 FIXME("Blending not supported yet\n");
1143 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1144 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1148 /* Vertex Normal Data (untransformed only)- */
1149 if (sd->u.s.normal.lpData != NULL) {
1151 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1152 nx = ptrToCoords[0];
1153 ny = ptrToCoords[1];
1154 nz = ptrToCoords[2];
1155 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1158 /* Point Size ----------------------------- */
1159 if (sd->u.s.pSize.lpData != NULL) {
1161 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1162 ptSize = ptrToCoords[0];
1163 VTRACE(("ptSize=%f\n", ptSize));
1164 FIXME("No support for ptSize yet\n");
1167 /* Diffuse -------------------------------- */
1168 if (sd->u.s.diffuse.lpData != NULL) {
1170 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1171 diffuseColor = ptrToCoords[0];
1172 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1175 /* Specular -------------------------------- */
1176 if (sd->u.s.specular.lpData != NULL) {
1178 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1179 specularColor = ptrToCoords[0];
1180 VTRACE(("specularColor=%lx\n", specularColor));
1183 /* Texture coords --------------------------- */
1184 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1186 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1187 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1191 /* Query tex coords */
1192 if (This->stateBlock->textures[textureNo] != NULL) {
1194 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1195 float *ptrToCoords = NULL;
1196 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1199 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1202 } else if (coordIdx < 0) {
1203 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1208 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1209 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1210 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1215 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
1217 /* The coords to supply depend completely on the fvf / vertex shader */
1218 switch (coordsToUse) {
1219 case 4: q = ptrToCoords[3]; /* drop through */
1220 case 3: r = ptrToCoords[2]; /* drop through */
1221 case 2: t = ptrToCoords[1]; /* drop through */
1222 case 1: s = ptrToCoords[0];
1225 /* Projected is more 'fun' - Move the last coord to the 'q'
1226 parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
1227 if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
1228 (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
1230 if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
1231 switch (coordsToUse) {
1232 case 0: /* Drop Through */
1234 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
1246 case 4: /* Nop here */
1249 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
1250 This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
1255 switch (coordsToUse) { /* Supply the provided texture coords */
1256 case WINED3DTTFF_COUNT1:
1257 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1258 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1259 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1264 case WINED3DTTFF_COUNT2:
1265 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1266 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1267 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1272 case WINED3DTTFF_COUNT3:
1273 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1274 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1275 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1277 glTexCoord3f(s, t, r);
1280 case WINED3DTTFF_COUNT4:
1281 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1282 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1283 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1285 glTexCoord4f(s, t, r, q);
1289 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1293 if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/TRUE) ++texture_idx;
1294 } /* End of textures */
1296 /* Diffuse -------------------------------- */
1297 if (sd->u.s.diffuse.lpData != NULL) {
1298 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1299 D3DCOLOR_B_G(diffuseColor),
1300 D3DCOLOR_B_B(diffuseColor),
1301 D3DCOLOR_B_A(diffuseColor));
1302 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1303 D3DCOLOR_B_R(diffuseColor),
1304 D3DCOLOR_B_G(diffuseColor),
1305 D3DCOLOR_B_B(diffuseColor),
1306 D3DCOLOR_B_A(diffuseColor)));
1308 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1311 /* Specular ------------------------------- */
1312 if (sd->u.s.specular.lpData != NULL) {
1313 /* special case where the fog density is stored in the diffuse alpha channel */
1314 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1315 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
1316 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1317 if(GL_SUPPORT(EXT_FOG_COORD)) {
1318 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1320 static BOOL warned = FALSE;
1322 /* TODO: Use the fog table code from old ddraw */
1323 FIXME("Implement fog for transformed vertices in software\n");
1329 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1330 D3DCOLOR_B_R(specularColor),
1331 D3DCOLOR_B_G(specularColor),
1332 D3DCOLOR_B_B(specularColor)));
1333 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1334 GL_EXTCALL(glSecondaryColor3ubEXT)(
1335 D3DCOLOR_B_R(specularColor),
1336 D3DCOLOR_B_G(specularColor),
1337 D3DCOLOR_B_B(specularColor));
1339 /* Do not worry if specular colour missing and disable request */
1340 VTRACE(("Specular color extensions not supplied\n"));
1343 if (vx_index == 0) {
1344 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1345 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1347 /* Do not worry if specular colour missing and disable request */
1348 VTRACE(("Specular color extensions not supplied\n"));
1353 /* Normal -------------------------------- */
1354 if (sd->u.s.normal.lpData != NULL) {
1355 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1356 glNormal3f(nx, ny, nz);
1358 if (vx_index == 0) glNormal3f(0, 0, 1);
1361 /* Position -------------------------------- */
1362 if (sd->u.s.position.lpData != NULL) {
1363 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1364 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1365 glVertex3f(x, y, z);
1367 GLfloat w = 1.0 / rhw;
1368 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1369 glVertex4f(x*w, y*w, z*w, w);
1373 /* For non indexed mode, step onto next parts */
1374 if (idxData == NULL) {
1380 checkGLcall("glEnd and previous calls");
1383 #if 0 /* TODO: Software/Hardware vertex blending support */
1385 * Draw with emulated vertex shaders
1386 * Note: strided data is uninitialized, as we need to pass the vertex
1387 * shader directly as ordering irs yet
1389 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1390 int PrimitiveType, ULONG NumPrimitives,
1391 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1393 unsigned int textureNo = 0;
1394 GLenum glPrimType = GL_POINTS;
1395 int NumVertexes = NumPrimitives;
1396 const short *pIdxBufS = NULL;
1397 const long *pIdxBufL = NULL;
1398 LONG SkipnStrides = 0;
1400 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1401 float rhw = 0.0f; /* rhw */
1402 float ptSize = 0.0f; /* Point size */
1403 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1404 int numcoords[8]; /* Number of coords */
1405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1407 IDirect3DVertexShaderImpl* vertexShader = NULL;
1409 TRACE("Using slow software vertex shader code\n");
1411 /* Variable Initialization */
1412 if (idxData != NULL) {
1413 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1414 else pIdxBufL = (const long *) idxData;
1417 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1418 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1420 /* Retrieve the VS information */
1421 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1423 /* Start drawing in GL */
1424 VTRACE(("glBegin(%x)\n", glPrimType));
1425 glBegin(glPrimType);
1427 /* For each primitive */
1428 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1430 /* For indexed data, we need to go a few more strides in */
1431 if (idxData != NULL) {
1433 /* Indexed so work out the number of strides to skip */
1435 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1436 SkipnStrides = pIdxBufS[startIdx+vx_index];
1438 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1439 SkipnStrides = pIdxBufL[startIdx+vx_index];
1443 /* Fill the vertex shader input */
1444 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1446 /* Initialize the output fields to the same defaults as it would normally have */
1447 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1448 vertexShader->output.oD[0].x = 1.0;
1449 vertexShader->output.oD[0].y = 1.0;
1450 vertexShader->output.oD[0].z = 1.0;
1451 vertexShader->output.oD[0].w = 1.0;
1453 /* Now execute the vertex shader */
1454 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1457 TRACE_VECTOR(vertexShader->output.oPos);
1458 TRACE_VECTOR(vertexShader->output.oD[0]);
1459 TRACE_VECTOR(vertexShader->output.oD[1]);
1460 TRACE_VECTOR(vertexShader->output.oT[0]);
1461 TRACE_VECTOR(vertexShader->output.oT[1]);
1462 TRACE_VECTOR(vertexShader->input.V[0]);
1463 TRACE_VECTOR(vertexShader->data->C[0]);
1464 TRACE_VECTOR(vertexShader->data->C[1]);
1465 TRACE_VECTOR(vertexShader->data->C[2]);
1466 TRACE_VECTOR(vertexShader->data->C[3]);
1467 TRACE_VECTOR(vertexShader->data->C[4]);
1468 TRACE_VECTOR(vertexShader->data->C[5]);
1469 TRACE_VECTOR(vertexShader->data->C[6]);
1470 TRACE_VECTOR(vertexShader->data->C[7]);
1473 /* Extract out the output */
1474 /* FIXME: Fog coords? */
1475 x = vertexShader->output.oPos.x;
1476 y = vertexShader->output.oPos.y;
1477 z = vertexShader->output.oPos.z;
1478 rhw = vertexShader->output.oPos.w;
1479 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1481 /** Update textures coords using vertexShader->output.oT[0->7] */
1482 memset(texcoords, 0x00, sizeof(texcoords));
1483 memset(numcoords, 0x00, sizeof(numcoords));
1484 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1485 if (This->stateBlock->textures[textureNo] != NULL) {
1486 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1487 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1488 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1489 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1490 if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1491 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1493 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1494 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1495 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1496 default: numcoords[textureNo] = 4;
1500 numcoords[textureNo] = 0;
1504 /* Draw using this information */
1507 TRUE, 0.0f, 0.0f, 1.0f,
1508 TRUE, (float*) &vertexShader->output.oD[0],
1509 TRUE, (float*) &vertexShader->output.oD[1],
1510 FALSE, ptSize, /* FIXME: Change back when supported */
1511 texcoords, numcoords);
1513 /* For non indexed mode, step onto next parts */
1514 if (idxData == NULL) {
1518 } /* for each vertex */
1521 checkGLcall("glEnd and previous calls");
1526 inline static void drawPrimitiveDrawStrided(
1527 IWineD3DDevice *iface,
1528 BOOL useVertexShaderFunction,
1529 BOOL usePixelShaderFunction,
1530 WineDirect3DVertexStridedData *dataLocations,
1532 UINT numberOfvertices,
1533 UINT numberOfIndicies,
1535 const void *idxData,
1541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1542 BOOL useDrawStridedSlow;
1544 int startStride = idxData == NULL ? 0 :
1545 idxData == (void *) -1 ? 0 :
1546 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1547 int endStride = startStride;
1548 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1549 startStride, endStride, numberOfIndicies, numberOfvertices);
1551 /* Generate some fixme's if unsupported functionality is being used */
1552 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1553 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1554 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1555 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1557 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1558 FIXME("Tweening is only valid with vertex shaders\n");
1560 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1561 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1563 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1564 FIXME("Extended attributes are only valid with vertex shaders\n");
1566 #undef BUFFER_OR_DATA
1568 /* Fixed pipeline, no fixups required - load arrays */
1569 if (!useVertexShaderFunction &&
1570 ((dataLocations->u.s.pSize.lpData == NULL &&
1571 dataLocations->u.s.diffuse.lpData == NULL &&
1572 dataLocations->u.s.specular.lpData == NULL) ||
1575 /* Load the vertex data using named arrays */
1576 TRACE("(%p) Loading vertex data\n", This);
1577 loadVertexData(iface, dataLocations);
1578 useDrawStridedSlow = FALSE;
1580 /* Shader pipeline - load attribute arrays */
1581 } else if(useVertexShaderFunction) {
1583 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1584 useDrawStridedSlow = FALSE;
1586 /* We compile the shader here because we need the vertex declaration
1587 * in order to determine if we need to do any swizzling for D3DCOLOR
1588 * registers. If the shader is already compiled this call will do nothing. */
1589 IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1590 /* Draw vertex by vertex */
1592 TRACE("Not loading vertex data\n");
1593 useDrawStridedSlow = TRUE;
1596 /* Make any shaders active */
1597 This->shader_backend->shader_select(iface, usePixelShaderFunction, useVertexShaderFunction);
1599 /* Load any global constants/uniforms that may have been set by the application */
1600 This->shader_backend->shader_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1602 /* Draw vertex-by-vertex */
1603 if (useDrawStridedSlow)
1604 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex);
1606 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex);
1608 /* Cleanup any shaders */
1609 This->shader_backend->shader_cleanup(usePixelShaderFunction, useVertexShaderFunction);
1611 /* Unload vertex data */
1612 if (useVertexShaderFunction) {
1613 unloadNumberedArrays(iface);
1615 unloadVertexData(iface);
1619 inline void drawPrimitiveTraceDataLocations(
1620 WineDirect3DVertexStridedData *dataLocations) {
1622 /* Dump out what parts we have supplied */
1623 TRACE("Strided Data:\n");
1624 TRACE_STRIDED((dataLocations), position);
1625 TRACE_STRIDED((dataLocations), blendWeights);
1626 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1627 TRACE_STRIDED((dataLocations), normal);
1628 TRACE_STRIDED((dataLocations), pSize);
1629 TRACE_STRIDED((dataLocations), diffuse);
1630 TRACE_STRIDED((dataLocations), specular);
1631 TRACE_STRIDED((dataLocations), texCoords[0]);
1632 TRACE_STRIDED((dataLocations), texCoords[1]);
1633 TRACE_STRIDED((dataLocations), texCoords[2]);
1634 TRACE_STRIDED((dataLocations), texCoords[3]);
1635 TRACE_STRIDED((dataLocations), texCoords[4]);
1636 TRACE_STRIDED((dataLocations), texCoords[5]);
1637 TRACE_STRIDED((dataLocations), texCoords[6]);
1638 TRACE_STRIDED((dataLocations), texCoords[7]);
1639 TRACE_STRIDED((dataLocations), position2);
1640 TRACE_STRIDED((dataLocations), normal2);
1641 TRACE_STRIDED((dataLocations), tangent);
1642 TRACE_STRIDED((dataLocations), binormal);
1643 TRACE_STRIDED((dataLocations), tessFactor);
1644 TRACE_STRIDED((dataLocations), fog);
1645 TRACE_STRIDED((dataLocations), depth);
1646 TRACE_STRIDED((dataLocations), sample);
1652 static void check_fbo_status(IWineD3DDevice *iface) {
1653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1655 GLenum status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
1657 case GL_FRAMEBUFFER_COMPLETE_EXT: TRACE("FBO complete.\n"); break;
1658 default: TRACE("FBO status %#x.\n", status); break;
1662 static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
1663 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1664 GLint old_binding = 0;
1666 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
1668 glDisable(GL_CULL_FACE);
1669 glDisable(GL_BLEND);
1670 glDisable(GL_ALPHA_TEST);
1671 glDisable(GL_STENCIL_TEST);
1672 glEnable(GL_DEPTH_TEST);
1673 glDepthFunc(GL_ALWAYS);
1675 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1676 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1677 glBindTexture(GL_TEXTURE_2D, texture);
1678 glEnable(GL_TEXTURE_2D);
1680 This->shader_backend->shader_select_depth_blt(iface);
1682 glBegin(GL_TRIANGLE_STRIP);
1683 glVertex2f(-1.0f, -1.0f);
1684 glVertex2f(1.0f, -1.0f);
1685 glVertex2f(-1.0f, 1.0f);
1686 glVertex2f(1.0f, 1.0f);
1689 glBindTexture(GL_TEXTURE_2D, old_binding);
1694 static void depth_copy(IWineD3DDevice *iface) {
1695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1696 IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
1698 /* Only copy the depth buffer if there is one. */
1699 if (!depth_stencil) return;
1701 /* TODO: Make this work for modes other than FBO */
1702 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
1704 if (This->render_offscreen) {
1705 static GLuint tmp_texture = 0;
1706 GLint old_binding = 0;
1708 TRACE("Copying onscreen depth buffer to offscreen surface\n");
1711 glGenTextures(1, &tmp_texture);
1714 /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
1715 * directly on the FBO texture. That's because we need to flip. */
1716 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1717 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1718 glBindTexture(GL_TEXTURE_2D, tmp_texture);
1719 glCopyTexImage2D(depth_stencil->glDescription.target,
1720 depth_stencil->glDescription.level,
1721 depth_stencil->glDescription.glFormatInternal,
1724 depth_stencil->currentDesc.Width,
1725 depth_stencil->currentDesc.Height,
1727 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1728 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1729 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
1730 glBindTexture(GL_TEXTURE_2D, old_binding);
1732 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
1733 checkGLcall("glBindFramebuffer()");
1734 depth_blt(iface, tmp_texture);
1735 checkGLcall("depth_blt");
1737 TRACE("Copying offscreen surface to onscreen depth buffer\n");
1739 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1740 checkGLcall("glBindFramebuffer()");
1741 depth_blt(iface, depth_stencil->glDescription.textureName);
1742 checkGLcall("depth_blt");
1746 /* Routine common to the draw primitive and draw indexed primitive routines */
1747 void drawPrimitive(IWineD3DDevice *iface,
1751 long StartVertexIndex,
1752 UINT numberOfVertices,
1755 const void *idxData,
1758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1759 BOOL useVertexShaderFunction = FALSE;
1760 BOOL usePixelShaderFunction = FALSE;
1761 IWineD3DSwapChainImpl *swapchain;
1764 DWORD dirtyState, idx;
1767 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
1768 * here simply check whether a shader was set, or the user disabled shaders */
1769 if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
1770 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
1771 useVertexShaderFunction = TRUE;
1773 if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
1774 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
1775 usePixelShaderFunction = TRUE;
1777 /* Invalidate the back buffer memory so LockRect will read it the next time */
1778 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
1779 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
1781 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
1782 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1786 /* Ok, we will be updating the screen from here onwards so grab the lock */
1789 /* Apply dirty states */
1790 for(i=0; i < This->numDirtyEntries; i++) {
1791 dirtyState = This->dirtyArray[i];
1792 idx = dirtyState >> 5;
1793 shift = dirtyState & 0x1f;
1794 This->isStateDirty[idx] &= ~(1 << shift);
1795 StateTable[dirtyState].apply(dirtyState, This->stateBlock);
1797 This->numDirtyEntries = 0; /* This makes the whole list clean */
1798 fixup = This->streamFixedUp;
1800 if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1801 check_fbo_status(iface);
1804 if (This->depth_copy_state == WINED3D_DCS_COPY) {
1807 This->depth_copy_state = WINED3D_DCS_INITIAL;
1809 /* Now initialize the materials state */
1810 init_materials(iface, (This->strided_streams.u.s.diffuse.lpData != NULL || This->strided_streams.u.s.diffuse.VBO != 0));
1814 /* Ok, Work out which primitive is requested and how many vertexes that
1816 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1817 if (numberOfVertices == 0 )
1818 numberOfVertices = calculatedNumberOfindices;
1820 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
1821 &This->strided_streams, StartVertexIndex, numberOfVertices, calculatedNumberOfindices, glPrimType,
1822 idxData, idxSize, minIndex, StartIdx, fixup);
1825 /* Finshed updating the screen, restore lock */
1827 TRACE("Done all gl drawing\n");
1830 #ifdef SHOW_FRAME_MAKEUP
1832 static long int primCounter = 0;
1833 /* NOTE: set primCounter to the value reported by drawprim
1834 before you want to to write frame makeup to /tmp */
1835 if (primCounter >= 0) {
1836 WINED3DLOCKED_RECT r;
1838 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
1839 sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
1840 TRACE("Saving screenshot %s\n", buffer);
1841 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1842 IWineD3DSurface_UnlockRect(This->renderTarget);
1844 #ifdef SHOW_TEXTURE_MAKEUP
1846 IWineD3DSurface *pSur;
1848 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1849 if (This->stateBlock->textures[textureNo] != NULL) {
1850 sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
1851 TRACE("Saving texture %s\n", buffer);
1852 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
1853 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
1854 IWineD3DSurface_SaveSnapshot(pSur, buffer);
1855 IWineD3DSurface_Release(pSur);
1857 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
1864 TRACE("drawprim #%d\n", primCounter);