push 337eb2e2d902d84a5d689451984c5832d7e04fc4
[wine/hacks.git] / dlls / wined3d / state.c
blob6c8e27302ae06e1c0838539e305191089f5efbdf
2 /*
3 * Direct3D state management
5 * Copyright 2002 Lionel Ulmer
6 * Copyright 2002-2005 Jason Edmeades
7 * Copyright 2003-2004 Raphael Junqueira
8 * Copyright 2004 Christian Costa
9 * Copyright 2005 Oliver Stieber
10 * Copyright 2006 Henri Verbeet
11 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "config.h"
29 #include <stdio.h>
30 #ifdef HAVE_FLOAT_H
31 # include <float.h>
32 #endif
33 #include "wined3d_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
36 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
38 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
40 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
42 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
43 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
44 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
46 if(STATE_IS_RENDER(state)) {
47 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
48 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
49 } else {
50 /* Shouldn't have an unknown type here */
51 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
55 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
56 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
57 * list without causing confusing terminal output. Deliberately no special debug name here
58 * because its undefined.
60 WARN("undefined state %d\n", state);
63 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
64 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
66 switch(Value) {
67 case WINED3DFILL_POINT:
68 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
69 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
70 break;
71 case WINED3DFILL_WIREFRAME:
72 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
73 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
74 break;
75 case WINED3DFILL_SOLID:
76 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
77 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
78 break;
79 default:
80 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
84 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
85 BOOL transformed;
87 /* Lighting is not enabled if transformed vertices are drawn
88 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
89 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
90 * vertex declaration applying function calls this function for updating
93 if(isStateDirty(context, STATE_VDECL)) {
94 return;
97 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
98 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
99 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
101 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
102 glEnable(GL_LIGHTING);
103 checkGLcall("glEnable GL_LIGHTING");
104 } else {
105 glDisable(GL_LIGHTING);
106 checkGLcall("glDisable GL_LIGHTING");
110 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
111 /* No z test without depth stencil buffers */
112 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
113 TRACE("No Z buffer - disabling depth test\n");
114 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
115 checkGLcall("glDisable GL_DEPTH_TEST");
116 return;
119 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
120 case WINED3DZB_FALSE:
121 glDisable(GL_DEPTH_TEST);
122 checkGLcall("glDisable GL_DEPTH_TEST");
123 break;
124 case WINED3DZB_TRUE:
125 glEnable(GL_DEPTH_TEST);
126 checkGLcall("glEnable GL_DEPTH_TEST");
127 break;
128 case WINED3DZB_USEW:
129 glEnable(GL_DEPTH_TEST);
130 checkGLcall("glEnable GL_DEPTH_TEST");
131 FIXME("W buffer is not well handled\n");
132 break;
133 default:
134 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
138 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
139 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
140 * switch
142 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
143 case WINED3DCULL_NONE:
144 glDisable(GL_CULL_FACE);
145 checkGLcall("glDisable GL_CULL_FACE");
146 break;
147 case WINED3DCULL_CW:
148 glEnable(GL_CULL_FACE);
149 checkGLcall("glEnable GL_CULL_FACE");
150 glCullFace(GL_FRONT);
151 checkGLcall("glCullFace(GL_FRONT)");
152 break;
153 case WINED3DCULL_CCW:
154 glEnable(GL_CULL_FACE);
155 checkGLcall("glEnable GL_CULL_FACE");
156 glCullFace(GL_BACK);
157 checkGLcall("glCullFace(GL_BACK)");
158 break;
159 default:
160 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
164 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
165 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
166 case WINED3DSHADE_FLAT:
167 glShadeModel(GL_FLAT);
168 checkGLcall("glShadeModel(GL_FLAT)");
169 break;
170 case WINED3DSHADE_GOURAUD:
171 glShadeModel(GL_SMOOTH);
172 checkGLcall("glShadeModel(GL_SMOOTH)");
173 break;
174 case WINED3DSHADE_PHONG:
175 FIXME("WINED3DSHADE_PHONG isn't supported\n");
176 break;
177 default:
178 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
182 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
183 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
184 glEnable(GL_DITHER);
185 checkGLcall("glEnable GL_DITHER");
186 } else {
187 glDisable(GL_DITHER);
188 checkGLcall("glDisable GL_DITHER");
192 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
193 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
194 * this has to be merged with ZENABLE and ZFUNC
196 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
197 glDepthMask(1);
198 checkGLcall("glDepthMask(1)");
199 } else {
200 glDepthMask(0);
201 checkGLcall("glDepthMask(0)");
205 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
206 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
208 if(glParm) {
209 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
210 static BOOL once = FALSE;
211 /* There are a few issues with this: First, our inability to
212 * select a proper Z depth, most of the time we're stuck with
213 * D24S8, even if the app selects D32 or D16. There seem to be
214 * some other precision problems which have to be debugged to
215 * make NOTEQUAL and EQUAL work properly
217 if(!once) {
218 once = TRUE;
219 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
223 glDepthFunc(glParm);
224 checkGLcall("glDepthFunc");
228 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
229 float col[4];
230 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
232 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
233 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
234 checkGLcall("glLightModel for MODEL_AMBIENT");
237 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
238 int srcBlend = GL_ZERO;
239 int dstBlend = GL_ZERO;
240 const StaticPixelFormatDesc *rtFormat;
241 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
243 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
244 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
245 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
246 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
247 const struct GlPixelFormatDesc *glDesc;
248 getFormatDescEntry(target->resource.format, &GLINFO_LOCATION, &glDesc);
250 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
251 * The d3d9 visual test confirms the behavior. */
252 if(!(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) {
253 glDisable(GL_BLEND);
254 checkGLcall("glDisable GL_BLEND");
255 return;
256 } else {
257 glEnable(GL_BLEND);
258 checkGLcall("glEnable GL_BLEND");
260 } else {
261 glDisable(GL_BLEND);
262 checkGLcall("glDisable GL_BLEND");
263 /* Nothing more to do - get out */
264 return;
267 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
268 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
269 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
270 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
271 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
272 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
273 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
274 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
275 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
277 /* To compensate the lack of format switching with backbuffer offscreen rendering,
278 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
279 * if the render target doesn't support alpha blending. A nonexistent alpha channel
280 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
282 case WINED3DBLEND_DESTALPHA :
283 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
284 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
285 break;
286 case WINED3DBLEND_INVDESTALPHA :
287 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
288 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
289 break;
291 case WINED3DBLEND_SRCALPHASAT :
292 dstBlend = GL_SRC_ALPHA_SATURATE;
293 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
294 break;
296 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
297 * values which are still valid up to d3d9. They should not occur as dest blend values
299 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
300 srcBlend = GL_SRC_ALPHA;
301 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
302 break;
304 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
305 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
306 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
307 break;
309 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
310 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
311 default:
312 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
315 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
316 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
317 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
318 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
319 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
320 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
321 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
322 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
323 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
324 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
326 case WINED3DBLEND_DESTALPHA :
327 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
328 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
329 break;
330 case WINED3DBLEND_INVDESTALPHA :
331 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
332 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
333 break;
335 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
336 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
337 break;
339 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
340 dstBlend = GL_SRC_ALPHA;
341 break;
343 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
344 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
345 default:
346 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
349 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
350 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
351 glEnable(GL_LINE_SMOOTH);
352 checkGLcall("glEnable(GL_LINE_SMOOTH)");
353 if(srcBlend != GL_SRC_ALPHA) {
354 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
356 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
357 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
359 } else {
360 glDisable(GL_LINE_SMOOTH);
361 checkGLcall("glDisable(GL_LINE_SMOOTH)");
364 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
365 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
366 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
369 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
370 int srcBlendAlpha = GL_ZERO;
371 int dstBlendAlpha = GL_ZERO;
373 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
374 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
375 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
376 return;
379 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
380 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
381 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
382 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
383 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
384 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
385 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
386 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
387 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
388 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
389 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
390 case WINED3DBLEND_SRCALPHASAT :
391 dstBlend = GL_SRC_ALPHA_SATURATE;
392 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
393 break;
394 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
395 * values which are still valid up to d3d9. They should not occur as dest blend values
397 case WINED3DBLEND_BOTHSRCALPHA :
398 dstBlendAlpha = GL_SRC_ALPHA;
399 srcBlendAlpha = GL_SRC_ALPHA;
400 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
401 break;
402 case WINED3DBLEND_BOTHINVSRCALPHA :
403 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
404 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
405 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
406 break;
407 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
408 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
409 default:
410 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
413 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
414 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
415 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
416 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
417 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
418 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
419 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
420 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
421 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
422 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
423 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
424 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
425 case WINED3DBLEND_BOTHSRCALPHA :
426 srcBlendAlpha = GL_SRC_ALPHA;
427 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
428 break;
429 case WINED3DBLEND_BOTHINVSRCALPHA :
430 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
431 dstBlendAlpha = GL_SRC_ALPHA;
432 break;
433 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
434 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
435 default:
436 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
439 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
440 checkGLcall("glBlendFuncSeparateEXT");
441 } else {
442 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
443 glBlendFunc(srcBlend, dstBlend);
444 checkGLcall("glBlendFunc");
447 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
448 so it may need updating */
449 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
450 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
451 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
455 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
456 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
459 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
460 float col[4];
462 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
463 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
464 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
465 checkGLcall("glBlendColor");
468 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
469 int glParm = 0;
470 float ref;
471 BOOL enable_ckey = FALSE;
473 IWineD3DSurfaceImpl *surf;
475 /* Find out if the texture on the first stage has a ckey set
476 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
477 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
478 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
479 * in case it finds some texture+colorkeyenable combination which needs extra care.
481 if(stateblock->textures[0] && (
482 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
483 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
484 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
486 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
487 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
488 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
489 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
490 * surface has alpha bits
492 if(fmt->alphaMask == 0x00000000) {
493 enable_ckey = TRUE;
498 if(enable_ckey || context->last_was_ckey) {
499 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
500 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
502 context->last_was_ckey = enable_ckey;
504 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
505 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
506 glEnable(GL_ALPHA_TEST);
507 checkGLcall("glEnable GL_ALPHA_TEST");
508 } else {
509 glDisable(GL_ALPHA_TEST);
510 checkGLcall("glDisable GL_ALPHA_TEST");
511 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
512 * enable call
514 return;
517 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
518 glParm = GL_NOTEQUAL;
519 ref = 0.0;
520 } else {
521 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
522 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
524 if(glParm) {
525 glAlphaFunc(glParm, ref);
526 checkGLcall("glAlphaFunc");
530 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
531 DWORD enable = 0xFFFFFFFF;
532 DWORD disable = 0x00000000;
534 if (use_vs(stateblock->wineD3DDevice)) {
535 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
536 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
537 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
538 * of that - don't do anything here and keep them disabled
540 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
541 static BOOL warned = FALSE;
542 if(!warned) {
543 FIXME("Clipping not supported with vertex shaders\n");
544 warned = TRUE;
547 return;
550 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
551 * of already set values
554 /* If enabling / disabling all
555 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
557 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
558 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
559 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
560 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
561 glDisable(GL_DEPTH_CLAMP_NV);
562 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
564 } else {
565 disable = 0xffffffff;
566 enable = 0x00;
567 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
568 glEnable(GL_DEPTH_CLAMP_NV);
569 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
573 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
574 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
575 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
576 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
577 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
578 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
580 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
581 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
582 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
583 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
584 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
585 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
587 /** update clipping status */
588 if (enable) {
589 stateblock->clip_status.ClipUnion = 0;
590 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
591 } else {
592 stateblock->clip_status.ClipUnion = 0;
593 stateblock->clip_status.ClipIntersection = 0;
597 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
598 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
601 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
602 int blendEquation = GL_FUNC_ADD;
603 int blendEquationAlpha = GL_FUNC_ADD;
605 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
606 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
607 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
608 return;
611 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
612 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
613 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
614 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
615 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
616 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
617 default:
618 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
621 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
622 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
623 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
624 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
625 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
626 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
627 default:
628 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
631 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
632 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
633 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
634 checkGLcall("glBlendEquationSeparateEXT");
635 } else {
636 TRACE("glBlendEquation(%x)\n", blendEquation);
637 GL_EXTCALL(glBlendEquationEXT(blendEquation));
638 checkGLcall("glBlendEquation");
642 static void
643 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
644 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
645 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
646 * specular color. This is wrong:
647 * Separate specular color means the specular colour is maintained separately, whereas
648 * single color means it is merged in. However in both cases they are being used to
649 * some extent.
650 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
651 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
652 * running 1.4 yet!
655 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
656 * Instead, we need to setup the FinalCombiner properly.
658 * The default setup for the FinalCombiner is:
660 * <variable> <input> <mapping> <usage>
661 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
662 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
663 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
664 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
665 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
667 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
669 * That's pretty much fine as it is, except for variable B, which needs to take
670 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
671 * whether WINED3DRS_SPECULARENABLE is enabled or not.
674 TRACE("Setting specular enable state and materials\n");
675 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
676 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
677 checkGLcall("glMaterialfv");
679 if(stateblock->material.Power > GL_LIMITS(shininess)) {
680 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
681 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
682 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
683 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
684 * them, it should be safe to do so without major visual distortions.
686 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
687 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
688 } else {
689 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
691 checkGLcall("glMaterialf(GL_SHININESS)");
693 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
694 glEnable(GL_COLOR_SUM_EXT);
695 } else {
696 TRACE("Specular colors cannot be enabled in this version of opengl\n");
698 checkGLcall("glEnable(GL_COLOR_SUM)");
700 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
701 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
702 checkGLcall("glFinalCombinerInputNV()");
704 } else {
705 const GLfloat black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
707 /* for the case of enabled lighting: */
708 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
709 checkGLcall("glMaterialfv");
711 /* for the case of disabled lighting: */
712 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
713 glDisable(GL_COLOR_SUM_EXT);
714 } else {
715 TRACE("Specular colors cannot be disabled in this version of opengl\n");
717 checkGLcall("glDisable(GL_COLOR_SUM)");
719 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
720 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
721 checkGLcall("glFinalCombinerInputNV()");
725 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
726 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
727 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
728 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
729 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
730 stateblock->material.Specular.b, stateblock->material.Specular.a);
731 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
732 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
734 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
735 checkGLcall("glMaterialfv(GL_AMBIENT)");
736 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
737 checkGLcall("glMaterialfv(GL_DIFFUSE)");
738 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
739 checkGLcall("glMaterialfv(GL_EMISSION)");
742 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
743 unsigned int i;
745 /* Note the texture color applies to all textures whereas
746 * GL_TEXTURE_ENV_COLOR applies to active only
748 float col[4];
749 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
751 /* And now the default texture color as well */
752 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
753 /* Note the WINED3DRS value applies to all textures, but GL has one
754 * per texture, so apply it now ready to be used!
756 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
757 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
758 checkGLcall("glActiveTextureARB");
759 } else if (i>0) {
760 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
763 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
764 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
768 static void
769 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
770 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
771 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
772 GL_EXTCALL(glActiveStencilFaceEXT(face));
773 checkGLcall("glActiveStencilFaceEXT(...)");
774 glStencilFunc(func, ref, mask);
775 checkGLcall("glStencilFunc(...)");
776 glStencilOp(stencilFail, depthFail, stencilPass);
777 checkGLcall("glStencilOp(...)");
780 static void
781 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
782 DWORD onesided_enable = FALSE;
783 DWORD twosided_enable = FALSE;
784 GLint func = GL_ALWAYS;
785 GLint func_ccw = GL_ALWAYS;
786 GLint ref = 0;
787 GLuint mask = 0;
788 GLint stencilFail = GL_KEEP;
789 GLint depthFail = GL_KEEP;
790 GLint stencilPass = GL_KEEP;
791 GLint stencilFail_ccw = GL_KEEP;
792 GLint depthFail_ccw = GL_KEEP;
793 GLint stencilPass_ccw = GL_KEEP;
795 /* No stencil test without a stencil buffer */
796 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
797 glDisable(GL_STENCIL_TEST);
798 checkGLcall("glDisable GL_STENCIL_TEST");
799 return;
802 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
803 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
804 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
805 func = GL_ALWAYS;
806 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
807 func_ccw = GL_ALWAYS;
808 ref = stateblock->renderState[WINED3DRS_STENCILREF];
809 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
810 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
811 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
812 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
813 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
814 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
815 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
817 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
818 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
819 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
820 onesided_enable, twosided_enable, ref, mask,
821 func, stencilFail, depthFail, stencilPass,
822 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
824 if (twosided_enable && onesided_enable) {
825 glEnable(GL_STENCIL_TEST);
826 checkGLcall("glEnable GL_STENCIL_TEST");
828 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
829 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
830 * which has an effect on the code below too. If we apply the front face
831 * afterwards, we are sure that the active stencil face is set to front,
832 * and other stencil functions which do not use two sided stencil do not have
833 * to set it back
835 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
836 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
837 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
838 stencilFail, depthFail, stencilPass);
839 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
840 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
841 checkGLcall("glStencilFuncSeparateATI(...)");
842 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
843 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
844 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
845 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
846 } else {
847 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
849 } else if(onesided_enable) {
850 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
851 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
852 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
855 /* This code disables the ATI extension as well, since the standard stencil functions are equal
856 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
858 glEnable(GL_STENCIL_TEST);
859 checkGLcall("glEnable GL_STENCIL_TEST");
860 glStencilFunc(func, ref, mask);
861 checkGLcall("glStencilFunc(...)");
862 glStencilOp(stencilFail, depthFail, stencilPass);
863 checkGLcall("glStencilOp(...)");
864 } else {
865 glDisable(GL_STENCIL_TEST);
866 checkGLcall("glDisable GL_STENCIL_TEST");
870 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
871 DWORD mask;
873 if(stateblock->wineD3DDevice->stencilBufferTarget) {
874 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
875 } else {
876 mask = 0;
879 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
880 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
881 glStencilMask(mask);
882 checkGLcall("glStencilMask");
883 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
884 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
885 glStencilMask(mask);
888 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
889 DWORD mask;
891 if(stateblock->wineD3DDevice->stencilBufferTarget) {
892 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
893 } else {
894 mask = 0;
897 glStencilMask(mask);
898 checkGLcall("glStencilMask");
901 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
902 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
903 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
904 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
905 float fogstart, fogend;
907 union {
908 DWORD d;
909 float f;
910 } tmpvalue;
912 if (!fogenable) {
913 /* No fog? Disable it, and we're done :-) */
914 glDisable(GL_FOG);
915 checkGLcall("glDisable GL_FOG");
916 if( use_ps(stateblock->wineD3DDevice)
917 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
918 /* disable fog in the pixel shader
919 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
920 * -1/(e-s) and e/(e-s) respectively.
922 glFogf(GL_FOG_START, 0.0f);
923 checkGLcall("glFogf(GL_FOG_START, fogstart)");
924 glFogf(GL_FOG_END, 1.0f);
925 checkGLcall("glFogf(GL_FOG_END, fogend)");
927 return;
930 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
931 fogstart = tmpvalue.f;
932 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
933 fogend = tmpvalue.f;
935 /* Fog Rules:
937 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
938 * It can use the Z value of the vertex, or the alpha component of the specular color.
939 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
940 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
941 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
943 * FOGTABLEMODE != NONE:
944 * The Z value is used, with the equation specified, no matter what vertex type.
946 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
947 * Per vertex fog is calculated using the specified fog equation and the parameters
949 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
950 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
951 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
954 * Rules for vertex fog with shaders:
956 * When mixing fixed function functionality with the programmable pipeline, D3D expects
957 * the fog computation to happen during transformation while openGL expects it to happen
958 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
959 * the pixel shader while openGL always expects the pixel shader to handle the blending.
960 * To solve this problem, WineD3D does:
961 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
962 * shader,
963 * and 2) disables the fog computation (in either the fixed function or programmable
964 * rasterizer) if using a vertex program.
967 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
968 * without shaders).
971 if( is_ps3 ) {
972 if( !use_vs(stateblock->wineD3DDevice)
973 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
974 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
978 if (use_vs(stateblock->wineD3DDevice)
979 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
980 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
981 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
982 /* Disable fog */
983 fogenable = FALSE;
984 } else {
985 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
986 glFogi(GL_FOG_MODE, GL_LINEAR);
987 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
988 fogstart = 1.0;
989 fogend = 0.0;
992 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
993 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
994 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
995 context->fog_coord = FALSE;
997 context->last_was_foggy_shader = TRUE;
999 else if( use_ps(stateblock->wineD3DDevice) ) {
1000 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1001 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
1003 WINED3DFOGMODE mode;
1004 context->last_was_foggy_shader = FALSE;
1006 /* If both fogmodes are set use the table fog mode */
1007 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1008 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
1009 else
1010 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1012 switch (mode) {
1013 case WINED3DFOG_EXP:
1014 case WINED3DFOG_EXP2:
1015 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1016 /* Disable fog */
1017 fogenable = FALSE;
1018 break;
1020 case WINED3DFOG_LINEAR:
1021 fogstart = -1.0f/(fogend-fogstart);
1022 fogend *= -fogstart;
1023 break;
1025 case WINED3DFOG_NONE:
1026 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1027 /* Disable fog */
1028 fogenable = FALSE;
1029 break;
1030 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1033 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1034 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1035 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1036 context->fog_coord = FALSE;
1039 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1040 * the system will apply only pixel(=table) fog effects."
1042 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1043 glHint(GL_FOG_HINT, GL_FASTEST);
1044 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1045 context->last_was_foggy_shader = FALSE;
1047 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1048 /* If processed vertices are used, fall through to the NONE case */
1049 case WINED3DFOG_EXP: {
1050 if(!context->last_was_rhw) {
1051 glFogi(GL_FOG_MODE, GL_EXP);
1052 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1053 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1054 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1055 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1056 context->fog_coord = FALSE;
1058 break;
1061 case WINED3DFOG_EXP2: {
1062 if(!context->last_was_rhw) {
1063 glFogi(GL_FOG_MODE, GL_EXP2);
1064 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1065 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1066 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1067 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1068 context->fog_coord = FALSE;
1070 break;
1073 case WINED3DFOG_LINEAR: {
1074 if(!context->last_was_rhw) {
1075 glFogi(GL_FOG_MODE, GL_LINEAR);
1076 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1077 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1078 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1079 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1080 context->fog_coord = FALSE;
1082 break;
1085 case WINED3DFOG_NONE: {
1086 /* Both are none? According to msdn the alpha channel of the specular
1087 * color contains a fog factor. Set it in drawStridedSlow.
1088 * Same happens with Vertexfog on transformed vertices
1090 if(GL_SUPPORT(EXT_FOG_COORD)) {
1091 if(context->fog_coord == FALSE) {
1092 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1093 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1094 context->fog_coord = TRUE;
1096 glFogi(GL_FOG_MODE, GL_LINEAR);
1097 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1098 fogstart = 0xff;
1099 fogend = 0x0;
1100 } else {
1101 /* Disable GL fog, handle this in software in drawStridedSlow */
1102 fogenable = FALSE;
1104 break;
1106 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1108 } else {
1109 glHint(GL_FOG_HINT, GL_NICEST);
1110 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1111 context->last_was_foggy_shader = FALSE;
1113 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1114 case WINED3DFOG_EXP:
1115 glFogi(GL_FOG_MODE, GL_EXP);
1116 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1117 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1118 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1119 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1120 context->fog_coord = FALSE;
1122 break;
1124 case WINED3DFOG_EXP2:
1125 glFogi(GL_FOG_MODE, GL_EXP2);
1126 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1127 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1128 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1129 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1130 context->fog_coord = FALSE;
1132 break;
1134 case WINED3DFOG_LINEAR:
1135 glFogi(GL_FOG_MODE, GL_LINEAR);
1136 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1137 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1138 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1139 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1140 context->fog_coord = FALSE;
1142 break;
1144 case WINED3DFOG_NONE: /* Won't happen */
1145 default:
1146 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1150 if(fogenable) {
1151 glEnable(GL_FOG);
1152 checkGLcall("glEnable GL_FOG");
1154 if(fogstart != fogend)
1156 glFogfv(GL_FOG_START, &fogstart);
1157 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1158 TRACE("Fog Start == %f\n", fogstart);
1160 glFogfv(GL_FOG_END, &fogend);
1161 checkGLcall("glFogf(GL_FOG_END, fogend)");
1162 TRACE("Fog End == %f\n", fogend);
1164 else
1166 glFogf(GL_FOG_START, -1.0 / 0.0);
1167 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1168 TRACE("Fog Start == %f\n", fogstart);
1170 glFogf(GL_FOG_END, 0.0);
1171 checkGLcall("glFogf(GL_FOG_END, fogend)");
1172 TRACE("Fog End == %f\n", fogend);
1174 } else {
1175 glDisable(GL_FOG);
1176 checkGLcall("glDisable GL_FOG");
1177 if( use_ps(stateblock->wineD3DDevice) ) {
1178 /* disable fog in the pixel shader
1179 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1180 * -1/(e-s) and e/(e-s) respectively.
1182 glFogf(GL_FOG_START, 0.0f);
1183 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1184 glFogf(GL_FOG_END, 1.0f);
1185 checkGLcall("glFogf(GL_FOG_END, fogend)");
1190 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1191 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1192 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1196 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1197 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1198 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1199 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1200 } else {
1201 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1202 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1206 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1207 float col[4];
1208 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1209 glFogfv(GL_FOG_COLOR, &col[0]);
1210 checkGLcall("glFog GL_FOG_COLOR");
1213 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1214 union {
1215 DWORD d;
1216 float f;
1217 } tmpvalue;
1218 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1219 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1220 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1223 /* TODO: Merge with primitive type + init_materials()!! */
1224 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1225 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1226 GLenum Parm = 0;
1227 const WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1228 BOOL isDiffuseSupplied;
1230 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1231 * The vertex declaration will call this function if the fixed function pipeline is used.
1234 if(isStateDirty(context, STATE_VDECL)) {
1235 return;
1238 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1240 context->num_untracked_materials = 0;
1241 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1242 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1243 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1244 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1245 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1246 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1248 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1249 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1250 Parm = GL_AMBIENT_AND_DIFFUSE;
1251 } else {
1252 Parm = GL_DIFFUSE;
1254 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1255 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1256 context->num_untracked_materials++;
1258 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1259 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1260 context->num_untracked_materials++;
1262 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1263 Parm = GL_AMBIENT;
1264 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1265 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1266 context->num_untracked_materials++;
1268 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1269 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1270 context->num_untracked_materials++;
1272 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1273 Parm = GL_EMISSION;
1274 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1275 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1276 context->num_untracked_materials++;
1278 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1279 Parm = GL_SPECULAR;
1283 /* Nothing changed, return. */
1284 if (Parm == context->tracking_parm) return;
1286 if(!Parm) {
1287 glDisable(GL_COLOR_MATERIAL);
1288 checkGLcall("glDisable GL_COLOR_MATERIAL");
1289 } else {
1290 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1291 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1292 glEnable(GL_COLOR_MATERIAL);
1293 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1296 /* Apparently calls to glMaterialfv are ignored for properties we're
1297 * tracking with glColorMaterial, so apply those here. */
1298 switch (context->tracking_parm) {
1299 case GL_AMBIENT_AND_DIFFUSE:
1300 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1301 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1302 checkGLcall("glMaterialfv");
1303 break;
1305 case GL_DIFFUSE:
1306 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1307 checkGLcall("glMaterialfv");
1308 break;
1310 case GL_AMBIENT:
1311 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1312 checkGLcall("glMaterialfv");
1313 break;
1315 case GL_EMISSION:
1316 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1317 checkGLcall("glMaterialfv");
1318 break;
1320 case GL_SPECULAR:
1321 /* Only change material color if specular is enabled, otherwise it is set to black */
1322 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1323 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1324 checkGLcall("glMaterialfv");
1325 } else {
1326 const GLfloat black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1327 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1328 checkGLcall("glMaterialfv");
1330 break;
1333 context->tracking_parm = Parm;
1336 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1337 union {
1338 DWORD d;
1339 WINED3DLINEPATTERN lp;
1340 } tmppattern;
1341 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1343 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1345 if (tmppattern.lp.wRepeatFactor) {
1346 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1347 checkGLcall("glLineStipple(repeat, linepattern)");
1348 glEnable(GL_LINE_STIPPLE);
1349 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1350 } else {
1351 glDisable(GL_LINE_STIPPLE);
1352 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1356 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1357 union {
1358 DWORD d;
1359 float f;
1360 } tmpvalue;
1362 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1363 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1364 TRACE("ZBias value %f\n", tmpvalue.f);
1365 glPolygonOffset(0, -tmpvalue.f);
1366 checkGLcall("glPolygonOffset(0, -Value)");
1367 glEnable(GL_POLYGON_OFFSET_FILL);
1368 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1369 glEnable(GL_POLYGON_OFFSET_LINE);
1370 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1371 glEnable(GL_POLYGON_OFFSET_POINT);
1372 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1373 } else {
1374 glDisable(GL_POLYGON_OFFSET_FILL);
1375 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1376 glDisable(GL_POLYGON_OFFSET_LINE);
1377 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1378 glDisable(GL_POLYGON_OFFSET_POINT);
1379 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1384 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1385 if(isStateDirty(context, STATE_VDECL)) {
1386 return;
1388 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1389 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1390 * by zero and is not properly defined in opengl, so avoid it
1392 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1393 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1394 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1395 glEnable(GL_NORMALIZE);
1396 checkGLcall("glEnable(GL_NORMALIZE);");
1397 } else {
1398 glDisable(GL_NORMALIZE);
1399 checkGLcall("glDisable(GL_NORMALIZE);");
1403 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1404 union {
1405 DWORD d;
1406 float f;
1407 } tmpvalue;
1409 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1410 if(tmpvalue.f != 1.0) {
1411 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1413 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1414 if(tmpvalue.f != 64.0) {
1415 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1420 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1421 union {
1422 DWORD d;
1423 float f;
1424 } min, max;
1426 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1427 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1429 /* Max point size trumps min point size */
1430 if(min.f > max.f) {
1431 min.f = max.f;
1434 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1435 checkGLcall("glPointParameterfEXT(...)");
1436 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1437 checkGLcall("glPointParameterfEXT(...)");
1440 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1441 union {
1442 DWORD d;
1443 float f;
1444 } min, max;
1446 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1447 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1449 /* Max point size trumps min point size */
1450 if(min.f > max.f) {
1451 min.f = max.f;
1454 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1455 checkGLcall("glPointParameterfARB(...)");
1456 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1457 checkGLcall("glPointParameterfARB(...)");
1460 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1461 /* TODO: Group this with the viewport */
1463 * POINTSCALEENABLE controls how point size value is treated. If set to
1464 * true, the point size is scaled with respect to height of viewport.
1465 * When set to false point size is in pixels.
1468 /* Default values */
1469 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1470 union {
1471 DWORD d;
1472 float f;
1473 } pointSize, A, B, C;
1475 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1476 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1477 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1478 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1480 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1481 GLfloat scaleFactor;
1482 float h = stateblock->viewport.Height;
1484 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1486 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1487 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1488 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1489 * are less than 1.0f. scale_factor = 1.0f / point_size.
1491 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1492 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1493 * is 1.0, but then accepts points below that and draws too small points
1495 pointSize.f = GL_LIMITS(pointsizemin);
1496 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1497 /* gl already scales the input to glPointSize,
1498 * d3d scales the result after the point size scale.
1499 * If the point size is bigger than the max size, use the
1500 * scaling to scale it bigger, and set the gl point size to max
1502 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1503 TRACE("scale: %f\n", scaleFactor);
1504 pointSize.f = GL_LIMITS(pointsize);
1505 } else {
1506 scaleFactor = 1.0f;
1508 scaleFactor = pow(h * scaleFactor, 2);
1510 att[0] = A.f / scaleFactor;
1511 att[1] = B.f / scaleFactor;
1512 att[2] = C.f / scaleFactor;
1515 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1516 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1517 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1519 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1520 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1521 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1522 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1523 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1526 glPointSize(pointSize.f);
1527 checkGLcall("glPointSize(...);");
1530 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1531 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1533 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1534 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1535 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1536 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1537 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1538 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1539 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1540 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1541 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1542 checkGLcall("glColorMask(...)");
1544 /* depends on WINED3DRS_COLORWRITEENABLE. */
1545 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1546 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1547 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1548 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1549 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1550 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1551 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1555 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1556 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1557 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1558 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1559 } else {
1560 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1561 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1565 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1566 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1567 TRACE("Last Pixel Drawing Enabled\n");
1568 } else {
1569 static BOOL warned;
1570 if (!warned) {
1571 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1572 warned = TRUE;
1573 } else {
1574 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1579 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1580 /* TODO: NV_POINT_SPRITE */
1581 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1582 TRACE("Point sprites not supported\n");
1586 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1587 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1588 glEnable(GL_POINT_SPRITE_ARB);
1589 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1590 } else {
1591 glDisable(GL_POINT_SPRITE_ARB);
1592 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1596 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1598 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1599 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1600 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1601 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1603 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1605 TRACE("Stub\n");
1606 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1607 stateblock->renderState[WINED3DRS_WRAP1] ||
1608 stateblock->renderState[WINED3DRS_WRAP2] ||
1609 stateblock->renderState[WINED3DRS_WRAP3] ||
1610 stateblock->renderState[WINED3DRS_WRAP4] ||
1611 stateblock->renderState[WINED3DRS_WRAP5] ||
1612 stateblock->renderState[WINED3DRS_WRAP6] ||
1613 stateblock->renderState[WINED3DRS_WRAP7] ||
1614 stateblock->renderState[WINED3DRS_WRAP8] ||
1615 stateblock->renderState[WINED3DRS_WRAP9] ||
1616 stateblock->renderState[WINED3DRS_WRAP10] ||
1617 stateblock->renderState[WINED3DRS_WRAP11] ||
1618 stateblock->renderState[WINED3DRS_WRAP12] ||
1619 stateblock->renderState[WINED3DRS_WRAP13] ||
1620 stateblock->renderState[WINED3DRS_WRAP14] ||
1621 stateblock->renderState[WINED3DRS_WRAP15] ) {
1622 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1626 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1627 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1628 WARN("Multisample antialiasing not supported by gl\n");
1632 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1633 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1634 glEnable(GL_MULTISAMPLE_ARB);
1635 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1636 } else {
1637 glDisable(GL_MULTISAMPLE_ARB);
1638 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1642 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1643 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1644 glEnable(GL_SCISSOR_TEST);
1645 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1646 } else {
1647 glDisable(GL_SCISSOR_TEST);
1648 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1652 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1653 union {
1654 DWORD d;
1655 float f;
1656 } tmpvalue;
1658 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1659 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1660 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1661 glEnable(GL_POLYGON_OFFSET_FILL);
1662 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1663 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1664 checkGLcall("glPolygonOffset(...)");
1665 } else {
1666 glDisable(GL_POLYGON_OFFSET_FILL);
1667 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1671 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1672 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1673 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1674 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1675 } else {
1676 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1677 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1681 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1682 TRACE("Stub\n");
1683 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1684 FIXME(" Stippled Alpha not supported yet.\n");
1687 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1688 TRACE("Stub\n");
1689 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1690 FIXME(" Antialias not supported yet.\n");
1693 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1694 TRACE("Stub\n");
1695 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1696 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1699 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1700 TRACE("Stub\n");
1701 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1702 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1705 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1706 union {
1707 DWORD d;
1708 float f;
1709 } tmpvalue;
1710 tmpvalue.f = 1.0f;
1712 TRACE("Stub\n");
1713 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1715 static BOOL displayed = FALSE;
1717 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1718 if(!displayed)
1719 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1721 displayed = TRUE;
1725 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1726 TRACE("Stub\n");
1727 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1728 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1731 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1732 TRACE("Stub\n");
1733 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1734 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1737 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1738 TRACE("Stub\n");
1739 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1740 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1743 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1744 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1745 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1749 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1750 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1751 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1755 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1756 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1757 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1761 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1762 if(stateblock->renderState[WINED3DRS_ROP2]) {
1763 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1767 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1768 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1769 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1773 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1774 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1775 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1779 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1780 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1781 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1785 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1786 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1787 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1791 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1792 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1793 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1797 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1798 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1799 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1803 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1804 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1805 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1809 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1810 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1811 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1815 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1816 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1817 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1821 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1822 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1823 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1827 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1828 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1829 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1833 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1834 #if defined (GL_VERSION_1_3)
1835 # define useext(A) A
1836 #elif defined (GL_EXT_texture_env_combine)
1837 # define useext(A) A##_EXT
1838 #elif defined (GL_ARB_texture_env_combine)
1839 # define useext(A) A##_ARB
1840 #endif
1842 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1843 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1844 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1845 * flag specifies the complement of the input should be used. */
1846 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1847 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1849 /* Calculate the operand */
1850 if (complement) {
1851 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1852 else *operand = GL_ONE_MINUS_SRC_COLOR;
1853 } else {
1854 if (from_alpha) *operand = GL_SRC_ALPHA;
1855 else *operand = GL_SRC_COLOR;
1858 /* Calculate the source */
1859 switch (arg & WINED3DTA_SELECTMASK) {
1860 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1861 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1862 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1863 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1864 case WINED3DTA_SPECULAR:
1866 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1867 * 'Secondary color' and isn't supported until base GL supports it
1868 * There is no concept of temp registers as far as I can tell
1870 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1871 *source = GL_TEXTURE;
1872 break;
1873 default:
1874 FIXME("Unrecognized texture arg %#x\n", arg);
1875 *source = GL_TEXTURE;
1876 break;
1880 /* Setup the texture operations texture stage states */
1881 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1883 GLenum src1, src2, src3;
1884 GLenum opr1, opr2, opr3;
1885 GLenum comb_target;
1886 GLenum src0_target, src1_target, src2_target;
1887 GLenum opr0_target, opr1_target, opr2_target;
1888 GLenum scal_target;
1889 GLenum opr=0, invopr, src3_target, opr3_target;
1890 BOOL Handled = FALSE;
1891 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1892 IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1894 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1896 /* This is called by a state handler which has the gl lock held and a context for the thread */
1898 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1899 the form (a1 <operation> a2). However, some of the more complex operations
1900 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1901 in a third parameter called a0. Therefore these are operations of the form
1902 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1904 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1905 functions below, expect their syntax to differ slightly to those listed in the
1906 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1907 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1909 if (isAlpha) {
1910 comb_target = useext(GL_COMBINE_ALPHA);
1911 src0_target = useext(GL_SOURCE0_ALPHA);
1912 src1_target = useext(GL_SOURCE1_ALPHA);
1913 src2_target = useext(GL_SOURCE2_ALPHA);
1914 opr0_target = useext(GL_OPERAND0_ALPHA);
1915 opr1_target = useext(GL_OPERAND1_ALPHA);
1916 opr2_target = useext(GL_OPERAND2_ALPHA);
1917 scal_target = GL_ALPHA_SCALE;
1919 else {
1920 comb_target = useext(GL_COMBINE_RGB);
1921 src0_target = useext(GL_SOURCE0_RGB);
1922 src1_target = useext(GL_SOURCE1_RGB);
1923 src2_target = useext(GL_SOURCE2_RGB);
1924 opr0_target = useext(GL_OPERAND0_RGB);
1925 opr1_target = useext(GL_OPERAND1_RGB);
1926 opr2_target = useext(GL_OPERAND2_RGB);
1927 scal_target = useext(GL_RGB_SCALE);
1930 /* If a texture stage references an invalid texture unit the stage just
1931 * passes through the result from the previous stage */
1932 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1933 arg1 = WINED3DTA_CURRENT;
1934 op = WINED3DTOP_SELECTARG1;
1937 /* From MSDN (WINED3DTSS_ALPHAARG1) :
1938 The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage,
1939 then the default argument is WINED3DTA_DIFFUSE.
1940 FIXME? If texture added/removed, may need to reset back as well? */
1941 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1942 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1943 } else {
1944 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1946 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1947 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1949 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1951 Handled = TRUE; /* Assume will be handled */
1953 /* Other texture operations require special extensions: */
1954 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1955 if (isAlpha) {
1956 opr = GL_SRC_ALPHA;
1957 invopr = GL_ONE_MINUS_SRC_ALPHA;
1958 src3_target = GL_SOURCE3_ALPHA_NV;
1959 opr3_target = GL_OPERAND3_ALPHA_NV;
1960 } else {
1961 opr = GL_SRC_COLOR;
1962 invopr = GL_ONE_MINUS_SRC_COLOR;
1963 src3_target = GL_SOURCE3_RGB_NV;
1964 opr3_target = GL_OPERAND3_RGB_NV;
1966 switch (op) {
1967 case WINED3DTOP_DISABLE: /* Only for alpha */
1968 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1969 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1970 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1971 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1972 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1973 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1974 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1975 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1976 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1977 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1978 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1979 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1980 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1981 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1982 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1983 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1984 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1985 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1986 break;
1987 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1988 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1989 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1990 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1991 if (op == WINED3DTOP_SELECTARG1) {
1992 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1993 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1994 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1995 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1996 } else {
1997 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1998 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1999 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2000 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2002 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2003 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2004 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2005 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2006 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2007 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2008 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2009 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2010 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2011 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2012 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2013 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2014 break;
2016 case WINED3DTOP_MODULATE:
2017 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2018 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2019 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2020 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2021 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2022 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2023 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2024 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2025 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2026 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2027 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2028 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2029 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2030 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2031 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2032 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2033 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2034 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2035 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2036 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2037 break;
2038 case WINED3DTOP_MODULATE2X:
2039 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2040 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2041 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2042 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2043 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2044 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2045 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2046 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2047 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2048 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2049 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2050 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2051 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2052 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2053 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2054 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2055 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2056 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2057 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2058 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2059 break;
2060 case WINED3DTOP_MODULATE4X:
2061 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2062 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2063 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2064 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2065 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2066 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2067 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2068 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2069 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2070 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2071 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2072 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2073 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2074 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2075 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2076 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2077 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2078 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2079 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2080 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2081 break;
2083 case WINED3DTOP_ADD:
2084 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2085 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2086 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2087 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2088 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2089 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2090 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2091 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2092 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2093 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2094 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2095 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2096 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2097 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2098 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2099 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2100 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2101 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2102 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2103 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2104 break;
2106 case WINED3DTOP_ADDSIGNED:
2107 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2108 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2109 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2110 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2111 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2112 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2113 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2114 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2115 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2116 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2117 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2118 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2119 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2120 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2121 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2122 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2123 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2124 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2125 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2126 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2127 break;
2129 case WINED3DTOP_ADDSIGNED2X:
2130 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2131 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2132 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2133 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2134 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2135 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2136 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2137 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2138 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2139 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2140 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2141 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2142 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2143 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2144 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2145 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2146 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2147 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2148 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2149 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2150 break;
2152 case WINED3DTOP_ADDSMOOTH:
2153 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2154 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2155 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2156 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2157 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2158 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2159 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2160 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2161 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2162 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2163 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2164 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2165 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2166 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2167 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2168 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2169 switch (opr1) {
2170 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2171 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2172 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2173 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2175 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2176 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2177 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2178 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2179 break;
2181 case WINED3DTOP_BLENDDIFFUSEALPHA:
2182 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2183 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2184 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2185 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2186 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2187 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2188 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2189 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2190 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2191 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2192 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2193 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2194 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2195 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2196 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2197 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2198 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2199 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2200 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2201 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2202 break;
2203 case WINED3DTOP_BLENDTEXTUREALPHA:
2204 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2205 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2206 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2207 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2208 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2209 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2210 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2211 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2212 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2213 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2214 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2215 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2216 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2217 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2218 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2219 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2220 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2221 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2222 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2223 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2224 break;
2225 case WINED3DTOP_BLENDFACTORALPHA:
2226 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2227 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2228 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2229 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2230 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2231 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2232 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2233 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2234 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2235 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2236 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2237 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2238 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2239 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2240 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2241 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2242 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2243 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2244 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2245 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2246 break;
2247 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2248 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2249 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2250 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2251 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2252 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2253 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2254 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2255 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2256 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2257 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2258 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2259 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2260 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2261 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2262 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2263 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2264 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2265 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2266 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2267 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2268 break;
2269 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2270 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2271 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2272 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2273 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2274 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2275 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2276 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2277 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2278 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2279 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2280 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2281 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2282 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2283 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2284 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2285 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2286 switch (opr) {
2287 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2288 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2290 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2291 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2292 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2293 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2294 break;
2295 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2296 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2297 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2298 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2299 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2300 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2301 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2302 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2303 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2304 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2305 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2306 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2307 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2308 switch (opr1) {
2309 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2310 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2312 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2313 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2314 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2315 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2316 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2317 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2318 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2319 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2320 break;
2321 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2322 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2323 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2324 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2325 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2326 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2327 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2328 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2329 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2330 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2331 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2332 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2333 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2334 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2335 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2336 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2337 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2338 switch (opr1) {
2339 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2340 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2341 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2342 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2344 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2345 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2346 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2347 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2348 break;
2349 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2350 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2351 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2352 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2353 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2354 switch (opr1) {
2355 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2356 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2357 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2358 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2360 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2361 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2362 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2363 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2364 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2365 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2366 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2367 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2368 switch (opr1) {
2369 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2370 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2372 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2373 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2374 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2375 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2376 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2377 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2378 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2379 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2380 break;
2381 case WINED3DTOP_MULTIPLYADD:
2382 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2383 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2384 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2385 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2386 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2387 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2388 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2389 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2390 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2391 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2392 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2393 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2394 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2395 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2396 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2397 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2398 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2399 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2400 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2401 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2402 break;
2404 case WINED3DTOP_BUMPENVMAP:
2408 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2409 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2411 default:
2412 Handled = FALSE;
2414 if (Handled) {
2415 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2416 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2418 return;
2420 } /* GL_NV_texture_env_combine4 */
2422 Handled = TRUE; /* Again, assume handled */
2423 switch (op) {
2424 case WINED3DTOP_DISABLE: /* Only for alpha */
2425 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2426 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2427 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2428 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2429 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2430 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2431 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2432 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2433 break;
2434 case WINED3DTOP_SELECTARG1:
2435 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2436 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2437 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2438 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2439 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2440 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2441 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2442 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2443 break;
2444 case WINED3DTOP_SELECTARG2:
2445 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2446 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2447 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2448 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2449 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2450 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2451 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2452 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2453 break;
2454 case WINED3DTOP_MODULATE:
2455 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2456 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2457 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2458 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2459 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2460 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2461 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2462 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2463 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2464 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2465 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2466 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2467 break;
2468 case WINED3DTOP_MODULATE2X:
2469 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2470 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2471 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2472 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2473 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2474 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2475 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2476 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2477 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2478 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2479 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2480 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2481 break;
2482 case WINED3DTOP_MODULATE4X:
2483 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2484 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2485 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2486 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2487 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2488 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2489 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2490 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2491 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2492 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2493 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2494 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2495 break;
2496 case WINED3DTOP_ADD:
2497 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2498 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2499 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2500 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2501 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2502 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2503 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2504 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2505 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2506 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2507 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2508 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2509 break;
2510 case WINED3DTOP_ADDSIGNED:
2511 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2512 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2513 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2514 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2515 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2516 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2517 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2518 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2519 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2520 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2521 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2522 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2523 break;
2524 case WINED3DTOP_ADDSIGNED2X:
2525 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2526 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2527 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2528 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2529 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2530 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2531 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2532 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2533 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2534 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2535 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2536 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2537 break;
2538 case WINED3DTOP_SUBTRACT:
2539 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2540 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2541 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2542 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2543 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2544 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2545 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2546 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2547 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2548 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2549 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2550 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2551 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2552 } else {
2553 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2555 break;
2557 case WINED3DTOP_BLENDDIFFUSEALPHA:
2558 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2559 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2560 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2561 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2562 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2563 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2564 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2565 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2566 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2567 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2568 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2569 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2570 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2571 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2572 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2573 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2574 break;
2575 case WINED3DTOP_BLENDTEXTUREALPHA:
2576 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2577 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2578 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2579 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2580 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2581 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2582 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2583 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2584 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2585 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2586 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2587 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2588 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2589 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2590 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2591 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2592 break;
2593 case WINED3DTOP_BLENDFACTORALPHA:
2594 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2595 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2596 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2597 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2598 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2599 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2600 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2601 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2602 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2603 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2604 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2605 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2606 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2607 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2608 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2609 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2610 break;
2611 case WINED3DTOP_BLENDCURRENTALPHA:
2612 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2613 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2614 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2615 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2616 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2617 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2618 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2619 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2620 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2621 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2622 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2623 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2624 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2625 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2626 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2627 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2628 break;
2629 case WINED3DTOP_DOTPRODUCT3:
2630 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2631 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2632 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2633 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2634 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2635 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2636 } else {
2637 FIXME("This version of opengl does not support GL_DOT3\n");
2639 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2640 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2641 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2642 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2643 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2644 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2645 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2646 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2647 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2648 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2649 break;
2650 case WINED3DTOP_LERP:
2651 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2652 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2653 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2654 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2655 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2656 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2657 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2658 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2659 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2660 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2661 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2662 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2663 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2664 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2665 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2666 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2667 break;
2668 case WINED3DTOP_ADDSMOOTH:
2669 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2670 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2671 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2672 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2673 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2674 switch (opr1) {
2675 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2676 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2677 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2678 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2680 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2681 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2682 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2683 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2684 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2685 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2686 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2687 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2688 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2689 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2690 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2691 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2692 } else
2693 Handled = FALSE;
2694 break;
2695 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2696 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2697 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2698 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2699 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2700 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2701 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2702 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2703 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2704 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2705 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2706 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2707 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2708 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2709 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2710 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2711 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2712 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2713 } else
2714 Handled = FALSE;
2715 break;
2716 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2717 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2718 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2719 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2720 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2721 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2722 switch (opr1) {
2723 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2724 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2725 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2726 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2728 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2729 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2730 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2731 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2732 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2733 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2734 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2735 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2736 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2737 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2738 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2739 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2740 } else
2741 Handled = FALSE;
2742 break;
2743 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2744 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2745 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2746 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2747 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2748 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2749 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2750 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2751 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2752 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2753 switch (opr1) {
2754 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2755 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2756 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2757 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2759 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2760 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2761 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2762 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2763 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2764 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2765 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2766 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2767 } else
2768 Handled = FALSE;
2769 break;
2770 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2771 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2772 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2773 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2774 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2775 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2776 switch (opr1) {
2777 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2778 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2779 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2780 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2782 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2783 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2784 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2785 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2786 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2787 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2788 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2789 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2790 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2791 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2792 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2793 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2794 } else
2795 Handled = FALSE;
2796 break;
2797 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2798 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2799 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2800 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2801 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2802 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2803 switch (opr1) {
2804 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2805 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2806 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2807 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2809 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2810 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2811 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2812 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2813 switch (opr1) {
2814 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2815 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2816 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2817 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2819 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2820 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2821 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2822 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2823 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2824 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2825 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2826 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2827 } else
2828 Handled = FALSE;
2829 break;
2830 case WINED3DTOP_MULTIPLYADD:
2831 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2832 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2833 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2834 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2835 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2836 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2837 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2838 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2839 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2840 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2841 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2842 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2843 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2844 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2845 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2846 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2847 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2848 } else
2849 Handled = FALSE;
2850 break;
2851 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2852 case WINED3DTOP_BUMPENVMAP:
2853 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2854 /* Technically texture shader support without register combiners is possible, but not expected to occur
2855 * on real world cards, so for now a fixme should be enough
2857 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2859 default:
2860 Handled = FALSE;
2863 if (Handled) {
2864 BOOL combineOK = TRUE;
2865 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2866 DWORD op2;
2868 if (isAlpha) {
2869 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2870 } else {
2871 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2874 /* Note: If COMBINE4 in effect can't go back to combine! */
2875 switch (op2) {
2876 case WINED3DTOP_ADDSMOOTH:
2877 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2878 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2879 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2880 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2881 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2882 case WINED3DTOP_MULTIPLYADD:
2883 /* Ignore those implemented in both cases */
2884 switch (op) {
2885 case WINED3DTOP_SELECTARG1:
2886 case WINED3DTOP_SELECTARG2:
2887 combineOK = FALSE;
2888 Handled = FALSE;
2889 break;
2890 default:
2891 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2892 return;
2897 if (combineOK) {
2898 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2899 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2901 return;
2905 /* After all the extensions, if still unhandled, report fixme */
2906 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2910 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2911 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2912 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2913 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2915 TRACE("Setting color op for stage %d\n", stage);
2917 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
2918 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2919 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2920 return;
2923 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2925 if (mapped_stage != -1) {
2926 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2927 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2928 FIXME("Attempt to enable unsupported stage!\n");
2929 return;
2931 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2932 checkGLcall("glActiveTextureARB");
2933 } else if (stage > 0) {
2934 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2935 return;
2939 if(stage >= stateblock->lowest_disabled_stage) {
2940 TRACE("Stage disabled\n");
2941 if (mapped_stage != -1) {
2942 /* Disable everything here */
2943 glDisable(GL_TEXTURE_2D);
2944 checkGLcall("glDisable(GL_TEXTURE_2D)");
2945 glDisable(GL_TEXTURE_3D);
2946 checkGLcall("glDisable(GL_TEXTURE_3D)");
2947 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2948 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2949 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2951 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2952 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2953 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2956 /* All done */
2957 return;
2960 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2961 * if the sampler for this stage is dirty
2963 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2964 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2967 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2968 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2969 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2970 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2971 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2974 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2975 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2976 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2977 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2978 DWORD op, arg1, arg2, arg0;
2980 TRACE("Setting alpha op for stage %d\n", stage);
2981 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2982 if (mapped_stage != -1) {
2983 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2984 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2985 FIXME("Attempt to enable unsupported stage!\n");
2986 return;
2988 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2989 checkGLcall("glActiveTextureARB");
2990 } else if (stage > 0) {
2991 /* We can't do anything here */
2992 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2993 return;
2997 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2998 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2999 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
3000 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
3002 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
3003 stateblock->textures[0] &&
3004 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
3005 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
3007 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
3008 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
3010 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
3011 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
3012 * cannot remove the texture's alpha channel entirely.
3014 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
3015 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
3016 * draw things like translucent text and perform other blending effects.
3018 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
3019 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
3020 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
3021 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
3022 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
3023 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
3024 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
3025 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
3027 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
3029 if(op == WINED3DTOP_DISABLE) {
3030 arg1 = WINED3DTA_TEXTURE;
3031 op = WINED3DTOP_SELECTARG1;
3033 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
3034 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
3035 arg2 = WINED3DTA_TEXTURE;
3036 op = WINED3DTOP_MODULATE;
3038 else arg1 = WINED3DTA_TEXTURE;
3040 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
3041 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
3042 arg1 = WINED3DTA_TEXTURE;
3043 op = WINED3DTOP_MODULATE;
3045 else arg2 = WINED3DTA_TEXTURE;
3050 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3051 * this if block here, and the other code(color keying, texture unit selection) are the same
3053 TRACE("Setting alpha op for stage %d\n", stage);
3054 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3055 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3056 op, arg1, arg2, arg0,
3057 mapped_stage,
3058 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
3059 } else {
3060 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3061 op, arg1, arg2, arg0);
3065 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3066 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3067 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3068 BOOL generated;
3069 int coordIdx;
3071 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3072 if(use_vs(stateblock->wineD3DDevice) ||
3073 isStateDirty(context, STATE_VDECL)) {
3074 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3075 return;
3078 if (mapped_stage == -1) return;
3080 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3081 if(mapped_stage >= GL_LIMITS(textures)) {
3082 return;
3084 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3085 checkGLcall("glActiveTextureARB");
3086 } else if (mapped_stage > 0) {
3087 /* We can't do anything here */
3088 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3089 return;
3091 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3092 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3094 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3095 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
3096 generated,
3097 context->last_was_rhw,
3098 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwStride ?
3099 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwType:
3100 WINED3DDECLTYPE_UNUSED,
3101 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3103 /* The sampler applying function calls us if this changes */
3104 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
3105 if(generated) {
3106 FIXME("Non-power2 texture being used with generated texture coords\n");
3108 TRACE("Non power two matrix multiply fixup\n");
3109 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3113 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3114 int texture_idx;
3116 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3117 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3118 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3122 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd, GLint *curVBO)
3124 const UINT *offset = stateblock->streamOffset;
3125 unsigned int mapped_stage = 0;
3126 unsigned int textureNo = 0;
3128 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
3129 /* Abort if we don't support the extension. */
3130 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
3131 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3132 return;
3135 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3136 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3138 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3139 if (mapped_stage == -1) continue;
3141 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
3142 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3143 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
3145 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
3146 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
3147 checkGLcall("glBindBufferARB");
3148 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
3151 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3152 checkGLcall("glClientActiveTextureARB");
3154 /* The coords to supply depend completely on the fvf / vertex shader */
3155 glTexCoordPointer(
3156 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
3157 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
3158 sd->u.s.texCoords[coordIdx].dwStride,
3159 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
3160 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3161 } else {
3162 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3165 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3166 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3167 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3168 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3172 checkGLcall("loadTexCoords");
3175 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3176 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3177 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3178 const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3179 const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3180 const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3181 const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3183 if (mapped_stage == -1) {
3184 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3185 return;
3188 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3189 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3190 return;
3192 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3193 checkGLcall("glActiveTextureARB");
3194 } else if (stage > 0) {
3195 /* We can't do anything here */
3196 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3197 return;
3200 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3202 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3203 * one flag, you can still specify an index value, which the system uses to
3204 * determine the texture wrapping mode.
3205 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3206 * means use the vertex position (camera-space) as the input texture coordinates
3207 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3208 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3209 * to the TEXCOORDINDEX value
3213 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3215 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
3216 case WINED3DTSS_TCI_PASSTHRU:
3217 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3218 glDisable(GL_TEXTURE_GEN_S);
3219 glDisable(GL_TEXTURE_GEN_T);
3220 glDisable(GL_TEXTURE_GEN_R);
3221 glDisable(GL_TEXTURE_GEN_Q);
3222 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3223 break;
3225 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3226 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3227 * as the input texture coordinates for this stage's texture transformation. This
3228 * equates roughly to EYE_LINEAR
3231 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3233 glMatrixMode(GL_MODELVIEW);
3234 glPushMatrix();
3235 glLoadIdentity();
3236 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3237 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3238 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3239 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3240 glPopMatrix();
3242 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3243 glEnable(GL_TEXTURE_GEN_S);
3244 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3245 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3246 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3247 glEnable(GL_TEXTURE_GEN_T);
3248 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3249 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3250 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3251 glEnable(GL_TEXTURE_GEN_R);
3252 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3253 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3254 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3256 break;
3258 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3260 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3261 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3263 glMatrixMode(GL_MODELVIEW);
3264 glPushMatrix();
3265 glLoadIdentity();
3266 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3267 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3268 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3269 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3270 glPopMatrix();
3272 glEnable(GL_TEXTURE_GEN_S);
3273 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3274 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3275 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3276 glEnable(GL_TEXTURE_GEN_T);
3277 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3278 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3279 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3280 glEnable(GL_TEXTURE_GEN_R);
3281 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3282 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3283 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3286 break;
3288 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3290 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3291 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3293 glMatrixMode(GL_MODELVIEW);
3294 glPushMatrix();
3295 glLoadIdentity();
3296 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3297 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3298 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3299 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3300 glPopMatrix();
3302 glEnable(GL_TEXTURE_GEN_S);
3303 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3304 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3305 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3306 glEnable(GL_TEXTURE_GEN_T);
3307 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3308 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3309 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3310 glEnable(GL_TEXTURE_GEN_R);
3311 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3312 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3313 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3316 break;
3318 /* Unhandled types: */
3319 default:
3320 /* Todo: */
3321 /* ? disable GL_TEXTURE_GEN_n ? */
3322 glDisable(GL_TEXTURE_GEN_S);
3323 glDisable(GL_TEXTURE_GEN_T);
3324 glDisable(GL_TEXTURE_GEN_R);
3325 glDisable(GL_TEXTURE_GEN_Q);
3326 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3327 break;
3330 /* Update the texture matrix */
3331 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3332 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3335 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3336 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3337 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3338 * and do all the things linked to it
3339 * TODO: Tidy that up to reload only the arrays of the changed unit
3341 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3343 unloadTexCoords(stateblock);
3344 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3348 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3349 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3351 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3352 * has an update pending
3354 if(isStateDirty(context, STATE_VDECL) ||
3355 isStateDirty(context, STATE_PIXELSHADER)) {
3356 return;
3359 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
3362 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3363 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3365 if(stateblock->pixelShader && stage != 0 &&
3366 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3367 /* The pixel shader has to know the luminance scale. Do a constants update if it
3368 * isn't scheduled anyway
3370 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3371 !isStateDirty(context, STATE_PIXELSHADER)) {
3372 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3377 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3378 BOOL texIsPow2 = FALSE;
3379 DWORD sampler = state - STATE_SAMPLER(0);
3380 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3382 if(!texture) return;
3383 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3384 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3385 * scaling is reapplied or removed, the texture matrix has to be reapplied
3387 * The mapped stage is already active because the sampler() function below, which is part of the
3388 * misc pipeline
3390 if(sampler < MAX_TEXTURES) {
3391 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
3392 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
3393 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
3394 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
3395 texIsPow2 = TRUE;
3397 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
3398 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
3399 texIsPow2 = TRUE;
3403 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
3404 context->lastWasPow2Texture[sampler] = texIsPow2;
3405 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3410 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3411 DWORD sampler = state - STATE_SAMPLER(0);
3412 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3413 union {
3414 float f;
3415 DWORD d;
3416 } tmpvalue;
3418 TRACE("Sampler: %d\n", sampler);
3419 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3420 * only has to bind textures and set the per texture states
3423 if (mapped_stage == -1) {
3424 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3425 return;
3428 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3429 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3430 return;
3432 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3433 checkGLcall("glActiveTextureARB");
3434 } else if (sampler > 0) {
3435 /* We can't do anything here */
3436 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3437 return;
3440 if(stateblock->textures[sampler]) {
3441 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
3442 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler]);
3443 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3445 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3446 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3447 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3448 GL_TEXTURE_LOD_BIAS_EXT,
3449 tmpvalue.f);
3450 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3453 if(!use_ps(stateblock->wineD3DDevice) && sampler < stateblock->lowest_disabled_stage) {
3454 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3455 /* If color keying is enabled update the alpha test, it depends on the existence
3456 * of a color key in stage 0
3458 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3461 } else if(mapped_stage < GL_LIMITS(textures)) {
3462 if(sampler < stateblock->lowest_disabled_stage) {
3463 /* TODO: What should I do with pixel shaders here ??? */
3464 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3465 /* If color keying is enabled update the alpha test, it depends on the existence
3466 * of a color key in stage 0
3468 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3470 } /* Otherwise tex_colorop disables the stage */
3471 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3472 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3476 static void apply_pshader_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3477 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3479 if (use_ps(device)) {
3480 if(!context->last_was_pshader) {
3481 state_fog(state, stateblock, context);
3483 context->last_was_pshader = TRUE;
3484 } else {
3485 if(context->last_was_pshader) {
3486 state_fog(state, stateblock, context);
3488 context->last_was_pshader = FALSE;
3492 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3493 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3494 BOOL use_pshader = use_ps(device);
3495 BOOL use_vshader = use_vs(device);
3496 int i;
3498 if (use_pshader) {
3499 if(!context->last_was_pshader) {
3500 /* Former draw without a pixel shader, some samplers
3501 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3502 * make sure to enable them
3504 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3505 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3506 sampler(STATE_SAMPLER(i), stateblock, context);
3509 } else {
3510 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3511 * if a different texture was bound. I don't have to do anything.
3514 } else {
3515 /* Disabled the pixel shader - color ops weren't applied
3516 * while it was enabled, so re-apply them.
3518 for(i=0; i < MAX_TEXTURES; i++) {
3519 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3520 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3521 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3526 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3527 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3529 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3530 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3535 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3536 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3537 if(stateblock->pixelShader && stage != 0 &&
3538 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3539 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3540 * anyway
3542 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3543 !isStateDirty(context, STATE_PIXELSHADER)) {
3544 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3549 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3550 /* This function is called by transform_view below if the view matrix was changed too
3552 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3553 * does not always update the world matrix, only on a switch between transformed
3554 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3555 * draw, but that should be rather rare and cheaper in total.
3557 glMatrixMode(GL_MODELVIEW);
3558 checkGLcall("glMatrixMode");
3560 if(context->last_was_rhw) {
3561 glLoadIdentity();
3562 checkGLcall("glLoadIdentity()");
3563 } else {
3564 /* In the general case, the view matrix is the identity matrix */
3565 if (stateblock->wineD3DDevice->view_ident) {
3566 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3567 checkGLcall("glLoadMatrixf");
3568 } else {
3569 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3570 checkGLcall("glLoadMatrixf");
3571 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3572 checkGLcall("glMultMatrixf");
3577 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3578 UINT index = state - STATE_CLIPPLANE(0);
3580 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3581 return;
3584 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3585 glMatrixMode(GL_MODELVIEW);
3586 glPushMatrix();
3587 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3589 TRACE("Clipplane [%f,%f,%f,%f]\n",
3590 stateblock->clipplane[index][0],
3591 stateblock->clipplane[index][1],
3592 stateblock->clipplane[index][2],
3593 stateblock->clipplane[index][3]);
3594 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3595 checkGLcall("glClipPlane");
3597 glPopMatrix();
3600 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3601 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3602 GLenum glMat;
3603 TRACE("Setting world matrix %d\n", matrix);
3605 if(matrix >= GL_LIMITS(blends)) {
3606 WARN("Unsupported blend matrix set\n");
3607 return;
3608 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3609 return;
3612 /* GL_MODELVIEW0_ARB: 0x1700
3613 * GL_MODELVIEW1_ARB: 0x850a
3614 * GL_MODELVIEW2_ARB: 0x8722
3615 * GL_MODELVIEW3_ARB: 0x8723
3616 * etc
3617 * GL_MODELVIEW31_ARB: 0x873F
3619 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3620 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3622 glMatrixMode(glMat);
3623 checkGLcall("glMatrixMode(glMat)");
3625 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3626 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3628 if(stateblock->wineD3DDevice->view_ident) {
3629 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3630 checkGLcall("glLoadMatrixf");
3631 } else {
3632 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3633 checkGLcall("glLoadMatrixf");
3634 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3635 checkGLcall("glMultMatrixf");
3639 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3640 static BOOL once = FALSE;
3642 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3643 case WINED3DVBF_1WEIGHTS:
3644 case WINED3DVBF_2WEIGHTS:
3645 case WINED3DVBF_3WEIGHTS:
3646 if(!once) {
3647 once = TRUE;
3648 /* TODO: Implement vertex blending in drawStridedSlow */
3649 FIXME("Vertex blending enabled, but not supported by hardware\n");
3651 break;
3653 case WINED3DVBF_TWEENING:
3654 WARN("Tweening not supported yet\n");
3658 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3659 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3661 switch(val) {
3662 case WINED3DVBF_1WEIGHTS:
3663 case WINED3DVBF_2WEIGHTS:
3664 case WINED3DVBF_3WEIGHTS:
3665 glEnable(GL_VERTEX_BLEND_ARB);
3666 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3668 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3669 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3671 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3673 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3674 int i;
3675 for(i = 1; i < GL_LIMITS(blends); i++) {
3676 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3677 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3680 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3682 break;
3684 case WINED3DVBF_DISABLE:
3685 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3686 glDisable(GL_VERTEX_BLEND_ARB);
3687 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3688 break;
3690 case WINED3DVBF_TWEENING:
3691 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3692 * vertex weights in the vertices?
3693 * For now we don't report that as supported, so a warn should suffice
3695 WARN("Tweening not supported yet\n");
3696 break;
3700 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3701 unsigned int k;
3703 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3704 * NOTE: We have to reset the positions even if the light/plane is not currently
3705 * enabled, since the call to enable it will not reset the position.
3706 * NOTE2: Apparently texture transforms do NOT need reapplying
3709 const PLIGHTINFOEL *light = NULL;
3711 glMatrixMode(GL_MODELVIEW);
3712 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3713 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3714 checkGLcall("glLoadMatrixf(...)");
3716 /* Reset lights. TODO: Call light apply func */
3717 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3718 light = stateblock->activeLights[k];
3719 if(!light) continue;
3720 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3721 checkGLcall("glLightfv posn");
3722 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3723 checkGLcall("glLightfv dirn");
3726 /* Reset Clipping Planes */
3727 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3728 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3729 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3733 if(context->last_was_rhw) {
3734 glLoadIdentity();
3735 checkGLcall("glLoadIdentity()");
3736 /* No need to update the world matrix, the identity is fine */
3737 return;
3740 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3741 * No need to do it here if the state is scheduled for update.
3743 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3744 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3747 /* Avoid looping over a number of matrices if the app never used the functionality */
3748 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3749 for(k = 1; k < GL_LIMITS(blends); k++) {
3750 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3751 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3757 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3758 glMatrixMode(GL_PROJECTION);
3759 checkGLcall("glMatrixMode(GL_PROJECTION)");
3760 glLoadIdentity();
3761 checkGLcall("glLoadIdentity");
3763 if(context->last_was_rhw) {
3764 double X, Y, height, width, minZ, maxZ;
3766 X = stateblock->viewport.X;
3767 Y = stateblock->viewport.Y;
3768 height = stateblock->viewport.Height;
3769 width = stateblock->viewport.Width;
3770 minZ = stateblock->viewport.MinZ;
3771 maxZ = stateblock->viewport.MaxZ;
3773 if(!stateblock->wineD3DDevice->untransformed) {
3774 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3775 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3776 * suppress depth clipping. This can be done because it is an orthogonal projection and
3777 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3778 * Persia 3D need this.
3780 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3781 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3782 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3783 * to the viewer.
3785 * Also note that this breaks z comparison against z values filled in with clear,
3786 * but no app depending on that and disabled clipping has been found yet. Comparing
3787 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3788 * surface removal.
3790 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3791 * but this would break Z buffer operation. Raising the range to something less than
3792 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3793 * problem either.
3795 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3796 if(stateblock->wineD3DDevice->render_offscreen) {
3797 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3798 } else {
3799 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3801 } else {
3802 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3803 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3804 * unmodified to opengl.
3806 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3807 * replacement shader.
3809 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3810 if(stateblock->wineD3DDevice->render_offscreen) {
3811 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3812 } else {
3813 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3816 checkGLcall("glOrtho");
3818 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3819 glTranslatef(0.5, 0.5, 0);
3820 checkGLcall("glTranslatef(0.5, 0.5, 0)");
3821 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3822 * render everything upside down when rendering offscreen. */
3823 if (stateblock->wineD3DDevice->render_offscreen) {
3824 glScalef(1.0, -1.0, 1.0);
3825 checkGLcall("glScalef");
3827 } else {
3828 /* The rule is that the window coordinate 0 does not correspond to the
3829 beginning of the first pixel, but the center of the first pixel.
3830 As a consequence if you want to correctly draw one line exactly from
3831 the left to the right end of the viewport (with all matrices set to
3832 be identity), the x coords of both ends of the line would be not
3833 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3834 instead.
3836 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3837 divide by the Width/Height, so we need the half range(1.0) to translate by
3838 half a pixel.
3840 The other fun is that d3d's output z range after the transformation is [0;1],
3841 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3842 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3843 of Z buffer precision and the clear values do not match in the z test. Thus scale
3844 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3848 * Careful with the order of operations here, we're essentially working backwards:
3849 * x = x + 1/w;
3850 * y = (y - 1/h) * flip;
3851 * z = z * 2 - 1;
3853 * Becomes:
3854 * glTranslatef(0.0, 0.0, -1.0);
3855 * glScalef(1.0, 1.0, 2.0);
3857 * glScalef(1.0, flip, 1.0);
3858 * glTranslatef(1/w, -1/h, 0.0);
3860 * This is equivalent to:
3861 * glTranslatef(1/w, -flip/h, -1.0)
3862 * glScalef(1.0, flip, 2.0);
3865 if (stateblock->wineD3DDevice->render_offscreen) {
3866 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3867 * render everything upside down when rendering offscreen. */
3868 glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3869 checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3870 glScalef(1.0, -1.0, 2.0);
3871 } else {
3872 glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3873 checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3874 glScalef(1.0, 1.0, 2.0);
3876 checkGLcall("glScalef");
3878 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3879 checkGLcall("glLoadMatrixf");
3883 /* This should match any arrays loaded in loadVertexData.
3884 * stateblock impl is required for GL_SUPPORT
3885 * TODO: Only load / unload arrays if we have to.
3887 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3888 glDisableClientState(GL_VERTEX_ARRAY);
3889 glDisableClientState(GL_NORMAL_ARRAY);
3890 glDisableClientState(GL_COLOR_ARRAY);
3891 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3892 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3894 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3895 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3897 unloadTexCoords(stateblock);
3900 /* This should match any arrays loaded in loadNumberedArrays
3901 * TODO: Only load / unload arrays if we have to.
3903 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
3904 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3905 GLint maxAttribs = 16;
3906 int i;
3908 /* Leave all the attribs disabled */
3909 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3910 /* MESA does not support it right not */
3911 if (glGetError() != GL_NO_ERROR)
3912 maxAttribs = 16;
3913 for (i = 0; i < maxAttribs; ++i) {
3914 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3915 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3916 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3917 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3918 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3919 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3920 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3922 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3923 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3927 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *strided)
3929 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3930 int i;
3931 const UINT *offset = stateblock->streamOffset;
3932 IWineD3DVertexBufferImpl *vb;
3933 DWORD_PTR shift_index;
3935 /* Default to no instancing */
3936 stateblock->wineD3DDevice->instancedDraw = FALSE;
3938 for (i = 0; i < MAX_ATTRIBS; i++) {
3940 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
3941 continue;
3943 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3944 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3945 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3946 stateblock->wineD3DDevice->instancedDraw = TRUE;
3947 continue;
3950 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3952 if(strided->u.input[i].dwStride) {
3953 if(curVBO != strided->u.input[i].VBO) {
3954 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3955 checkGLcall("glBindBufferARB");
3956 curVBO = strided->u.input[i].VBO;
3958 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3959 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3960 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3961 * vbo we won't be load converted attributes anyway
3963 if(curVBO && vb->conv_shift) {
3964 TRACE("Loading attribute from shifted buffer\n");
3965 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
3966 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3967 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3968 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3969 shift_index = shift_index % strided->u.input[i].dwStride;
3970 GL_EXTCALL(glVertexAttribPointerARB(i,
3971 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3972 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3973 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3974 vb->conv_stride,
3976 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
3977 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3978 offset[strided->u.input[i].streamNo]));
3980 } else {
3981 GL_EXTCALL(glVertexAttribPointerARB(i,
3982 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3983 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3984 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3985 strided->u.input[i].dwStride,
3987 strided->u.input[i].lpData +
3988 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3989 offset[strided->u.input[i].streamNo]) );
3991 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3992 } else {
3993 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3994 * set up the attribute statically. But we have to figure out the system memory address.
3996 const BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3997 if(strided->u.input[i].VBO) {
3998 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3999 ptr += (long) vb->resource.allocatedMemory;
4001 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
4003 switch(strided->u.input[i].dwType) {
4004 case WINED3DDECLTYPE_FLOAT1:
4005 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
4006 break;
4007 case WINED3DDECLTYPE_FLOAT2:
4008 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
4009 break;
4010 case WINED3DDECLTYPE_FLOAT3:
4011 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
4012 break;
4013 case WINED3DDECLTYPE_FLOAT4:
4014 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
4015 break;
4017 case WINED3DDECLTYPE_UBYTE4:
4018 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4019 break;
4020 case WINED3DDECLTYPE_UBYTE4N:
4021 case WINED3DDECLTYPE_D3DCOLOR:
4022 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4023 break;
4025 case WINED3DDECLTYPE_SHORT2:
4026 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4027 break;
4028 case WINED3DDECLTYPE_SHORT4:
4029 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4030 break;
4032 case WINED3DDECLTYPE_SHORT2N:
4034 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4035 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4036 break;
4038 case WINED3DDECLTYPE_USHORT2N:
4040 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4041 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4042 break;
4044 case WINED3DDECLTYPE_SHORT4N:
4045 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4046 break;
4047 case WINED3DDECLTYPE_USHORT4N:
4048 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4049 break;
4051 case WINED3DDECLTYPE_UDEC3:
4052 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4053 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4054 break;
4055 case WINED3DDECLTYPE_DEC3N:
4056 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4057 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4058 break;
4060 case WINED3DDECLTYPE_FLOAT16_2:
4061 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4062 * byte float according to the IEEE standard
4064 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4065 break;
4066 case WINED3DDECLTYPE_FLOAT16_4:
4067 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4068 break;
4070 case WINED3DDECLTYPE_UNUSED:
4071 default:
4072 ERR("Unexpected declaration in stride 0 attributes\n");
4073 break;
4078 checkGLcall("Loading numbered arrays");
4081 /* Used from 2 different functions, and too big to justify making it inlined */
4082 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd)
4084 const UINT *offset = stateblock->streamOffset;
4085 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
4087 TRACE("Using fast vertex array code\n");
4089 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4090 stateblock->wineD3DDevice->instancedDraw = FALSE;
4092 /* Blend Data ---------------------------------------------- */
4093 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
4094 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
4096 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4097 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
4098 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4100 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4101 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4103 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
4105 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4106 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
4107 sd->u.s.blendWeights.dwStride,
4108 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4110 if(curVBO != sd->u.s.blendWeights.VBO) {
4111 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
4112 checkGLcall("glBindBufferARB");
4113 curVBO = sd->u.s.blendWeights.VBO;
4116 GL_EXTCALL(glWeightPointerARB)(
4117 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
4118 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
4119 sd->u.s.blendWeights.dwStride,
4120 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4122 checkGLcall("glWeightPointerARB");
4124 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
4125 static BOOL warned;
4126 if (!warned)
4128 FIXME("blendMatrixIndices support\n");
4129 warned = TRUE;
4132 } else {
4133 /* TODO: support blends in drawStridedSlow
4134 * No need to write a FIXME here, this is done after the general vertex decl decoding
4136 WARN("unsupported blending in openGl\n");
4138 } else {
4139 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4140 static const GLbyte one = 1;
4141 GL_EXTCALL(glWeightbvARB(1, &one));
4142 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4146 /* Point Size ----------------------------------------------*/
4147 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
4149 /* no such functionality in the fixed function GL pipeline */
4150 TRACE("Cannot change ptSize here in openGl\n");
4151 /* TODO: Implement this function in using shaders if they are available */
4155 /* Vertex Pointers -----------------------------------------*/
4156 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
4157 /* Note dwType == float3 or float4 == 2 or 3 */
4158 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
4159 sd->u.s.position.dwStride,
4160 sd->u.s.position.dwType + 1,
4161 sd->u.s.position.lpData));
4163 if(curVBO != sd->u.s.position.VBO) {
4164 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
4165 checkGLcall("glBindBufferARB");
4166 curVBO = sd->u.s.position.VBO;
4169 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
4170 handling for rhw mode should not impact screen position whereas in GL it does.
4171 This may result in very slightly distorted textures in rhw mode.
4172 There's always the other option of fixing the view matrix to
4173 prevent w from having any effect.
4175 This only applies to user pointer sources, in VBOs the vertices are fixed up
4177 if(sd->u.s.position.VBO == 0) {
4178 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
4179 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4180 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4181 } else {
4182 glVertexPointer(
4183 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
4184 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4185 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4187 checkGLcall("glVertexPointer(...)");
4188 glEnableClientState(GL_VERTEX_ARRAY);
4189 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4192 /* Normals -------------------------------------------------*/
4193 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
4194 /* Note dwType == float3 or float4 == 2 or 3 */
4195 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
4196 sd->u.s.normal.dwStride,
4197 sd->u.s.normal.lpData));
4198 if(curVBO != sd->u.s.normal.VBO) {
4199 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
4200 checkGLcall("glBindBufferARB");
4201 curVBO = sd->u.s.normal.VBO;
4203 glNormalPointer(
4204 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
4205 sd->u.s.normal.dwStride,
4206 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
4207 checkGLcall("glNormalPointer(...)");
4208 glEnableClientState(GL_NORMAL_ARRAY);
4209 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4211 } else {
4212 glNormal3f(0, 0, 0);
4213 checkGLcall("glNormal3f(0, 0, 0)");
4216 /* Diffuse Colour --------------------------------------------*/
4217 /* WARNING: Data here MUST be in RGBA format, so cannot */
4218 /* go directly into fast mode from app pgm, because */
4219 /* directx requires data in BGRA format. */
4220 /* currently fixupVertices swizzles the format, but this isn't*/
4221 /* very practical when using VBOs */
4222 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4223 /* , or the user doesn't care and wants the speed advantage */
4225 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
4226 /* Note dwType == float3 or float4 == 2 or 3 */
4227 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4228 sd->u.s.diffuse.dwStride,
4229 sd->u.s.diffuse.lpData));
4231 if(curVBO != sd->u.s.diffuse.VBO) {
4232 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
4233 checkGLcall("glBindBufferARB");
4234 curVBO = sd->u.s.diffuse.VBO;
4237 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
4238 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
4239 sd->u.s.diffuse.dwStride,
4240 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
4241 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4242 glEnableClientState(GL_COLOR_ARRAY);
4243 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4245 } else {
4246 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4247 checkGLcall("glColor4f(1, 1, 1, 1)");
4250 /* Specular Colour ------------------------------------------*/
4251 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
4252 TRACE("setting specular colour\n");
4253 /* Note dwType == float3 or float4 == 2 or 3 */
4254 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4255 sd->u.s.specular.dwStride,
4256 sd->u.s.specular.lpData));
4257 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4258 if(curVBO != sd->u.s.specular.VBO) {
4259 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
4260 checkGLcall("glBindBufferARB");
4261 curVBO = sd->u.s.specular.VBO;
4263 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
4264 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
4265 sd->u.s.specular.dwStride,
4266 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
4267 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4268 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4269 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4270 } else {
4272 /* Missing specular color is not critical, no warnings */
4273 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4276 } else {
4277 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4278 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4279 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4280 } else {
4282 /* Missing specular color is not critical, no warnings */
4283 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4287 /* Texture coords -------------------------------------------*/
4288 loadTexCoords(stateblock, sd, &curVBO);
4291 static inline void drawPrimitiveTraceDataLocations(const WineDirect3DVertexStridedData *dataLocations)
4293 /* Dump out what parts we have supplied */
4294 TRACE("Strided Data:\n");
4295 TRACE_STRIDED((dataLocations), position);
4296 TRACE_STRIDED((dataLocations), blendWeights);
4297 TRACE_STRIDED((dataLocations), blendMatrixIndices);
4298 TRACE_STRIDED((dataLocations), normal);
4299 TRACE_STRIDED((dataLocations), pSize);
4300 TRACE_STRIDED((dataLocations), diffuse);
4301 TRACE_STRIDED((dataLocations), specular);
4302 TRACE_STRIDED((dataLocations), texCoords[0]);
4303 TRACE_STRIDED((dataLocations), texCoords[1]);
4304 TRACE_STRIDED((dataLocations), texCoords[2]);
4305 TRACE_STRIDED((dataLocations), texCoords[3]);
4306 TRACE_STRIDED((dataLocations), texCoords[4]);
4307 TRACE_STRIDED((dataLocations), texCoords[5]);
4308 TRACE_STRIDED((dataLocations), texCoords[6]);
4309 TRACE_STRIDED((dataLocations), texCoords[7]);
4310 TRACE_STRIDED((dataLocations), position2);
4311 TRACE_STRIDED((dataLocations), normal2);
4312 TRACE_STRIDED((dataLocations), tangent);
4313 TRACE_STRIDED((dataLocations), binormal);
4314 TRACE_STRIDED((dataLocations), tessFactor);
4315 TRACE_STRIDED((dataLocations), fog);
4316 TRACE_STRIDED((dataLocations), depth);
4317 TRACE_STRIDED((dataLocations), sample);
4319 return;
4322 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4323 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4324 BOOL fixup = FALSE;
4325 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
4326 BOOL useVertexShaderFunction;
4328 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
4329 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
4330 useVertexShaderFunction = TRUE;
4331 } else {
4332 useVertexShaderFunction = FALSE;
4336 if(device->up_strided) {
4337 /* Note: this is a ddraw fixed-function code path */
4338 TRACE("================ Strided Input ===================\n");
4339 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
4341 if(TRACE_ON(d3d)) {
4342 drawPrimitiveTraceDataLocations(dataLocations);
4344 } else {
4345 /* Note: This is a fixed function or shader codepath.
4346 * This means it must handle both types of strided data.
4347 * Shaders must go through here to zero the strided data, even if they
4348 * don't set any declaration at all
4350 TRACE("================ Vertex Declaration ===================\n");
4351 memset(dataLocations, 0, sizeof(*dataLocations));
4352 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
4353 useVertexShaderFunction, dataLocations, &fixup);
4356 if (dataLocations->u.s.position_transformed) {
4357 useVertexShaderFunction = FALSE;
4360 /* Unload the old arrays before loading the new ones to get old junk out */
4361 if(context->numberedArraysLoaded) {
4362 unloadNumberedArrays(stateblock);
4363 context->numberedArraysLoaded = FALSE;
4365 if(context->namedArraysLoaded) {
4366 unloadVertexData(stateblock);
4367 context->namedArraysLoaded = FALSE;
4370 if(useVertexShaderFunction) {
4371 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4372 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4373 device->useDrawStridedSlow = TRUE;
4374 context->numberedArraysLoaded = FALSE;
4375 } else {
4376 TRACE("Loading numbered arrays\n");
4377 loadNumberedArrays(stateblock, dataLocations);
4378 device->useDrawStridedSlow = FALSE;
4379 context->numberedArraysLoaded = TRUE;
4381 } else if (fixup ||
4382 (dataLocations->u.s.pSize.lpData == NULL &&
4383 dataLocations->u.s.diffuse.lpData == NULL &&
4384 dataLocations->u.s.specular.lpData == NULL)) {
4385 /* Load the vertex data using named arrays */
4386 TRACE("Loading vertex data\n");
4387 loadVertexData(stateblock, dataLocations);
4388 device->useDrawStridedSlow = FALSE;
4389 context->namedArraysLoaded = TRUE;
4390 } else {
4391 TRACE("Not loading vertex data\n");
4392 device->useDrawStridedSlow = TRUE;
4395 /* Generate some fixme's if unsupported functionality is being used */
4396 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
4397 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
4398 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
4399 FIXME("Tweening is only valid with vertex shaders\n");
4401 if (!useVertexShaderFunction && BUFFER_OR_DATA(binormal)) {
4402 FIXME("Binormal bump mapping is only valid with vertex shaders\n");
4404 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
4405 FIXME("Extended attributes are only valid with vertex shaders\n");
4407 #undef BUFFER_OR_DATA
4410 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4411 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
4412 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
4413 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
4414 BOOL transformed;
4415 /* Some stuff is in the device until we have per context tracking */
4416 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4417 BOOL wasrhw = context->last_was_rhw;
4419 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
4420 * here simply check whether a shader was set, or the user disabled shaders
4422 if (use_vs(device)) {
4423 useVertexShaderFunction = TRUE;
4425 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
4426 updateFog = TRUE;
4428 } else if(context->last_was_foggy_shader) {
4429 updateFog = TRUE;
4432 transformed = device->strided_streams.u.s.position_transformed;
4433 if (transformed) useVertexShaderFunction = FALSE;
4435 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4436 updateFog = TRUE;
4439 /* Reapply lighting if it is not scheduled for reapplication already */
4440 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4441 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4444 if (transformed) {
4445 context->last_was_rhw = TRUE;
4446 } else {
4448 /* Untransformed, so relies on the view and projection matrices */
4449 context->last_was_rhw = FALSE;
4450 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4451 device->untransformed = TRUE;
4453 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4454 * Not needed as long as only hw shaders are supported
4457 /* This sets the shader output position correction constants.
4458 * TODO: Move to the viewport state
4460 if (useVertexShaderFunction) {
4461 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4462 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4466 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4467 * off this function will be called again anyway to make sure they're properly set
4469 if(!useVertexShaderFunction) {
4470 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4471 * or transformed / untransformed was switched
4473 if(wasrhw != context->last_was_rhw &&
4474 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4475 !isStateDirty(context, STATE_VIEWPORT)) {
4476 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4478 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4479 * mode.
4481 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4482 * this check will fail and the matrix not applied again. This is OK because a simple
4483 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4484 * needs of the vertex declaration.
4486 * World and view matrix go into the same gl matrix, so only apply them when neither is
4487 * dirty
4489 if(transformed != wasrhw &&
4490 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4491 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4492 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4495 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4496 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4499 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4500 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4502 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4503 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4505 } else {
4506 if(!context->last_was_vshader) {
4507 int i;
4508 static BOOL warned = FALSE;
4509 /* Disable all clip planes to get defined results on all drivers. See comment in the
4510 * state_clipping state handler
4512 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4513 glDisable(GL_CLIP_PLANE0 + i);
4514 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4517 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4518 FIXME("Clipping not supported with vertex shaders\n");
4519 warned = TRUE;
4521 if(wasrhw) {
4522 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4523 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4524 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4525 * fixed function vertex processing states back in a sane state before switching to shaders
4527 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4528 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4530 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4531 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4537 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4538 * application
4540 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4541 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4543 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4544 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4548 context->last_was_vshader = useVertexShaderFunction;
4550 if(updateFog) {
4551 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
4553 if(!useVertexShaderFunction) {
4554 int i;
4555 for(i = 0; i < MAX_TEXTURES; i++) {
4556 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4557 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4563 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4564 UINT width, height;
4565 IWineD3DSurfaceImpl *target;
4567 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4568 checkGLcall("glDepthRange");
4569 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4571 if(stateblock->wineD3DDevice->render_offscreen) {
4572 glViewport(stateblock->viewport.X,
4573 stateblock->viewport.Y,
4574 stateblock->viewport.Width, stateblock->viewport.Height);
4575 } else {
4576 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4577 target->get_drawable_size(target, &width, &height);
4579 glViewport(stateblock->viewport.X,
4580 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4581 stateblock->viewport.Width, stateblock->viewport.Height);
4584 checkGLcall("glViewport");
4587 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4588 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4589 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4590 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4591 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4593 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4594 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4598 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4599 UINT Index = state - STATE_ACTIVELIGHT(0);
4600 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4602 if(!lightInfo) {
4603 glDisable(GL_LIGHT0 + Index);
4604 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4605 } else {
4606 float quad_att;
4607 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4609 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4610 glMatrixMode(GL_MODELVIEW);
4611 glPushMatrix();
4612 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4614 /* Diffuse: */
4615 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4616 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4617 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4618 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4619 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4620 checkGLcall("glLightfv");
4622 /* Specular */
4623 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4624 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4625 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4626 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4627 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4628 checkGLcall("glLightfv");
4630 /* Ambient */
4631 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4632 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4633 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4634 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4635 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4636 checkGLcall("glLightfv");
4638 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4639 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4640 } else {
4641 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
4644 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4645 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4646 * Attenuation0 to NaN and crashes in the gl lib
4649 switch (lightInfo->OriginalParms.Type) {
4650 case WINED3DLIGHT_POINT:
4651 /* Position */
4652 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4653 checkGLcall("glLightfv");
4654 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4655 checkGLcall("glLightf");
4656 /* Attenuation - Are these right? guessing... */
4657 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4658 checkGLcall("glLightf");
4659 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4660 checkGLcall("glLightf");
4661 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4662 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4663 checkGLcall("glLightf");
4664 /* FIXME: Range */
4665 break;
4667 case WINED3DLIGHT_SPOT:
4668 /* Position */
4669 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4670 checkGLcall("glLightfv");
4671 /* Direction */
4672 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4673 checkGLcall("glLightfv");
4674 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4675 checkGLcall("glLightf");
4676 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4677 checkGLcall("glLightf");
4678 /* Attenuation - Are these right? guessing... */
4679 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4680 checkGLcall("glLightf");
4681 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4682 checkGLcall("glLightf");
4683 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4684 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4685 checkGLcall("glLightf");
4686 /* FIXME: Range */
4687 break;
4689 case WINED3DLIGHT_DIRECTIONAL:
4690 /* Direction */
4691 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4692 checkGLcall("glLightfv");
4693 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4694 checkGLcall("glLightf");
4695 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4696 checkGLcall("glLightf");
4697 break;
4699 default:
4700 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4703 /* Restore the modelview matrix */
4704 glPopMatrix();
4706 glEnable(GL_LIGHT0 + Index);
4707 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4710 return;
4713 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4714 RECT *pRect = &stateblock->scissorRect;
4715 UINT height;
4716 UINT width;
4717 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4719 target->get_drawable_size(target, &width, &height);
4720 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4721 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4723 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4724 pRect->right - pRect->left, pRect->bottom - pRect->top);
4726 if (stateblock->wineD3DDevice->render_offscreen) {
4727 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4728 } else {
4729 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4731 checkGLcall("glScissor");
4734 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4735 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4736 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4737 } else {
4738 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
4739 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
4743 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4744 if(stateblock->wineD3DDevice->render_offscreen) {
4745 glFrontFace(GL_CCW);
4746 checkGLcall("glFrontFace(GL_CCW)");
4747 } else {
4748 glFrontFace(GL_CW);
4749 checkGLcall("glFrontFace(GL_CW)");
4753 const struct StateEntryTemplate misc_state_template[] = {
4754 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4755 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4756 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4757 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4758 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4759 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4760 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4761 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4762 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4763 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4764 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
4765 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
4766 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
4767 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
4768 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4769 * vshader loadings are untied from each other
4771 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4772 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4773 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4774 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4775 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4776 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4777 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4778 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4779 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4780 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4781 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4782 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4783 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4784 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4785 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4786 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4787 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4788 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4789 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4790 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4791 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4792 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4793 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4794 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4795 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4796 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4797 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4798 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4799 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4800 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4801 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4802 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4803 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4804 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4805 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4806 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4807 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4808 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4809 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4810 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4811 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4812 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4813 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4814 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4815 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4816 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4817 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4818 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4819 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4820 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4822 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
4823 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4824 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
4825 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
4826 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
4827 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
4828 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
4829 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
4830 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
4831 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
4832 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
4833 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
4834 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
4835 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
4836 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4837 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4838 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4839 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4840 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
4841 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
4842 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
4843 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
4844 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
4845 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
4846 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
4847 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
4848 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
4849 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
4850 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
4851 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
4852 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
4853 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4854 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4855 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4856 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4857 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4858 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4859 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4860 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4861 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
4862 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4863 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4864 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4865 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4866 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4867 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4868 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4869 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4870 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4871 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4872 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4873 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4874 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4875 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4876 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4877 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4878 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4879 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4880 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4881 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4882 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4883 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
4884 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
4885 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
4886 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
4887 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
4888 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
4889 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4890 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4891 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4892 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4893 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4894 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4895 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4896 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4897 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 },
4898 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
4899 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4900 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4901 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 },
4902 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
4903 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4904 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4905 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4906 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4907 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
4908 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 },
4909 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4910 /* Samplers */
4911 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
4912 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
4913 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
4914 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
4915 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
4916 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
4917 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
4918 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
4919 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
4920 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
4921 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
4922 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
4923 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
4924 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
4925 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
4926 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
4927 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
4928 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
4929 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
4930 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
4931 {0 /* Terminate */, { 0, 0 }, 0 },
4934 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4935 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
4936 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
4937 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4938 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4939 /* Clip planes */
4940 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
4941 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
4942 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
4943 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
4944 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
4945 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
4946 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
4947 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
4948 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
4949 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
4950 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
4951 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
4952 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
4953 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
4954 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
4955 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
4956 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
4957 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
4958 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
4959 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
4960 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
4961 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
4962 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
4963 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
4964 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
4965 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
4966 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
4967 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
4968 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
4969 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
4970 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
4971 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
4972 /* Lights */
4973 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
4974 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
4975 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
4976 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
4977 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
4978 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
4979 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
4980 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
4981 /* Viewport */
4982 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
4983 /* Transform states follow */
4984 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
4985 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
4986 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4987 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4988 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4989 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4990 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4991 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4992 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4993 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4994 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4995 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, 0 },
4996 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, 0 },
4997 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, 0 },
4998 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, 0 },
4999 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, 0 },
5000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, 0 },
5001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, 0 },
5002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, 0 },
5003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, 0 },
5004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, 0 },
5005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, 0 },
5006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, 0 },
5007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, 0 },
5008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, 0 },
5009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, 0 },
5010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, 0 },
5011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, 0 },
5012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, 0 },
5013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, 0 },
5014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, 0 },
5015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, 0 },
5016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, 0 },
5017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, 0 },
5018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, 0 },
5019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, 0 },
5020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, 0 },
5021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, 0 },
5022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, 0 },
5023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, 0 },
5024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, 0 },
5025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, 0 },
5026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, 0 },
5027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, 0 },
5028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, 0 },
5029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, 0 },
5030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, 0 },
5031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, 0 },
5032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, 0 },
5033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, 0 },
5034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, 0 },
5035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, 0 },
5036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, 0 },
5037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, 0 },
5038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, 0 },
5039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, 0 },
5040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, 0 },
5041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, 0 },
5042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, 0 },
5043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, 0 },
5044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, 0 },
5045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, 0 },
5046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, 0 },
5047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, 0 },
5048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, 0 },
5049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, 0 },
5050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, 0 },
5051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, 0 },
5052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, 0 },
5053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, 0 },
5054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, 0 },
5055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, 0 },
5056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, 0 },
5057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, 0 },
5058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, 0 },
5059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, 0 },
5060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, 0 },
5061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, 0 },
5062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, 0 },
5063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, 0 },
5064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, 0 },
5065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, 0 },
5066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, 0 },
5067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, 0 },
5068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, 0 },
5069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, 0 },
5070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, 0 },
5071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, 0 },
5072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, 0 },
5073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, 0 },
5074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, 0 },
5075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, 0 },
5076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, 0 },
5077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, 0 },
5078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, 0 },
5079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, 0 },
5080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, 0 },
5081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, 0 },
5082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, 0 },
5083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, 0 },
5084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, 0 },
5085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, 0 },
5086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, 0 },
5087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, 0 },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, 0 },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, 0 },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, 0 },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, 0 },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, 0 },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, 0 },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, 0 },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, 0 },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, 0 },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, 0 },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, 0 },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, 0 },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, 0 },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, 0 },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, 0 },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, 0 },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, 0 },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, 0 },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, 0 },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, 0 },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, 0 },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, 0 },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, 0 },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, 0 },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, 0 },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, 0 },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, 0 },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, 0 },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, 0 },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, 0 },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, 0 },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, 0 },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, 0 },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, 0 },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, 0 },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, 0 },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, 0 },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, 0 },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, 0 },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, 0 },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, 0 },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, 0 },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, 0 },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, 0 },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, 0 },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, 0 },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, 0 },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, 0 },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, 0 },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, 0 },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, 0 },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, 0 },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, 0 },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, 0 },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, 0 },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, 0 },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, 0 },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, 0 },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, 0 },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, 0 },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, 0 },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, 0 },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, 0 },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, 0 },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, 0 },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, 0 },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, 0 },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, 0 },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, 0 },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, 0 },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, 0 },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, 0 },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, 0 },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, 0 },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, 0 },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, 0 },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, 0 },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, 0 },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, 0 },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, 0 },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, 0 },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, 0 },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, 0 },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, 0 },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, 0 },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, 0 },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, 0 },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, 0 },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, 0 },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, 0 },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, 0 },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, 0 },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, 0 },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, 0 },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, 0 },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, 0 },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, 0 },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, 0 },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, 0 },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, 0 },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, 0 },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, 0 },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, 0 },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, 0 },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, 0 },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, 0 },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, 0 },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, 0 },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, 0 },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, 0 },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, 0 },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, 0 },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, 0 },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, 0 },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, 0 },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, 0 },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, 0 },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, 0 },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, 0 },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, 0 },
5208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, 0 },
5209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, 0 },
5210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, 0 },
5211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, 0 },
5212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, 0 },
5213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, 0 },
5214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, 0 },
5215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, 0 },
5216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, 0 },
5217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, 0 },
5218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, 0 },
5219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, 0 },
5220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, 0 },
5221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, 0 },
5222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, 0 },
5223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, 0 },
5224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, 0 },
5225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, 0 },
5226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, 0 },
5227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, 0 },
5228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, 0 },
5229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, 0 },
5230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, 0 },
5231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, 0 },
5232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, 0 },
5233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, 0 },
5234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, 0 },
5235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, 0 },
5236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, 0 },
5237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, 0 },
5238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, 0 },
5239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, 0 },
5240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, 0 },
5241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, 0 },
5242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, 0 },
5243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, 0 },
5244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, 0 },
5245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, 0 },
5246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, 0 },
5247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, 0 },
5248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, 0 },
5249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, 0 },
5250 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5251 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5252 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5253 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5254 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5255 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5256 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5257 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5258 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5259 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5260 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5261 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5262 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5263 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5264 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5265 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5266 /* Fog */
5267 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5268 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5269 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5270 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5271 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5272 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
5273 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
5274 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5275 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 },
5276 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5277 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5278 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
5279 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
5280 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5281 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
5282 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
5283 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5284 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5285 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5286 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5287 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5288 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, 0 },
5289 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5290 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5291 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5292 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5293 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5294 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 },
5295 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5296 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5297 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5298 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5299 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5300 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5301 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5302 /* pixel shaders need a different fog input */
5303 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pshader_fog }, 0 },
5304 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5305 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5306 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5308 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5309 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5310 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
5311 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5312 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5313 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
5314 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5315 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5316 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
5317 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5318 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5319 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
5320 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5321 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5322 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
5323 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5324 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5325 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
5326 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5327 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5328 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
5329 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5330 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5331 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
5332 {0 /* Terminate */, { 0, 0 }, 0 },
5335 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5336 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5337 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5338 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5339 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5340 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5341 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5342 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5343 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5344 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5345 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5346 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5347 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5348 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5349 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5350 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5351 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5352 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5353 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5354 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5355 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5356 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5357 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5358 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5359 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5360 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5361 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5362 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5363 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5364 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5365 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5366 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5367 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5368 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5369 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5370 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5371 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5372 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5373 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5374 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5375 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5376 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5377 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5378 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5379 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5380 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5381 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5382 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5383 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5384 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5385 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5386 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5387 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5388 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5389 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5390 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5391 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5392 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5393 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5394 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5395 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5396 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5397 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5398 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5399 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5400 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5401 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5402 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5403 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5404 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5405 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5406 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5407 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5408 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5409 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5410 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5411 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5412 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5413 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5414 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5415 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5416 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5417 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5418 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
5419 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
5420 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
5421 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
5422 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
5423 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
5424 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
5425 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
5426 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
5427 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
5428 {0 /* Terminate */, { 0, 0 }, 0 },
5430 #undef GLINFO_LOCATION
5432 #define GLINFO_LOCATION (*gl_info)
5433 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5435 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5437 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5438 WINED3DTEXOPCAPS_ADDSIGNED |
5439 WINED3DTEXOPCAPS_ADDSIGNED2X |
5440 WINED3DTEXOPCAPS_MODULATE |
5441 WINED3DTEXOPCAPS_MODULATE2X |
5442 WINED3DTEXOPCAPS_MODULATE4X |
5443 WINED3DTEXOPCAPS_SELECTARG1 |
5444 WINED3DTEXOPCAPS_SELECTARG2 |
5445 WINED3DTEXOPCAPS_DISABLE;
5447 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5448 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5449 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5450 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5451 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5452 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5453 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5454 WINED3DTEXOPCAPS_LERP |
5455 WINED3DTEXOPCAPS_SUBTRACT;
5457 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5458 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5459 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5460 WINED3DTEXOPCAPS_MULTIPLYADD |
5461 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5462 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5463 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5465 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5466 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5468 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5469 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5472 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5473 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5474 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5476 if (TRACE_ON(d3d))
5478 TRACE("Checking support for fixup:\n");
5479 dump_color_fixup_desc(fixup);
5482 /* We only support identity conversions. */
5483 if (is_identity_fixup(fixup))
5485 TRACE("[OK]\n");
5486 return TRUE;
5489 TRACE("[FAILED]\n");
5490 return FALSE;
5493 const struct fragment_pipeline ffp_fragment_pipeline = {
5494 ffp_enable,
5495 ffp_fragment_get_caps,
5496 ffp_fragment_alloc,
5497 ffp_fragment_free,
5498 ffp_color_fixup_supported,
5499 ffp_fragmentstate_template,
5500 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5503 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5505 unsigned int i;
5506 for(i = 0; funcs[i]; i++);
5507 return i;
5510 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5511 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5512 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5515 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5516 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5517 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5518 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5521 void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5522 const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5523 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5525 unsigned int i, type, handlers;
5526 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5527 const struct StateEntryTemplate *cur;
5528 BOOL set[STATE_HIGHEST + 1];
5530 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5532 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5533 StateTable[i].representative = 0;
5534 StateTable[i].apply = state_undefined;
5537 for(type = 0; type < 3; type++) {
5538 /* This switch decides the order in which the states are applied */
5539 switch(type) {
5540 case 0: cur = misc; break;
5541 case 1: cur = fragment->states; break;
5542 case 2: cur = vertex; break;
5543 default: cur = NULL; /* Stupid compiler */
5545 if(!cur) continue;
5547 /* GL extension filtering should not prevent multiple handlers being applied from different
5548 * pipeline parts
5550 memset(set, 0, sizeof(set));
5552 for(i = 0; cur[i].state; i++) {
5554 /* Only use the first matching state with the available extension from one template.
5555 * e.g.
5556 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5557 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5559 * if GL_XYZ_fancy is supported, ignore the 2nd line
5561 if(set[cur[i].state]) continue;
5562 /* Skip state lines depending on unsupported extensions */
5563 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5564 set[cur[i].state] = TRUE;
5565 /* In some cases having an extension means that nothing has to be
5566 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5567 * supported, the texture coordinate fixup can be ignored. If the
5568 * apply function is used, mark the state set(done above) to prevent
5569 * applying later lines, but do not record anything in the state
5570 * table
5572 if(!cur[i].content.apply) continue;
5574 handlers = num_handlers(multistate_funcs[cur[i].state]);
5575 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5576 switch(handlers) {
5577 case 0:
5578 StateTable[cur[i].state].apply = cur[i].content.apply;
5579 break;
5580 case 1:
5581 StateTable[cur[i].state].apply = multistate_apply_2;
5582 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5584 sizeof(**dev_multistate_funcs) * 2);
5585 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5586 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5587 break;
5588 case 2:
5589 StateTable[cur[i].state].apply = multistate_apply_3;
5590 HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
5591 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5593 sizeof(**dev_multistate_funcs) * 3);
5594 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5595 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5596 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5597 break;
5598 default:
5599 ERR("Unexpected amount of state handlers for state %u: %u\n",
5600 cur[i].state, handlers + 1);
5603 if(StateTable[cur[i].state].representative &&
5604 StateTable[cur[i].state].representative != cur[i].content.representative) {
5605 FIXME("State %u has different representatives in different pipeline parts\n",
5606 cur[i].state);
5608 StateTable[cur[i].state].representative = cur[i].content.representative;
5612 #undef GLINFO_LOCATION