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
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
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 */
41 /* Issues the glBegin call for gl given the primitive type and count */
42 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
46 DWORD NumVertexes = NumPrimitives;
48 switch (PrimitiveType) {
51 *primType = GL_POINTS;
52 NumVertexes = NumPrimitives;
58 NumVertexes = NumPrimitives * 2;
62 TRACE("LINE_STRIP\n");
63 *primType = GL_LINE_STRIP;
64 NumVertexes = NumPrimitives + 1;
67 case D3DPT_TRIANGLELIST:
69 *primType = GL_TRIANGLES;
70 NumVertexes = NumPrimitives * 3;
73 case D3DPT_TRIANGLESTRIP:
74 TRACE("TRIANGLE_STRIP\n");
75 *primType = GL_TRIANGLE_STRIP;
76 NumVertexes = NumPrimitives + 2;
79 case D3DPT_TRIANGLEFAN:
80 TRACE("TRIANGLE_FAN\n");
81 *primType = GL_TRIANGLE_FAN;
82 NumVertexes = NumPrimitives + 2;
86 FIXME("Unhandled primitive\n");
87 *primType = GL_POINTS;
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 == FALSE) ||
113 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
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");
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
168 glMatrixMode(GL_MODELVIEW);
169 checkGLcall("glMatrixMode(GL_MODELVIEW)");
171 checkGLcall("glLoadIdentity");
173 glMatrixMode(GL_PROJECTION);
174 checkGLcall("glMatrixMode(GL_PROJECTION)");
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 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
186 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
187 checkGLcall("glOrtho");
189 /* Window Coord 0 is the middle of the first pixel, so translate by half
190 a pixel (See comment above glTranslate below) */
191 glTranslatef(0.375, 0.375, 0);
192 checkGLcall("glTranslatef(0.375, 0.375, 0)");
193 if (This->renderUpsideDown) {
194 glMultMatrixf(invymat);
195 checkGLcall("glMultMatrixf(invymat)");
198 /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
199 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
200 if(GL_SUPPORT(EXT_FOG_COORD)) {
201 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
202 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
203 glFogi(GL_FOG_MODE, GL_LINEAR);
204 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
205 /* The dx fog range in this case is fixed to 0 - 255,
206 * but in GL it still depends on the fog start and end (according to the ext)
207 * Use this to turn around the fog as it's needed. That prevents some
208 * calculations during drawing :-)
210 glFogf(GL_FOG_START, (float) 0xff);
211 checkGLcall("glFogfv GL_FOG_END");
212 glFogf(GL_FOG_END, 0.0);
213 checkGLcall("glFogfv GL_FOG_START");
215 /* Disable GL fog, handle this in software in drawStridedSlow */
217 checkGLcall("glDisable(GL_FOG)");
222 /* Setup views - Transformed & lit if RHW, else untransformed.
223 Only unlit if Normals are supplied
224 Returns: Whether to restore lighting afterwards */
225 static void primitiveInitState(
226 IWineD3DDevice *iface,
227 WineDirect3DVertexStridedData* strided,
229 BOOL* lighting_changed,
230 BOOL* lighting_original) {
232 BOOL fixed_vtx_transformed =
233 (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
234 strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) &&
235 strided->u.s.position_transformed;
238 strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
239 strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
243 *lighting_changed = FALSE;
245 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
246 set by the appropriate render state. Note Vertex Shader output is already lit */
247 if (fixed_vtx_lit || useVS) {
248 *lighting_changed = TRUE;
249 *lighting_original = glIsEnabled(GL_LIGHTING);
250 glDisable(GL_LIGHTING);
251 checkGLcall("glDisable(GL_LIGHTING);");
252 TRACE("Disabled lighting, old state = %d\n", *lighting_original);
255 if (!useVS && fixed_vtx_transformed) {
256 d3ddevice_set_ortho(This);
260 /* Untransformed, so relies on the view and projection matrices */
262 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
263 /* Only reapply when have to */
264 This->modelview_valid = TRUE;
265 glMatrixMode(GL_MODELVIEW);
266 checkGLcall("glMatrixMode");
268 /* In the general case, the view matrix is the identity matrix */
269 if (This->view_ident) {
270 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
271 checkGLcall("glLoadMatrixf");
273 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
274 checkGLcall("glLoadMatrixf");
275 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
276 checkGLcall("glMultMatrixf");
280 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
281 /* Only reapply when have to */
282 This->proj_valid = TRUE;
283 glMatrixMode(GL_PROJECTION);
284 checkGLcall("glMatrixMode");
286 /* The rule is that the window coordinate 0 does not correspond to the
287 beginning of the first pixel, but the center of the first pixel.
288 As a consequence if you want to correctly draw one line exactly from
289 the left to the right end of the viewport (with all matrices set to
290 be identity), the x coords of both ends of the line would be not
291 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
295 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
296 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
298 if (This->renderUpsideDown) {
299 glMultMatrixf(invymat);
300 checkGLcall("glMultMatrixf(invymat)");
302 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
303 checkGLcall("glLoadMatrixf");
306 /* Vertex Shader output is already transformed, so set up identity matrices */
307 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
308 come along this needs to take into account whether s/w ones were
311 glMatrixMode(GL_MODELVIEW);
312 checkGLcall("glMatrixMode");
314 glMatrixMode(GL_PROJECTION);
315 checkGLcall("glMatrixMode");
317 /* Window Coord 0 is the middle of the first pixel, so translate by half
318 a pixel (See comment above glTranslate above) */
319 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
320 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
321 if (This->renderUpsideDown) {
322 glMultMatrixf(invymat);
323 checkGLcall("glMultMatrixf(invymat)");
325 This->modelview_valid = FALSE;
326 This->proj_valid = FALSE;
328 This->last_was_rhw = FALSE;
330 /* Restore fogging */
331 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
332 if(GL_SUPPORT(EXT_FOG_COORD)) {
333 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
334 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)\n");
335 /* Reapply the fog range */
336 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
337 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
338 /* Restore the fog mode */
339 IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
341 /* Enable GL_FOG again because we disabled it above */
343 checkGLcall("glEnable(GL_FOG)");
349 static BOOL fixed_get_input(
350 BYTE usage, BYTE usage_idx,
351 unsigned int* regnum) {
355 /* Those positions must have the order in the
356 * named part of the strided data */
358 if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
360 else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
362 else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
364 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
366 else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
368 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
370 else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
372 else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < D3DDP_MAXTEXCOORD)
373 *regnum = 7 + usage_idx;
374 else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
375 *regnum = 7 + D3DDP_MAXTEXCOORD;
376 else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
377 *regnum = 8 + D3DDP_MAXTEXCOORD;
378 else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
379 *regnum = 9 + D3DDP_MAXTEXCOORD;
380 else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
381 *regnum = 10 + D3DDP_MAXTEXCOORD;
382 else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
383 *regnum = 11 + D3DDP_MAXTEXCOORD;
384 else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
385 *regnum = 12 + D3DDP_MAXTEXCOORD;
386 else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
387 *regnum = 13 + D3DDP_MAXTEXCOORD;
388 else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
389 *regnum = 14 + D3DDP_MAXTEXCOORD;
392 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
393 debug_d3ddeclusage(usage), usage_idx);
399 void primitiveDeclarationConvertToStridedData(
400 IWineD3DDevice *iface,
401 BOOL useVertexShaderFunction,
402 WineDirect3DVertexStridedData *strided,
403 LONG BaseVertexIndex,
406 /* We need to deal with frequency data!*/
409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
410 IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
412 WINED3DVERTEXELEMENT *element;
416 /* Locate the vertex declaration */
417 if (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
418 TRACE("Using vertex declaration from shader\n");
419 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
421 TRACE("Using vertex declaration\n");
422 vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
425 /* Translate the declaration into strided data */
426 for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
431 element = vertexDeclaration->pDeclarationWine + i;
432 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclarationWine, element, i, vertexDeclaration->declarationWNumElements);
433 if (This->stateBlock->streamIsUP) {
434 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
436 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
437 if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
439 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
440 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
441 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
443 if( streamVBO != 0) *fixup = TRUE;
444 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
447 stride = This->stateBlock->streamStride[element->Stream];
448 data += (BaseVertexIndex * stride);
449 data += element->Offset;
452 TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
454 if (useVertexShaderFunction && reg != -1 && (data || streamVBO) ) {
455 WINED3DGLTYPE glType = glTypeLookup[element->Type];
457 TRACE("(%p) : Set vertex attrib pointer: reg 0x%08x, d3d type 0x%08x, stride 0x%08lx, data %p)\n", This, reg, element->Type, stride, data);
459 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, streamVBO));
460 checkGLcall("glBindBufferARB");
461 GL_EXTCALL(glVertexAttribPointerARB(reg, glType.size, glType.glType, glType.normalized, stride, data));
462 checkGLcall("glVertexAttribPointerARB");
463 GL_EXTCALL(glEnableVertexAttribArrayARB(reg));
464 checkGLcall("glEnableVertexAttribArrayARB");
467 stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
469 TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
470 "stream=%u, offset=%u, stride=%lu, VBO=%u]\n",
471 useVertexShaderFunction? "shader": "fixed function", idx,
472 debug_d3ddeclusage(element->Usage), element->UsageIndex,
473 element->Stream, element->Offset, stride, streamVBO);
475 strided->u.input[idx].lpData = data;
476 strided->u.input[idx].dwType = element->Type;
477 strided->u.input[idx].dwStride = stride;
478 strided->u.input[idx].VBO = streamVBO;
479 if (element->Usage == D3DDECLUSAGE_POSITION)
480 strided->u.s.position_transformed = FALSE;
481 else if (element->Usage == D3DDECLUSAGE_POSITIONT)
482 strided->u.s.position_transformed = TRUE;
487 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
491 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
492 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
494 /* Either 3 or 4 floats depending on the FVF */
495 /* FIXME: Can blending data be in a different stream to the position data?
496 and if so using the fixed pipeline how do we handle it */
497 if (thisFVF & D3DFVF_POSITION_MASK) {
498 strided->u.s.position.lpData = data;
499 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
500 strided->u.s.position.dwStride = stride;
501 strided->u.s.position.VBO = streamVBO;
502 data += 3 * sizeof(float);
503 if (thisFVF & D3DFVF_XYZRHW) {
504 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
505 strided->u.s.position_transformed = TRUE;
506 data += sizeof(float);
508 strided->u.s.position_transformed = FALSE;
511 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
512 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
513 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
514 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
516 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
517 TRACE("Setting blend Weights to %p\n", data);
518 strided->u.s.blendWeights.lpData = data;
519 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
520 strided->u.s.blendWeights.dwStride = stride;
521 strided->u.s.blendWeights.VBO = streamVBO;
522 data += numBlends * sizeof(FLOAT);
524 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
525 strided->u.s.blendMatrixIndices.lpData = data;
526 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
527 strided->u.s.blendMatrixIndices.dwStride= stride;
528 strided->u.s.blendMatrixIndices.VBO = streamVBO;
529 data += sizeof(DWORD);
533 /* Normal is always 3 floats */
534 if (thisFVF & D3DFVF_NORMAL) {
535 strided->u.s.normal.lpData = data;
536 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
537 strided->u.s.normal.dwStride = stride;
538 strided->u.s.normal.VBO = streamVBO;
539 data += 3 * sizeof(FLOAT);
542 /* Pointsize is a single float */
543 if (thisFVF & D3DFVF_PSIZE) {
544 strided->u.s.pSize.lpData = data;
545 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
546 strided->u.s.pSize.dwStride = stride;
547 strided->u.s.pSize.VBO = streamVBO;
548 data += sizeof(FLOAT);
551 /* Diffuse is 4 unsigned bytes */
552 if (thisFVF & D3DFVF_DIFFUSE) {
553 strided->u.s.diffuse.lpData = data;
554 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
555 strided->u.s.diffuse.dwStride = stride;
556 strided->u.s.diffuse.VBO = streamVBO;
557 data += sizeof(DWORD);
560 /* Specular is 4 unsigned bytes */
561 if (thisFVF & D3DFVF_SPECULAR) {
562 strided->u.s.specular.lpData = data;
563 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
564 strided->u.s.specular.dwStride = stride;
565 strided->u.s.specular.VBO = streamVBO;
566 data += sizeof(DWORD);
570 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
571 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
573 /* numTextures indicates the number of texture coordinates supplied */
574 /* However, the first set may not be for stage 0 texture - it all */
575 /* depends on D3DTSS_TEXCOORDINDEX. */
576 /* The number of bytes for each coordinate set is based off */
577 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
579 /* So, for each supplied texture extract the coords */
580 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
582 strided->u.s.texCoords[textureNo].lpData = data;
583 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
584 strided->u.s.texCoords[textureNo].dwStride = stride;
585 strided->u.s.texCoords[textureNo].VBO = streamVBO;
586 numCoords[textureNo] = coordIdxInfo & 0x03;
589 data += sizeof(float);
590 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
591 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
592 data += sizeof(float);
593 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
594 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
595 data += sizeof(float);
596 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
597 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
598 data += sizeof(float);
602 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
606 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, LONG BaseVertexIndex, BOOL *fixup) {
608 short LoopThroughTo = 0;
612 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
614 /* OK, Now to setup the data locations
615 For the non-created vertex shaders, the VertexShader var holds the real
616 FVF and only stream 0 matters
617 For the created vertex shaders, there is an FVF per stream */
618 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
619 LoopThroughTo = MAX_STREAMS;
624 /* Work through stream by stream */
625 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
626 DWORD stride = This->stateBlock->streamStride[nStream];
630 /* Skip empty streams */
631 if (This->stateBlock->streamSource[nStream] == NULL) continue;
633 /* Retrieve appropriate FVF */
634 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
635 thisFVF = This->stateBlock->fvf;
636 /* Handle memory passed directly as well as vertex buffers */
637 if (This->stateBlock->streamIsUP) {
639 data = (BYTE *)This->stateBlock->streamSource[nStream];
641 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
642 /* GetMemory binds the VBO */
643 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
645 if(streamVBO != 0 ) *fixup = TRUE;
649 #if 0 /* TODO: Vertex shader support */
650 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
651 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
654 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
655 if (thisFVF == 0) continue;
657 /* Now convert the stream into pointers */
659 /* Shuffle to the beginning of the vertexes to render and index from there */
660 data = data + (BaseVertexIndex * stride);
662 primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
666 #if 0 /* TODO: Software Shaders */
667 /* Draw a single vertex using this information */
668 static void draw_vertex(IWineD3DDevice *iface, /* interface */
669 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
670 BOOL isNormal, float nx, float ny, float nz, /* normal */
671 BOOL isDiffuse, float *dRGBA, /* 1st colors */
672 BOOL isSpecular, float *sRGB, /* 2ndry colors */
673 BOOL isPtSize, float ptSize, /* pointSize */
674 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
676 unsigned int textureNo;
678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
680 /* Diffuse -------------------------------- */
683 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
686 /* Specular Colour ------------------------------------------*/
688 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
689 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
690 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
692 VTRACE(("Specular color extensions not supplied\n"));
696 /* Normal -------------------------------- */
698 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
699 glNormal3f(nx, ny, nz);
702 /* Point Size ----------------------------------------------*/
705 /* no such functionality in the fixed function GL pipeline */
706 FIXME("Cannot change ptSize here in openGl\n");
709 /* Texture coords --------------------------- */
710 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
712 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
713 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
717 /* Query tex coords */
718 if (This->stateBlock->textures[textureNo] != NULL) {
720 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
721 if (coordIdx >= MAX_TEXTURES) {
722 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
724 } else if (numcoords[coordIdx] == 0) {
725 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
729 /* Initialize vars */
735 switch (numcoords[coordIdx]) {
736 case 4: q = texcoords[coordIdx].w; /* drop through */
737 case 3: r = texcoords[coordIdx].z; /* drop through */
738 case 2: t = texcoords[coordIdx].y; /* drop through */
739 case 1: s = texcoords[coordIdx].x;
742 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
744 VTRACE(("tex:%d, s=%f\n", textureNo, s));
745 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
746 GLMULTITEXCOORD1F(textureNo, s);
752 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
753 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
754 GLMULTITEXCOORD2F(textureNo, s, t);
760 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
761 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
762 GLMULTITEXCOORD3F(textureNo, s, t, r);
764 glTexCoord3f(s, t, r);
768 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
769 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
770 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
772 glTexCoord4f(s, t, r, q);
776 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
780 } /* End of textures */
782 /* Position -------------------------------- */
784 if (1.0f == rhw || rhw < 0.00001f) {
785 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
788 /* Cannot optimize by dividing through by rhw as rhw is required
789 later for perspective in the GL pipeline for vertex shaders */
790 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
791 glVertex4f(x,y,z,rhw);
795 #endif /* TODO: Software shaders */
797 void loadNumberedArrays(
798 IWineD3DDevice *iface,
799 WineDirect3DVertexStridedData *sd,
800 DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
805 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
806 if ((sd->u.s._arrayName.lpData != NULL || sd->u.s._arrayName.VBO != 0) && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \
807 unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & D3DSP_REGNUM_MASK; \
808 TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, #_arrayName); \
809 if(curVBO != sd->u.s._arrayName.VBO) { \
810 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s._arrayName.VBO)); \
811 checkGLcall("glBindBufferARB"); \
812 curVBO = sd->u.s._arrayName.VBO; \
814 GL_EXTCALL(glVertexAttribPointerARB(idx, \
815 WINED3D_ATR_SIZE(sd->u.s._arrayName.dwType), \
816 WINED3D_ATR_GLTYPE(sd->u.s._arrayName.dwType), \
817 WINED3D_ATR_NORMALIZED(sd->u.s._arrayName.dwType), \
818 sd->u.s._arrayName.dwStride, \
819 sd->u.s._arrayName.lpData)); \
820 GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
824 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
825 if ((sd->u.s.position2.lpData != NULL || sd->u.s.position2.VBO != 0)&& arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \
826 unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & D3DSP_REGNUM_MASK; \
827 TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, "position2"); \
828 if(curVBO != sd->u.s.position2.VBO) { \
829 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position2.VBO)); \
830 checkGLcall("glBindBufferARB"); \
831 curVBO = sd->u.s.position2.VBO; \
833 GL_EXTCALL(glVertexAttribPointerARB(idx, \
834 WINED3D_ATR_SIZE(sd->u.s.position2.dwType), \
835 WINED3D_ATR_GLTYPE(sd->u.s.position2.dwType), \
836 WINED3D_ATR_NORMALIZED(sd->u.s.position2.dwType), \
837 sd->u.s.position2.dwStride, \
838 ((char *)sd->u.s.position2.lpData) + \
839 WINED3D_ATR_SIZE(sd->u.s.position2.dwType) * \
840 WINED3D_ATR_TYPESIZE(sd->u.s.position2.dwType) * _lookupNumber)); \
841 GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
844 /* Generate some lookup tables */
845 /* drop the RHW coord, there must be a nicer way of doing this. */
846 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
847 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position2.dwType);
849 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
850 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
851 LOAD_NUMBERED_ARRAY(position,POSITION);
852 LOAD_NUMBERED_ARRAY(normal,NORMAL);
853 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
854 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
855 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
856 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
857 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
858 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
859 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
860 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
861 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
862 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
863 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
864 #if 0 /* TODO: Samplers may allow for more texture coords */
865 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
866 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
867 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
868 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
869 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
870 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
871 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
872 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
874 LOAD_NUMBERED_ARRAY(position,POSITIONT);
876 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
877 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
878 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
879 LOAD_NUMBERED_ARRAY(position2,POSITION2);
880 /* there can be lots of position arrays */
881 LOAD_NUMBERED_POSITION_ARRAY(0);
882 LOAD_NUMBERED_POSITION_ARRAY(1);
883 LOAD_NUMBERED_POSITION_ARRAY(2);
884 LOAD_NUMBERED_POSITION_ARRAY(3);
885 LOAD_NUMBERED_POSITION_ARRAY(4);
886 LOAD_NUMBERED_POSITION_ARRAY(5);
887 LOAD_NUMBERED_POSITION_ARRAY(6);
888 LOAD_NUMBERED_POSITION_ARRAY(7);
889 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
890 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
891 LOAD_NUMBERED_ARRAY(fog,FOG);
892 LOAD_NUMBERED_ARRAY(depth,DEPTH);
893 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
895 #undef LOAD_NUMBERED_ARRAY
898 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
899 unsigned int textureNo = 0;
900 unsigned int texture_idx = 0;
901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
904 TRACE("Using fast vertex array code\n");
905 /* Blend Data ---------------------------------------------- */
906 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
907 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
910 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
913 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
914 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
917 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
918 sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
919 /* FIXME("TODO\n");*/
920 /* Note dwType == float3 or float4 == 2 or 3 */
923 /* with this on, the normals appear to be being modified,
924 but the vertices aren't being translated as they should be
925 Maybe the world matrix aren't being setup properly? */
926 glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
930 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %ld, %p)\n",
931 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
932 sd->u.s.blendWeights.dwStride,
933 sd->u.s.blendWeights.lpData));
935 if(curVBO != sd->u.s.blendWeights.VBO) {
936 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
937 checkGLcall("glBindBufferARB");
938 curVBO = sd->u.s.blendWeights.VBO;
941 GL_EXTCALL(glWeightPointerARB)(
942 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
943 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
944 sd->u.s.blendWeights.dwStride,
945 sd->u.s.blendWeights.lpData);
947 checkGLcall("glWeightPointerARB");
949 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
950 static BOOL showfixme = TRUE;
952 FIXME("blendMatrixIndices support\n");
957 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
958 /* FIXME("TODO\n");*/
961 GL_EXTCALL(glVertexWeightPointerEXT)(
962 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
963 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
964 sd->u.s.blendWeights.dwStride,
965 sd->u.s.blendWeights.lpData);
966 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
967 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
968 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
972 /* TODO: support blends in fixupVertices */
973 FIXME("unsupported blending in openGl\n");
976 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
977 #if 0 /* TODO: Vertex blending */
978 glDisable(GL_VERTEX_BLEND_ARB);
980 TRACE("ARB_VERTEX_BLEND\n");
981 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
982 TRACE(" EXT_VERTEX_WEIGHTING\n");
983 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
984 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
989 #if 0 /* FOG ----------------------------------------------*/
990 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
992 if (GL_SUPPORT(EXT_FOG_COORD) {
993 glEnableClientState(GL_FOG_COORDINATE_EXT);
994 (GL_EXTCALL)(FogCoordPointerEXT)(
995 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
996 sd->u.s.fog.dwStride,
999 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
1000 /* FIXME: fixme once */
1001 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
1004 if (GL_SUPPRT(EXT_FOR_COORD) {
1005 /* make sure fog is disabled */
1006 glDisableClientState(GL_FOG_COORDINATE_EXT);
1011 #if 0 /* tangents ----------------------------------------------*/
1012 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
1013 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
1015 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1016 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
1017 glEnable(GL_TANGENT_ARRAY_EXT);
1018 (GL_EXTCALL)(TangentPointerEXT)(
1019 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
1020 sd->u.s.tangent.dwStride,
1021 sd->u.s.tangent.lpData);
1023 glDisable(GL_TANGENT_ARRAY_EXT);
1025 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
1026 glEnable(GL_BINORMAL_ARRAY_EXT);
1027 (GL_EXTCALL)(BinormalPointerEXT)(
1028 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
1029 sd->u.s.binormal.dwStride,
1030 sd->u.s.binormal.lpData);
1032 glDisable(GL_BINORMAL_ARRAY_EXT);
1036 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
1037 /* FIXME: fixme once */
1038 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
1041 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
1042 /* make sure fog is disabled */
1043 glDisable(GL_TANGENT_ARRAY_EXT);
1044 glDisable(GL_BINORMAL_ARRAY_EXT);
1049 /* Point Size ----------------------------------------------*/
1050 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
1052 /* no such functionality in the fixed function GL pipeline */
1053 TRACE("Cannot change ptSize here in openGl\n");
1054 /* TODO: Implement this function in using shaders if they are available */
1058 /* Vertex Pointers -----------------------------------------*/
1059 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
1060 /* Note dwType == float3 or float4 == 2 or 3 */
1061 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1062 sd->u.s.position.dwStride,
1063 sd->u.s.position.dwType + 1,
1064 sd->u.s.position.lpData));
1066 if(curVBO != sd->u.s.position.VBO) {
1067 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
1068 checkGLcall("glBindBufferARB");
1069 curVBO = sd->u.s.position.VBO;
1072 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1073 handling for rhw mode should not impact screen position whereas in GL it does.
1074 This may result in very slightly distored textures in rhw mode, but
1075 a very minimal different. There's always the other option of
1076 fixing the view matrix to prevent w from having any effect
1078 This only applies to user pointer sources, in VBOs the vertices are fixed up
1080 if(sd->u.s.position.VBO == 0) {
1081 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
1082 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1083 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1086 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
1087 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
1088 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1090 checkGLcall("glVertexPointer(...)");
1091 glEnableClientState(GL_VERTEX_ARRAY);
1092 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1095 glDisableClientState(GL_VERTEX_ARRAY);
1096 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1099 /* Normals -------------------------------------------------*/
1100 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
1101 /* Note dwType == float3 or float4 == 2 or 3 */
1102 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1103 sd->u.s.normal.dwStride,
1104 sd->u.s.normal.lpData));
1105 if(curVBO != sd->u.s.normal.VBO) {
1106 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
1107 checkGLcall("glBindBufferARB");
1108 curVBO = sd->u.s.normal.VBO;
1111 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
1112 sd->u.s.normal.dwStride,
1113 sd->u.s.normal.lpData);
1114 checkGLcall("glNormalPointer(...)");
1115 glEnableClientState(GL_NORMAL_ARRAY);
1116 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1119 glDisableClientState(GL_NORMAL_ARRAY);
1120 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1121 glNormal3f(0, 0, 1);
1122 checkGLcall("glNormal3f(0, 0, 1)");
1125 /* Diffuse Colour --------------------------------------------*/
1126 /* WARNING: Data here MUST be in RGBA format, so cannot */
1127 /* go directly into fast mode from app pgm, because */
1128 /* directx requires data in BGRA format. */
1129 /* currently fixupVertices swizels the format, but this isn't */
1130 /* very practical when using VBOS */
1131 /* NOTE: Unless we write a vertex shader to swizel the colour */
1132 /* , or the user doesn't care and wants the speed advantage */
1134 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
1135 /* Note dwType == float3 or float4 == 2 or 3 */
1136 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1137 sd->u.s.diffuse.dwStride,
1138 sd->u.s.diffuse.lpData));
1140 if(curVBO != sd->u.s.diffuse.VBO) {
1141 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
1142 checkGLcall("glBindBufferARB");
1143 curVBO = sd->u.s.diffuse.VBO;
1145 glColorPointer(4, GL_UNSIGNED_BYTE,
1146 sd->u.s.diffuse.dwStride,
1147 sd->u.s.diffuse.lpData);
1148 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1149 glEnableClientState(GL_COLOR_ARRAY);
1150 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1153 glDisableClientState(GL_COLOR_ARRAY);
1154 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1155 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1156 checkGLcall("glColor4f(1, 1, 1, 1)");
1159 /* Specular Colour ------------------------------------------*/
1160 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
1161 TRACE("setting specular colour\n");
1162 /* Note dwType == float3 or float4 == 2 or 3 */
1163 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1164 sd->u.s.specular.dwStride,
1165 sd->u.s.specular.lpData));
1166 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1167 if(curVBO != sd->u.s.specular.VBO) {
1168 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
1169 checkGLcall("glBindBufferARB");
1170 curVBO = sd->u.s.specular.VBO;
1172 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1173 sd->u.s.specular.dwStride,
1174 sd->u.s.specular.lpData);
1175 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1176 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1177 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1180 /* Missing specular color is not critical, no warnings */
1181 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1185 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1187 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1188 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1189 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1190 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1193 /* Missing specular color is not critical, no warnings */
1194 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1198 /* Texture coords -------------------------------------------*/
1200 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1201 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1202 /* Abort if we don't support the extension. */
1203 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1204 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1208 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
1209 /* Select the correct texture stage */
1210 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1213 if (This->stateBlock->textures[textureNo] != NULL) {
1214 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1215 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1217 if (coordIdx >= MAX_TEXTURES) {
1218 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1220 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1222 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
1223 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1224 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1225 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
1228 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1229 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1230 checkGLcall("glBindBufferARB");
1231 curVBO = sd->u.s.texCoords[coordIdx].VBO;
1233 /* The coords to supply depend completely on the fvf / vertex shader */
1235 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1236 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1237 sd->u.s.texCoords[coordIdx].dwStride,
1238 sd->u.s.texCoords[coordIdx].lpData);
1239 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1241 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1242 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1243 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1245 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1247 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1248 for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1249 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1250 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1251 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1256 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1257 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1260 if (idxData != NULL /* This crashes sometimes!*/) {
1261 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1262 idxData = idxData == (void *)-1 ? NULL : idxData;
1265 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1266 glEnableClientState(GL_INDEX_ARRAY);
1268 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1269 (const char *)idxData+(idxSize * startIdx));
1270 #else /* using drawRangeElements may be faster */
1272 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1273 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1274 (const char *)idxData+(idxSize * startIdx));
1276 checkGLcall("glDrawRangeElements");
1280 /* Note first is now zero as we shuffled along earlier */
1281 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1282 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1283 checkGLcall("glDrawArrays");
1291 * Actually draw using the supplied information.
1292 * Slower GL version which extracts info about each vertex in turn
1295 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1296 UINT NumVertexes, GLenum glPrimType,
1297 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1299 unsigned int textureNo = 0;
1300 unsigned int texture_idx = 0;
1301 const short *pIdxBufS = NULL;
1302 const long *pIdxBufL = NULL;
1303 LONG SkipnStrides = 0;
1305 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1306 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1307 float rhw = 0.0f; /* rhw */
1308 float ptSize = 0.0f; /* Point size */
1309 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1310 DWORD specularColor = 0; /* Specular Color */
1311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1313 TRACE("Using slow vertex array code\n");
1315 /* Variable Initialization */
1316 if (idxData != NULL) {
1317 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1318 else pIdxBufL = (const long *) idxData;
1321 /* Start drawing in GL */
1322 VTRACE(("glBegin(%x)\n", glPrimType));
1323 glBegin(glPrimType);
1325 /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1326 * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1329 /* For each primitive */
1330 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1332 /* Initialize diffuse color */
1333 diffuseColor = 0xFFFFFFFF;
1335 /* For indexed data, we need to go a few more strides in */
1336 if (idxData != NULL) {
1338 /* Indexed so work out the number of strides to skip */
1340 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1341 SkipnStrides = pIdxBufS[startIdx + vx_index];
1343 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1344 SkipnStrides = pIdxBufL[startIdx + vx_index];
1348 /* Position Information ------------------ */
1349 if (sd->u.s.position.lpData != NULL) {
1351 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1356 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1358 /* RHW follows, only if transformed, ie 4 floats were provided */
1359 if (sd->u.s.position_transformed) {
1360 rhw = ptrToCoords[3];
1361 VTRACE(("rhw=%f\n", rhw));
1365 /* Blending data -------------------------- */
1366 if (sd->u.s.blendWeights.lpData != NULL) {
1367 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1368 FIXME("Blending not supported yet\n");
1370 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1371 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1375 /* Vertex Normal Data (untransformed only)- */
1376 if (sd->u.s.normal.lpData != NULL) {
1378 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1379 nx = ptrToCoords[0];
1380 ny = ptrToCoords[1];
1381 nz = ptrToCoords[2];
1382 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1385 /* Point Size ----------------------------- */
1386 if (sd->u.s.pSize.lpData != NULL) {
1388 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1389 ptSize = ptrToCoords[0];
1390 VTRACE(("ptSize=%f\n", ptSize));
1391 FIXME("No support for ptSize yet\n");
1394 /* Diffuse -------------------------------- */
1395 if (sd->u.s.diffuse.lpData != NULL) {
1397 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1398 diffuseColor = ptrToCoords[0];
1399 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1402 /* Specular -------------------------------- */
1403 if (sd->u.s.specular.lpData != NULL) {
1405 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1406 specularColor = ptrToCoords[0];
1407 VTRACE(("specularColor=%lx\n", specularColor));
1410 /* Texture coords --------------------------- */
1411 for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1413 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1414 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1418 /* Query tex coords */
1419 if (This->stateBlock->textures[textureNo] != NULL) {
1421 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1422 float *ptrToCoords = NULL;
1423 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1426 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1428 } else if (coordIdx < 0) {
1429 FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1433 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1434 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1435 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1439 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1441 /* The coords to supply depend completely on the fvf / vertex shader */
1442 switch (coordsToUse) {
1443 case 4: q = ptrToCoords[3]; /* drop through */
1444 case 3: r = ptrToCoords[2]; /* drop through */
1445 case 2: t = ptrToCoords[1]; /* drop through */
1446 case 1: s = ptrToCoords[0];
1449 /* Projected is more 'fun' - Move the last coord to the 'q'
1450 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1451 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1452 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1454 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1455 switch (coordsToUse) {
1456 case 0: /* Drop Through */
1458 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1470 case 4: /* Nop here */
1473 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1474 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1479 switch (coordsToUse) { /* Supply the provided texture coords */
1480 case D3DTTFF_COUNT1:
1481 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1482 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1483 GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1488 case D3DTTFF_COUNT2:
1489 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1490 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1491 GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1496 case D3DTTFF_COUNT3:
1497 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1498 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1499 GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1501 glTexCoord3f(s, t, r);
1504 case D3DTTFF_COUNT4:
1505 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1506 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1507 GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1509 glTexCoord4f(s, t, r, q);
1513 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1517 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
1518 } /* End of textures */
1520 /* Diffuse -------------------------------- */
1521 if (sd->u.s.diffuse.lpData != NULL) {
1522 glColor4ub(D3DCOLOR_B_R(diffuseColor),
1523 D3DCOLOR_B_G(diffuseColor),
1524 D3DCOLOR_B_B(diffuseColor),
1525 D3DCOLOR_B_A(diffuseColor));
1526 VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n",
1527 D3DCOLOR_B_R(diffuseColor),
1528 D3DCOLOR_B_G(diffuseColor),
1529 D3DCOLOR_B_B(diffuseColor),
1530 D3DCOLOR_B_A(diffuseColor)));
1532 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1535 /* Specular ------------------------------- */
1536 if (sd->u.s.specular.lpData != NULL) {
1537 /* special case where the fog density is stored in the diffuse alpha channel */
1538 if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1539 (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
1540 This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
1541 if(GL_SUPPORT(EXT_FOG_COORD)) {
1542 GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1544 static BOOL warned = FALSE;
1546 /* TODO: Use the fog table code from old ddraw */
1547 FIXME("Implement fog for transformed vertices in software\n");
1553 VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
1554 D3DCOLOR_B_R(specularColor),
1555 D3DCOLOR_B_G(specularColor),
1556 D3DCOLOR_B_B(specularColor)));
1557 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1558 GL_EXTCALL(glSecondaryColor3ubEXT)(
1559 D3DCOLOR_B_R(specularColor),
1560 D3DCOLOR_B_G(specularColor),
1561 D3DCOLOR_B_B(specularColor));
1563 /* Do not worry if specular colour missing and disable request */
1564 VTRACE(("Specular color extensions not supplied\n"));
1567 if (vx_index == 0) {
1568 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1569 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1571 /* Do not worry if specular colour missing and disable request */
1572 VTRACE(("Specular color extensions not supplied\n"));
1577 /* Normal -------------------------------- */
1578 if (sd->u.s.normal.lpData != NULL) {
1579 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1580 glNormal3f(nx, ny, nz);
1582 if (vx_index == 0) glNormal3f(0, 0, 1);
1585 /* Position -------------------------------- */
1586 if (sd->u.s.position.lpData != NULL) {
1587 if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1588 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1589 glVertex3f(x, y, z);
1591 GLfloat w = 1.0 / rhw;
1592 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1593 glVertex4f(x*w, y*w, z*w, w);
1597 /* For non indexed mode, step onto next parts */
1598 if (idxData == NULL) {
1604 checkGLcall("glEnd and previous calls");
1607 #if 0 /* TODO: Software/Hardware vertex blending support */
1609 * Draw with emulated vertex shaders
1610 * Note: strided data is uninitialized, as we need to pass the vertex
1611 * shader directly as ordering irs yet
1613 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1614 int PrimitiveType, ULONG NumPrimitives,
1615 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1617 unsigned int textureNo = 0;
1618 GLenum glPrimType = GL_POINTS;
1619 int NumVertexes = NumPrimitives;
1620 const short *pIdxBufS = NULL;
1621 const long *pIdxBufL = NULL;
1622 LONG SkipnStrides = 0;
1624 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1625 float rhw = 0.0f; /* rhw */
1626 float ptSize = 0.0f; /* Point size */
1627 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1628 int numcoords[8]; /* Number of coords */
1629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1631 IDirect3DVertexShaderImpl* vertexShader = NULL;
1633 TRACE("Using slow software vertex shader code\n");
1635 /* Variable Initialization */
1636 if (idxData != NULL) {
1637 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1638 else pIdxBufL = (const long *) idxData;
1641 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1642 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1644 /* Retrieve the VS information */
1645 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1647 /* Start drawing in GL */
1648 VTRACE(("glBegin(%x)\n", glPrimType));
1649 glBegin(glPrimType);
1651 /* For each primitive */
1652 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1654 /* For indexed data, we need to go a few more strides in */
1655 if (idxData != NULL) {
1657 /* Indexed so work out the number of strides to skip */
1659 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1660 SkipnStrides = pIdxBufS[startIdx+vx_index];
1662 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1663 SkipnStrides = pIdxBufL[startIdx+vx_index];
1667 /* Fill the vertex shader input */
1668 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1670 /* Initialize the output fields to the same defaults as it would normally have */
1671 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1672 vertexShader->output.oD[0].x = 1.0;
1673 vertexShader->output.oD[0].y = 1.0;
1674 vertexShader->output.oD[0].z = 1.0;
1675 vertexShader->output.oD[0].w = 1.0;
1677 /* Now execute the vertex shader */
1678 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1681 TRACE_VECTOR(vertexShader->output.oPos);
1682 TRACE_VECTOR(vertexShader->output.oD[0]);
1683 TRACE_VECTOR(vertexShader->output.oD[1]);
1684 TRACE_VECTOR(vertexShader->output.oT[0]);
1685 TRACE_VECTOR(vertexShader->output.oT[1]);
1686 TRACE_VECTOR(vertexShader->input.V[0]);
1687 TRACE_VECTOR(vertexShader->data->C[0]);
1688 TRACE_VECTOR(vertexShader->data->C[1]);
1689 TRACE_VECTOR(vertexShader->data->C[2]);
1690 TRACE_VECTOR(vertexShader->data->C[3]);
1691 TRACE_VECTOR(vertexShader->data->C[4]);
1692 TRACE_VECTOR(vertexShader->data->C[5]);
1693 TRACE_VECTOR(vertexShader->data->C[6]);
1694 TRACE_VECTOR(vertexShader->data->C[7]);
1697 /* Extract out the output */
1698 /* FIXME: Fog coords? */
1699 x = vertexShader->output.oPos.x;
1700 y = vertexShader->output.oPos.y;
1701 z = vertexShader->output.oPos.z;
1702 rhw = vertexShader->output.oPos.w;
1703 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1705 /** Update textures coords using vertexShader->output.oT[0->7] */
1706 memset(texcoords, 0x00, sizeof(texcoords));
1707 memset(numcoords, 0x00, sizeof(numcoords));
1708 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1709 if (This->stateBlock->textures[textureNo] != NULL) {
1710 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1711 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1712 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1713 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1714 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1715 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1717 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1718 case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1719 case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1720 default: numcoords[textureNo] = 4;
1724 numcoords[textureNo] = 0;
1728 /* Draw using this information */
1731 TRUE, 0.0f, 0.0f, 1.0f,
1732 TRUE, (float*) &vertexShader->output.oD[0],
1733 TRUE, (float*) &vertexShader->output.oD[1],
1734 FALSE, ptSize, /* FIXME: Change back when supported */
1735 texcoords, numcoords);
1737 /* For non indexed mode, step onto next parts */
1738 if (idxData == NULL) {
1742 } /* for each vertex */
1745 checkGLcall("glEnd and previous calls");
1750 inline static void drawPrimitiveDrawStrided(
1751 IWineD3DDevice *iface,
1752 BOOL useVertexShaderFunction,
1753 BOOL usePixelShaderFunction,
1754 WineDirect3DVertexStridedData *dataLocations,
1755 UINT numberOfvertices,
1756 UINT numberOfIndicies,
1758 const void *idxData,
1764 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1765 BOOL useDrawStridedSlow;
1767 int startStride = idxData == NULL ? 0 :
1768 idxData == (void *) -1 ? 0 :
1769 (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1770 int endStride = startStride;
1771 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1772 startStride, endStride, numberOfIndicies, numberOfvertices);
1774 /* Generate some fixme's if unsupported functionality is being used */
1775 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1776 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1777 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1778 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1780 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1781 FIXME("Tweening is only valid with vertex shaders\n");
1783 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1784 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1786 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1787 FIXME("Extended attributes are only valid with vertex shaders\n");
1789 #undef BUFFER_OR_DATA
1791 /* Fixed pipeline, no fixups required - load arrays */
1792 if (!useVertexShaderFunction &&
1793 ((dataLocations->u.s.pSize.lpData == NULL &&
1794 dataLocations->u.s.diffuse.lpData == NULL &&
1795 dataLocations->u.s.specular.lpData == NULL) ||
1798 /* Load the vertex data using named arrays */
1799 TRACE("(%p) Loading vertex data\n", This);
1800 loadVertexData(iface, dataLocations);
1801 useDrawStridedSlow = FALSE;
1803 /* Shader pipeline - load attribute arrays */
1804 } else if(useVertexShaderFunction) {
1806 loadNumberedArrays(iface, dataLocations,
1807 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->semantics_in);
1808 useDrawStridedSlow = FALSE;
1810 /* Draw vertex by vertex */
1812 TRACE("Not loading vertex data\n");
1813 useDrawStridedSlow = TRUE;
1816 /* If GLSL is used for either pixel or vertex shaders, make a GLSL program
1817 * Otherwise set 0, which restores fixed function */
1818 if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
1819 (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
1820 set_glsl_shader_program(iface);
1822 This->stateBlock->shaderPrgId = 0;
1824 /* If GLSL is used now, or might have been used before, (re)set the program */
1825 if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
1826 wined3d_settings.ps_selected_mode == SHADER_GLSL) {
1828 if (This->stateBlock->shaderPrgId)
1829 TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
1830 GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
1831 checkGLcall("glUseProgramObjectARB");
1834 if (useVertexShaderFunction) {
1836 TRACE("Using vertex shader\n");
1838 if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
1839 /* Bind the vertex program */
1840 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1841 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
1842 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1844 /* Enable OpenGL vertex programs */
1845 glEnable(GL_VERTEX_PROGRAM_ARB);
1846 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1847 TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n",
1848 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1852 if (usePixelShaderFunction) {
1854 TRACE("Using pixel shader\n");
1856 if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
1857 /* Bind the fragment program */
1858 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1859 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1860 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1862 /* Enable OpenGL fragment programs */
1863 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1864 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1865 TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1866 This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1870 /* Load any global constants/uniforms that may have been set by the application */
1871 if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
1872 shader_glsl_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1873 else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
1874 shader_arb_load_constants((IWineD3DStateBlock*)This->stateBlock, usePixelShaderFunction, useVertexShaderFunction);
1876 /* Draw vertex-by-vertex */
1877 if (useDrawStridedSlow)
1878 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1880 drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
1882 /* Cleanup vertex program */
1883 if (useVertexShaderFunction) {
1884 /* disable any attribs (this is the same for both GLSL and ARB modes) */
1887 /* Leave all the attribs disabled */
1888 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1889 /* MESA does not support it right not */
1890 if (glGetError() != GL_NO_ERROR)
1892 for (i = 0; i < maxAttribs; ++i) {
1893 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1894 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1897 if (wined3d_settings.vs_selected_mode == SHADER_ARB)
1898 glDisable(GL_VERTEX_PROGRAM_ARB);
1901 /* Cleanup fragment program */
1902 if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB)
1903 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1906 inline void drawPrimitiveTraceDataLocations(
1907 WineDirect3DVertexStridedData *dataLocations) {
1909 /* Dump out what parts we have supplied */
1910 TRACE("Strided Data:\n");
1911 TRACE_STRIDED((dataLocations), position);
1912 TRACE_STRIDED((dataLocations), blendWeights);
1913 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1914 TRACE_STRIDED((dataLocations), normal);
1915 TRACE_STRIDED((dataLocations), pSize);
1916 TRACE_STRIDED((dataLocations), diffuse);
1917 TRACE_STRIDED((dataLocations), specular);
1918 TRACE_STRIDED((dataLocations), texCoords[0]);
1919 TRACE_STRIDED((dataLocations), texCoords[1]);
1920 TRACE_STRIDED((dataLocations), texCoords[2]);
1921 TRACE_STRIDED((dataLocations), texCoords[3]);
1922 TRACE_STRIDED((dataLocations), texCoords[4]);
1923 TRACE_STRIDED((dataLocations), texCoords[5]);
1924 TRACE_STRIDED((dataLocations), texCoords[6]);
1925 TRACE_STRIDED((dataLocations), texCoords[7]);
1926 TRACE_STRIDED((dataLocations), position2);
1927 TRACE_STRIDED((dataLocations), normal2);
1928 TRACE_STRIDED((dataLocations), tangent);
1929 TRACE_STRIDED((dataLocations), binormal);
1930 TRACE_STRIDED((dataLocations), tessFactor);
1931 TRACE_STRIDED((dataLocations), fog);
1932 TRACE_STRIDED((dataLocations), depth);
1933 TRACE_STRIDED((dataLocations), sample);
1939 static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
1942 for (i = 0; i < GL_LIMITS(samplers); ++i) {
1943 /* Pixel shader support should imply multitexture support. */
1944 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1945 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1946 checkGLcall("glActiveTextureARB");
1948 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1951 if (!This->stateBlock->textures[i]) continue;
1953 /* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
1954 glDisable(GL_TEXTURE_1D);
1955 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1956 switch(This->stateBlock->textureDimensions[i]) {
1958 glDisable(GL_TEXTURE_3D);
1959 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1962 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1963 glDisable(GL_TEXTURE_2D);
1965 case GLTEXTURECUBEMAP:
1966 glDisable(GL_TEXTURE_2D);
1967 glDisable(GL_TEXTURE_3D);
1970 glEnable(This->stateBlock->textureDimensions[i]);
1972 /* Upload texture, apply states */
1973 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1974 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
1975 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1979 /* uploads textures and setup texture states ready for rendering */
1980 static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1981 INT current_sampler = 0;
1982 float constant_color[4];
1985 /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
1986 * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
1987 * Register combiners however provide up to 8 combiner stages. In order to
1988 * take advantage of this, we need to be separate D3D texture stages from
1989 * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
1990 * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
1991 * corresponds to MaxTextureBlendStages in the caps. */
1993 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1994 glEnable(GL_REGISTER_COMBINERS_NV);
1995 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
1996 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
1999 for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
2000 INT texture_idx = -1;
2002 /* D3DTOP_DISABLE disables the current & any higher texture stages */
2003 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
2005 if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
2006 texture_idx = current_sampler++;
2008 /* Active the texture unit corresponding to the current texture stage */
2009 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2010 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2011 checkGLcall("glActiveTextureARB");
2013 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2017 if (This->stateBlock->textures[i]) {
2018 /* Enable the correct target. */
2019 glDisable(GL_TEXTURE_1D);
2020 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
2021 switch(This->stateBlock->textureDimensions[i]) {
2023 glDisable(GL_TEXTURE_3D);
2024 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2027 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2028 glDisable(GL_TEXTURE_2D);
2030 case GLTEXTURECUBEMAP:
2031 glDisable(GL_TEXTURE_2D);
2032 glDisable(GL_TEXTURE_3D);
2036 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
2037 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
2038 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2040 glEnable(This->stateBlock->textureDimensions[i]);
2043 /* Upload texture, apply states */
2044 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2045 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
2046 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2047 } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2048 /* ARB_texture_env_combine needs a valid texture bound to the
2049 * texture unit, even if it isn't used. Bind a dummy texture. */
2050 glDisable(GL_TEXTURE_2D);
2051 glDisable(GL_TEXTURE_3D);
2052 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2053 glEnable(GL_TEXTURE_1D);
2054 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2055 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2058 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2059 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2060 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2061 set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2062 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2063 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2064 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
2067 set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2068 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2069 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2070 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
2073 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2074 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2075 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2076 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2078 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2079 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2080 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2081 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2085 /* If we're using register combiners, set the amount of *used* combiners.
2086 * Ie, the number of stages below the first stage to have a color op of
2087 * D3DTOP_DISABLE. */
2088 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2089 /* NUM_GENERAL_COMBINERS_NV should be > 0 */
2090 if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
2091 else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
2094 /* Disable the remaining texture units. */
2095 for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
2096 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
2097 glDisable(GL_TEXTURE_1D);
2098 glDisable(GL_TEXTURE_2D);
2099 glDisable(GL_TEXTURE_3D);
2100 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2104 /* Routine common to the draw primitive and draw indexed primitive routines */
2105 void drawPrimitive(IWineD3DDevice *iface,
2109 long StartVertexIndex,
2110 UINT numberOfVertices,
2113 const void *idxData,
2115 WineDirect3DVertexStridedData *DrawPrimStrideData) {
2117 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2118 BOOL useVertexShaderFunction = FALSE;
2119 BOOL usePixelShaderFunction = FALSE;
2120 WineDirect3DVertexStridedData *dataLocations;
2121 IWineD3DSwapChainImpl *swapchain;
2125 BOOL lighting_changed, lighting_original = FALSE;
2127 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
2128 * here simply check whether a shader was set, or the user disabled shaders */
2129 if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
2130 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL)
2131 useVertexShaderFunction = TRUE;
2133 if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
2134 ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function)
2135 usePixelShaderFunction = TRUE;
2137 /* Invalidate the back buffer memory so LockRect will read it the next time */
2138 for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
2139 IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
2141 if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
2142 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2146 /* Ok, we will be updating the screen from here onwards so grab the lock */
2149 if(DrawPrimStrideData) {
2150 TRACE("================ Strided Input ===================\n");
2151 dataLocations = DrawPrimStrideData;
2154 else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2156 TRACE("================ Vertex Declaration ===================\n");
2157 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2158 if(!dataLocations) {
2159 ERR("Out of memory!\n");
2162 primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fixup);
2165 TRACE("================ FVF ===================\n");
2166 dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2167 if(!dataLocations) {
2168 ERR("Out of memory!\n");
2171 primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
2174 /* write out some debug information*/
2175 drawPrimitiveTraceDataLocations(dataLocations);
2177 /* Setup transform matrices and sort out */
2178 primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
2180 /* Now initialize the materials state */
2181 init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
2183 if (usePixelShaderFunction) {
2184 drawPrimitiveUploadTexturesPS(This);
2186 drawPrimitiveUploadTextures(This);
2191 /* Ok, Work out which primitive is requested and how many vertexes that
2193 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2194 if (numberOfVertices == 0 )
2195 numberOfVertices = calculatedNumberOfindices;
2197 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
2198 dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType,
2199 idxData, idxSize, minIndex, StartIdx, fixup);
2202 if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2204 /* If vertex shaders or no normals, restore previous lighting state */
2205 if (lighting_changed) {
2206 if (lighting_original) glEnable(GL_LIGHTING);
2207 else glDisable(GL_LIGHTING);
2208 TRACE("Restored lighting to original state\n");
2211 /* Finshed updating the screen, restore lock */
2213 TRACE("Done all gl drawing\n");
2216 #ifdef SHOW_FRAME_MAKEUP
2218 static long int primCounter = 0;
2219 /* NOTE: set primCounter to the value reported by drawprim
2220 before you want to to write frame makeup to /tmp */
2221 if (primCounter >= 0) {
2222 WINED3DLOCKED_RECT r;
2224 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2225 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2226 TRACE("Saving screenshot %s\n", buffer);
2227 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2228 IWineD3DSurface_UnlockRect(This->renderTarget);
2230 #ifdef SHOW_TEXTURE_MAKEUP
2232 IWineD3DSurface *pSur;
2234 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2235 if (This->stateBlock->textures[textureNo] != NULL) {
2236 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2237 TRACE("Saving texture %s\n", buffer);
2238 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2239 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2240 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2241 IWineD3DSurface_Release(pSur);
2243 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2250 TRACE("drawprim #%ld\n", primCounter);