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
9 * Copyright 2007 Stefan Dösinger for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw
);
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 static BOOL
fixed_get_input(
95 BYTE usage
, BYTE usage_idx
,
96 unsigned int* regnum
) {
100 /* Those positions must have the order in the
101 * named part of the strided data */
103 if ((usage
== WINED3DDECLUSAGE_POSITION
|| usage
== WINED3DDECLUSAGE_POSITIONT
) && usage_idx
== 0)
105 else if (usage
== WINED3DDECLUSAGE_BLENDWEIGHT
&& usage_idx
== 0)
107 else if (usage
== WINED3DDECLUSAGE_BLENDINDICES
&& usage_idx
== 0)
109 else if (usage
== WINED3DDECLUSAGE_NORMAL
&& usage_idx
== 0)
111 else if (usage
== WINED3DDECLUSAGE_PSIZE
&& usage_idx
== 0)
113 else if (usage
== WINED3DDECLUSAGE_COLOR
&& usage_idx
== 0)
115 else if (usage
== WINED3DDECLUSAGE_COLOR
&& usage_idx
== 1)
117 else if (usage
== WINED3DDECLUSAGE_TEXCOORD
&& usage_idx
< WINED3DDP_MAXTEXCOORD
)
118 *regnum
= 7 + usage_idx
;
119 else if ((usage
== WINED3DDECLUSAGE_POSITION
|| usage
== WINED3DDECLUSAGE_POSITIONT
) && usage_idx
== 1)
120 *regnum
= 7 + WINED3DDP_MAXTEXCOORD
;
121 else if (usage
== WINED3DDECLUSAGE_NORMAL
&& usage_idx
== 1)
122 *regnum
= 8 + WINED3DDP_MAXTEXCOORD
;
123 else if (usage
== WINED3DDECLUSAGE_TANGENT
&& usage_idx
== 0)
124 *regnum
= 9 + WINED3DDP_MAXTEXCOORD
;
125 else if (usage
== WINED3DDECLUSAGE_BINORMAL
&& usage_idx
== 0)
126 *regnum
= 10 + WINED3DDP_MAXTEXCOORD
;
127 else if (usage
== WINED3DDECLUSAGE_TESSFACTOR
&& usage_idx
== 0)
128 *regnum
= 11 + WINED3DDP_MAXTEXCOORD
;
129 else if (usage
== WINED3DDECLUSAGE_FOG
&& usage_idx
== 0)
130 *regnum
= 12 + WINED3DDP_MAXTEXCOORD
;
131 else if (usage
== WINED3DDECLUSAGE_DEPTH
&& usage_idx
== 0)
132 *regnum
= 13 + WINED3DDP_MAXTEXCOORD
;
133 else if (usage
== WINED3DDECLUSAGE_SAMPLE
&& usage_idx
== 0)
134 *regnum
= 14 + WINED3DDP_MAXTEXCOORD
;
137 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
138 debug_d3ddeclusage(usage
), usage_idx
);
144 void primitiveDeclarationConvertToStridedData(
145 IWineD3DDevice
*iface
,
146 BOOL useVertexShaderFunction
,
147 WineDirect3DVertexStridedData
*strided
,
150 /* We need to deal with frequency data!*/
153 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
154 IWineD3DVertexDeclarationImpl
* vertexDeclaration
= (IWineD3DVertexDeclarationImpl
*)This
->stateBlock
->vertexDecl
;
156 WINED3DVERTEXELEMENT
*element
;
159 char isPreLoaded
[MAX_STREAMS
];
160 DWORD preLoadStreams
[MAX_STREAMS
], numPreloadStreams
= 0;
162 memset(isPreLoaded
, 0, sizeof(isPreLoaded
));
164 /* Translate the declaration into strided data */
165 for (i
= 0 ; i
< vertexDeclaration
->declarationWNumElements
- 1; ++i
) {
170 element
= vertexDeclaration
->pDeclarationWine
+ i
;
171 TRACE("%p Element %p (%d of %d)\n", vertexDeclaration
->pDeclarationWine
,
172 element
, i
+ 1, vertexDeclaration
->declarationWNumElements
- 1);
174 if (This
->stateBlock
->streamSource
[element
->Stream
] == NULL
)
177 if (This
->stateBlock
->streamIsUP
) {
178 TRACE("Stream is up %d, %p\n", element
->Stream
, This
->stateBlock
->streamSource
[element
->Stream
]);
180 data
= (BYTE
*)This
->stateBlock
->streamSource
[element
->Stream
];
182 TRACE("Stream isn't up %d, %p\n", element
->Stream
, This
->stateBlock
->streamSource
[element
->Stream
]);
183 if(!isPreLoaded
[element
->Stream
]) {
184 preLoadStreams
[numPreloadStreams
] = element
->Stream
;
186 isPreLoaded
[element
->Stream
] = 1;
188 data
= IWineD3DVertexBufferImpl_GetMemory(This
->stateBlock
->streamSource
[element
->Stream
], 0, &streamVBO
);
190 if( streamVBO
!= 0) *fixup
= TRUE
;
191 else if(*fixup
&& This
->stateBlock
->vertexShader
== NULL
) {
192 /* This may be bad with the fixed function pipeline */
193 FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
197 stride
= This
->stateBlock
->streamStride
[element
->Stream
];
198 data
+= element
->Offset
;
201 TRACE("Offset %d Stream %d UsageIndex %d\n", element
->Offset
, element
->Stream
, element
->UsageIndex
);
203 if (useVertexShaderFunction
)
204 stride_used
= vshader_get_input(This
->stateBlock
->vertexShader
,
205 element
->Usage
, element
->UsageIndex
, &idx
);
207 stride_used
= fixed_get_input(element
->Usage
, element
->UsageIndex
, &idx
);
210 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
211 "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
212 useVertexShaderFunction
? "shader": "fixed function", idx
,
213 debug_d3ddeclusage(element
->Usage
), element
->UsageIndex
,
214 element
->Stream
, element
->Offset
, stride
, streamVBO
);
216 strided
->u
.input
[idx
].lpData
= data
;
217 strided
->u
.input
[idx
].dwType
= element
->Type
;
218 strided
->u
.input
[idx
].dwStride
= stride
;
219 strided
->u
.input
[idx
].VBO
= streamVBO
;
220 strided
->u
.input
[idx
].streamNo
= element
->Stream
;
221 if (!useVertexShaderFunction
) {
222 if (element
->Usage
== WINED3DDECLUSAGE_POSITION
)
223 strided
->u
.s
.position_transformed
= FALSE
;
224 else if (element
->Usage
== WINED3DDECLUSAGE_POSITIONT
)
225 strided
->u
.s
.position_transformed
= TRUE
;
229 /* Now call PreLoad on all the vertex buffers. In the very rare case
230 * that the buffers stopps converting PreLoad will dirtify the VDECL again.
231 * The vertex buffer can now use the strided structure in the device instead of finding its
234 * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
237 for(i
=0; i
< numPreloadStreams
; i
++) {
238 IWineD3DVertexBuffer_PreLoad(This
->stateBlock
->streamSource
[preLoadStreams
[i
]]);
242 void primitiveConvertFVFtoOffset(DWORD thisFVF
, DWORD stride
, BYTE
*data
, WineDirect3DVertexStridedData
*strided
, GLint streamVBO
, UINT streamNo
) {
246 int coordIdxInfo
= 0x00; /* Information on number of coords supplied */
247 int numCoords
[8]; /* Holding place for WINED3DFVF_TEXTUREFORMATx */
249 /* Either 3 or 4 floats depending on the FVF */
250 /* FIXME: Can blending data be in a different stream to the position data?
251 and if so using the fixed pipeline how do we handle it */
252 if (thisFVF
& WINED3DFVF_POSITION_MASK
) {
253 strided
->u
.s
.position
.lpData
= data
;
254 strided
->u
.s
.position
.dwType
= WINED3DDECLTYPE_FLOAT3
;
255 strided
->u
.s
.position
.dwStride
= stride
;
256 strided
->u
.s
.position
.VBO
= streamVBO
;
257 strided
->u
.s
.position
.streamNo
= streamNo
;
258 data
+= 3 * sizeof(float);
259 if (thisFVF
& WINED3DFVF_XYZRHW
) {
260 strided
->u
.s
.position
.dwType
= WINED3DDECLTYPE_FLOAT4
;
261 strided
->u
.s
.position_transformed
= TRUE
;
262 data
+= sizeof(float);
264 strided
->u
.s
.position_transformed
= FALSE
;
267 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
268 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
269 numBlends
= 1 + (((thisFVF
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
270 if(thisFVF
& WINED3DFVF_LASTBETA_UBYTE4
) numBlends
--;
272 if ((thisFVF
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
) {
273 TRACE("Setting blend Weights to %p\n", data
);
274 strided
->u
.s
.blendWeights
.lpData
= data
;
275 strided
->u
.s
.blendWeights
.dwType
= WINED3DDECLTYPE_FLOAT1
+ numBlends
- 1;
276 strided
->u
.s
.blendWeights
.dwStride
= stride
;
277 strided
->u
.s
.blendWeights
.VBO
= streamVBO
;
278 strided
->u
.s
.blendWeights
.streamNo
= streamNo
;
279 data
+= numBlends
* sizeof(FLOAT
);
281 if (thisFVF
& WINED3DFVF_LASTBETA_UBYTE4
) {
282 strided
->u
.s
.blendMatrixIndices
.lpData
= data
;
283 strided
->u
.s
.blendMatrixIndices
.dwType
= WINED3DDECLTYPE_UBYTE4
;
284 strided
->u
.s
.blendMatrixIndices
.dwStride
= stride
;
285 strided
->u
.s
.blendMatrixIndices
.VBO
= streamVBO
;
286 strided
->u
.s
.blendMatrixIndices
.streamNo
= streamNo
;
287 data
+= sizeof(DWORD
);
291 /* Normal is always 3 floats */
292 if (thisFVF
& WINED3DFVF_NORMAL
) {
293 strided
->u
.s
.normal
.lpData
= data
;
294 strided
->u
.s
.normal
.dwType
= WINED3DDECLTYPE_FLOAT3
;
295 strided
->u
.s
.normal
.dwStride
= stride
;
296 strided
->u
.s
.normal
.VBO
= streamVBO
;
297 strided
->u
.s
.normal
.streamNo
= streamNo
;
298 data
+= 3 * sizeof(FLOAT
);
301 /* Pointsize is a single float */
302 if (thisFVF
& WINED3DFVF_PSIZE
) {
303 strided
->u
.s
.pSize
.lpData
= data
;
304 strided
->u
.s
.pSize
.dwType
= WINED3DDECLTYPE_FLOAT1
;
305 strided
->u
.s
.pSize
.dwStride
= stride
;
306 strided
->u
.s
.pSize
.VBO
= streamVBO
;
307 strided
->u
.s
.pSize
.streamNo
= streamNo
;
308 data
+= sizeof(FLOAT
);
311 /* Diffuse is 4 unsigned bytes */
312 if (thisFVF
& WINED3DFVF_DIFFUSE
) {
313 strided
->u
.s
.diffuse
.lpData
= data
;
314 strided
->u
.s
.diffuse
.dwType
= WINED3DDECLTYPE_SHORT4
;
315 strided
->u
.s
.diffuse
.dwStride
= stride
;
316 strided
->u
.s
.diffuse
.VBO
= streamVBO
;
317 strided
->u
.s
.diffuse
.streamNo
= streamNo
;
318 data
+= sizeof(DWORD
);
321 /* Specular is 4 unsigned bytes */
322 if (thisFVF
& WINED3DFVF_SPECULAR
) {
323 strided
->u
.s
.specular
.lpData
= data
;
324 strided
->u
.s
.specular
.dwType
= WINED3DDECLTYPE_SHORT4
;
325 strided
->u
.s
.specular
.dwStride
= stride
;
326 strided
->u
.s
.specular
.VBO
= streamVBO
;
327 strided
->u
.s
.specular
.streamNo
= streamNo
;
328 data
+= sizeof(DWORD
);
332 numTextures
= (thisFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
333 coordIdxInfo
= (thisFVF
& 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
335 /* numTextures indicates the number of texture coordinates supplied */
336 /* However, the first set may not be for stage 0 texture - it all */
337 /* depends on WINED3DTSS_TEXCOORDINDEX. */
338 /* The number of bytes for each coordinate set is based off */
339 /* WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
341 /* So, for each supplied texture extract the coords */
342 for (textureNo
= 0; textureNo
< numTextures
; ++textureNo
) {
344 strided
->u
.s
.texCoords
[textureNo
].lpData
= data
;
345 strided
->u
.s
.texCoords
[textureNo
].dwType
= WINED3DDECLTYPE_FLOAT1
;
346 strided
->u
.s
.texCoords
[textureNo
].dwStride
= stride
;
347 strided
->u
.s
.texCoords
[textureNo
].VBO
= streamVBO
;
348 strided
->u
.s
.texCoords
[textureNo
].streamNo
= streamNo
;
349 numCoords
[textureNo
] = coordIdxInfo
& 0x03;
352 data
+= sizeof(float);
353 if (numCoords
[textureNo
] != WINED3DFVF_TEXTUREFORMAT1
) {
354 strided
->u
.s
.texCoords
[textureNo
].dwType
= WINED3DDECLTYPE_FLOAT2
;
355 data
+= sizeof(float);
356 if (numCoords
[textureNo
] != WINED3DFVF_TEXTUREFORMAT2
) {
357 strided
->u
.s
.texCoords
[textureNo
].dwType
= WINED3DDECLTYPE_FLOAT3
;
358 data
+= sizeof(float);
359 if (numCoords
[textureNo
] != WINED3DFVF_TEXTUREFORMAT3
) {
360 strided
->u
.s
.texCoords
[textureNo
].dwType
= WINED3DDECLTYPE_FLOAT4
;
361 data
+= sizeof(float);
365 coordIdxInfo
= coordIdxInfo
>> 2; /* Drop bottom two bits */
369 void primitiveConvertToStridedData(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*strided
, BOOL
*fixup
) {
370 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
372 DWORD stride
= This
->stateBlock
->streamStride
[0];
376 /* Retrieve appropriate FVF */
377 thisFVF
= This
->stateBlock
->fvf
;
378 /* Handle memory passed directly as well as vertex buffers */
379 if (This
->stateBlock
->streamIsUP
) {
381 data
= (BYTE
*)This
->stateBlock
->streamSource
[0];
383 /* The for loop should iterate through here only once per stream, so we don't need magic to prevent double loading
386 data
= IWineD3DVertexBufferImpl_GetMemory(This
->stateBlock
->streamSource
[0], 0, &streamVBO
);
388 if(streamVBO
!= 0 ) *fixup
= TRUE
;
391 VTRACE(("FVF for stream 0 is %lx\n", thisFVF
));
393 /* Now convert the stream into pointers */
394 primitiveConvertFVFtoOffset(thisFVF
, stride
, data
, strided
, streamVBO
, 0);
396 /* Now call PreLoad on the vertex buffer. In the very rare case
397 * that the buffers stopps converting PreLoad will dirtify the VDECL again.
398 * The vertex buffer can now use the strided structure in the device instead of finding its
401 if(!This
->stateBlock
->streamIsUP
) {
402 IWineD3DVertexBuffer_PreLoad(This
->stateBlock
->streamSource
[0]);
406 static void drawStridedFast(IWineD3DDevice
*iface
,UINT numberOfVertices
, GLenum glPrimitiveType
,
407 const void *idxData
, short idxSize
, ULONG minIndex
, ULONG startIdx
, ULONG startVertex
) {
408 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
410 if (idxSize
!= 0 /* This crashes sometimes!*/) {
411 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This
, glPrimitiveType
, numberOfVertices
, minIndex
);
412 idxData
= idxData
== (void *)-1 ? NULL
: idxData
;
414 glDrawElements(glPrimitiveType
, numberOfVertices
, idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
,
415 (const char *)idxData
+(idxSize
* startIdx
));
416 #else /* using drawRangeElements may be faster */
418 glDrawRangeElements(glPrimitiveType
, minIndex
, minIndex
+ numberOfVertices
- 1, numberOfVertices
,
419 idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
,
420 (const char *)idxData
+(idxSize
* startIdx
));
422 checkGLcall("glDrawRangeElements");
426 /* Note first is now zero as we shuffled along earlier */
427 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This
, glPrimitiveType
, numberOfVertices
);
428 glDrawArrays(glPrimitiveType
, startVertex
, numberOfVertices
);
429 checkGLcall("glDrawArrays");
437 * Actually draw using the supplied information.
438 * Slower GL version which extracts info about each vertex in turn
441 static void drawStridedSlow(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*sd
,
442 UINT NumVertexes
, GLenum glPrimType
,
443 const void *idxData
, short idxSize
, ULONG minIndex
, ULONG startIdx
, ULONG startVertex
) {
445 unsigned int textureNo
= 0;
446 unsigned int texture_idx
= 0;
447 const short *pIdxBufS
= NULL
;
448 const long *pIdxBufL
= NULL
;
450 float x
= 0.0f
, y
= 0.0f
, z
= 0.0f
; /* x,y,z coordinates */
451 float rhw
= 0.0f
; /* rhw */
452 DWORD diffuseColor
= 0xFFFFFFFF; /* Diffuse Color */
453 DWORD specularColor
= 0; /* Specular Color */
454 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
455 UINT
*streamOffset
= This
->stateBlock
->streamOffset
;
456 LONG SkipnStrides
= startVertex
+ This
->stateBlock
->loadBaseVertexIndex
;
458 BYTE
*texCoords
[WINED3DDP_MAXTEXCOORD
];
459 BYTE
*diffuse
= NULL
, *specular
= NULL
, *normal
= NULL
, *position
= NULL
;
461 TRACE("Using slow vertex array code\n");
463 /* Variable Initialization */
465 /* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer.
466 * If the index buffer has no vbo(not supported or other reason), or with user pointer drawing
467 * idxData will be != NULL
469 if(idxData
== NULL
) {
470 idxData
= ((IWineD3DIndexBufferImpl
*) This
->stateBlock
->pIndexData
)->resource
.allocatedMemory
;
473 if (idxSize
== 2) pIdxBufS
= (const short *) idxData
;
474 else pIdxBufL
= (const long *) idxData
;
477 /* Adding the stream offset once is cheaper than doing it every iteration. Do not modify the strided data, it is a pointer
478 * to the strided Data in the device and might be needed intact on the next draw
480 for (textureNo
= 0, texture_idx
= 0; textureNo
< GL_LIMITS(texture_stages
); ++textureNo
) {
481 if(sd
->u
.s
.texCoords
[textureNo
].lpData
) {
482 texCoords
[textureNo
] = sd
->u
.s
.texCoords
[textureNo
].lpData
+ streamOffset
[sd
->u
.s
.texCoords
[textureNo
].streamNo
];
484 texCoords
[textureNo
] = NULL
;
487 if(sd
->u
.s
.diffuse
.lpData
) {
488 diffuse
= sd
->u
.s
.diffuse
.lpData
+ streamOffset
[sd
->u
.s
.diffuse
.streamNo
];
490 if(sd
->u
.s
.specular
.lpData
) {
491 specular
= sd
->u
.s
.specular
.lpData
+ streamOffset
[sd
->u
.s
.specular
.streamNo
];
493 if(sd
->u
.s
.normal
.lpData
) {
494 normal
= sd
->u
.s
.normal
.lpData
+ streamOffset
[sd
->u
.s
.normal
.streamNo
];
496 if(sd
->u
.s
.position
.lpData
) {
497 position
= sd
->u
.s
.position
.lpData
+ streamOffset
[sd
->u
.s
.position
.streamNo
];
500 /* Start drawing in GL */
501 VTRACE(("glBegin(%x)\n", glPrimType
));
504 /* Default settings for data that is not passed */
505 if (sd
->u
.s
.normal
.lpData
== NULL
) {
508 if(sd
->u
.s
.diffuse
.lpData
!= NULL
) {
509 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
511 if(sd
->u
.s
.specular
.lpData
!= NULL
) {
512 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
513 GL_EXTCALL(glSecondaryColor3fEXT
)(0, 0, 0);
517 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
518 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
521 /* For each primitive */
522 for (vx_index
= 0; vx_index
< NumVertexes
; ++vx_index
) {
524 /* Initialize diffuse color */
525 diffuseColor
= 0xFFFFFFFF;
527 /* Blending data and Point sizes are not supported by this function. They are not supported by the fixed
528 * function pipeline at all. A Fixme for them is printed after decoding the vertex declaration
531 /* For indexed data, we need to go a few more strides in */
532 if (idxData
!= NULL
) {
534 /* Indexed so work out the number of strides to skip */
536 VTRACE(("Idx for vertex %d = %d\n", vx_index
, pIdxBufS
[startIdx
+vx_index
]));
537 SkipnStrides
= pIdxBufS
[startIdx
+ vx_index
] + This
->stateBlock
->loadBaseVertexIndex
;
539 VTRACE(("Idx for vertex %d = %d\n", vx_index
, pIdxBufL
[startIdx
+vx_index
]));
540 SkipnStrides
= pIdxBufL
[startIdx
+ vx_index
] + This
->stateBlock
->loadBaseVertexIndex
;
544 /* Texture coords --------------------------- */
545 for (textureNo
= 0, texture_idx
= 0; textureNo
< GL_LIMITS(texture_stages
); ++textureNo
) {
547 if (!GL_SUPPORT(ARB_MULTITEXTURE
) && textureNo
> 0) {
548 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
552 /* Query tex coords */
553 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
555 int coordIdx
= This
->stateBlock
->textureState
[textureNo
][WINED3DTSS_TEXCOORDINDEX
];
556 float *ptrToCoords
= NULL
;
557 float s
= 0.0, t
= 0.0, r
= 0.0, q
= 0.0;
560 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo
));
563 } else if (coordIdx
< 0) {
564 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo
, coordIdx
);
569 ptrToCoords
= (float *)(texCoords
[coordIdx
] + (SkipnStrides
* sd
->u
.s
.texCoords
[coordIdx
].dwStride
));
570 if (texCoords
[coordIdx
] == NULL
) {
571 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo
);
576 int coordsToUse
= sd
->u
.s
.texCoords
[coordIdx
].dwType
+ 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
578 /* The coords to supply depend completely on the fvf / vertex shader */
579 switch (coordsToUse
) {
580 case 4: q
= ptrToCoords
[3]; /* drop through */
581 case 3: r
= ptrToCoords
[2]; /* drop through */
582 case 2: t
= ptrToCoords
[1]; /* drop through */
583 case 1: s
= ptrToCoords
[0];
586 /* Projected is more 'fun' - Move the last coord to the 'q'
587 parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
588 if ((This
->stateBlock
->textureState
[textureNo
][WINED3DTSS_TEXTURETRANSFORMFLAGS
] != WINED3DTTFF_DISABLE
) &&
589 (This
->stateBlock
->textureState
[textureNo
][WINED3DTSS_TEXTURETRANSFORMFLAGS
] & WINED3DTTFF_PROJECTED
)) {
591 if (This
->stateBlock
->textureState
[textureNo
][WINED3DTSS_TEXTURETRANSFORMFLAGS
] & WINED3DTTFF_PROJECTED
) {
592 switch (coordsToUse
) {
593 case 0: /* Drop Through */
595 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
607 case 4: /* Nop here */
610 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
611 This
->stateBlock
->textureState
[textureNo
][WINED3DTSS_TEXTURETRANSFORMFLAGS
] & WINED3DTTFF_PROJECTED
);
616 switch (coordsToUse
) { /* Supply the provided texture coords */
617 case WINED3DTTFF_COUNT1
:
618 VTRACE(("tex:%d, s=%f\n", textureNo
, s
));
619 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
620 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx
, s
));
625 case WINED3DTTFF_COUNT2
:
626 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo
, s
, t
));
627 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
628 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx
, s
, t
));
633 case WINED3DTTFF_COUNT3
:
634 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo
, s
, t
, r
));
635 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
636 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx
, s
, t
, r
));
638 glTexCoord3f(s
, t
, r
);
641 case WINED3DTTFF_COUNT4
:
642 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo
, s
, t
, r
, q
));
643 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
644 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx
, s
, t
, r
, q
));
646 glTexCoord4f(s
, t
, r
, q
);
650 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse
);
654 if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/TRUE
) ++texture_idx
;
655 } /* End of textures */
657 /* Diffuse -------------------------------- */
659 DWORD
*ptrToCoords
= (DWORD
*)(diffuse
+ (SkipnStrides
* sd
->u
.s
.diffuse
.dwStride
));
660 diffuseColor
= ptrToCoords
[0];
661 VTRACE(("diffuseColor=%lx\n", diffuseColor
));
663 glColor4ub(D3DCOLOR_B_R(diffuseColor
),
664 D3DCOLOR_B_G(diffuseColor
),
665 D3DCOLOR_B_B(diffuseColor
),
666 D3DCOLOR_B_A(diffuseColor
));
667 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
668 D3DCOLOR_B_R(diffuseColor
),
669 D3DCOLOR_B_G(diffuseColor
),
670 D3DCOLOR_B_B(diffuseColor
),
671 D3DCOLOR_B_A(diffuseColor
)));
674 /* Specular ------------------------------- */
676 DWORD
*ptrToCoords
= (DWORD
*)(specular
+ (SkipnStrides
* sd
->u
.s
.specular
.dwStride
));
677 specularColor
= ptrToCoords
[0];
678 VTRACE(("specularColor=%lx\n", specularColor
));
680 /* special case where the fog density is stored in the diffuse alpha channel */
681 if(This
->stateBlock
->renderState
[WINED3DRS_FOGENABLE
] &&
682 (This
->stateBlock
->renderState
[WINED3DRS_FOGVERTEXMODE
] == WINED3DFOG_NONE
|| sd
->u
.s
.position
.dwType
== WINED3DDECLTYPE_FLOAT4
)&&
683 This
->stateBlock
->renderState
[WINED3DRS_FOGTABLEMODE
] == WINED3DFOG_NONE
) {
684 if(GL_SUPPORT(EXT_FOG_COORD
)) {
685 GL_EXTCALL(glFogCoordfEXT(specularColor
>> 24));
687 static BOOL warned
= FALSE
;
689 /* TODO: Use the fog table code from old ddraw */
690 FIXME("Implement fog for transformed vertices in software\n");
696 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
697 D3DCOLOR_B_R(specularColor
),
698 D3DCOLOR_B_G(specularColor
),
699 D3DCOLOR_B_B(specularColor
)));
700 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
701 GL_EXTCALL(glSecondaryColor3ubEXT
)(
702 D3DCOLOR_B_R(specularColor
),
703 D3DCOLOR_B_G(specularColor
),
704 D3DCOLOR_B_B(specularColor
));
706 /* Do not worry if specular colour missing and disable request */
707 VTRACE(("Specular color extensions not supplied\n"));
711 /* Normal -------------------------------- */
712 if (normal
!= NULL
) {
713 float *ptrToCoords
= (float *)(normal
+ (SkipnStrides
* sd
->u
.s
.normal
.dwStride
));
715 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", ptrToCoords
[0], ptrToCoords
[1], ptrToCoords
[2]));
716 glNormal3f(ptrToCoords
[0], ptrToCoords
[1], ptrToCoords
[2]);
719 /* Position -------------------------------- */
721 float *ptrToCoords
= (float *)(position
+ (SkipnStrides
* sd
->u
.s
.position
.dwStride
));
726 VTRACE(("x,y,z=%f,%f,%f\n", x
,y
,z
));
728 /* RHW follows, only if transformed, ie 4 floats were provided */
729 if (sd
->u
.s
.position_transformed
) {
730 rhw
= ptrToCoords
[3];
731 VTRACE(("rhw=%f\n", rhw
));
734 if (1.0f
== rhw
|| ((rhw
< eps
) && (rhw
> -eps
))) {
735 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x
,y
,z
));
738 GLfloat w
= 1.0 / rhw
;
739 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x
,y
,z
,rhw
));
740 glVertex4f(x
*w
, y
*w
, z
*w
, w
);
744 /* For non indexed mode, step onto next parts */
745 if (idxData
== NULL
) {
751 checkGLcall("glEnd and previous calls");
754 static void check_fbo_status(IWineD3DDevice
*iface
) {
755 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
757 GLenum status
= GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
));
759 case GL_FRAMEBUFFER_COMPLETE_EXT
: TRACE("FBO complete.\n"); break;
760 default: TRACE("FBO status %#x.\n", status
); break;
764 static void depth_blt(IWineD3DDevice
*iface
, GLuint texture
) {
765 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
766 GLint old_binding
= 0;
768 glPushAttrib(GL_ENABLE_BIT
| GL_DEPTH_BUFFER_BIT
);
770 glDisable(GL_CULL_FACE
);
772 glDisable(GL_ALPHA_TEST
);
773 glDisable(GL_STENCIL_TEST
);
774 glEnable(GL_DEPTH_TEST
);
775 glDepthFunc(GL_ALWAYS
);
777 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
778 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &old_binding
);
779 glBindTexture(GL_TEXTURE_2D
, texture
);
780 glEnable(GL_TEXTURE_2D
);
782 This
->shader_backend
->shader_select_depth_blt(iface
);
784 glBegin(GL_TRIANGLE_STRIP
);
785 glVertex2f(-1.0f
, -1.0f
);
786 glVertex2f(1.0f
, -1.0f
);
787 glVertex2f(-1.0f
, 1.0f
);
788 glVertex2f(1.0f
, 1.0f
);
791 glBindTexture(GL_TEXTURE_2D
, old_binding
);
795 /* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders,
796 * and this seems easier and more efficient than providing the shader backend with a private
797 * storage to read and restore the old shader settings
799 This
->shader_backend
->shader_select(iface
,
800 This
->stateBlock
->pixelShader
&& ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.function
,
801 This
->stateBlock
->vertexShader
&& ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.function
);
804 static void depth_copy(IWineD3DDevice
*iface
) {
805 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
806 IWineD3DSurfaceImpl
*depth_stencil
= (IWineD3DSurfaceImpl
*)This
->depthStencilBuffer
;
808 /* Only copy the depth buffer if there is one. */
809 if (!depth_stencil
) return;
811 /* TODO: Make this work for modes other than FBO */
812 if (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) return;
814 if (This
->render_offscreen
) {
815 static GLuint tmp_texture
= 0;
816 GLint old_binding
= 0;
818 TRACE("Copying onscreen depth buffer to offscreen surface\n");
821 glGenTextures(1, &tmp_texture
);
824 /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
825 * directly on the FBO texture. That's because we need to flip. */
826 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
827 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &old_binding
);
828 glBindTexture(GL_TEXTURE_2D
, tmp_texture
);
829 glCopyTexImage2D(depth_stencil
->glDescription
.target
,
830 depth_stencil
->glDescription
.level
,
831 depth_stencil
->glDescription
.glFormatInternal
,
834 depth_stencil
->currentDesc
.Width
,
835 depth_stencil
->currentDesc
.Height
,
837 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
838 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
839 glTexParameteri(GL_TEXTURE_2D
, GL_DEPTH_TEXTURE_MODE_ARB
, GL_LUMINANCE
);
840 glBindTexture(GL_TEXTURE_2D
, old_binding
);
842 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, This
->fbo
));
843 checkGLcall("glBindFramebuffer()");
844 depth_blt(iface
, tmp_texture
);
845 checkGLcall("depth_blt");
847 TRACE("Copying offscreen surface to onscreen depth buffer\n");
849 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
850 checkGLcall("glBindFramebuffer()");
851 depth_blt(iface
, depth_stencil
->glDescription
.textureName
);
852 checkGLcall("depth_blt");
856 inline void drawStridedInstanced(IWineD3DDevice
*iface
, WineDirect3DVertexStridedData
*sd
, UINT numberOfVertices
,
857 GLenum glPrimitiveType
, const void *idxData
, short idxSize
, ULONG minIndex
,
858 ULONG startIdx
, ULONG startVertex
) {
859 UINT numInstances
= 0;
860 int numInstancedAttribs
= 0, i
, j
;
861 UINT instancedData
[sizeof(sd
->u
.input
) / sizeof(sd
->u
.input
[0]) /* 16 */];
862 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
863 IWineD3DStateBlockImpl
*stateblock
= This
->stateBlock
;
866 /* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
867 * We don't support this for now
869 * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
870 * But the StreamSourceFreq value has a different meaning in that situation.
872 FIXME("Non-indexed instanced drawing is not supported\n");
876 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This
, glPrimitiveType
, numberOfVertices
, minIndex
);
877 idxData
= idxData
== (void *)-1 ? NULL
: idxData
;
879 /* First, figure out how many instances we have to draw */
880 for(i
= 0; i
< MAX_STREAMS
; i
++) {
881 /* Look at all non-instanced streams */
882 if(!(stateblock
->streamFlags
[i
] & WINED3DSTREAMSOURCE_INSTANCEDATA
) &&
883 stateblock
->streamSource
[i
]) {
884 int inst
= stateblock
->streamFreq
[i
];
886 if(numInstances
&& inst
!= numInstances
) {
887 ERR("Two streams specify a different number of instances. Got %d, new is %d\n", numInstances
, inst
);
893 for(i
= 0; i
< sizeof(sd
->u
.input
) / sizeof(sd
->u
.input
[0]); i
++) {
894 if(stateblock
->streamFlags
[sd
->u
.input
[i
].streamNo
] & WINED3DSTREAMSOURCE_INSTANCEDATA
) {
895 instancedData
[numInstancedAttribs
] = i
;
896 numInstancedAttribs
++;
900 /* now draw numInstances instances :-) */
901 for(i
= 0; i
< numInstances
; i
++) {
902 /* Specify the instanced attributes using immediate mode calls */
903 for(j
= 0; j
< numInstancedAttribs
; j
++) {
904 BYTE
*ptr
= sd
->u
.input
[instancedData
[j
]].lpData
+
905 sd
->u
.input
[instancedData
[j
]].dwStride
* i
+
906 stateblock
->streamOffset
[sd
->u
.input
[instancedData
[j
]].streamNo
];
907 if(sd
->u
.input
[instancedData
[j
]].VBO
) {
908 IWineD3DVertexBufferImpl
*vb
= (IWineD3DVertexBufferImpl
*) stateblock
->streamSource
[sd
->u
.input
[instancedData
[j
]].streamNo
];
909 ptr
+= (long) vb
->resource
.allocatedMemory
;
912 switch(sd
->u
.input
[instancedData
[j
]].dwType
) {
913 case WINED3DDECLTYPE_FLOAT1
:
914 GL_EXTCALL(glVertexAttrib1fvARB(instancedData
[j
], (float *) ptr
));
916 case WINED3DDECLTYPE_FLOAT2
:
917 GL_EXTCALL(glVertexAttrib2fvARB(instancedData
[j
], (float *) ptr
));
919 case WINED3DDECLTYPE_FLOAT3
:
920 GL_EXTCALL(glVertexAttrib3fvARB(instancedData
[j
], (float *) ptr
));
922 case WINED3DDECLTYPE_FLOAT4
:
923 GL_EXTCALL(glVertexAttrib4fvARB(instancedData
[j
], (float *) ptr
));
926 case WINED3DDECLTYPE_UBYTE4
:
927 GL_EXTCALL(glVertexAttrib4NubvARB(instancedData
[j
], ptr
));
929 case WINED3DDECLTYPE_UBYTE4N
:
930 case WINED3DDECLTYPE_D3DCOLOR
:
931 GL_EXTCALL(glVertexAttrib4NubvARB(instancedData
[j
], ptr
));
934 case WINED3DDECLTYPE_SHORT2
:
935 GL_EXTCALL(glVertexAttrib4svARB(instancedData
[j
], (GLshort
*) ptr
));
937 case WINED3DDECLTYPE_SHORT4
:
938 GL_EXTCALL(glVertexAttrib4svARB(instancedData
[j
], (GLshort
*) ptr
));
941 case WINED3DDECLTYPE_SHORT2N
:
943 GLshort s
[4] = {((short *) ptr
)[0], ((short *) ptr
)[1], 0, 1};
944 GL_EXTCALL(glVertexAttrib4NsvARB(instancedData
[j
], s
));
947 case WINED3DDECLTYPE_USHORT2N
:
949 GLushort s
[4] = {((unsigned short *) ptr
)[0], ((unsigned short *) ptr
)[1], 0, 1};
950 GL_EXTCALL(glVertexAttrib4NusvARB(instancedData
[j
], s
));
953 case WINED3DDECLTYPE_SHORT4N
:
954 GL_EXTCALL(glVertexAttrib4NsvARB(instancedData
[j
], (GLshort
*) ptr
));
956 case WINED3DDECLTYPE_USHORT4N
:
957 GL_EXTCALL(glVertexAttrib4NusvARB(instancedData
[j
], (GLushort
*) ptr
));
960 case WINED3DDECLTYPE_UDEC3
:
961 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
962 /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */
964 case WINED3DDECLTYPE_DEC3N
:
965 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
966 /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */
969 case WINED3DDECLTYPE_FLOAT16_2
:
970 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
971 * byte float according to the IEEE standard
973 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
975 case WINED3DDECLTYPE_FLOAT16_4
:
976 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
979 case WINED3DDECLTYPE_UNUSED
:
981 ERR("Unexpected declaration in instanced attributes\n");
986 glDrawElements(glPrimitiveType
, numberOfVertices
, idxSize
== 2 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
,
987 (const char *)idxData
+(idxSize
* startIdx
));
988 checkGLcall("glDrawElements");
992 /* Routine common to the draw primitive and draw indexed primitive routines */
993 void drawPrimitive(IWineD3DDevice
*iface
,
997 long StartVertexIndex
,
998 UINT numberOfVertices
,
1001 const void *idxData
,
1004 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1007 /* Signals other modules that a drawing is in progress and the stateblock finalized */
1008 This
->isInDraw
= TRUE
;
1010 /* Invalidate the back buffer memory so LockRect will read it the next time */
1011 for(i
= 0; i
< GL_LIMITS(buffers
); i
++) {
1012 if(This
->render_targets
[i
]) {
1013 ((IWineD3DSurfaceImpl
*) This
->render_targets
[i
])->Flags
|= SFLAG_GLDIRTY
;
1017 /* Ok, we will be updating the screen from here onwards so grab the lock */
1020 ActivateContext(This
, This
->render_targets
[0], CTXUSAGE_DRAWPRIM
);
1022 if (TRACE_ON(d3d_draw
) && wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
1023 check_fbo_status(iface
);
1026 if (This
->depth_copy_state
== WINED3D_DCS_COPY
) {
1029 This
->depth_copy_state
= WINED3D_DCS_INITIAL
;
1033 /* Ok, Work out which primitive is requested and how many vertexes that
1035 UINT calculatedNumberOfindices
= primitiveToGl(PrimitiveType
, NumPrimitives
, &glPrimType
);
1036 if (numberOfVertices
== 0 )
1037 numberOfVertices
= calculatedNumberOfindices
;
1039 if (This
->useDrawStridedSlow
) {
1040 /* Immediate mode drawing */
1041 drawStridedSlow(iface
, &This
->strided_streams
, calculatedNumberOfindices
,
1042 glPrimType
, idxData
, idxSize
, minIndex
, StartIdx
, StartVertexIndex
);
1043 } else if(This
->instancedDraw
) {
1044 /* Instancing emulation with mixing immediate mode and arrays */
1045 drawStridedInstanced(iface
, &This
->strided_streams
, calculatedNumberOfindices
, glPrimType
,
1046 idxData
, idxSize
, minIndex
, StartIdx
, StartVertexIndex
);
1048 /* Simple array draw call */
1049 drawStridedFast(iface
, calculatedNumberOfindices
, glPrimType
,
1050 idxData
, idxSize
, minIndex
, StartIdx
, StartVertexIndex
);
1054 /* Finshed updating the screen, restore lock */
1056 TRACE("Done all gl drawing\n");
1059 #ifdef SHOW_FRAME_MAKEUP
1061 static long int primCounter
= 0;
1062 /* NOTE: set primCounter to the value reported by drawprim
1063 before you want to to write frame makeup to /tmp */
1064 if (primCounter
>= 0) {
1065 WINED3DLOCKED_RECT r
;
1067 IWineD3DSurface_LockRect(This
->renderTarget
, &r
, NULL
, WINED3DLOCK_READONLY
);
1068 sprintf(buffer
, "/tmp/backbuffer_%d.tga", primCounter
);
1069 TRACE("Saving screenshot %s\n", buffer
);
1070 IWineD3DSurface_SaveSnapshot(This
->renderTarget
, buffer
);
1071 IWineD3DSurface_UnlockRect(This
->renderTarget
);
1073 #ifdef SHOW_TEXTURE_MAKEUP
1075 IWineD3DSurface
*pSur
;
1077 for (textureNo
= 0; textureNo
< GL_LIMITS(textures
); ++textureNo
) {
1078 if (This
->stateBlock
->textures
[textureNo
] != NULL
) {
1079 sprintf(buffer
, "/tmp/texture_%p_%d_%d.tga", This
->stateBlock
->textures
[textureNo
], primCounter
, textureNo
);
1080 TRACE("Saving texture %s\n", buffer
);
1081 if (IWineD3DBaseTexture_GetType(This
->stateBlock
->textures
[textureNo
]) == WINED3DRTYPE_TEXTURE
) {
1082 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)This
->stateBlock
->textures
[textureNo
], 0, &pSur
);
1083 IWineD3DSurface_SaveSnapshot(pSur
, buffer
);
1084 IWineD3DSurface_Release(pSur
);
1086 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This
->stateBlock
->textures
[textureNo
]));
1093 TRACE("drawprim #%d\n", primCounter
);
1098 /* Control goes back to the device, stateblock values may change again */
1099 This
->isInDraw
= FALSE
;