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 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 void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
159 /* If the last draw was transformed as well, no need to reapply all the matrixes */
160 if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
162 double X, Y, height, width, minZ, maxZ;
163 This->last_was_rhw = TRUE;
164 This->viewport_changed = FALSE;
166 /* Transformed already into viewport coordinates, so we do not need transform
167 matrices. Reset all matrices to identity and leave the default matrix in world
169 glMatrixMode(GL_MODELVIEW);
170 checkGLcall("glMatrixMode(GL_MODELVIEW)");
172 checkGLcall("glLoadIdentity");
174 glMatrixMode(GL_PROJECTION);
175 checkGLcall("glMatrixMode(GL_PROJECTION)");
177 checkGLcall("glLoadIdentity");
179 /* Set up the viewport to be full viewport */
180 X = This->stateBlock->viewport.X;
181 Y = This->stateBlock->viewport.Y;
182 height = This->stateBlock->viewport.Height;
183 width = This->stateBlock->viewport.Width;
184 minZ = This->stateBlock->viewport.MinZ;
185 maxZ = This->stateBlock->viewport.MaxZ;
186 if(!This->untransformed) {
187 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
188 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
190 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
191 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
193 checkGLcall("glOrtho");
195 /* Window Coord 0 is the middle of the first pixel, so translate by half
196 a pixel (See comment above glTranslate below) */
197 glTranslatef(0.375, 0.375, 0);
198 checkGLcall("glTranslatef(0.375, 0.375, 0)");
199 /* D3D texture coordinates are flipped compared to OpenGL ones, so
200 * render everything upside down when rendering offscreen. */
201 if (This->render_offscreen) {
202 glMultMatrixf(invymat);
203 checkGLcall("glMultMatrixf(invymat)");
206 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
207 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
208 if(GL_SUPPORT(EXT_FOG_COORD)) {
209 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
210 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
211 glFogi(GL_FOG_MODE, GL_LINEAR);
212 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
213 /* The dx fog range in this case is fixed to 0 - 255,
214 * but in GL it still depends on the fog start and end (according to the ext)
215 * Use this to turn around the fog as it's needed. That prevents some
216 * calculations during drawing :-)
218 glFogf(GL_FOG_START, (float) 0xff);
219 checkGLcall("glFogfv GL_FOG_END");
220 glFogf(GL_FOG_END, 0.0);
221 checkGLcall("glFogfv GL_FOG_START");
223 /* Disable GL fog, handle this in software in drawStridedSlow */
225 checkGLcall("glDisable(GL_FOG)");
230 /* Setup views - Transformed & lit if RHW, else untransformed.
231 Only unlit if Normals are supplied
232 Returns: Whether to restore lighting afterwards */
233 static void primitiveInitState(
234 IWineD3DDevice *iface,
235 WineDirect3DVertexStridedData* strided,
237 BOOL* lighting_changed,
238 BOOL* lighting_original) {
240 BOOL fixed_vtx_transformed =
241 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
242 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
243 strided->u.s.position_transformed;
246 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
247 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
249 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
251 *lighting_changed = FALSE;
253 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
254 set by the appropriate render state. Note Vertex Shader output is already lit */
255 if (fixed_vtx_lit || useVS) {
256 *lighting_changed = TRUE;
257 *lighting_original = glIsEnabled(GL_LIGHTING);
258 glDisable(GL_LIGHTING);
259 checkGLcall("glDisable(GL_LIGHTING);");
260 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
263 if (!useVS && fixed_vtx_transformed) {
264 d3ddevice_set_ortho(This);
268 /* Untransformed, so relies on the view and projection matrices */
269 This->untransformed = TRUE;
271 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
272 /* Only reapply when have to */
273 This->modelview_valid = TRUE;
274 glMatrixMode(GL_MODELVIEW);
275 checkGLcall("glMatrixMode");
277 /* In the general case, the view matrix is the identity matrix */
278 if (This->view_ident) {
279 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
280 checkGLcall("glLoadMatrixf");
282 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
283 checkGLcall("glLoadMatrixf");
284 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
285 checkGLcall("glMultMatrixf");
289 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
290 /* Only reapply when have to */
291 This->proj_valid = TRUE;
292 glMatrixMode(GL_PROJECTION);
293 checkGLcall("glMatrixMode");
295 /* The rule is that the window coordinate 0 does not correspond to the
296 beginning of the first pixel, but the center of the first pixel.
297 As a consequence if you want to correctly draw one line exactly from
298 the left to the right end of the viewport (with all matrices set to
299 be identity), the x coords of both ends of the line would be not
300 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
304 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
305 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
307 /* D3D texture coordinates are flipped compared to OpenGL ones, so
308 * render everything upside down when rendering offscreen. */
309 if (This->render_offscreen) {
310 glMultMatrixf(invymat);
311 checkGLcall("glMultMatrixf(invymat)");
313 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
314 checkGLcall("glLoadMatrixf");
317 /* Vertex Shader output is already transformed, so set up identity matrices */
319 This->posFixup[1] = This->render_offscreen ? -1.0 : 1.0;
320 This->posFixup[2] = 0.9 / This->stateBlock->viewport.Width;
321 This->posFixup[3] = -0.9 / This->stateBlock->viewport.Height;
323 This->last_was_rhw = FALSE;
326 if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
327 /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
328 * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
329 glFogi(GL_FOG_MODE, GL_LINEAR);
330 glFogf(GL_FOG_START, 1.0f);
331 glFogf(GL_FOG_END, 0.0f);
333 } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE]
334 && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
336 if(GL_SUPPORT(EXT_FOG_COORD)) {
337 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
338 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
339 /* Reapply the fog range */
340 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
341 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
342 /* Restore the fog mode */
343 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
345 /* Enable GL_FOG again because we disabled it above */
347 checkGLcall("glEnable(GL_FOG)");
353 static BOOL fixed_get_input(
354 BYTE usage, BYTE usage_idx,
355 unsigned int* regnum) {
359 /* Those positions must have the order in the
360 * named part of the strided data */
362 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
364 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
366 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
368 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
370 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
372 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
374 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
376 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
377 *regnum = 7 + usage_idx;
378 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
379 *regnum = 7 + WINED3DDP_MAXTEXCOORD;
380 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
381 *regnum = 8 + WINED3DDP_MAXTEXCOORD;
382 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
383 *regnum = 9 + WINED3DDP_MAXTEXCOORD;
384 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
385 *regnum = 10 + WINED3DDP_MAXTEXCOORD;
386 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
387 *regnum = 11 + WINED3DDP_MAXTEXCOORD;
388 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
389 *regnum = 12 + WINED3DDP_MAXTEXCOORD;
390 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
391 *regnum = 13 + WINED3DDP_MAXTEXCOORD;
392 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
393 *regnum = 14 + WINED3DDP_MAXTEXCOORD;
396 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
397 debug_d3ddeclusage(usage), usage_idx);
403 void primitiveDeclarationConvertToStridedData(
404 IWineD3DDevice *iface,
405 BOOL useVertexShaderFunction,
406 WineDirect3DVertexStridedData *strided,
407 LONG BaseVertexIndex,
410 /* We need to deal with frequency data!*/
413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
414 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
416 WINED3DVERTEXELEMENT *element;
420 /* Locate the vertex declaration */
421 if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
422 TRACE("Using vertex declaration from shader\n");
423 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
425 TRACE("Using vertex declaration\n");
426 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
429 /* Translate the declaration into strided data */
430 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
435 element = vertexDeclaration->pDeclarationWine + i;
436 TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
437 element, i + 1, vertexDeclaration->declarationWNumElements - 1);
439 if (This->stateBlock->streamSource[element->Stream] == NULL)
442 if (This->stateBlock->streamIsUP) {
443 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
445 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
446 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
448 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
449 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
450 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
452 if( streamVBO != 0) *fixup = TRUE;
453 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
456 stride = This->stateBlock->streamStride[element->Stream];
457 data += (BaseVertexIndex * stride);
458 data += element->Offset;
461 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
463 if (useVertexShaderFunction)
464 stride_used = vshader_get_input(This->stateBlock->vertexShader,
465 element->Usage, element->UsageIndex, &idx);
467 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
470 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
471 "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
472 useVertexShaderFunction? "shader": "fixed function", idx,
473 debug_d3ddeclusage(element->Usage), element->UsageIndex,
474 element->Stream, element->Offset, stride, streamVBO);
476 strided->u.input[idx].lpData = data;
477 strided->u.input[idx].dwType = element->Type;
478 strided->u.input[idx].dwStride = stride;
479 strided->u.input[idx].VBO = streamVBO;
480 if (!useVertexShaderFunction) {
481 if (element->Usage == D3DDECLUSAGE_POSITION)
482 strided->u.s.position_transformed = FALSE;
483 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
484 strided->u.s.position_transformed = TRUE;
490 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
494 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
495 int numCoords[8]; /* Holding place for WINED3DFVF_TEXTUREFORMATx */
497 /* Either 3 or 4 floats depending on the FVF */
498 /* FIXME: Can blending data be in a different stream to the position data?
499 and if so using the fixed pipeline how do we handle it */
500 if (thisFVF & WINED3DFVF_POSITION_MASK) {
501 strided->u.s.position.lpData = data;
502 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
503 strided->u.s.position.dwStride = stride;
504 strided->u.s.position.VBO = streamVBO;
505 data += 3 * sizeof(float);
506 if (thisFVF & WINED3DFVF_XYZRHW) {
507 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
508 strided->u.s.position_transformed = TRUE;
509 data += sizeof(float);
511 strided->u.s.position_transformed = FALSE;
514 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
515 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
516 numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
517 if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
519 if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
520 TRACE("Setting blend Weights to %p\n", data);
521 strided->u.s.blendWeights.lpData = data;
522 strided->u.s.blendWeights.dwType = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
523 strided->u.s.blendWeights.dwStride = stride;
524 strided->u.s.blendWeights.VBO = streamVBO;
525 data += numBlends * sizeof(FLOAT);
527 if (thisFVF & WINED3DFVF_LASTBETA_UBYTE4) {
528 strided->u.s.blendMatrixIndices.lpData = data;
529 strided->u.s.blendMatrixIndices.dwType = WINED3DDECLTYPE_UBYTE4;
530 strided->u.s.blendMatrixIndices.dwStride= stride;
531 strided->u.s.blendMatrixIndices.VBO = streamVBO;
532 data += sizeof(DWORD);
536 /* Normal is always 3 floats */
537 if (thisFVF & WINED3DFVF_NORMAL) {
538 strided->u.s.normal.lpData = data;
539 strided->u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
540 strided->u.s.normal.dwStride = stride;
541 strided->u.s.normal.VBO = streamVBO;
542 data += 3 * sizeof(FLOAT);
545 /* Pointsize is a single float */
546 if (thisFVF & WINED3DFVF_PSIZE) {
547 strided->u.s.pSize.lpData = data;
548 strided->u.s.pSize.dwType = WINED3DDECLTYPE_FLOAT1;
549 strided->u.s.pSize.dwStride = stride;
550 strided->u.s.pSize.VBO = streamVBO;
551 data += sizeof(FLOAT);
554 /* Diffuse is 4 unsigned bytes */
555 if (thisFVF & WINED3DFVF_DIFFUSE) {
556 strided->u.s.diffuse.lpData = data;
557 strided->u.s.diffuse.dwType = WINED3DDECLTYPE_SHORT4;
558 strided->u.s.diffuse.dwStride = stride;
559 strided->u.s.diffuse.VBO = streamVBO;
560 data += sizeof(DWORD);
563 /* Specular is 4 unsigned bytes */
564 if (thisFVF & WINED3DFVF_SPECULAR) {
565 strided->u.s.specular.lpData = data;
566 strided->u.s.specular.dwType = WINED3DDECLTYPE_SHORT4;
567 strided->u.s.specular.dwStride = stride;
568 strided->u.s.specular.VBO = streamVBO;
569 data += sizeof(DWORD);
573 numTextures = (thisFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
574 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
576 /* numTextures indicates the number of texture coordinates supplied */
577 /* However, the first set may not be for stage 0 texture - it all */
578 /* depends on WINED3DTSS_TEXCOORDINDEX. */
579 /* The number of bytes for each coordinate set is based off */
580 /* WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
582 /* So, for each supplied texture extract the coords */
583 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
585 strided->u.s.texCoords[textureNo].lpData = data;
586 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT1;
587 strided->u.s.texCoords[textureNo].dwStride = stride;
588 strided->u.s.texCoords[textureNo].VBO = streamVBO;
589 numCoords[textureNo] = coordIdxInfo & 0x03;
592 data += sizeof(float);
593 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT1) {
594 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
595 data += sizeof(float);
596 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT2) {
597 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
598 data += sizeof(float);
599 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT3) {
600 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
601 data += sizeof(float);
605 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
609 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
611 short LoopThroughTo = 0;
615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
617 /* OK, Now to setup the data locations
618 For the non-created vertex shaders, the VertexShader var holds the real
619 FVF and only stream 0 matters
620 For the created vertex shaders, there is an FVF per stream */
621 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
622 LoopThroughTo = MAX_STREAMS;
627 /* Work through stream by stream */
628 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
629 DWORD stride = This->stateBlock->streamStride[nStream];
633 /* Skip empty streams */
634 if (This->stateBlock->streamSource[nStream] == NULL) continue;
636 /* Retrieve appropriate FVF */
637 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
638 thisFVF = This->stateBlock->fvf;
639 /* Handle memory passed directly as well as vertex buffers */
640 if (This->stateBlock->streamIsUP) {
642 data = (BYTE *)This->stateBlock->streamSource[nStream];
644 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
645 /* GetMemory binds the VBO */
646 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
648 if(streamVBO != 0 ) *fixup = TRUE;
652 #if 0 /* TODO: Vertex shader support */
653 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
654 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
657 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
658 if (thisFVF == 0) continue;
660 /* Now convert the stream into pointers */
662 /* Shuffle to the beginning of the vertexes to render and index from there */
663 data = data + (BaseVertexIndex * stride);
665 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
669 #if 0 /* TODO: Software Shaders */
670 /* Draw a single vertex using this information */
671 static void draw_vertex(IWineD3DDevice *iface, /* interface */
672 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
673 BOOL isNormal, float nx, float ny, float nz, /* normal */
674 BOOL isDiffuse, float *dRGBA, /* 1st colors */
675 BOOL isSpecular, float *sRGB, /* 2ndry colors */
676 BOOL isPtSize, float ptSize, /* pointSize */
677 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
679 unsigned int textureNo;
681 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
683 /* Diffuse -------------------------------- */
686 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
689 /* Specular Colour ------------------------------------------*/
691 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
692 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
693 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
695 VTRACE(("Specular color extensions not supplied\n"));
699 /* Normal -------------------------------- */
701 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
702 glNormal3f(nx, ny, nz);
705 /* Point Size ----------------------------------------------*/
708 /* no such functionality in the fixed function GL pipeline */
709 FIXME("Cannot change ptSize here in openGl\n");
712 /* Texture coords --------------------------- */
713 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
715 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
716 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
720 /* Query tex coords */
721 if (This->stateBlock->textures[textureNo] != NULL) {
723 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
724 if (coordIdx >= MAX_TEXTURES) {
725 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
727 } else if (numcoords[coordIdx] == 0) {
728 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
732 /* Initialize vars */
738 switch (numcoords[coordIdx]) {
739 case 4: q = texcoords[coordIdx].w; /* drop through */
740 case 3: r = texcoords[coordIdx].z; /* drop through */
741 case 2: t = texcoords[coordIdx].y; /* drop through */
742 case 1: s = texcoords[coordIdx].x;
745 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
746 case WINED3DTTFF_COUNT1:
747 VTRACE(("tex:%d, s=%f\n", textureNo, s));
748 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
749 GLMULTITEXCOORD1F(textureNo, s);
754 case WINED3DTTFF_COUNT2:
755 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
756 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
757 GLMULTITEXCOORD2F(textureNo, s, t);
762 case WINED3DTTFF_COUNT3:
763 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
764 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
765 GLMULTITEXCOORD3F(textureNo, s, t, r);
767 glTexCoord3f(s, t, r);
770 case WINED3DTTFF_COUNT4:
771 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
772 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
773 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
775 glTexCoord4f(s, t, r, q);
779 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
783 } /* End of textures */
785 /* Position -------------------------------- */
787 if (1.0f == rhw || rhw < 0.00001f) {
788 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
791 /* Cannot optimize by dividing through by rhw as rhw is required
792 later for perspective in the GL pipeline for vertex shaders */
793 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
794 glVertex4f(x,y,z,rhw);
798 #endif /* TODO: Software shaders */
800 /* This should match any arrays loaded in loadNumberedArrays. */
801 /* TODO: Only load / unload arrays if we have to. */
802 static void unloadNumberedArrays(IWineD3DDevice *iface) {
803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
805 /* disable any attribs (this is the same for both GLSL and ARB modes) */
809 /* Leave all the attribs disabled */
810 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
811 /* MESA does not support it right not */
812 if (glGetError() != GL_NO_ERROR)
814 for (i = 0; i < maxAttribs; ++i) {
815 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
816 checkGLcall("glDisableVertexAttribArrayARB(reg);");
820 /* TODO: Only load / unload arrays if we have to. */
821 static void loadNumberedArrays(
822 IWineD3DDevice *iface,
823 IWineD3DVertexShader *shader,
824 WineDirect3DVertexStridedData *strided) {
826 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
827 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
830 for (i = 0; i < MAX_ATTRIBS; i++) {
832 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
835 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
837 if(curVBO != strided->u.input[i].VBO) {
838 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
839 checkGLcall("glBindBufferARB");
840 curVBO = strided->u.input[i].VBO;
842 GL_EXTCALL(glVertexAttribPointerARB(i,
843 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
844 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
845 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
846 strided->u.input[i].dwStride,
847 strided->u.input[i].lpData));
848 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
852 /* This should match any arrays loaded in loadVertexData. */
853 /* TODO: Only load / unload arrays if we have to. */
854 static void unloadVertexData(IWineD3DDevice *iface) {
855 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
858 glDisableClientState(GL_VERTEX_ARRAY);
859 glDisableClientState(GL_NORMAL_ARRAY);
860 glDisableClientState(GL_COLOR_ARRAY);
861 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
862 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
864 for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
865 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
866 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
870 /* TODO: Only load / unload arrays if we have to. */
871 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
872 unsigned int textureNo = 0;
873 unsigned int texture_idx = 0;
874 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
875 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
877 TRACE("Using fast vertex array code\n");
878 /* Blend Data ---------------------------------------------- */
879 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
880 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
883 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
886 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
887 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
890 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
891 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
892 /* FIXME("TODO\n");*/
893 /* Note dwType == float3 or float4 == 2 or 3 */
896 /* with this on, the normals appear to be being modified,
897 but the vertices aren't being translated as they should be
898 Maybe the world matrix aren't being setup properly? */
899 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
903 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
904 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
905 sd->u.s.blendWeights.dwStride,
906 sd->u.s.blendWeights.lpData));
908 if(curVBO != sd->u.s.blendWeights.VBO) {
909 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
910 checkGLcall("glBindBufferARB");
911 curVBO = sd->u.s.blendWeights.VBO;
914 GL_EXTCALL(glWeightPointerARB)(
915 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
916 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
917 sd->u.s.blendWeights.dwStride,
918 sd->u.s.blendWeights.lpData);
920 checkGLcall("glWeightPointerARB");
922 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
923 static BOOL showfixme = TRUE;
925 FIXME("blendMatrixIndices support\n");
930 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
931 /* FIXME("TODO\n");*/
934 GL_EXTCALL(glVertexWeightPointerEXT)(
935 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
936 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
937 sd->u.s.blendWeights.dwStride,
938 sd->u.s.blendWeights.lpData);
939 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
940 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
941 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
945 /* TODO: support blends in fixupVertices */
946 FIXME("unsupported blending in openGl\n");
949 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
950 #if 0 /* TODO: Vertex blending */
951 glDisable(GL_VERTEX_BLEND_ARB);
953 TRACE("ARB_VERTEX_BLEND\n");
954 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
955 TRACE(" EXT_VERTEX_WEIGHTING\n");
956 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
957 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
962 #if 0 /* FOG ----------------------------------------------*/
963 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
965 if (GL_SUPPORT(EXT_FOG_COORD) {
966 glEnableClientState(GL_FOG_COORDINATE_EXT);
967 (GL_EXTCALL)(FogCoordPointerEXT)(
968 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
969 sd->u.s.fog.dwStride,
972 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
973 /* FIXME: fixme once */
974 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
977 if (GL_SUPPRT(EXT_FOR_COORD) {
978 /* make sure fog is disabled */
979 glDisableClientState(GL_FOG_COORDINATE_EXT);
984 #if 0 /* tangents ----------------------------------------------*/
985 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
986 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
988 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
989 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
990 glEnable(GL_TANGENT_ARRAY_EXT);
991 (GL_EXTCALL)(TangentPointerEXT)(
992 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
993 sd->u.s.tangent.dwStride,
994 sd->u.s.tangent.lpData);
996 glDisable(GL_TANGENT_ARRAY_EXT);
998 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
999 glEnable(GL_BINORMAL_ARRAY_EXT);
1000 (GL_EXTCALL)(BinormalPointerEXT)(
1001 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
1002 sd->u.s.binormal.dwStride,
1003 sd->u.s.binormal.lpData);
1005 glDisable(GL_BINORMAL_ARRAY_EXT);
1009 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1010 /* FIXME: fixme once */
1011 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1014 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1015 /* make sure fog is disabled */
1016 glDisable(GL_TANGENT_ARRAY_EXT);
1017 glDisable(GL_BINORMAL_ARRAY_EXT);
1022 /* Point Size ----------------------------------------------*/
1023 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
1025 /* no such functionality in the fixed function GL pipeline */
1026 TRACE("Cannot change ptSize here in openGl\n");
1027 /* TODO: Implement this function in using shaders if they are available */
1031 /* Vertex Pointers -----------------------------------------*/
1032 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
1033 /* Note dwType == float3 or float4 == 2 or 3 */
1034 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
1035 sd->u.s.position.dwStride,
1036 sd->u.s.position.dwType + 1,
1037 sd->u.s.position.lpData));
1039 if(curVBO != sd->u.s.position.VBO) {
1040 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1041 checkGLcall("glBindBufferARB");
1042 curVBO = sd->u.s.position.VBO;
1045 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1046 handling for rhw mode should not impact screen position whereas in GL it does.
1047 This may result in very slightly distored textures in rhw mode, but
1048 a very minimal different. There's always the other option of
1049 fixing the view matrix to prevent w from having any effect
1051 This only applies to user pointer sources, in VBOs the vertices are fixed up
1053 if(sd->u.s.position.VBO == 0) {
1054 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1055 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1056 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1059 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1060 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1061 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1063 checkGLcall("glVertexPointer(...)");
1064 glEnableClientState(GL_VERTEX_ARRAY);
1065 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1068 glDisableClientState(GL_VERTEX_ARRAY);
1069 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1072 /* Normals -------------------------------------------------*/
1073 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1074 /* Note dwType == float3 or float4 == 2 or 3 */
1075 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
1076 sd->u.s.normal.dwStride,
1077 sd->u.s.normal.lpData));
1078 if(curVBO != sd->u.s.normal.VBO) {
1079 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1080 checkGLcall("glBindBufferARB");
1081 curVBO = sd->u.s.normal.VBO;
1084 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1085 sd->u.s.normal.dwStride,
1086 sd->u.s.normal.lpData);
1087 checkGLcall("glNormalPointer(...)");
1088 glEnableClientState(GL_NORMAL_ARRAY);
1089 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1092 glDisableClientState(GL_NORMAL_ARRAY);
1093 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1094 glNormal3f(0, 0, 1);
1095 checkGLcall("glNormal3f(0, 0, 1)");
1098 /* Diffuse Colour --------------------------------------------*/
1099 /* WARNING: Data here MUST be in RGBA format, so cannot */
1100 /* go directly into fast mode from app pgm, because */
1101 /* directx requires data in BGRA format. */
1102 /* currently fixupVertices swizels the format, but this isn't */
1103 /* very practical when using VBOS */
1104 /* NOTE: Unless we write a vertex shader to swizel the colour */
1105 /* , or the user doesn't care and wants the speed advantage */
1107 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1108 /* Note dwType == float3 or float4 == 2 or 3 */
1109 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1110 sd->u.s.diffuse.dwStride,
1111 sd->u.s.diffuse.lpData));
1113 if(curVBO != sd->u.s.diffuse.VBO) {
1114 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1115 checkGLcall("glBindBufferARB");
1116 curVBO = sd->u.s.diffuse.VBO;
1118 glColorPointer(4, GL_UNSIGNED_BYTE,
1119 sd->u.s.diffuse.dwStride,
1120 sd->u.s.diffuse.lpData);
1121 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1122 glEnableClientState(GL_COLOR_ARRAY);
1123 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1126 glDisableClientState(GL_COLOR_ARRAY);
1127 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1128 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1129 checkGLcall("glColor4f(1, 1, 1, 1)");
1132 /* Specular Colour ------------------------------------------*/
1133 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1134 TRACE("setting specular colour\n");
1135 /* Note dwType == float3 or float4 == 2 or 3 */
1136 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1137 sd->u.s.specular.dwStride,
1138 sd->u.s.specular.lpData));
1139 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1140 if(curVBO != sd->u.s.specular.VBO) {
1141 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1142 checkGLcall("glBindBufferARB");
1143 curVBO = sd->u.s.specular.VBO;
1145 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1146 sd->u.s.specular.dwStride,
1147 sd->u.s.specular.lpData);
1148 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1149 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1150 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1153 /* Missing specular color is not critical, no warnings */
1154 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1158 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1160 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1161 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1162 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1163 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1166 /* Missing specular color is not critical, no warnings */
1167 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1171 /* Texture coords -------------------------------------------*/
1173 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1174 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1175 /* Abort if we don't support the extension. */
1176 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1177 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1181 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1182 /* Select the correct texture stage */
1183 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1186 if (This->stateBlock->textures[textureNo] != NULL) {
1187 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1189 if (coordIdx >= MAX_TEXTURES) {
1190 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1191 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1192 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1194 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1195 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1196 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1197 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1200 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1201 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1202 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1203 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1204 checkGLcall("glBindBufferARB");
1205 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1207 /* The coords to supply depend completely on the fvf / vertex shader */
1209 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1210 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1211 sd->u.s.texCoords[coordIdx].dwStride,
1212 sd->u.s.texCoords[coordIdx].lpData);
1213 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1215 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1216 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1217 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1219 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1221 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1222 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1223 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1224 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1225 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1230 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1231 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1232 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1234 if (idxData != NULL /* This crashes sometimes!*/) {
1235 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1236 idxData = idxData == (void *)-1 ? NULL : idxData;
1239 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1240 glEnableClientState(GL_INDEX_ARRAY);
1242 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1243 (const char *)idxData+(idxSize * startIdx));
1244 #else /* using drawRangeElements may be faster */
1246 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1247 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1248 (const char *)idxData+(idxSize * startIdx));
1250 checkGLcall("glDrawRangeElements");
1254 /* Note first is now zero as we shuffled along earlier */
1255 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1256 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1257 checkGLcall("glDrawArrays");
1265 * Actually draw using the supplied information.
1266 * Slower GL version which extracts info about each vertex in turn
1269 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1270 UINT NumVertexes, GLenum glPrimType,
1271 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1273 unsigned int textureNo = 0;
1274 unsigned int texture_idx = 0;
1275 const short *pIdxBufS = NULL;
1276 const long *pIdxBufL = NULL;
1277 LONG SkipnStrides = 0;
1279 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1280 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1281 float rhw = 0.0f; /* rhw */
1282 float ptSize = 0.0f; /* Point size */
1283 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1284 DWORD specularColor = 0; /* Specular Color */
1285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1287 TRACE("Using slow vertex array code\n");
1289 /* Variable Initialization */
1290 if (idxData != NULL) {
1291 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1292 else pIdxBufL = (const long *) idxData;
1295 /* Start drawing in GL */
1296 VTRACE(("glBegin(%x)\n", glPrimType));
1297 glBegin(glPrimType);
1299 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1300 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1303 /* For each primitive */
1304 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1306 /* Initialize diffuse color */
1307 diffuseColor = 0xFFFFFFFF;
1309 /* For indexed data, we need to go a few more strides in */
1310 if (idxData != NULL) {
1312 /* Indexed so work out the number of strides to skip */
1314 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1315 SkipnStrides = pIdxBufS[startIdx + vx_index];
1317 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1318 SkipnStrides = pIdxBufL[startIdx + vx_index];
1322 /* Position Information ------------------ */
1323 if (sd->u.s.position.lpData != NULL) {
1325 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1330 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1332 /* RHW follows, only if transformed, ie 4 floats were provided */
1333 if (sd->u.s.position_transformed) {
1334 rhw = ptrToCoords[3];
1335 VTRACE(("rhw=%f\n", rhw));
1339 /* Blending data -------------------------- */
1340 if (sd->u.s.blendWeights.lpData != NULL) {
1341 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1342 FIXME("Blending not supported yet\n");
1344 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1345 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1349 /* Vertex Normal Data (untransformed only)- */
1350 if (sd->u.s.normal.lpData != NULL) {
1352 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1353 nx = ptrToCoords[0];
1354 ny = ptrToCoords[1];
1355 nz = ptrToCoords[2];
1356 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1359 /* Point Size ----------------------------- */
1360 if (sd->u.s.pSize.lpData != NULL) {
1362 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1363 ptSize = ptrToCoords[0];
1364 VTRACE(("ptSize=%f\n", ptSize));
1365 FIXME("No support for ptSize yet\n");
1368 /* Diffuse -------------------------------- */
1369 if (sd->u.s.diffuse.lpData != NULL) {
1371 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1372 diffuseColor = ptrToCoords[0];
1373 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1376 /* Specular -------------------------------- */
1377 if (sd->u.s.specular.lpData != NULL) {
1379 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1380 specularColor = ptrToCoords[0];
1381 VTRACE(("specularColor=%lx\n", specularColor));
1384 /* Texture coords --------------------------- */
1385 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1387 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1388 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1392 /* Query tex coords */
1393 if (This->stateBlock->textures[textureNo] != NULL) {
1395 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1396 float *ptrToCoords = NULL;
1397 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1400 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1403 } else if (coordIdx < 0) {
1404 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1409 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1410 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1411 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1416 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
1418 /* The coords to supply depend completely on the fvf / vertex shader */
1419 switch (coordsToUse) {
1420 case 4: q = ptrToCoords[3]; /* drop through */
1421 case 3: r = ptrToCoords[2]; /* drop through */
1422 case 2: t = ptrToCoords[1]; /* drop through */
1423 case 1: s = ptrToCoords[0];
1426 /* Projected is more 'fun' - Move the last coord to the 'q'
1427 parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
1428 if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
1429 (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
1431 if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
1432 switch (coordsToUse) {
1433 case 0: /* Drop Through */
1435 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
1447 case 4: /* Nop here */
1450 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
1451 This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
1456 switch (coordsToUse) { /* Supply the provided texture coords */
1457 case WINED3DTTFF_COUNT1:
1458 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1459 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1460 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1465 case WINED3DTTFF_COUNT2:
1466 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1467 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1468 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1473 case WINED3DTTFF_COUNT3:
1474 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1475 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1476 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1478 glTexCoord3f(s, t, r);
1481 case WINED3DTTFF_COUNT4:
1482 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1483 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1484 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1486 glTexCoord4f(s, t, r, q);
1490 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1494 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1495 } /* End of textures */
1497 /* Diffuse -------------------------------- */
1498 if (sd->u.s.diffuse.lpData != NULL) {
1499 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1500 D3DCOLOR_B_G(diffuseColor),
1501 D3DCOLOR_B_B(diffuseColor),
1502 D3DCOLOR_B_A(diffuseColor));
1503 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1504 D3DCOLOR_B_R(diffuseColor),
1505 D3DCOLOR_B_G(diffuseColor),
1506 D3DCOLOR_B_B(diffuseColor),
1507 D3DCOLOR_B_A(diffuseColor)));
1509 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1512 /* Specular ------------------------------- */
1513 if (sd->u.s.specular.lpData != NULL) {
1514 /* special case where the fog density is stored in the diffuse alpha channel */
1515 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1516 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
1517 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1518 if(GL_SUPPORT(EXT_FOG_COORD)) {
1519 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1521 static BOOL warned = FALSE;
1523 /* TODO: Use the fog table code from old ddraw */
1524 FIXME("Implement fog for transformed vertices in software\n");
1530 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1531 D3DCOLOR_B_R(specularColor),
1532 D3DCOLOR_B_G(specularColor),
1533 D3DCOLOR_B_B(specularColor)));
1534 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1535 GL_EXTCALL(glSecondaryColor3ubEXT)(
1536 D3DCOLOR_B_R(specularColor),
1537 D3DCOLOR_B_G(specularColor),
1538 D3DCOLOR_B_B(specularColor));
1540 /* Do not worry if specular colour missing and disable request */
1541 VTRACE(("Specular color extensions not supplied\n"));
1544 if (vx_index == 0) {
1545 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1546 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1548 /* Do not worry if specular colour missing and disable request */
1549 VTRACE(("Specular color extensions not supplied\n"));
1554 /* Normal -------------------------------- */
1555 if (sd->u.s.normal.lpData != NULL) {
1556 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1557 glNormal3f(nx, ny, nz);
1559 if (vx_index == 0) glNormal3f(0, 0, 1);
1562 /* Position -------------------------------- */
1563 if (sd->u.s.position.lpData != NULL) {
1564 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1565 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1566 glVertex3f(x, y, z);
1568 GLfloat w = 1.0 / rhw;
1569 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1570 glVertex4f(x*w, y*w, z*w, w);
1574 /* For non indexed mode, step onto next parts */
1575 if (idxData == NULL) {
1581 checkGLcall("glEnd and previous calls");
1584 #if 0 /* TODO: Software/Hardware vertex blending support */
1586 * Draw with emulated vertex shaders
1587 * Note: strided data is uninitialized, as we need to pass the vertex
1588 * shader directly as ordering irs yet
1590 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1591 int PrimitiveType, ULONG NumPrimitives,
1592 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1594 unsigned int textureNo = 0;
1595 GLenum glPrimType = GL_POINTS;
1596 int NumVertexes = NumPrimitives;
1597 const short *pIdxBufS = NULL;
1598 const long *pIdxBufL = NULL;
1599 LONG SkipnStrides = 0;
1601 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1602 float rhw = 0.0f; /* rhw */
1603 float ptSize = 0.0f; /* Point size */
1604 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1605 int numcoords[8]; /* Number of coords */
1606 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1608 IDirect3DVertexShaderImpl* vertexShader = NULL;
1610 TRACE("Using slow software vertex shader code\n");
1612 /* Variable Initialization */
1613 if (idxData != NULL) {
1614 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1615 else pIdxBufL = (const long *) idxData;
1618 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1619 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1621 /* Retrieve the VS information */
1622 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1624 /* Start drawing in GL */
1625 VTRACE(("glBegin(%x)\n", glPrimType));
1626 glBegin(glPrimType);
1628 /* For each primitive */
1629 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1631 /* For indexed data, we need to go a few more strides in */
1632 if (idxData != NULL) {
1634 /* Indexed so work out the number of strides to skip */
1636 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1637 SkipnStrides = pIdxBufS[startIdx+vx_index];
1639 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1640 SkipnStrides = pIdxBufL[startIdx+vx_index];
1644 /* Fill the vertex shader input */
1645 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1647 /* Initialize the output fields to the same defaults as it would normally have */
1648 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1649 vertexShader->output.oD[0].x = 1.0;
1650 vertexShader->output.oD[0].y = 1.0;
1651 vertexShader->output.oD[0].z = 1.0;
1652 vertexShader->output.oD[0].w = 1.0;
1654 /* Now execute the vertex shader */
1655 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1658 TRACE_VECTOR(vertexShader->output.oPos);
1659 TRACE_VECTOR(vertexShader->output.oD[0]);
1660 TRACE_VECTOR(vertexShader->output.oD[1]);
1661 TRACE_VECTOR(vertexShader->output.oT[0]);
1662 TRACE_VECTOR(vertexShader->output.oT[1]);
1663 TRACE_VECTOR(vertexShader->input.V[0]);
1664 TRACE_VECTOR(vertexShader->data->C[0]);
1665 TRACE_VECTOR(vertexShader->data->C[1]);
1666 TRACE_VECTOR(vertexShader->data->C[2]);
1667 TRACE_VECTOR(vertexShader->data->C[3]);
1668 TRACE_VECTOR(vertexShader->data->C[4]);
1669 TRACE_VECTOR(vertexShader->data->C[5]);
1670 TRACE_VECTOR(vertexShader->data->C[6]);
1671 TRACE_VECTOR(vertexShader->data->C[7]);
1674 /* Extract out the output */
1675 /* FIXME: Fog coords? */
1676 x = vertexShader->output.oPos.x;
1677 y = vertexShader->output.oPos.y;
1678 z = vertexShader->output.oPos.z;
1679 rhw = vertexShader->output.oPos.w;
1680 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1682 /** Update textures coords using vertexShader->output.oT[0->7] */
1683 memset(texcoords, 0x00, sizeof(texcoords));
1684 memset(numcoords, 0x00, sizeof(numcoords));
1685 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1686 if (This->stateBlock->textures[textureNo] != NULL) {
1687 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1688 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1689 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1690 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1691 if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1692 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1694 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1695 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1696 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1697 default: numcoords[textureNo] = 4;
1701 numcoords[textureNo] = 0;
1705 /* Draw using this information */
1708 TRUE, 0.0f, 0.0f, 1.0f,
1709 TRUE, (float*) &vertexShader->output.oD[0],
1710 TRUE, (float*) &vertexShader->output.oD[1],
1711 FALSE, ptSize, /* FIXME: Change back when supported */
1712 texcoords, numcoords);
1714 /* For non indexed mode, step onto next parts */
1715 if (idxData == NULL) {
1719 } /* for each vertex */
1722 checkGLcall("glEnd and previous calls");
1727 inline static void drawPrimitiveDrawStrided(
1728 IWineD3DDevice *iface,
1729 BOOL useVertexShaderFunction,
1730 BOOL usePixelShaderFunction,
1731 WineDirect3DVertexStridedData *dataLocations,
1732 UINT numberOfvertices,
1733 UINT numberOfIndicies,
1735 const void *idxData,
1741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1742 BOOL useDrawStridedSlow;
1744 int startStride = idxData == NULL ? 0 :
1745 idxData == (void *) -1 ? 0 :
1746 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1747 int endStride = startStride;
1748 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1749 startStride, endStride, numberOfIndicies, numberOfvertices);
1751 /* Generate some fixme's if unsupported functionality is being used */
1752 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1753 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1754 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1755 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1757 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1758 FIXME("Tweening is only valid with vertex shaders\n");
1760 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1761 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1763 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1764 FIXME("Extended attributes are only valid with vertex shaders\n");
1766 #undef BUFFER_OR_DATA
1768 /* Fixed pipeline, no fixups required - load arrays */
1769 if (!useVertexShaderFunction &&
1770 ((dataLocations->u.s.pSize.lpData == NULL &&
1771 dataLocations->u.s.diffuse.lpData == NULL &&
1772 dataLocations->u.s.specular.lpData == NULL) ||
1775 /* Load the vertex data using named arrays */
1776 TRACE("(%p) Loading vertex data\n", This);
1777 loadVertexData(iface, dataLocations);
1778 useDrawStridedSlow = FALSE;
1780 /* Shader pipeline - load attribute arrays */
1781 } else if(useVertexShaderFunction) {
1783 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1784 useDrawStridedSlow = FALSE;
1786 /* We compile the shader here because we need the vertex declaration
1787 * in order to determine if we need to do any swizzling for D3DCOLOR
1788 * registers. If the shader is already compiled this call will do nothing. */
1789 IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1790 /* Draw vertex by vertex */
1792 TRACE("Not loading vertex data\n");
1793 useDrawStridedSlow = TRUE;
1796 if(usePixelShaderFunction) {
1797 /* We compile the shader here because it depends on the texture stage state
1798 * setup of the bound textures. If the shader is already compiled and the texture stage
1799 * state setup matches the program this function will do nothing
1801 IWineD3DPixelShader_CompileShader(This->stateBlock->pixelShader);
1804 /* Make any shaders active */
1805 This->shader_backend->shader_select(iface, usePixelShaderFunction, useVertexShaderFunction);
1807 /* Load any global constants/uniforms that may have been set by the application */
1808 This->shader_backend->shader_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1810 /* Draw vertex-by-vertex */
1811 if (useDrawStridedSlow)
1812 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1814 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1816 /* Cleanup any shaders */
1817 This->shader_backend->shader_cleanup(usePixelShaderFunction, useVertexShaderFunction);
1819 /* Unload vertex data */
1820 if (useVertexShaderFunction) {
1821 unloadNumberedArrays(iface);
1823 unloadVertexData(iface);
1827 inline void drawPrimitiveTraceDataLocations(
1828 WineDirect3DVertexStridedData *dataLocations) {
1830 /* Dump out what parts we have supplied */
1831 TRACE("Strided Data:\n");
1832 TRACE_STRIDED((dataLocations), position);
1833 TRACE_STRIDED((dataLocations), blendWeights);
1834 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1835 TRACE_STRIDED((dataLocations), normal);
1836 TRACE_STRIDED((dataLocations), pSize);
1837 TRACE_STRIDED((dataLocations), diffuse);
1838 TRACE_STRIDED((dataLocations), specular);
1839 TRACE_STRIDED((dataLocations), texCoords[0]);
1840 TRACE_STRIDED((dataLocations), texCoords[1]);
1841 TRACE_STRIDED((dataLocations), texCoords[2]);
1842 TRACE_STRIDED((dataLocations), texCoords[3]);
1843 TRACE_STRIDED((dataLocations), texCoords[4]);
1844 TRACE_STRIDED((dataLocations), texCoords[5]);
1845 TRACE_STRIDED((dataLocations), texCoords[6]);
1846 TRACE_STRIDED((dataLocations), texCoords[7]);
1847 TRACE_STRIDED((dataLocations), position2);
1848 TRACE_STRIDED((dataLocations), normal2);
1849 TRACE_STRIDED((dataLocations), tangent);
1850 TRACE_STRIDED((dataLocations), binormal);
1851 TRACE_STRIDED((dataLocations), tessFactor);
1852 TRACE_STRIDED((dataLocations), fog);
1853 TRACE_STRIDED((dataLocations), depth);
1854 TRACE_STRIDED((dataLocations), sample);
1860 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1863 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1864 /* Pixel shader support should imply multitexture support. */
1865 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1866 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1867 checkGLcall("glActiveTextureARB");
1869 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1872 if (!This->stateBlock->textures[i]) continue;
1874 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1875 glDisable(GL_TEXTURE_1D);
1876 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1877 switch(This->stateBlock->textureDimensions[i]) {
1879 glDisable(GL_TEXTURE_3D);
1880 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1883 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1884 glDisable(GL_TEXTURE_2D);
1886 case GL_TEXTURE_CUBE_MAP_ARB:
1887 glDisable(GL_TEXTURE_2D);
1888 glDisable(GL_TEXTURE_3D);
1891 glEnable(This->stateBlock->textureDimensions[i]);
1893 /* Upload texture, apply states */
1894 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1895 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1896 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1900 /* uploads textures and setup texture states ready for rendering */
1901 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1902 INT current_sampler = 0;
1903 float constant_color[4];
1906 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1907 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1908 * Register combiners however provide up to 8 combiner stages. In order to
1909 * take advantage of this, we need to be separate D3D texture stages from
1910 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1911 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1912 * corresponds to MaxTextureBlendStages in the caps. */
1914 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1915 glEnable(GL_REGISTER_COMBINERS_NV);
1916 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1917 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1920 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1921 INT texture_idx = -1;
1923 /* WINED3DTOP_DISABLE disables the current & any higher texture stages */
1924 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) break;
1926 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1927 texture_idx = current_sampler++;
1929 /* Active the texture unit corresponding to the current texture stage */
1930 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1931 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1932 checkGLcall("glActiveTextureARB");
1934 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1938 if (This->stateBlock->textures[i]) {
1939 /* Enable the correct target. */
1940 glDisable(GL_TEXTURE_1D);
1941 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1942 switch(This->stateBlock->textureDimensions[i]) {
1944 glDisable(GL_TEXTURE_3D);
1945 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1948 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1949 glDisable(GL_TEXTURE_2D);
1951 case GL_TEXTURE_CUBE_MAP_ARB:
1952 glDisable(GL_TEXTURE_2D);
1953 glDisable(GL_TEXTURE_3D);
1957 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1958 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1959 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1961 glEnable(This->stateBlock->textureDimensions[i]);
1964 /* Upload texture, apply states */
1965 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1966 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
1967 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1968 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1969 /* ARB_texture_env_combine needs a valid texture bound to the
1970 * texture unit, even if it isn't used. Bind a dummy texture. */
1971 glDisable(GL_TEXTURE_2D);
1972 glDisable(GL_TEXTURE_3D);
1973 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1974 glEnable(GL_TEXTURE_1D);
1975 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1976 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1979 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1980 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1981 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1982 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1983 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1984 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1985 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
1988 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1989 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1990 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1991 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
1994 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1995 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1996 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1997 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1999 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2000 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2001 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2002 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2006 /* If we're using register combiners, set the amount of *used* combiners.
2007 * Ie, the number of stages below the first stage to have a color op of
2008 * WINED3DTOP_DISABLE. */
2009 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2010 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2011 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2012 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2015 /* Disable the remaining texture units. */
2016 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2017 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2018 glDisable(GL_TEXTURE_1D);
2019 glDisable(GL_TEXTURE_2D);
2020 glDisable(GL_TEXTURE_3D);
2021 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2025 static void check_fbo_status(IWineD3DDevice *iface) {
2026 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2028 GLenum status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
2030 case GL_FRAMEBUFFER_COMPLETE_EXT: TRACE("FBO complete.\n"); break;
2031 default: TRACE("FBO status %#x.\n", status); break;
2035 static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
2036 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2038 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
2040 glDisable(GL_CULL_FACE);
2041 glDisable(GL_BLEND);
2042 glDisable(GL_ALPHA_TEST);
2043 glDisable(GL_STENCIL_TEST);
2044 glEnable(GL_DEPTH_TEST);
2045 glDepthFunc(GL_ALWAYS);
2047 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2048 glBindTexture(GL_TEXTURE_2D, texture);
2049 glEnable(GL_TEXTURE_2D);
2051 This->shader_backend->shader_select_depth_blt(iface);
2053 glBegin(GL_TRIANGLE_STRIP);
2054 glVertex2f(-1.0f, -1.0f);
2055 glVertex2f(1.0f, -1.0f);
2056 glVertex2f(-1.0f, 1.0f);
2057 glVertex2f(1.0f, 1.0f);
2063 static void depth_copy(IWineD3DDevice *iface) {
2064 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2065 IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
2067 /* Only copy the depth buffer if there is one. */
2068 if (!depth_stencil) return;
2070 /* TODO: Make this work for modes other than FBO */
2071 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
2073 if (This->render_offscreen) {
2074 static GLuint tmp_texture = 0;
2076 TRACE("Copying onscreen depth buffer to offscreen surface\n");
2079 glGenTextures(1, &tmp_texture);
2082 /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
2083 * directly on the FBO texture. That's because we need to flip. */
2084 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
2085 glBindTexture(GL_TEXTURE_2D, tmp_texture);
2086 glCopyTexImage2D(depth_stencil->glDescription.target,
2087 depth_stencil->glDescription.level,
2088 depth_stencil->glDescription.glFormatInternal,
2091 depth_stencil->currentDesc.Width,
2092 depth_stencil->currentDesc.Height,
2094 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2096 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
2098 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
2099 checkGLcall("glBindFramebuffer()");
2100 depth_blt(iface, tmp_texture);
2101 checkGLcall("depth_blt");
2103 TRACE("Copying offscreen surface to onscreen depth buffer\n");
2105 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
2106 checkGLcall("glBindFramebuffer()");
2107 depth_blt(iface, depth_stencil->glDescription.textureName);
2108 checkGLcall("depth_blt");
2112 /* Routine common to the draw primitive and draw indexed primitive routines */
2113 void drawPrimitive(IWineD3DDevice *iface,
2117 long StartVertexIndex,
2118 UINT numberOfVertices,
2121 const void *idxData,
2123 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2126 BOOL useVertexShaderFunction = FALSE;
2127 BOOL usePixelShaderFunction = FALSE;
2128 WineDirect3DVertexStridedData *dataLocations;
2129 IWineD3DSwapChainImpl *swapchain;
2133 BOOL lighting_changed, lighting_original = FALSE;
2135 if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
2136 check_fbo_status(iface);
2139 if (This->depth_copy_state == WINED3D_DCS_COPY) {
2142 This->depth_copy_state = WINED3D_DCS_INITIAL;
2144 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2145 * here simply check whether a shader was set, or the user disabled shaders */
2146 if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2147 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2148 useVertexShaderFunction = TRUE;
2150 if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2151 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2152 usePixelShaderFunction = TRUE;
2154 /* Invalidate the back buffer memory so LockRect will read it the next time */
2155 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2156 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2158 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2162 /* Ok, we will be updating the screen from here onwards so grab the lock */
2165 if(DrawPrimStrideData) {
2167 /* Note: this is a ddraw fixed-function code path */
2169 TRACE("================ Strided Input ===================\n");
2170 dataLocations = DrawPrimStrideData;
2171 drawPrimitiveTraceDataLocations(dataLocations);
2175 else if (This->stateBlock->vertexDecl || This->stateBlock->vertexShader) {
2177 /* Note: This is a fixed function or shader codepath.
2178 * This means it must handle both types of strided data.
2179 * Shaders must go through here to zero the strided data, even if they
2180 * don't set any declaration at all */
2182 TRACE("================ Vertex Declaration ===================\n");
2183 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2184 if(!dataLocations) {
2185 ERR("Out of memory!\n");
2189 if (This->stateBlock->vertexDecl != NULL ||
2190 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2192 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2193 dataLocations, StartVertexIndex, &fixup);
2197 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2198 * It is reachable through d3d8, but only for fixed-function.
2199 * It will not work properly for shaders. */
2201 TRACE("================ FVF ===================\n");
2202 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2203 if(!dataLocations) {
2204 ERR("Out of memory!\n");
2207 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2208 drawPrimitiveTraceDataLocations(dataLocations);
2211 /* Setup transform matrices and sort out */
2212 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2214 /* Now initialize the materials state */
2215 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2217 if (usePixelShaderFunction) {
2218 drawPrimitiveUploadTexturesPS(This);
2220 drawPrimitiveUploadTextures(This);
2225 /* Ok, Work out which primitive is requested and how many vertexes that
2227 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2228 if (numberOfVertices == 0 )
2229 numberOfVertices = calculatedNumberOfindices;
2231 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2232 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2233 idxData, idxSize, minIndex, StartIdx, fixup);
2236 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2238 /* If vertex shaders or no normals, restore previous lighting state */
2239 if (lighting_changed) {
2240 if (lighting_original) glEnable(GL_LIGHTING);
2241 else glDisable(GL_LIGHTING);
2242 TRACE("Restored lighting to original state\n");
2245 /* Finshed updating the screen, restore lock */
2247 TRACE("Done all gl drawing\n");
2250 #ifdef SHOW_FRAME_MAKEUP
2252 static long int primCounter = 0;
2253 /* NOTE: set primCounter to the value reported by drawprim
2254 before you want to to write frame makeup to /tmp */
2255 if (primCounter >= 0) {
2256 WINED3DLOCKED_RECT r;
2258 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2259 sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
2260 TRACE("Saving screenshot %s\n", buffer);
2261 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2262 IWineD3DSurface_UnlockRect(This->renderTarget);
2264 #ifdef SHOW_TEXTURE_MAKEUP
2266 IWineD3DSurface *pSur;
2268 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2269 if (This->stateBlock->textures[textureNo] != NULL) {
2270 sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2271 TRACE("Saving texture %s\n", buffer);
2272 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2273 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2274 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2275 IWineD3DSurface_Release(pSur);
2277 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2284 TRACE("drawprim #%d\n", primCounter);