oledlg: Initialize the paste list.
[wine/hacks.git] / dlls / wined3d / drawprim.c
blobf880aadd12a515f04f95a529a6c292e401c2e689
1 /*
2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
31 #include <stdio.h>
33 #if 0 /* TODO */
34 extern IWineD3DVertexShaderImpl* VertexShaders[64];
35 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
36 extern IWineD3DPixelShaderImpl* PixelShaders[64];
38 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
39 #endif
41 /* Issues the glBegin call for gl given the primitive type and count */
42 static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType,
43 DWORD NumPrimitives,
44 GLenum *primType)
46 DWORD NumVertexes = NumPrimitives;
48 switch (PrimitiveType) {
49 case WINED3DPT_POINTLIST:
50 TRACE("POINTS\n");
51 *primType = GL_POINTS;
52 NumVertexes = NumPrimitives;
53 break;
55 case WINED3DPT_LINELIST:
56 TRACE("LINES\n");
57 *primType = GL_LINES;
58 NumVertexes = NumPrimitives * 2;
59 break;
61 case WINED3DPT_LINESTRIP:
62 TRACE("LINE_STRIP\n");
63 *primType = GL_LINE_STRIP;
64 NumVertexes = NumPrimitives + 1;
65 break;
67 case WINED3DPT_TRIANGLELIST:
68 TRACE("TRIANGLES\n");
69 *primType = GL_TRIANGLES;
70 NumVertexes = NumPrimitives * 3;
71 break;
73 case WINED3DPT_TRIANGLESTRIP:
74 TRACE("TRIANGLE_STRIP\n");
75 *primType = GL_TRIANGLE_STRIP;
76 NumVertexes = NumPrimitives + 2;
77 break;
79 case WINED3DPT_TRIANGLEFAN:
80 TRACE("TRIANGLE_FAN\n");
81 *primType = GL_TRIANGLE_FAN;
82 NumVertexes = NumPrimitives + 2;
83 break;
85 default:
86 FIXME("Unhandled primitive\n");
87 *primType = GL_POINTS;
88 break;
90 return NumVertexes;
93 /* Ensure the appropriate material states are set up - only change
94 state if really required */
95 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
97 BOOL requires_material_reset = FALSE;
98 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
100 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
101 /* If we have not set up the material color tracking, do it now as required */
102 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
103 checkGLcall("glDisable GL_COLOR_MATERIAL");
104 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
105 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
106 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
107 glEnable(GL_COLOR_MATERIAL);
108 checkGLcall("glEnable GL_COLOR_MATERIAL");
109 This->tracking_color = IS_TRACKING;
110 requires_material_reset = TRUE; /* Restore material settings as will be used */
112 } else if ((This->tracking_color == IS_TRACKING && !isDiffuseSupplied) ||
113 (This->tracking_color == NEEDS_TRACKING && !isDiffuseSupplied)) {
114 /* If we are tracking the current color but one isn't supplied, don't! */
115 glDisable(GL_COLOR_MATERIAL);
116 checkGLcall("glDisable GL_COLOR_MATERIAL");
117 This->tracking_color = NEEDS_TRACKING;
118 requires_material_reset = TRUE; /* Restore material settings as will be used */
120 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
121 /* No need to reset material colors since no change to gl_color_material */
122 requires_material_reset = FALSE;
124 } else if (This->tracking_color == NEEDS_DISABLE) {
125 glDisable(GL_COLOR_MATERIAL);
126 checkGLcall("glDisable GL_COLOR_MATERIAL");
127 This->tracking_color = DISABLED_TRACKING;
128 requires_material_reset = TRUE; /* Restore material settings as will be used */
131 /* Reset the material colors which may have been tracking the color*/
132 if (requires_material_reset) {
133 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
134 checkGLcall("glMaterialfv");
135 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
136 checkGLcall("glMaterialfv");
137 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
138 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
139 checkGLcall("glMaterialfv");
140 } else {
141 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
142 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
143 checkGLcall("glMaterialfv");
145 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
146 checkGLcall("glMaterialfv");
151 static GLfloat invymat[16] = {
152 1.0f, 0.0f, 0.0f, 0.0f,
153 0.0f, -1.0f, 0.0f, 0.0f,
154 0.0f, 0.0f, 1.0f, 0.0f,
155 0.0f, 0.0f, 0.0f, 1.0f};
157 void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
158 /* If the last draw was transformed as well, no need to reapply all the matrixes */
159 if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
161 double X, Y, height, width, minZ, maxZ;
162 This->last_was_rhw = TRUE;
163 This->viewport_changed = FALSE;
165 /* Transformed already into viewport coordinates, so we do not need transform
166 matrices. Reset all matrices to identity and leave the default matrix in world
167 mode. */
168 glMatrixMode(GL_MODELVIEW);
169 checkGLcall("glMatrixMode(GL_MODELVIEW)");
170 glLoadIdentity();
171 checkGLcall("glLoadIdentity");
173 glMatrixMode(GL_PROJECTION);
174 checkGLcall("glMatrixMode(GL_PROJECTION)");
175 glLoadIdentity();
176 checkGLcall("glLoadIdentity");
178 /* Set up the viewport to be full viewport */
179 X = This->stateBlock->viewport.X;
180 Y = This->stateBlock->viewport.Y;
181 height = This->stateBlock->viewport.Height;
182 width = This->stateBlock->viewport.Width;
183 minZ = This->stateBlock->viewport.MinZ;
184 maxZ = This->stateBlock->viewport.MaxZ;
185 if(!This->untransformed) {
186 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
187 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
188 } else {
189 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
190 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
192 checkGLcall("glOrtho");
194 /* Window Coord 0 is the middle of the first pixel, so translate by half
195 a pixel (See comment above glTranslate below) */
196 glTranslatef(0.375, 0.375, 0);
197 checkGLcall("glTranslatef(0.375, 0.375, 0)");
198 if (This->renderUpsideDown) {
199 glMultMatrixf(invymat);
200 checkGLcall("glMultMatrixf(invymat)");
203 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
204 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
205 if(GL_SUPPORT(EXT_FOG_COORD)) {
206 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
207 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
208 glFogi(GL_FOG_MODE, GL_LINEAR);
209 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
210 /* The dx fog range in this case is fixed to 0 - 255,
211 * but in GL it still depends on the fog start and end (according to the ext)
212 * Use this to turn around the fog as it's needed. That prevents some
213 * calculations during drawing :-)
215 glFogf(GL_FOG_START, (float) 0xff);
216 checkGLcall("glFogfv GL_FOG_END");
217 glFogf(GL_FOG_END, 0.0);
218 checkGLcall("glFogfv GL_FOG_START");
219 } else {
220 /* Disable GL fog, handle this in software in drawStridedSlow */
221 glDisable(GL_FOG);
222 checkGLcall("glDisable(GL_FOG)");
227 /* Setup views - Transformed & lit if RHW, else untransformed.
228 Only unlit if Normals are supplied
229 Returns: Whether to restore lighting afterwards */
230 static void primitiveInitState(
231 IWineD3DDevice *iface,
232 WineDirect3DVertexStridedData* strided,
233 BOOL useVS,
234 BOOL* lighting_changed,
235 BOOL* lighting_original) {
237 BOOL fixed_vtx_transformed =
238 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
239 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
240 strided->u.s.position_transformed;
242 BOOL fixed_vtx_lit =
243 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
244 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
248 *lighting_changed = FALSE;
250 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
251 set by the appropriate render state. Note Vertex Shader output is already lit */
252 if (fixed_vtx_lit || useVS) {
253 *lighting_changed = TRUE;
254 *lighting_original = glIsEnabled(GL_LIGHTING);
255 glDisable(GL_LIGHTING);
256 checkGLcall("glDisable(GL_LIGHTING);");
257 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
260 if (!useVS && fixed_vtx_transformed) {
261 d3ddevice_set_ortho(This);
263 } else {
265 /* Untransformed, so relies on the view and projection matrices */
266 This->untransformed = TRUE;
268 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
269 /* Only reapply when have to */
270 This->modelview_valid = TRUE;
271 glMatrixMode(GL_MODELVIEW);
272 checkGLcall("glMatrixMode");
274 /* In the general case, the view matrix is the identity matrix */
275 if (This->view_ident) {
276 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
277 checkGLcall("glLoadMatrixf");
278 } else {
279 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
280 checkGLcall("glLoadMatrixf");
281 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
282 checkGLcall("glMultMatrixf");
286 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
287 /* Only reapply when have to */
288 This->proj_valid = TRUE;
289 glMatrixMode(GL_PROJECTION);
290 checkGLcall("glMatrixMode");
292 /* The rule is that the window coordinate 0 does not correspond to the
293 beginning of the first pixel, but the center of the first pixel.
294 As a consequence if you want to correctly draw one line exactly from
295 the left to the right end of the viewport (with all matrices set to
296 be identity), the x coords of both ends of the line would be not
297 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
298 instead. */
299 glLoadIdentity();
301 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
302 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
304 if (This->renderUpsideDown) {
305 glMultMatrixf(invymat);
306 checkGLcall("glMultMatrixf(invymat)");
308 glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
309 checkGLcall("glLoadMatrixf");
312 /* Vertex Shader output is already transformed, so set up identity matrices */
313 if (useVS) {
314 This->posFixup[1] = This->renderUpsideDown ? -1.0 : 1.0;
315 This->posFixup[2] = 0.9 / This->stateBlock->viewport.Width;
316 This->posFixup[3] = -0.9 / This->stateBlock->viewport.Height;
318 This->last_was_rhw = FALSE;
320 /* Setup fogging */
321 if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
322 /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
323 * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
324 glFogi(GL_FOG_MODE, GL_LINEAR);
325 glFogf(GL_FOG_START, 1.0f);
326 glFogf(GL_FOG_END, 0.0f);
328 } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE]
329 && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
331 if(GL_SUPPORT(EXT_FOG_COORD)) {
332 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
333 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
334 /* Reapply the fog range */
335 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
336 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
337 /* Restore the fog mode */
338 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
339 } else {
340 /* Enable GL_FOG again because we disabled it above */
341 glEnable(GL_FOG);
342 checkGLcall("glEnable(GL_FOG)");
348 static BOOL fixed_get_input(
349 BYTE usage, BYTE usage_idx,
350 unsigned int* regnum) {
352 *regnum = -1;
354 /* Those positions must have the order in the
355 * named part of the strided data */
357 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
358 *regnum = 0;
359 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
360 *regnum = 1;
361 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
362 *regnum = 2;
363 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
364 *regnum = 3;
365 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
366 *regnum = 4;
367 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
368 *regnum = 5;
369 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
370 *regnum = 6;
371 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
372 *regnum = 7 + usage_idx;
373 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
374 *regnum = 7 + WINED3DDP_MAXTEXCOORD;
375 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
376 *regnum = 8 + WINED3DDP_MAXTEXCOORD;
377 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
378 *regnum = 9 + WINED3DDP_MAXTEXCOORD;
379 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
380 *regnum = 10 + WINED3DDP_MAXTEXCOORD;
381 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
382 *regnum = 11 + WINED3DDP_MAXTEXCOORD;
383 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
384 *regnum = 12 + WINED3DDP_MAXTEXCOORD;
385 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
386 *regnum = 13 + WINED3DDP_MAXTEXCOORD;
387 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
388 *regnum = 14 + WINED3DDP_MAXTEXCOORD;
390 if (*regnum < 0) {
391 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
392 debug_d3ddeclusage(usage), usage_idx);
393 return FALSE;
395 return TRUE;
398 void primitiveDeclarationConvertToStridedData(
399 IWineD3DDevice *iface,
400 BOOL useVertexShaderFunction,
401 WineDirect3DVertexStridedData *strided,
402 LONG BaseVertexIndex,
403 BOOL *fixup) {
405 /* We need to deal with frequency data!*/
407 BYTE *data = NULL;
408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
409 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
410 int i;
411 WINED3DVERTEXELEMENT *element;
412 DWORD stride;
413 int reg;
415 /* Locate the vertex declaration */
416 if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
417 TRACE("Using vertex declaration from shader\n");
418 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
419 } else {
420 TRACE("Using vertex declaration\n");
421 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
424 /* Translate the declaration into strided data */
425 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
426 GLint streamVBO = 0;
427 BOOL stride_used;
428 unsigned int idx;
430 element = vertexDeclaration->pDeclarationWine + i;
431 TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
432 element, i + 1, vertexDeclaration->declarationWNumElements - 1);
434 if (This->stateBlock->streamSource[element->Stream] == NULL)
435 continue;
437 if (This->stateBlock->streamIsUP) {
438 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
439 streamVBO = 0;
440 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
441 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
442 } else {
443 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
444 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
445 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
446 if(fixup) {
447 if( streamVBO != 0) *fixup = TRUE;
448 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
451 stride = This->stateBlock->streamStride[element->Stream];
452 data += (BaseVertexIndex * stride);
453 data += element->Offset;
454 reg = element->Reg;
456 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
458 if (useVertexShaderFunction)
459 stride_used = vshader_get_input(This->stateBlock->vertexShader,
460 element->Usage, element->UsageIndex, &idx);
461 else
462 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
464 if (stride_used) {
465 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
466 "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
467 useVertexShaderFunction? "shader": "fixed function", idx,
468 debug_d3ddeclusage(element->Usage), element->UsageIndex,
469 element->Stream, element->Offset, stride, streamVBO);
471 strided->u.input[idx].lpData = data;
472 strided->u.input[idx].dwType = element->Type;
473 strided->u.input[idx].dwStride = stride;
474 strided->u.input[idx].VBO = streamVBO;
475 if (!useVertexShaderFunction) {
476 if (element->Usage == D3DDECLUSAGE_POSITION)
477 strided->u.s.position_transformed = FALSE;
478 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
479 strided->u.s.position_transformed = TRUE;
485 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
486 int numBlends;
487 int numTextures;
488 int textureNo;
489 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
490 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
492 /* Either 3 or 4 floats depending on the FVF */
493 /* FIXME: Can blending data be in a different stream to the position data?
494 and if so using the fixed pipeline how do we handle it */
495 if (thisFVF & D3DFVF_POSITION_MASK) {
496 strided->u.s.position.lpData = data;
497 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT3;
498 strided->u.s.position.dwStride = stride;
499 strided->u.s.position.VBO = streamVBO;
500 data += 3 * sizeof(float);
501 if (thisFVF & D3DFVF_XYZRHW) {
502 strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
503 strided->u.s.position_transformed = TRUE;
504 data += sizeof(float);
505 } else
506 strided->u.s.position_transformed = FALSE;
509 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
510 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
511 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
512 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
514 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
515 TRACE("Setting blend Weights to %p\n", data);
516 strided->u.s.blendWeights.lpData = data;
517 strided->u.s.blendWeights.dwType = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
518 strided->u.s.blendWeights.dwStride = stride;
519 strided->u.s.blendWeights.VBO = streamVBO;
520 data += numBlends * sizeof(FLOAT);
522 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
523 strided->u.s.blendMatrixIndices.lpData = data;
524 strided->u.s.blendMatrixIndices.dwType = WINED3DDECLTYPE_UBYTE4;
525 strided->u.s.blendMatrixIndices.dwStride= stride;
526 strided->u.s.blendMatrixIndices.VBO = streamVBO;
527 data += sizeof(DWORD);
531 /* Normal is always 3 floats */
532 if (thisFVF & D3DFVF_NORMAL) {
533 strided->u.s.normal.lpData = data;
534 strided->u.s.normal.dwType = WINED3DDECLTYPE_FLOAT3;
535 strided->u.s.normal.dwStride = stride;
536 strided->u.s.normal.VBO = streamVBO;
537 data += 3 * sizeof(FLOAT);
540 /* Pointsize is a single float */
541 if (thisFVF & D3DFVF_PSIZE) {
542 strided->u.s.pSize.lpData = data;
543 strided->u.s.pSize.dwType = WINED3DDECLTYPE_FLOAT1;
544 strided->u.s.pSize.dwStride = stride;
545 strided->u.s.pSize.VBO = streamVBO;
546 data += sizeof(FLOAT);
549 /* Diffuse is 4 unsigned bytes */
550 if (thisFVF & D3DFVF_DIFFUSE) {
551 strided->u.s.diffuse.lpData = data;
552 strided->u.s.diffuse.dwType = WINED3DDECLTYPE_SHORT4;
553 strided->u.s.diffuse.dwStride = stride;
554 strided->u.s.diffuse.VBO = streamVBO;
555 data += sizeof(DWORD);
558 /* Specular is 4 unsigned bytes */
559 if (thisFVF & D3DFVF_SPECULAR) {
560 strided->u.s.specular.lpData = data;
561 strided->u.s.specular.dwType = WINED3DDECLTYPE_SHORT4;
562 strided->u.s.specular.dwStride = stride;
563 strided->u.s.specular.VBO = streamVBO;
564 data += sizeof(DWORD);
567 /* Texture coords */
568 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
569 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
571 /* numTextures indicates the number of texture coordinates supplied */
572 /* However, the first set may not be for stage 0 texture - it all */
573 /* depends on WINED3DTSS_TEXCOORDINDEX. */
574 /* The number of bytes for each coordinate set is based off */
575 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
577 /* So, for each supplied texture extract the coords */
578 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
580 strided->u.s.texCoords[textureNo].lpData = data;
581 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT1;
582 strided->u.s.texCoords[textureNo].dwStride = stride;
583 strided->u.s.texCoords[textureNo].VBO = streamVBO;
584 numCoords[textureNo] = coordIdxInfo & 0x03;
586 /* Always one set */
587 data += sizeof(float);
588 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
589 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
590 data += sizeof(float);
591 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
592 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
593 data += sizeof(float);
594 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
595 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
596 data += sizeof(float);
600 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
604 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
606 short LoopThroughTo = 0;
607 short nStream;
608 GLint streamVBO = 0;
610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
612 /* OK, Now to setup the data locations
613 For the non-created vertex shaders, the VertexShader var holds the real
614 FVF and only stream 0 matters
615 For the created vertex shaders, there is an FVF per stream */
616 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
617 LoopThroughTo = MAX_STREAMS;
618 } else {
619 LoopThroughTo = 1;
622 /* Work through stream by stream */
623 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
624 DWORD stride = This->stateBlock->streamStride[nStream];
625 BYTE *data = NULL;
626 DWORD thisFVF = 0;
628 /* Skip empty streams */
629 if (This->stateBlock->streamSource[nStream] == NULL) continue;
631 /* Retrieve appropriate FVF */
632 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
633 thisFVF = This->stateBlock->fvf;
634 /* Handle memory passed directly as well as vertex buffers */
635 if (This->stateBlock->streamIsUP) {
636 streamVBO = 0;
637 data = (BYTE *)This->stateBlock->streamSource[nStream];
638 } else {
639 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
640 /* GetMemory binds the VBO */
641 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
642 if(fixup) {
643 if(streamVBO != 0 ) *fixup = TRUE;
646 } else {
647 #if 0 /* TODO: Vertex shader support */
648 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
649 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
650 #endif
652 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
653 if (thisFVF == 0) continue;
655 /* Now convert the stream into pointers */
657 /* Shuffle to the beginning of the vertexes to render and index from there */
658 data = data + (BaseVertexIndex * stride);
660 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
664 #if 0 /* TODO: Software Shaders */
665 /* Draw a single vertex using this information */
666 static void draw_vertex(IWineD3DDevice *iface, /* interface */
667 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
668 BOOL isNormal, float nx, float ny, float nz, /* normal */
669 BOOL isDiffuse, float *dRGBA, /* 1st colors */
670 BOOL isSpecular, float *sRGB, /* 2ndry colors */
671 BOOL isPtSize, float ptSize, /* pointSize */
672 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
674 unsigned int textureNo;
675 float s, t, r, q;
676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
678 /* Diffuse -------------------------------- */
679 if (isDiffuse) {
680 glColor4fv(dRGBA);
681 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
684 /* Specular Colour ------------------------------------------*/
685 if (isSpecular) {
686 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
687 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
688 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
689 } else {
690 VTRACE(("Specular color extensions not supplied\n"));
694 /* Normal -------------------------------- */
695 if (isNormal) {
696 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
697 glNormal3f(nx, ny, nz);
700 /* Point Size ----------------------------------------------*/
701 if (isPtSize) {
703 /* no such functionality in the fixed function GL pipeline */
704 FIXME("Cannot change ptSize here in openGl\n");
707 /* Texture coords --------------------------- */
708 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
710 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
711 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
712 continue ;
715 /* Query tex coords */
716 if (This->stateBlock->textures[textureNo] != NULL) {
718 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
719 if (coordIdx >= MAX_TEXTURES) {
720 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
721 continue;
722 } else if (numcoords[coordIdx] == 0) {
723 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
724 continue;
725 } else {
727 /* Initialize vars */
728 s = 0.0f;
729 t = 0.0f;
730 r = 0.0f;
731 q = 0.0f;
733 switch (numcoords[coordIdx]) {
734 case 4: q = texcoords[coordIdx].w; /* drop through */
735 case 3: r = texcoords[coordIdx].z; /* drop through */
736 case 2: t = texcoords[coordIdx].y; /* drop through */
737 case 1: s = texcoords[coordIdx].x;
740 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
741 case WINED3DTTFF_COUNT1:
742 VTRACE(("tex:%d, s=%f\n", textureNo, s));
743 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
744 GLMULTITEXCOORD1F(textureNo, s);
745 } else {
746 glTexCoord1f(s);
748 break;
749 case WINED3DTTFF_COUNT2:
750 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
751 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
752 GLMULTITEXCOORD2F(textureNo, s, t);
753 } else {
754 glTexCoord2f(s, t);
756 break;
757 case WINED3DTTFF_COUNT3:
758 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
759 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
760 GLMULTITEXCOORD3F(textureNo, s, t, r);
761 } else {
762 glTexCoord3f(s, t, r);
764 break;
765 case WINED3DTTFF_COUNT4:
766 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
767 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
768 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
769 } else {
770 glTexCoord4f(s, t, r, q);
772 break;
773 default:
774 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
778 } /* End of textures */
780 /* Position -------------------------------- */
781 if (isXYZ) {
782 if (1.0f == rhw || rhw < 0.00001f) {
783 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
784 glVertex3f(x, y, z);
785 } else {
786 /* Cannot optimize by dividing through by rhw as rhw is required
787 later for perspective in the GL pipeline for vertex shaders */
788 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
789 glVertex4f(x,y,z,rhw);
793 #endif /* TODO: Software shaders */
795 /* This should match any arrays loaded in loadNumberedArrays. */
796 /* TODO: Only load / unload arrays if we have to. */
797 static void unloadNumberedArrays(IWineD3DDevice *iface) {
798 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
800 /* disable any attribs (this is the same for both GLSL and ARB modes) */
801 GLint maxAttribs;
802 int i;
804 /* Leave all the attribs disabled */
805 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
806 /* MESA does not support it right not */
807 if (glGetError() != GL_NO_ERROR)
808 maxAttribs = 16;
809 for (i = 0; i < maxAttribs; ++i) {
810 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
811 checkGLcall("glDisableVertexAttribArrayARB(reg);");
815 /* TODO: Only load / unload arrays if we have to. */
816 static void loadNumberedArrays(
817 IWineD3DDevice *iface,
818 IWineD3DVertexShader *shader,
819 WineDirect3DVertexStridedData *strided) {
821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
822 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
823 int i;
825 for (i = 0; i < MAX_ATTRIBS; i++) {
827 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
828 continue;
830 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
832 if(curVBO != strided->u.input[i].VBO) {
833 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
834 checkGLcall("glBindBufferARB");
835 curVBO = strided->u.input[i].VBO;
837 GL_EXTCALL(glVertexAttribPointerARB(i,
838 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
839 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
840 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
841 strided->u.input[i].dwStride,
842 strided->u.input[i].lpData));
843 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
847 /* This should match any arrays loaded in loadVertexData. */
848 /* TODO: Only load / unload arrays if we have to. */
849 static void unloadVertexData(IWineD3DDevice *iface) {
850 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
851 int texture_idx;
853 glDisableClientState(GL_VERTEX_ARRAY);
854 glDisableClientState(GL_NORMAL_ARRAY);
855 glDisableClientState(GL_COLOR_ARRAY);
856 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
857 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
859 for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
860 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
861 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
865 /* TODO: Only load / unload arrays if we have to. */
866 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
867 unsigned int textureNo = 0;
868 unsigned int texture_idx = 0;
869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
870 GLint curVBO = -1;
872 TRACE("Using fast vertex array code\n");
873 /* Blend Data ---------------------------------------------- */
874 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
875 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
878 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
880 #if 1
881 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
882 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
883 #endif
885 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
886 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
887 /* FIXME("TODO\n");*/
888 /* Note dwType == float3 or float4 == 2 or 3 */
890 #if 0
891 /* with this on, the normals appear to be being modified,
892 but the vertices aren't being translated as they should be
893 Maybe the world matrix aren't being setup properly? */
894 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
895 #endif
898 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
899 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
900 sd->u.s.blendWeights.dwStride,
901 sd->u.s.blendWeights.lpData));
903 if(curVBO != sd->u.s.blendWeights.VBO) {
904 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
905 checkGLcall("glBindBufferARB");
906 curVBO = sd->u.s.blendWeights.VBO;
909 GL_EXTCALL(glWeightPointerARB)(
910 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
911 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
912 sd->u.s.blendWeights.dwStride,
913 sd->u.s.blendWeights.lpData);
915 checkGLcall("glWeightPointerARB");
917 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
918 static BOOL showfixme = TRUE;
919 if(showfixme){
920 FIXME("blendMatrixIndices support\n");
921 showfixme = FALSE;
925 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
926 /* FIXME("TODO\n");*/
927 #if 0
929 GL_EXTCALL(glVertexWeightPointerEXT)(
930 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
931 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
932 sd->u.s.blendWeights.dwStride,
933 sd->u.s.blendWeights.lpData);
934 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
935 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
936 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
937 #endif
939 } else {
940 /* TODO: support blends in fixupVertices */
941 FIXME("unsupported blending in openGl\n");
943 } else {
944 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
945 #if 0 /* TODO: Vertex blending */
946 glDisable(GL_VERTEX_BLEND_ARB);
947 #endif
948 TRACE("ARB_VERTEX_BLEND\n");
949 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
950 TRACE(" EXT_VERTEX_WEIGHTING\n");
951 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
952 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
957 #if 0 /* FOG ----------------------------------------------*/
958 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
959 /* TODO: fog*/
960 if (GL_SUPPORT(EXT_FOG_COORD) {
961 glEnableClientState(GL_FOG_COORDINATE_EXT);
962 (GL_EXTCALL)(FogCoordPointerEXT)(
963 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
964 sd->u.s.fog.dwStride,
965 sd->u.s.fog.lpData);
966 } else {
967 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
968 /* FIXME: fixme once */
969 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
971 } else {
972 if (GL_SUPPRT(EXT_FOR_COORD) {
973 /* make sure fog is disabled */
974 glDisableClientState(GL_FOG_COORDINATE_EXT);
977 #endif
979 #if 0 /* tangents ----------------------------------------------*/
980 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
981 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
982 /* TODO: tangents*/
983 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
984 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
985 glEnable(GL_TANGENT_ARRAY_EXT);
986 (GL_EXTCALL)(TangentPointerEXT)(
987 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
988 sd->u.s.tangent.dwStride,
989 sd->u.s.tangent.lpData);
990 } else {
991 glDisable(GL_TANGENT_ARRAY_EXT);
993 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
994 glEnable(GL_BINORMAL_ARRAY_EXT);
995 (GL_EXTCALL)(BinormalPointerEXT)(
996 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
997 sd->u.s.binormal.dwStride,
998 sd->u.s.binormal.lpData);
999 } else{
1000 glDisable(GL_BINORMAL_ARRAY_EXT);
1003 } else {
1004 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1005 /* FIXME: fixme once */
1006 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1008 } else {
1009 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1010 /* make sure fog is disabled */
1011 glDisable(GL_TANGENT_ARRAY_EXT);
1012 glDisable(GL_BINORMAL_ARRAY_EXT);
1015 #endif
1017 /* Point Size ----------------------------------------------*/
1018 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
1020 /* no such functionality in the fixed function GL pipeline */
1021 TRACE("Cannot change ptSize here in openGl\n");
1022 /* TODO: Implement this function in using shaders if they are available */
1026 /* Vertex Pointers -----------------------------------------*/
1027 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
1028 /* Note dwType == float3 or float4 == 2 or 3 */
1029 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
1030 sd->u.s.position.dwStride,
1031 sd->u.s.position.dwType + 1,
1032 sd->u.s.position.lpData));
1034 if(curVBO != sd->u.s.position.VBO) {
1035 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1036 checkGLcall("glBindBufferARB");
1037 curVBO = sd->u.s.position.VBO;
1040 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1041 handling for rhw mode should not impact screen position whereas in GL it does.
1042 This may result in very slightly distored textures in rhw mode, but
1043 a very minimal different. There's always the other option of
1044 fixing the view matrix to prevent w from having any effect
1046 This only applies to user pointer sources, in VBOs the vertices are fixed up
1048 if(sd->u.s.position.VBO == 0) {
1049 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1050 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1051 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1052 } else {
1053 glVertexPointer(
1054 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1055 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1056 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1058 checkGLcall("glVertexPointer(...)");
1059 glEnableClientState(GL_VERTEX_ARRAY);
1060 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1062 } else {
1063 glDisableClientState(GL_VERTEX_ARRAY);
1064 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1067 /* Normals -------------------------------------------------*/
1068 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1069 /* Note dwType == float3 or float4 == 2 or 3 */
1070 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
1071 sd->u.s.normal.dwStride,
1072 sd->u.s.normal.lpData));
1073 if(curVBO != sd->u.s.normal.VBO) {
1074 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1075 checkGLcall("glBindBufferARB");
1076 curVBO = sd->u.s.normal.VBO;
1078 glNormalPointer(
1079 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1080 sd->u.s.normal.dwStride,
1081 sd->u.s.normal.lpData);
1082 checkGLcall("glNormalPointer(...)");
1083 glEnableClientState(GL_NORMAL_ARRAY);
1084 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1086 } else {
1087 glDisableClientState(GL_NORMAL_ARRAY);
1088 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1089 glNormal3f(0, 0, 1);
1090 checkGLcall("glNormal3f(0, 0, 1)");
1093 /* Diffuse Colour --------------------------------------------*/
1094 /* WARNING: Data here MUST be in RGBA format, so cannot */
1095 /* go directly into fast mode from app pgm, because */
1096 /* directx requires data in BGRA format. */
1097 /* currently fixupVertices swizels the format, but this isn't */
1098 /* very practical when using VBOS */
1099 /* NOTE: Unless we write a vertex shader to swizel the colour */
1100 /* , or the user doesn't care and wants the speed advantage */
1102 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1103 /* Note dwType == float3 or float4 == 2 or 3 */
1104 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1105 sd->u.s.diffuse.dwStride,
1106 sd->u.s.diffuse.lpData));
1108 if(curVBO != sd->u.s.diffuse.VBO) {
1109 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1110 checkGLcall("glBindBufferARB");
1111 curVBO = sd->u.s.diffuse.VBO;
1113 glColorPointer(4, GL_UNSIGNED_BYTE,
1114 sd->u.s.diffuse.dwStride,
1115 sd->u.s.diffuse.lpData);
1116 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1117 glEnableClientState(GL_COLOR_ARRAY);
1118 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1120 } else {
1121 glDisableClientState(GL_COLOR_ARRAY);
1122 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1123 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1124 checkGLcall("glColor4f(1, 1, 1, 1)");
1127 /* Specular Colour ------------------------------------------*/
1128 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1129 TRACE("setting specular colour\n");
1130 /* Note dwType == float3 or float4 == 2 or 3 */
1131 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
1132 sd->u.s.specular.dwStride,
1133 sd->u.s.specular.lpData));
1134 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1135 if(curVBO != sd->u.s.specular.VBO) {
1136 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1137 checkGLcall("glBindBufferARB");
1138 curVBO = sd->u.s.specular.VBO;
1140 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1141 sd->u.s.specular.dwStride,
1142 sd->u.s.specular.lpData);
1143 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1144 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1145 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1146 } else {
1148 /* Missing specular color is not critical, no warnings */
1149 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1152 } else {
1153 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1155 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1156 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1157 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1158 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1159 } else {
1161 /* Missing specular color is not critical, no warnings */
1162 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1166 /* Texture coords -------------------------------------------*/
1168 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1169 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1170 /* Abort if we don't support the extension. */
1171 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1172 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1173 continue;
1176 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1177 /* Select the correct texture stage */
1178 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1181 if (This->stateBlock->textures[textureNo] != NULL) {
1182 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1184 if (coordIdx >= MAX_TEXTURES) {
1185 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1186 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1187 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1189 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1190 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1191 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1192 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1194 } else {
1195 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1196 textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1197 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1198 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1199 checkGLcall("glBindBufferARB");
1200 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1202 /* The coords to supply depend completely on the fvf / vertex shader */
1203 glTexCoordPointer(
1204 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1205 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1206 sd->u.s.texCoords[coordIdx].dwStride,
1207 sd->u.s.texCoords[coordIdx].lpData);
1208 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1210 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1211 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1212 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1214 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1216 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1217 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1218 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1220 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1225 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1226 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1227 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1229 if (idxData != NULL /* This crashes sometimes!*/) {
1230 TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1231 idxData = idxData == (void *)-1 ? NULL : idxData;
1232 #if 1
1233 #if 0
1234 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1235 glEnableClientState(GL_INDEX_ARRAY);
1236 #endif
1237 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1238 (const char *)idxData+(idxSize * startIdx));
1239 #else /* using drawRangeElements may be faster */
1241 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1242 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1243 (const char *)idxData+(idxSize * startIdx));
1244 #endif
1245 checkGLcall("glDrawRangeElements");
1247 } else {
1249 /* Note first is now zero as we shuffled along earlier */
1250 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1251 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1252 checkGLcall("glDrawArrays");
1256 return;
1260 * Actually draw using the supplied information.
1261 * Slower GL version which extracts info about each vertex in turn
1264 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1265 UINT NumVertexes, GLenum glPrimType,
1266 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1268 unsigned int textureNo = 0;
1269 unsigned int texture_idx = 0;
1270 const short *pIdxBufS = NULL;
1271 const long *pIdxBufL = NULL;
1272 LONG SkipnStrides = 0;
1273 LONG vx_index;
1274 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1275 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1276 float rhw = 0.0f; /* rhw */
1277 float ptSize = 0.0f; /* Point size */
1278 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1279 DWORD specularColor = 0; /* Specular Color */
1280 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1282 TRACE("Using slow vertex array code\n");
1284 /* Variable Initialization */
1285 if (idxData != NULL) {
1286 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1287 else pIdxBufL = (const long *) idxData;
1290 /* Start drawing in GL */
1291 VTRACE(("glBegin(%x)\n", glPrimType));
1292 glBegin(glPrimType);
1294 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1295 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1298 /* For each primitive */
1299 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1301 /* Initialize diffuse color */
1302 diffuseColor = 0xFFFFFFFF;
1304 /* For indexed data, we need to go a few more strides in */
1305 if (idxData != NULL) {
1307 /* Indexed so work out the number of strides to skip */
1308 if (idxSize == 2) {
1309 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1310 SkipnStrides = pIdxBufS[startIdx + vx_index];
1311 } else {
1312 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1313 SkipnStrides = pIdxBufL[startIdx + vx_index];
1317 /* Position Information ------------------ */
1318 if (sd->u.s.position.lpData != NULL) {
1320 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1321 x = ptrToCoords[0];
1322 y = ptrToCoords[1];
1323 z = ptrToCoords[2];
1324 rhw = 1.0;
1325 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1327 /* RHW follows, only if transformed, ie 4 floats were provided */
1328 if (sd->u.s.position_transformed) {
1329 rhw = ptrToCoords[3];
1330 VTRACE(("rhw=%f\n", rhw));
1334 /* Blending data -------------------------- */
1335 if (sd->u.s.blendWeights.lpData != NULL) {
1336 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1337 FIXME("Blending not supported yet\n");
1339 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1340 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1344 /* Vertex Normal Data (untransformed only)- */
1345 if (sd->u.s.normal.lpData != NULL) {
1347 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1348 nx = ptrToCoords[0];
1349 ny = ptrToCoords[1];
1350 nz = ptrToCoords[2];
1351 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1354 /* Point Size ----------------------------- */
1355 if (sd->u.s.pSize.lpData != NULL) {
1357 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1358 ptSize = ptrToCoords[0];
1359 VTRACE(("ptSize=%f\n", ptSize));
1360 FIXME("No support for ptSize yet\n");
1363 /* Diffuse -------------------------------- */
1364 if (sd->u.s.diffuse.lpData != NULL) {
1366 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1367 diffuseColor = ptrToCoords[0];
1368 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1371 /* Specular -------------------------------- */
1372 if (sd->u.s.specular.lpData != NULL) {
1374 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1375 specularColor = ptrToCoords[0];
1376 VTRACE(("specularColor=%lx\n", specularColor));
1379 /* Texture coords --------------------------- */
1380 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1382 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1383 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1384 continue ;
1387 /* Query tex coords */
1388 if (This->stateBlock->textures[textureNo] != NULL) {
1390 int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1391 float *ptrToCoords = NULL;
1392 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1394 if (coordIdx > 7) {
1395 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1396 ++texture_idx;
1397 continue;
1398 } else if (coordIdx < 0) {
1399 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1400 ++texture_idx;
1401 continue;
1404 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1405 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1406 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1407 ++texture_idx;
1408 continue;
1409 } else {
1411 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
1413 /* The coords to supply depend completely on the fvf / vertex shader */
1414 switch (coordsToUse) {
1415 case 4: q = ptrToCoords[3]; /* drop through */
1416 case 3: r = ptrToCoords[2]; /* drop through */
1417 case 2: t = ptrToCoords[1]; /* drop through */
1418 case 1: s = ptrToCoords[0];
1421 /* Projected is more 'fun' - Move the last coord to the 'q'
1422 parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
1423 if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
1424 (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
1426 if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
1427 switch (coordsToUse) {
1428 case 0: /* Drop Through */
1429 case 1:
1430 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
1431 break;
1432 case 2:
1433 q = t;
1434 t = 0.0;
1435 coordsToUse = 4;
1436 break;
1437 case 3:
1438 q = r;
1439 r = 0.0;
1440 coordsToUse = 4;
1441 break;
1442 case 4: /* Nop here */
1443 break;
1444 default:
1445 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
1446 This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
1451 switch (coordsToUse) { /* Supply the provided texture coords */
1452 case WINED3DTTFF_COUNT1:
1453 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1454 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1455 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1456 } else {
1457 glTexCoord1f(s);
1459 break;
1460 case WINED3DTTFF_COUNT2:
1461 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1462 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1463 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1464 } else {
1465 glTexCoord2f(s, t);
1467 break;
1468 case WINED3DTTFF_COUNT3:
1469 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1470 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1471 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1472 } else {
1473 glTexCoord3f(s, t, r);
1475 break;
1476 case WINED3DTTFF_COUNT4:
1477 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1478 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1479 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1480 } else {
1481 glTexCoord4f(s, t, r, q);
1483 break;
1484 default:
1485 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1489 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1490 } /* End of textures */
1492 /* Diffuse -------------------------------- */
1493 if (sd->u.s.diffuse.lpData != NULL) {
1494 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1495 D3DCOLOR_B_G(diffuseColor),
1496 D3DCOLOR_B_B(diffuseColor),
1497 D3DCOLOR_B_A(diffuseColor));
1498 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1499 D3DCOLOR_B_R(diffuseColor),
1500 D3DCOLOR_B_G(diffuseColor),
1501 D3DCOLOR_B_B(diffuseColor),
1502 D3DCOLOR_B_A(diffuseColor)));
1503 } else {
1504 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1507 /* Specular ------------------------------- */
1508 if (sd->u.s.specular.lpData != NULL) {
1509 /* special case where the fog density is stored in the diffuse alpha channel */
1510 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1511 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
1512 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1513 if(GL_SUPPORT(EXT_FOG_COORD)) {
1514 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1515 } else {
1516 static BOOL warned = FALSE;
1517 if(!warned) {
1518 /* TODO: Use the fog table code from old ddraw */
1519 FIXME("Implement fog for transformed vertices in software\n");
1520 warned = TRUE;
1525 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1526 D3DCOLOR_B_R(specularColor),
1527 D3DCOLOR_B_G(specularColor),
1528 D3DCOLOR_B_B(specularColor)));
1529 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1530 GL_EXTCALL(glSecondaryColor3ubEXT)(
1531 D3DCOLOR_B_R(specularColor),
1532 D3DCOLOR_B_G(specularColor),
1533 D3DCOLOR_B_B(specularColor));
1534 } else {
1535 /* Do not worry if specular colour missing and disable request */
1536 VTRACE(("Specular color extensions not supplied\n"));
1538 } else {
1539 if (vx_index == 0) {
1540 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1541 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1542 } else {
1543 /* Do not worry if specular colour missing and disable request */
1544 VTRACE(("Specular color extensions not supplied\n"));
1549 /* Normal -------------------------------- */
1550 if (sd->u.s.normal.lpData != NULL) {
1551 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1552 glNormal3f(nx, ny, nz);
1553 } else {
1554 if (vx_index == 0) glNormal3f(0, 0, 1);
1557 /* Position -------------------------------- */
1558 if (sd->u.s.position.lpData != NULL) {
1559 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1560 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1561 glVertex3f(x, y, z);
1562 } else {
1563 GLfloat w = 1.0 / rhw;
1564 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1565 glVertex4f(x*w, y*w, z*w, w);
1569 /* For non indexed mode, step onto next parts */
1570 if (idxData == NULL) {
1571 ++SkipnStrides;
1575 glEnd();
1576 checkGLcall("glEnd and previous calls");
1579 #if 0 /* TODO: Software/Hardware vertex blending support */
1581 * Draw with emulated vertex shaders
1582 * Note: strided data is uninitialized, as we need to pass the vertex
1583 * shader directly as ordering irs yet
1585 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1586 int PrimitiveType, ULONG NumPrimitives,
1587 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1589 unsigned int textureNo = 0;
1590 GLenum glPrimType = GL_POINTS;
1591 int NumVertexes = NumPrimitives;
1592 const short *pIdxBufS = NULL;
1593 const long *pIdxBufL = NULL;
1594 LONG SkipnStrides = 0;
1595 LONG vx_index;
1596 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1597 float rhw = 0.0f; /* rhw */
1598 float ptSize = 0.0f; /* Point size */
1599 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1600 int numcoords[8]; /* Number of coords */
1601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1603 IDirect3DVertexShaderImpl* vertexShader = NULL;
1605 TRACE("Using slow software vertex shader code\n");
1607 /* Variable Initialization */
1608 if (idxData != NULL) {
1609 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1610 else pIdxBufL = (const long *) idxData;
1613 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1614 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1616 /* Retrieve the VS information */
1617 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1619 /* Start drawing in GL */
1620 VTRACE(("glBegin(%x)\n", glPrimType));
1621 glBegin(glPrimType);
1623 /* For each primitive */
1624 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1626 /* For indexed data, we need to go a few more strides in */
1627 if (idxData != NULL) {
1629 /* Indexed so work out the number of strides to skip */
1630 if (idxSize == 2) {
1631 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1632 SkipnStrides = pIdxBufS[startIdx+vx_index];
1633 } else {
1634 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1635 SkipnStrides = pIdxBufL[startIdx+vx_index];
1639 /* Fill the vertex shader input */
1640 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1642 /* Initialize the output fields to the same defaults as it would normally have */
1643 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1644 vertexShader->output.oD[0].x = 1.0;
1645 vertexShader->output.oD[0].y = 1.0;
1646 vertexShader->output.oD[0].z = 1.0;
1647 vertexShader->output.oD[0].w = 1.0;
1649 /* Now execute the vertex shader */
1650 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1653 TRACE_VECTOR(vertexShader->output.oPos);
1654 TRACE_VECTOR(vertexShader->output.oD[0]);
1655 TRACE_VECTOR(vertexShader->output.oD[1]);
1656 TRACE_VECTOR(vertexShader->output.oT[0]);
1657 TRACE_VECTOR(vertexShader->output.oT[1]);
1658 TRACE_VECTOR(vertexShader->input.V[0]);
1659 TRACE_VECTOR(vertexShader->data->C[0]);
1660 TRACE_VECTOR(vertexShader->data->C[1]);
1661 TRACE_VECTOR(vertexShader->data->C[2]);
1662 TRACE_VECTOR(vertexShader->data->C[3]);
1663 TRACE_VECTOR(vertexShader->data->C[4]);
1664 TRACE_VECTOR(vertexShader->data->C[5]);
1665 TRACE_VECTOR(vertexShader->data->C[6]);
1666 TRACE_VECTOR(vertexShader->data->C[7]);
1669 /* Extract out the output */
1670 /* FIXME: Fog coords? */
1671 x = vertexShader->output.oPos.x;
1672 y = vertexShader->output.oPos.y;
1673 z = vertexShader->output.oPos.z;
1674 rhw = vertexShader->output.oPos.w;
1675 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1677 /** Update textures coords using vertexShader->output.oT[0->7] */
1678 memset(texcoords, 0x00, sizeof(texcoords));
1679 memset(numcoords, 0x00, sizeof(numcoords));
1680 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1681 if (This->stateBlock->textures[textureNo] != NULL) {
1682 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1683 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1684 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1685 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1686 if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1687 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1688 } else {
1689 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1690 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1691 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1692 default: numcoords[textureNo] = 4;
1695 } else {
1696 numcoords[textureNo] = 0;
1700 /* Draw using this information */
1701 draw_vertex(iface,
1702 TRUE, x, y, z, rhw,
1703 TRUE, 0.0f, 0.0f, 1.0f,
1704 TRUE, (float*) &vertexShader->output.oD[0],
1705 TRUE, (float*) &vertexShader->output.oD[1],
1706 FALSE, ptSize, /* FIXME: Change back when supported */
1707 texcoords, numcoords);
1709 /* For non indexed mode, step onto next parts */
1710 if (idxData == NULL) {
1711 ++SkipnStrides;
1714 } /* for each vertex */
1716 glEnd();
1717 checkGLcall("glEnd and previous calls");
1720 #endif
1722 inline static void drawPrimitiveDrawStrided(
1723 IWineD3DDevice *iface,
1724 BOOL useVertexShaderFunction,
1725 BOOL usePixelShaderFunction,
1726 WineDirect3DVertexStridedData *dataLocations,
1727 UINT numberOfvertices,
1728 UINT numberOfIndicies,
1729 GLenum glPrimType,
1730 const void *idxData,
1731 short idxSize,
1732 int minIndex,
1733 long StartIdx,
1734 BOOL fixup) {
1736 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1737 BOOL useDrawStridedSlow;
1739 int startStride = idxData == NULL ? 0 :
1740 idxData == (void *) -1 ? 0 :
1741 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1742 int endStride = startStride;
1743 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1744 startStride, endStride, numberOfIndicies, numberOfvertices);
1746 /* Generate some fixme's if unsupported functionality is being used */
1747 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1748 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1749 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1750 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1752 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1753 FIXME("Tweening is only valid with vertex shaders\n");
1755 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1756 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1758 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1759 FIXME("Extended attributes are only valid with vertex shaders\n");
1761 #undef BUFFER_OR_DATA
1763 /* Fixed pipeline, no fixups required - load arrays */
1764 if (!useVertexShaderFunction &&
1765 ((dataLocations->u.s.pSize.lpData == NULL &&
1766 dataLocations->u.s.diffuse.lpData == NULL &&
1767 dataLocations->u.s.specular.lpData == NULL) ||
1768 fixup) ) {
1770 /* Load the vertex data using named arrays */
1771 TRACE("(%p) Loading vertex data\n", This);
1772 loadVertexData(iface, dataLocations);
1773 useDrawStridedSlow = FALSE;
1775 /* Shader pipeline - load attribute arrays */
1776 } else if(useVertexShaderFunction) {
1778 loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1779 useDrawStridedSlow = FALSE;
1781 /* We compile the shader here because we need the vertex declaration
1782 * in order to determine if we need to do any swizzling for D3DCOLOR
1783 * registers. If the shader is already compiled this call will do nothing. */
1784 IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1785 /* Draw vertex by vertex */
1786 } else {
1787 TRACE("Not loading vertex data\n");
1788 useDrawStridedSlow = TRUE;
1791 if(usePixelShaderFunction) {
1792 /* We compile the shader here because it depends on the texture stage state
1793 * setup of the bound textures. If the shader is already compiled and the texture stage
1794 * state setup matches the program this function will do nothing
1796 IWineD3DPixelShader_CompileShader(This->stateBlock->pixelShader);
1798 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1799 * Otherwise set NULL, to restore fixed function */
1800 if ((This->vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1801 (This->ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1802 set_glsl_shader_program(iface);
1803 else
1804 This->stateBlock->glsl_program = NULL;
1806 /* If GLSL is used now, or might have been used before, (re)set the program */
1807 if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL) {
1809 GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
1810 if (progId)
1811 TRACE_(d3d_shader)("Using GLSL program %u\n", progId);
1812 GL_EXTCALL(glUseProgramObjectARB(progId));
1813 checkGLcall("glUseProgramObjectARB");
1816 if (useVertexShaderFunction) {
1818 TRACE("Using vertex shader\n");
1820 if (This->vs_selected_mode == SHADER_ARB) {
1821 /* Bind the vertex program */
1822 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1823 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1824 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1826 /* Enable OpenGL vertex programs */
1827 glEnable(GL_VERTEX_PROGRAM_ARB);
1828 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1829 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1830 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1834 if (usePixelShaderFunction) {
1836 TRACE("Using pixel shader\n");
1838 if (This->ps_selected_mode == SHADER_ARB) {
1839 /* Bind the fragment program */
1840 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1841 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1842 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1844 /* Enable OpenGL fragment programs */
1845 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1846 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1847 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1848 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1852 /* Load any global constants/uniforms that may have been set by the application */
1853 if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL)
1854 shader_glsl_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1855 else if (This->vs_selected_mode == SHADER_ARB || This->ps_selected_mode == SHADER_ARB)
1856 shader_arb_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1858 /* Draw vertex-by-vertex */
1859 if (useDrawStridedSlow)
1860 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1861 else
1862 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1864 /* Cleanup vertex program */
1865 if (useVertexShaderFunction) {
1866 unloadNumberedArrays(iface);
1868 if (This->vs_selected_mode == SHADER_ARB)
1869 glDisable(GL_VERTEX_PROGRAM_ARB);
1870 } else {
1871 unloadVertexData(iface);
1874 /* Cleanup fragment program */
1875 if (usePixelShaderFunction && This->ps_selected_mode == SHADER_ARB)
1876 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1879 inline void drawPrimitiveTraceDataLocations(
1880 WineDirect3DVertexStridedData *dataLocations) {
1882 /* Dump out what parts we have supplied */
1883 TRACE("Strided Data:\n");
1884 TRACE_STRIDED((dataLocations), position);
1885 TRACE_STRIDED((dataLocations), blendWeights);
1886 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1887 TRACE_STRIDED((dataLocations), normal);
1888 TRACE_STRIDED((dataLocations), pSize);
1889 TRACE_STRIDED((dataLocations), diffuse);
1890 TRACE_STRIDED((dataLocations), specular);
1891 TRACE_STRIDED((dataLocations), texCoords[0]);
1892 TRACE_STRIDED((dataLocations), texCoords[1]);
1893 TRACE_STRIDED((dataLocations), texCoords[2]);
1894 TRACE_STRIDED((dataLocations), texCoords[3]);
1895 TRACE_STRIDED((dataLocations), texCoords[4]);
1896 TRACE_STRIDED((dataLocations), texCoords[5]);
1897 TRACE_STRIDED((dataLocations), texCoords[6]);
1898 TRACE_STRIDED((dataLocations), texCoords[7]);
1899 TRACE_STRIDED((dataLocations), position2);
1900 TRACE_STRIDED((dataLocations), normal2);
1901 TRACE_STRIDED((dataLocations), tangent);
1902 TRACE_STRIDED((dataLocations), binormal);
1903 TRACE_STRIDED((dataLocations), tessFactor);
1904 TRACE_STRIDED((dataLocations), fog);
1905 TRACE_STRIDED((dataLocations), depth);
1906 TRACE_STRIDED((dataLocations), sample);
1908 return;
1912 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1913 INT i;
1915 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1916 /* Pixel shader support should imply multitexture support. */
1917 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1918 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1919 checkGLcall("glActiveTextureARB");
1920 } else if (i) {
1921 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1924 if (!This->stateBlock->textures[i]) continue;
1926 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1927 glDisable(GL_TEXTURE_1D);
1928 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1929 switch(This->stateBlock->textureDimensions[i]) {
1930 case GL_TEXTURE_2D:
1931 glDisable(GL_TEXTURE_3D);
1932 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1933 break;
1934 case GL_TEXTURE_3D:
1935 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1936 glDisable(GL_TEXTURE_2D);
1937 break;
1938 case GLTEXTURECUBEMAP:
1939 glDisable(GL_TEXTURE_2D);
1940 glDisable(GL_TEXTURE_3D);
1941 break;
1943 glEnable(This->stateBlock->textureDimensions[i]);
1945 /* Upload texture, apply states */
1946 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1947 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1948 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1952 /* uploads textures and setup texture states ready for rendering */
1953 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1954 INT current_sampler = 0;
1955 float constant_color[4];
1956 unsigned int i;
1958 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1959 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1960 * Register combiners however provide up to 8 combiner stages. In order to
1961 * take advantage of this, we need to be separate D3D texture stages from
1962 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1963 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1964 * corresponds to MaxTextureBlendStages in the caps. */
1966 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1967 glEnable(GL_REGISTER_COMBINERS_NV);
1968 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1969 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1972 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
1973 INT texture_idx = -1;
1975 /* WINED3DTOP_DISABLE disables the current & any higher texture stages */
1976 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) break;
1978 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
1979 texture_idx = current_sampler++;
1981 /* Active the texture unit corresponding to the current texture stage */
1982 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1983 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1984 checkGLcall("glActiveTextureARB");
1985 } else if (i) {
1986 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1990 if (This->stateBlock->textures[i]) {
1991 /* Enable the correct target. */
1992 glDisable(GL_TEXTURE_1D);
1993 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1994 switch(This->stateBlock->textureDimensions[i]) {
1995 case GL_TEXTURE_2D:
1996 glDisable(GL_TEXTURE_3D);
1997 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1998 break;
1999 case GL_TEXTURE_3D:
2000 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2001 glDisable(GL_TEXTURE_2D);
2002 break;
2003 case GLTEXTURECUBEMAP:
2004 glDisable(GL_TEXTURE_2D);
2005 glDisable(GL_TEXTURE_3D);
2006 break;
2009 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2010 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
2011 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2012 } else {
2013 glEnable(This->stateBlock->textureDimensions[i]);
2016 /* Upload texture, apply states */
2017 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2018 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
2019 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2020 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2021 /* ARB_texture_env_combine needs a valid texture bound to the
2022 * texture unit, even if it isn't used. Bind a dummy texture. */
2023 glDisable(GL_TEXTURE_2D);
2024 glDisable(GL_TEXTURE_3D);
2025 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2026 glEnable(GL_TEXTURE_1D);
2027 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2028 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2031 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2032 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2033 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2034 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2035 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2036 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2037 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
2038 texture_idx);
2039 /* alphaop */
2040 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2041 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2042 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2043 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2044 texture_idx);
2045 } else {
2046 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2047 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2048 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2049 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2050 /* alphaop */
2051 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2052 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2053 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2054 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2058 /* If we're using register combiners, set the amount of *used* combiners.
2059 * Ie, the number of stages below the first stage to have a color op of
2060 * WINED3DTOP_DISABLE. */
2061 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2062 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2063 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2064 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2067 /* Disable the remaining texture units. */
2068 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2069 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2070 glDisable(GL_TEXTURE_1D);
2071 glDisable(GL_TEXTURE_2D);
2072 glDisable(GL_TEXTURE_3D);
2073 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2077 /* Routine common to the draw primitive and draw indexed primitive routines */
2078 void drawPrimitive(IWineD3DDevice *iface,
2079 int PrimitiveType,
2080 long NumPrimitives,
2081 /* for Indexed: */
2082 long StartVertexIndex,
2083 UINT numberOfVertices,
2084 long StartIdx,
2085 short idxSize,
2086 const void *idxData,
2087 int minIndex,
2088 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2090 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2091 BOOL useVertexShaderFunction = FALSE;
2092 BOOL usePixelShaderFunction = FALSE;
2093 WineDirect3DVertexStridedData *dataLocations;
2094 IWineD3DSwapChainImpl *swapchain;
2095 int i;
2096 BOOL fixup = FALSE;
2098 BOOL lighting_changed, lighting_original = FALSE;
2100 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2101 * here simply check whether a shader was set, or the user disabled shaders */
2102 if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2103 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2104 useVertexShaderFunction = TRUE;
2106 if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2107 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2108 usePixelShaderFunction = TRUE;
2110 /* Invalidate the back buffer memory so LockRect will read it the next time */
2111 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2112 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2113 if(swapchain) {
2114 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2115 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2119 /* Ok, we will be updating the screen from here onwards so grab the lock */
2120 ENTER_GL();
2122 if(DrawPrimStrideData) {
2124 /* Note: this is a ddraw fixed-function code path */
2126 TRACE("================ Strided Input ===================\n");
2127 dataLocations = DrawPrimStrideData;
2128 drawPrimitiveTraceDataLocations(dataLocations);
2129 fixup = FALSE;
2132 else if (This->stateBlock->vertexDecl || This->stateBlock->vertexShader) {
2134 /* Note: This is a fixed function or shader codepath.
2135 * This means it must handle both types of strided data.
2136 * Shaders must go through here to zero the strided data, even if they
2137 * don't set any declaration at all */
2139 TRACE("================ Vertex Declaration ===================\n");
2140 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2141 if(!dataLocations) {
2142 ERR("Out of memory!\n");
2143 return;
2146 if (This->stateBlock->vertexDecl != NULL ||
2147 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)
2149 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction,
2150 dataLocations, StartVertexIndex, &fixup);
2152 } else {
2154 /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
2155 * It is reachable through d3d8, but only for fixed-function.
2156 * It will not work properly for shaders. */
2158 TRACE("================ FVF ===================\n");
2159 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2160 if(!dataLocations) {
2161 ERR("Out of memory!\n");
2162 return;
2164 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2165 drawPrimitiveTraceDataLocations(dataLocations);
2168 /* Setup transform matrices and sort out */
2169 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2171 /* Now initialize the materials state */
2172 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2174 if (usePixelShaderFunction) {
2175 drawPrimitiveUploadTexturesPS(This);
2176 } else {
2177 drawPrimitiveUploadTextures(This);
2181 GLenum glPrimType;
2182 /* Ok, Work out which primitive is requested and how many vertexes that
2183 will be */
2184 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2185 if (numberOfVertices == 0 )
2186 numberOfVertices = calculatedNumberOfindices;
2188 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2189 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2190 idxData, idxSize, minIndex, StartIdx, fixup);
2193 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2195 /* If vertex shaders or no normals, restore previous lighting state */
2196 if (lighting_changed) {
2197 if (lighting_original) glEnable(GL_LIGHTING);
2198 else glDisable(GL_LIGHTING);
2199 TRACE("Restored lighting to original state\n");
2202 /* Finshed updating the screen, restore lock */
2203 LEAVE_GL();
2204 TRACE("Done all gl drawing\n");
2206 /* Diagnostics */
2207 #ifdef SHOW_FRAME_MAKEUP
2209 static long int primCounter = 0;
2210 /* NOTE: set primCounter to the value reported by drawprim
2211 before you want to to write frame makeup to /tmp */
2212 if (primCounter >= 0) {
2213 WINED3DLOCKED_RECT r;
2214 char buffer[80];
2215 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2216 sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
2217 TRACE("Saving screenshot %s\n", buffer);
2218 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2219 IWineD3DSurface_UnlockRect(This->renderTarget);
2221 #ifdef SHOW_TEXTURE_MAKEUP
2223 IWineD3DSurface *pSur;
2224 int textureNo;
2225 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2226 if (This->stateBlock->textures[textureNo] != NULL) {
2227 sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2228 TRACE("Saving texture %s\n", buffer);
2229 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2230 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2231 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2232 IWineD3DSurface_Release(pSur);
2233 } else {
2234 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2239 #endif
2241 TRACE("drawprim #%d\n", primCounter);
2242 ++primCounter;
2244 #endif