wined3d: Initial post pixelshader blending support. [attempt 2].
[wine/wine-kai.git] / dlls / wined3d / state.c
blob171827371bcc4b877b8f39ff6dee08e8de817af7
1 /*
2 * Direct3D state management
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2007 Stefan Dösinger for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
39 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
45 if(STATE_IS_RENDER(state)) {
46 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
48 } else {
49 /* Shouldn't have an unknown type here */
50 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56 * list without causing confusing terminal output. Deliberately no special debug name here
57 * because its undefined.
59 WARN("undefined state %d\n", state);
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
65 switch(Value) {
66 case WINED3DFILL_POINT:
67 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
69 break;
70 case WINED3DFILL_WIREFRAME:
71 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
73 break;
74 case WINED3DFILL_SOLID:
75 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
77 break;
78 default:
79 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
84 BOOL transformed;
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
93 return;
96 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
97 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
98 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
100 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
101 glEnable(GL_LIGHTING);
102 checkGLcall("glEnable GL_LIGHTING");
103 } else {
104 glDisable(GL_LIGHTING);
105 checkGLcall("glDisable GL_LIGHTING");
109 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
110 /* No z test without depth stencil buffers */
111 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
112 TRACE("No Z buffer - disabling depth test\n");
113 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
114 checkGLcall("glDisable GL_DEPTH_TEST");
115 return;
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
122 break;
123 case WINED3DZB_TRUE:
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
126 break;
127 case WINED3DZB_USEW:
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
131 break;
132 default:
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
138 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
139 * switch
141 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
142 case WINED3DCULL_NONE:
143 glDisable(GL_CULL_FACE);
144 checkGLcall("glDisable GL_CULL_FACE");
145 break;
146 case WINED3DCULL_CW:
147 glEnable(GL_CULL_FACE);
148 checkGLcall("glEnable GL_CULL_FACE");
149 glCullFace(GL_FRONT);
150 checkGLcall("glCullFace(GL_FRONT)");
151 break;
152 case WINED3DCULL_CCW:
153 glEnable(GL_CULL_FACE);
154 checkGLcall("glEnable GL_CULL_FACE");
155 glCullFace(GL_BACK);
156 checkGLcall("glCullFace(GL_BACK)");
157 break;
158 default:
159 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
163 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
164 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
165 case WINED3DSHADE_FLAT:
166 glShadeModel(GL_FLAT);
167 checkGLcall("glShadeModel(GL_FLAT)");
168 break;
169 case WINED3DSHADE_GOURAUD:
170 glShadeModel(GL_SMOOTH);
171 checkGLcall("glShadeModel(GL_SMOOTH)");
172 break;
173 case WINED3DSHADE_PHONG:
174 FIXME("WINED3DSHADE_PHONG isn't supported\n");
175 break;
176 default:
177 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
181 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
182 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
183 glEnable(GL_DITHER);
184 checkGLcall("glEnable GL_DITHER");
185 } else {
186 glDisable(GL_DITHER);
187 checkGLcall("glDisable GL_DITHER");
191 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
192 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
193 * this has to be merged with ZENABLE and ZFUNC
195 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
196 glDepthMask(1);
197 checkGLcall("glDepthMask(1)");
198 } else {
199 glDepthMask(0);
200 checkGLcall("glDepthMask(0)");
204 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
205 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
207 if(glParm) {
208 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
209 static BOOL once = FALSE;
210 /* There are a few issues with this: First, our inability to
211 * select a proper Z depth, most of the time we're stuck with
212 * D24S8, even if the app selects D32 or D16. There seem to be
213 * some other precision problems which have to be debugged to
214 * make NOTEQUAL and EQUAL work properly
216 if(!once) {
217 once = TRUE;
218 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
222 glDepthFunc(glParm);
223 checkGLcall("glDepthFunc");
227 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
228 float col[4];
229 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
231 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
232 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
233 checkGLcall("glLightModel for MODEL_AMBIENT");
236 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
237 int srcBlend = GL_ZERO;
238 int dstBlend = GL_ZERO;
239 const StaticPixelFormatDesc *rtFormat;
240 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
242 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
243 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
244 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
245 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
246 const GlPixelFormatDesc *glDesc;
247 getFormatDescEntry(target->resource.format, &GLINFO_LOCATION, &glDesc);
249 /* When pixel shaders are used on a format that doesn't offer blending, disable blending else we could face a big performance penalty. */
250 if(!(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) && use_ps(stateblock->wineD3DDevice)) {
251 glDisable(GL_BLEND);
252 checkGLcall("glDisable GL_BLEND");
253 return;
254 } else {
255 glEnable(GL_BLEND);
256 checkGLcall("glEnable GL_BLEND");
258 } else {
259 glDisable(GL_BLEND);
260 checkGLcall("glDisable GL_BLEND");
261 /* Nothing more to do - get out */
262 return;
265 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
266 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
267 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
268 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
269 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
270 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
271 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
272 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
273 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
275 /* To compensate the lack of format switching with backbuffer offscreen rendering,
276 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
277 * if the render target doesn't support alpha blending. A nonexistent alpha channel
278 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
280 case WINED3DBLEND_DESTALPHA :
281 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
282 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
283 break;
284 case WINED3DBLEND_INVDESTALPHA :
285 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
286 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
287 break;
289 case WINED3DBLEND_SRCALPHASAT :
290 dstBlend = GL_SRC_ALPHA_SATURATE;
291 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
292 break;
294 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
295 * values which are still valid up to d3d9. They should not occur as dest blend values
297 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
298 srcBlend = GL_SRC_ALPHA;
299 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
300 break;
302 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
303 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
304 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
305 break;
307 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
308 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
309 default:
310 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
313 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
314 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
315 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
316 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
317 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
318 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
319 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
320 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
321 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
322 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
324 case WINED3DBLEND_DESTALPHA :
325 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
326 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
327 break;
328 case WINED3DBLEND_INVDESTALPHA :
329 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
330 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
331 break;
333 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
334 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
335 break;
337 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
338 dstBlend = GL_SRC_ALPHA;
339 break;
341 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
342 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
343 default:
344 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
347 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
348 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
349 glEnable(GL_LINE_SMOOTH);
350 checkGLcall("glEnable(GL_LINE_SMOOTH)");
351 if(srcBlend != GL_SRC_ALPHA) {
352 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
354 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
355 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
357 } else {
358 glDisable(GL_LINE_SMOOTH);
359 checkGLcall("glDisable(GL_LINE_SMOOTH)");
362 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
363 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
364 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
367 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
368 int srcBlendAlpha = GL_ZERO;
369 int dstBlendAlpha = GL_ZERO;
371 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
372 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
373 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
374 return;
377 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
378 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
379 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
380 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
381 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
382 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
383 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
384 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
385 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
386 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
387 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
388 case WINED3DBLEND_SRCALPHASAT :
389 dstBlend = GL_SRC_ALPHA_SATURATE;
390 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
391 break;
392 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
393 * values which are still valid up to d3d9. They should not occur as dest blend values
395 case WINED3DBLEND_BOTHSRCALPHA :
396 dstBlendAlpha = GL_SRC_ALPHA;
397 srcBlendAlpha = GL_SRC_ALPHA;
398 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
399 break;
400 case WINED3DBLEND_BOTHINVSRCALPHA :
401 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
402 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
403 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
404 break;
405 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
406 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
407 default:
408 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
411 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
412 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
413 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
414 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
415 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
416 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
417 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
418 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
419 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
420 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
421 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
422 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
423 case WINED3DBLEND_BOTHSRCALPHA :
424 srcBlendAlpha = GL_SRC_ALPHA;
425 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
426 break;
427 case WINED3DBLEND_BOTHINVSRCALPHA :
428 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
429 dstBlendAlpha = GL_SRC_ALPHA;
430 break;
431 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
432 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
433 default:
434 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
437 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
438 checkGLcall("glBlendFuncSeparateEXT");
439 } else {
440 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
441 glBlendFunc(srcBlend, dstBlend);
442 checkGLcall("glBlendFunc");
445 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
446 so it may need updating */
447 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
448 const struct StateEntry *StateTable = stateblock->wineD3DDevice->shader_backend->StateTable;
449 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
453 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
454 float col[4];
456 if(!GL_SUPPORT(EXT_BLEND_COLOR)) {
457 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
458 return;
461 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
462 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
463 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
464 checkGLcall("glBlendColor");
467 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
468 int glParm = 0;
469 float ref;
470 BOOL enable_ckey = FALSE;
472 IWineD3DSurfaceImpl *surf;
474 /* Find out if the texture on the first stage has a ckey set
475 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
476 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
477 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
478 * in case it finds some texture+colorkeyenable combination which needs extra care.
480 if(stateblock->textures[0] && (
481 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
482 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
483 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
485 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
486 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
487 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
488 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
489 * surface has alpha bits
491 if(fmt->alphaMask == 0x00000000) {
492 enable_ckey = TRUE;
497 if(enable_ckey || context->last_was_ckey) {
498 const struct StateEntry *StateTable = stateblock->wineD3DDevice->shader_backend->StateTable;
499 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
501 context->last_was_ckey = enable_ckey;
503 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
504 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
505 glEnable(GL_ALPHA_TEST);
506 checkGLcall("glEnable GL_ALPHA_TEST");
507 } else {
508 glDisable(GL_ALPHA_TEST);
509 checkGLcall("glDisable GL_ALPHA_TEST");
510 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
511 * enable call
513 return;
516 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
517 glParm = GL_NOTEQUAL;
518 ref = 0.0;
519 } else {
520 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
521 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
523 if(glParm) {
524 glAlphaFunc(glParm, ref);
525 checkGLcall("glAlphaFunc");
529 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
530 DWORD enable = 0xFFFFFFFF;
531 DWORD disable = 0x00000000;
533 if (use_vs(stateblock->wineD3DDevice)) {
534 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
535 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
536 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
537 * of that - don't do anything here and keep them disabled
539 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
540 static BOOL warned = FALSE;
541 if(!warned) {
542 FIXME("Clipping not supported with vertex shaders\n");
543 warned = TRUE;
546 return;
549 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
550 * of already set values
553 /* If enabling / disabling all
554 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
556 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
557 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
558 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
559 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
560 glDisable(GL_DEPTH_CLAMP_NV);
561 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
563 } else {
564 disable = 0xffffffff;
565 enable = 0x00;
566 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
567 glEnable(GL_DEPTH_CLAMP_NV);
568 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
572 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
573 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
574 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
575 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
576 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
577 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
579 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
580 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
581 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
582 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
583 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
584 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
586 /** update clipping status */
587 if (enable) {
588 stateblock->clip_status.ClipUnion = 0;
589 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
590 } else {
591 stateblock->clip_status.ClipUnion = 0;
592 stateblock->clip_status.ClipIntersection = 0;
596 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
597 int blendEquation = GL_FUNC_ADD;
598 int blendEquationAlpha = GL_FUNC_ADD;
600 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
601 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
602 return;
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 dissortions.
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 float 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 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
752 /* And now the default texture color as well */
753 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
754 /* Note the WINED3DRS value applies to all textures, but GL has one
755 * per texture, so apply it now ready to be used!
757 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
758 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
759 checkGLcall("glActiveTextureARB");
760 } else if (i>0) {
761 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
764 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
765 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
767 } else {
768 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
772 static void
773 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
774 #if 0 /* Don't use OpenGL 2.0 calls for now */
775 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
776 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
777 checkGLcall("glStencilFuncSeparate(...)");
778 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
779 checkGLcall("glStencilOpSeparate(...)");
781 else
782 #endif
783 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
784 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
785 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
786 GL_EXTCALL(glActiveStencilFaceEXT(face));
787 checkGLcall("glActiveStencilFaceEXT(...)");
788 glStencilFunc(func, ref, mask);
789 checkGLcall("glStencilFunc(...)");
790 glStencilOp(stencilFail, depthFail, stencilPass);
791 checkGLcall("glStencilOp(...)");
792 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
793 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
794 checkGLcall("glStencilFuncSeparateATI(...)");
795 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
796 checkGLcall("glStencilOpSeparateATI(...)");
797 } else {
798 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
802 static void
803 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
804 DWORD onesided_enable = FALSE;
805 DWORD twosided_enable = FALSE;
806 GLint func = GL_ALWAYS;
807 GLint func_ccw = GL_ALWAYS;
808 GLint ref = 0;
809 GLuint mask = 0;
810 GLint stencilFail = GL_KEEP;
811 GLint depthFail = GL_KEEP;
812 GLint stencilPass = GL_KEEP;
813 GLint stencilFail_ccw = GL_KEEP;
814 GLint depthFail_ccw = GL_KEEP;
815 GLint stencilPass_ccw = GL_KEEP;
817 /* No stencil test without a stencil buffer */
818 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
819 glDisable(GL_STENCIL_TEST);
820 checkGLcall("glDisable GL_STENCIL_TEST");
821 return;
824 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
825 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
826 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
827 func = GL_ALWAYS;
828 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
829 func_ccw = GL_ALWAYS;
830 ref = stateblock->renderState[WINED3DRS_STENCILREF];
831 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
832 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
833 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
834 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
835 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
836 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
837 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
839 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
840 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
841 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
842 onesided_enable, twosided_enable, ref, mask,
843 func, stencilFail, depthFail, stencilPass,
844 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
846 if (twosided_enable && onesided_enable) {
847 glEnable(GL_STENCIL_TEST);
848 checkGLcall("glEnable GL_STENCIL_TEST");
850 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
851 * which has an effect on the code below too. If we apply the front face
852 * afterwards, we are sure that the active stencil face is set to front,
853 * and other stencil functions which do not use two sided stencil do not have
854 * to set it back
856 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
857 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
858 } else if(onesided_enable) {
859 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
860 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
861 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
864 glEnable(GL_STENCIL_TEST);
865 checkGLcall("glEnable GL_STENCIL_TEST");
866 glStencilFunc(func, ref, mask);
867 checkGLcall("glStencilFunc(...)");
868 glStencilOp(stencilFail, depthFail, stencilPass);
869 checkGLcall("glStencilOp(...)");
870 } else {
871 glDisable(GL_STENCIL_TEST);
872 checkGLcall("glDisable GL_STENCIL_TEST");
876 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
877 DWORD mask;
879 if(stateblock->wineD3DDevice->stencilBufferTarget) {
880 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
881 } else {
882 mask = 0;
885 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
886 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
887 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
888 glStencilMask(mask);
889 checkGLcall("glStencilMask");
890 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
891 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
892 glStencilMask(mask);
893 } else {
894 glStencilMask(mask);
896 checkGLcall("glStencilMask");
899 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
900 /* TODO: Put this into the vertex type block once that is in the state table */
901 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
902 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
903 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
904 float fogstart, fogend;
906 union {
907 DWORD d;
908 float f;
909 } tmpvalue;
911 if (!fogenable) {
912 /* No fog? Disable it, and we're done :-) */
913 glDisable(GL_FOG);
914 checkGLcall("glDisable GL_FOG");
915 if( use_ps(stateblock->wineD3DDevice)
916 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
917 /* disable fog in the pixel shader
918 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
919 * -1/(e-s) and e/(e-s) respectively.
921 glFogf(GL_FOG_START, 0.0f);
922 checkGLcall("glFogf(GL_FOG_START, fogstart)");
923 glFogf(GL_FOG_END, 1.0f);
924 checkGLcall("glFogf(GL_FOG_END, fogend)");
926 return;
929 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
930 fogstart = tmpvalue.f;
931 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
932 fogend = tmpvalue.f;
934 /* Fog Rules:
936 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
937 * It can use the Z value of the vertex, or the alpha component of the specular color.
938 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
939 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
940 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
942 * FOGTABLEMODE != NONE:
943 * The Z value is used, with the equation specified, no matter what vertex type.
945 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
946 * Per vertex fog is calculated using the specified fog equation and the parameters
948 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
949 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
950 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
953 * Rules for vertex fog with shaders:
955 * When mixing fixed function functionality with the programmable pipeline, D3D expects
956 * the fog computation to happen during transformation while openGL expects it to happen
957 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
958 * the pixel shader while openGL always expects the pixel shader to handle the blending.
959 * To solve this problem, WineD3D does:
960 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
961 * shader,
962 * and 2) disables the fog computation (in either the fixed function or programmable
963 * rasterizer) if using a vertex program.
966 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
967 * without shaders).
970 if( is_ps3 ) {
971 if( !use_vs(stateblock->wineD3DDevice)
972 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
973 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
977 if (use_vs(stateblock->wineD3DDevice)
978 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
979 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
980 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
981 /* Disable fog */
982 fogenable = FALSE;
983 } else {
984 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
985 glFogi(GL_FOG_MODE, GL_LINEAR);
986 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
987 fogstart = 1.0;
988 fogend = 0.0;
991 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
992 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
993 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
994 context->fog_coord = FALSE;
996 context->last_was_foggy_shader = TRUE;
998 else if( use_ps(stateblock->wineD3DDevice) ) {
999 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1000 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
1002 WINED3DFOGMODE mode;
1003 context->last_was_foggy_shader = FALSE;
1005 /* If both fogmodes are set use the table fog mode */
1006 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1007 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
1008 else
1009 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1011 switch (mode) {
1012 case WINED3DFOG_EXP:
1013 case WINED3DFOG_EXP2:
1014 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1015 /* Disable fog */
1016 fogenable = FALSE;
1017 break;
1019 case WINED3DFOG_LINEAR:
1020 fogstart = -1.0f/(fogend-fogstart);
1021 fogend *= -fogstart;
1022 break;
1024 case WINED3DFOG_NONE:
1025 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1026 /* Disable fog */
1027 fogenable = FALSE;
1028 break;
1029 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1032 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1033 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1034 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1035 context->fog_coord = FALSE;
1038 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1039 * the system will apply only pixel(=table) fog effects."
1041 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1042 glHint(GL_FOG_HINT, GL_FASTEST);
1043 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1044 context->last_was_foggy_shader = FALSE;
1046 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1047 /* If processed vertices are used, fall through to the NONE case */
1048 case WINED3DFOG_EXP: {
1049 if(!context->last_was_rhw) {
1050 glFogi(GL_FOG_MODE, GL_EXP);
1051 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1052 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1053 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1054 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1055 context->fog_coord = FALSE;
1057 break;
1060 case WINED3DFOG_EXP2: {
1061 if(!context->last_was_rhw) {
1062 glFogi(GL_FOG_MODE, GL_EXP2);
1063 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1064 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1065 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1066 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1067 context->fog_coord = FALSE;
1069 break;
1072 case WINED3DFOG_LINEAR: {
1073 if(!context->last_was_rhw) {
1074 glFogi(GL_FOG_MODE, GL_LINEAR);
1075 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1076 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1077 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1078 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1079 context->fog_coord = FALSE;
1081 break;
1084 case WINED3DFOG_NONE: {
1085 /* Both are none? According to msdn the alpha channel of the specular
1086 * color contains a fog factor. Set it in drawStridedSlow.
1087 * Same happens with Vertexfog on transformed vertices
1089 if(GL_SUPPORT(EXT_FOG_COORD)) {
1090 if(context->fog_coord == FALSE) {
1091 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1092 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1093 context->fog_coord = TRUE;
1095 glFogi(GL_FOG_MODE, GL_LINEAR);
1096 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1097 fogstart = 0xff;
1098 fogend = 0x0;
1099 } else {
1100 /* Disable GL fog, handle this in software in drawStridedSlow */
1101 fogenable = FALSE;
1103 break;
1105 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1107 } else {
1108 glHint(GL_FOG_HINT, GL_NICEST);
1109 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1110 context->last_was_foggy_shader = FALSE;
1112 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1113 case WINED3DFOG_EXP:
1114 glFogi(GL_FOG_MODE, GL_EXP);
1115 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1116 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1117 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1118 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1119 context->fog_coord = FALSE;
1121 break;
1123 case WINED3DFOG_EXP2:
1124 glFogi(GL_FOG_MODE, GL_EXP2);
1125 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1126 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1127 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1128 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1129 context->fog_coord = FALSE;
1131 break;
1133 case WINED3DFOG_LINEAR:
1134 glFogi(GL_FOG_MODE, GL_LINEAR);
1135 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1136 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1137 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1138 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1139 context->fog_coord = FALSE;
1141 break;
1143 case WINED3DFOG_NONE: /* Won't happen */
1144 default:
1145 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1149 if(fogenable) {
1150 glEnable(GL_FOG);
1151 checkGLcall("glEnable GL_FOG");
1153 if(fogstart != fogend)
1155 glFogfv(GL_FOG_START, &fogstart);
1156 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1157 TRACE("Fog Start == %f\n", fogstart);
1159 glFogfv(GL_FOG_END, &fogend);
1160 checkGLcall("glFogf(GL_FOG_END, fogend)");
1161 TRACE("Fog End == %f\n", fogend);
1163 else
1165 glFogf(GL_FOG_START, -1.0 / 0.0);
1166 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1167 TRACE("Fog Start == %f\n", fogstart);
1169 glFogf(GL_FOG_END, 0.0);
1170 checkGLcall("glFogf(GL_FOG_END, fogend)");
1171 TRACE("Fog End == %f\n", fogend);
1173 } else {
1174 glDisable(GL_FOG);
1175 checkGLcall("glDisable GL_FOG");
1176 if( use_ps(stateblock->wineD3DDevice) ) {
1177 /* disable fog in the pixel shader
1178 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1179 * -1/(e-s) and e/(e-s) respectively.
1181 glFogf(GL_FOG_START, 0.0f);
1182 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1183 glFogf(GL_FOG_END, 1.0f);
1184 checkGLcall("glFogf(GL_FOG_END, fogend)");
1189 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1190 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1191 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1192 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1193 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1194 } else {
1195 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1197 } else {
1198 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1199 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1200 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1205 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1206 float col[4];
1207 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1208 glFogfv(GL_FOG_COLOR, &col[0]);
1209 checkGLcall("glFog GL_FOG_COLOR");
1212 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1213 union {
1214 DWORD d;
1215 float f;
1216 } tmpvalue;
1217 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1218 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1219 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1222 /* TODO: Merge with primitive type + init_materials()!! */
1223 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1224 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1225 GLenum Parm = 0;
1226 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1227 BOOL isDiffuseSupplied;
1229 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1230 * The vertex declaration will call this function if the fixed function pipeline is used.
1233 if(isStateDirty(context, STATE_VDECL)) {
1234 return;
1237 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1239 context->num_untracked_materials = 0;
1240 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1241 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1242 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1243 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1244 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1245 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1247 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1248 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1249 Parm = GL_AMBIENT_AND_DIFFUSE;
1250 } else {
1251 Parm = GL_DIFFUSE;
1253 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1254 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1255 context->num_untracked_materials++;
1257 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1258 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1259 context->num_untracked_materials++;
1261 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1262 Parm = GL_AMBIENT;
1263 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1264 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1265 context->num_untracked_materials++;
1267 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1268 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1269 context->num_untracked_materials++;
1271 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1272 Parm = GL_EMISSION;
1273 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1274 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1275 context->num_untracked_materials++;
1277 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1278 Parm = GL_SPECULAR;
1282 /* Nothing changed, return. */
1283 if (Parm == context->tracking_parm) return;
1285 if(!Parm) {
1286 glDisable(GL_COLOR_MATERIAL);
1287 checkGLcall("glDisable GL_COLOR_MATERIAL");
1288 } else {
1289 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1290 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1291 glEnable(GL_COLOR_MATERIAL);
1292 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1295 /* Apparently calls to glMaterialfv are ignored for properties we're
1296 * tracking with glColorMaterial, so apply those here. */
1297 switch (context->tracking_parm) {
1298 case GL_AMBIENT_AND_DIFFUSE:
1299 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1300 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1301 checkGLcall("glMaterialfv");
1302 break;
1304 case GL_DIFFUSE:
1305 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1306 checkGLcall("glMaterialfv");
1307 break;
1309 case GL_AMBIENT:
1310 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1311 checkGLcall("glMaterialfv");
1312 break;
1314 case GL_EMISSION:
1315 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1316 checkGLcall("glMaterialfv");
1317 break;
1319 case GL_SPECULAR:
1320 /* Only change material color if specular is enabled, otherwise it is set to black */
1321 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1322 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1323 checkGLcall("glMaterialfv");
1324 } else {
1325 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1326 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1327 checkGLcall("glMaterialfv");
1329 break;
1332 context->tracking_parm = Parm;
1335 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1336 union {
1337 DWORD d;
1338 WINED3DLINEPATTERN lp;
1339 } tmppattern;
1340 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1342 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1344 if (tmppattern.lp.wRepeatFactor) {
1345 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1346 checkGLcall("glLineStipple(repeat, linepattern)");
1347 glEnable(GL_LINE_STIPPLE);
1348 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1349 } else {
1350 glDisable(GL_LINE_STIPPLE);
1351 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1355 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1356 union {
1357 DWORD d;
1358 float f;
1359 } tmpvalue;
1361 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1362 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1363 TRACE("ZBias value %f\n", tmpvalue.f);
1364 glPolygonOffset(0, -tmpvalue.f);
1365 checkGLcall("glPolygonOffset(0, -Value)");
1366 glEnable(GL_POLYGON_OFFSET_FILL);
1367 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1368 glEnable(GL_POLYGON_OFFSET_LINE);
1369 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1370 glEnable(GL_POLYGON_OFFSET_POINT);
1371 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1372 } else {
1373 glDisable(GL_POLYGON_OFFSET_FILL);
1374 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1375 glDisable(GL_POLYGON_OFFSET_LINE);
1376 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1377 glDisable(GL_POLYGON_OFFSET_POINT);
1378 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1383 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1384 if(isStateDirty(context, STATE_VDECL)) {
1385 return;
1387 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1388 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1389 * by zero and is not properly defined in opengl, so avoid it
1391 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1392 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1393 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1394 glEnable(GL_NORMALIZE);
1395 checkGLcall("glEnable(GL_NORMALIZE);");
1396 } else {
1397 glDisable(GL_NORMALIZE);
1398 checkGLcall("glDisable(GL_NORMALIZE);");
1402 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1403 union {
1404 DWORD d;
1405 float f;
1406 } tmpvalue;
1408 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1409 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1410 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1411 checkGLcall("glPointParameterfARB(...)");
1413 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1414 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1415 checkGLcall("glPointParameterfEXT(...)");
1416 } else if(tmpvalue.f != 1.0) {
1417 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1421 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1422 union {
1423 DWORD d;
1424 float f;
1425 } tmpvalue;
1427 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1428 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1429 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1430 checkGLcall("glPointParameterfARB(...)");
1432 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1433 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1434 checkGLcall("glPointParameterfEXT(...)");
1435 } else if(tmpvalue.f != 64.0) {
1436 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1440 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1441 /* TODO: Group this with the viewport */
1443 * POINTSCALEENABLE controls how point size value is treated. If set to
1444 * true, the point size is scaled with respect to height of viewport.
1445 * When set to false point size is in pixels.
1448 /* Default values */
1449 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1450 union {
1451 DWORD d;
1452 float f;
1453 } pointSize, A, B, C;
1455 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1456 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1457 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1458 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1460 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1461 GLfloat scaleFactor;
1462 float h = stateblock->viewport.Height;
1464 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1466 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1467 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1468 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1469 * are less than 1.0f. scale_factor = 1.0f / point_size.
1471 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1472 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1473 * is 1.0, but then accepts points below that and draws too small points
1475 pointSize.f = GL_LIMITS(pointsizemin);
1476 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1477 /* gl already scales the input to glPointSize,
1478 * d3d scales the result after the point size scale.
1479 * If the point size is bigger than the max size, use the
1480 * scaling to scale it bigger, and set the gl point size to max
1482 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1483 TRACE("scale: %f\n", scaleFactor);
1484 pointSize.f = GL_LIMITS(pointsize);
1485 } else {
1486 scaleFactor = 1.0f;
1488 scaleFactor = pow(h * scaleFactor, 2);
1490 att[0] = A.f / scaleFactor;
1491 att[1] = B.f / scaleFactor;
1492 att[2] = C.f / scaleFactor;
1495 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1496 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1497 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1499 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1500 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1501 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1502 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1503 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1506 glPointSize(pointSize.f);
1507 checkGLcall("glPointSize(...);");
1510 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1511 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1513 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1514 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1515 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1516 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1517 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1518 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1519 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1520 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1521 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1522 checkGLcall("glColorMask(...)");
1524 /* depends on WINED3DRS_COLORWRITEENABLE. */
1525 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1526 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1527 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1528 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1529 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1530 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1531 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1535 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1536 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1537 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1538 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1539 } else {
1540 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1541 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1545 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1546 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1547 TRACE("Last Pixel Drawing Enabled\n");
1548 } else {
1549 static BOOL first = TRUE;
1550 if(first) {
1551 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1552 first = FALSE;
1553 } else {
1554 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1559 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1560 /* TODO: NV_POINT_SPRITE */
1561 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1562 TRACE("Point sprites not supported\n");
1563 return;
1566 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1567 glEnable(GL_POINT_SPRITE_ARB);
1568 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1569 } else {
1570 glDisable(GL_POINT_SPRITE_ARB);
1571 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1575 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1577 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1578 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1579 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1580 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1582 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1584 TRACE("Stub\n");
1585 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1586 stateblock->renderState[WINED3DRS_WRAP1] ||
1587 stateblock->renderState[WINED3DRS_WRAP2] ||
1588 stateblock->renderState[WINED3DRS_WRAP3] ||
1589 stateblock->renderState[WINED3DRS_WRAP4] ||
1590 stateblock->renderState[WINED3DRS_WRAP5] ||
1591 stateblock->renderState[WINED3DRS_WRAP6] ||
1592 stateblock->renderState[WINED3DRS_WRAP7] ||
1593 stateblock->renderState[WINED3DRS_WRAP8] ||
1594 stateblock->renderState[WINED3DRS_WRAP9] ||
1595 stateblock->renderState[WINED3DRS_WRAP10] ||
1596 stateblock->renderState[WINED3DRS_WRAP11] ||
1597 stateblock->renderState[WINED3DRS_WRAP12] ||
1598 stateblock->renderState[WINED3DRS_WRAP13] ||
1599 stateblock->renderState[WINED3DRS_WRAP14] ||
1600 stateblock->renderState[WINED3DRS_WRAP15] ) {
1601 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1605 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1606 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1607 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1608 glEnable(GL_MULTISAMPLE_ARB);
1609 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1610 } else {
1611 glDisable(GL_MULTISAMPLE_ARB);
1612 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1614 } else {
1615 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1616 WARN("Multisample antialiasing not supported by gl\n");
1621 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1622 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1623 glEnable(GL_SCISSOR_TEST);
1624 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1625 } else {
1626 glDisable(GL_SCISSOR_TEST);
1627 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1631 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1632 union {
1633 DWORD d;
1634 float f;
1635 } tmpvalue;
1637 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1638 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1639 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1640 glEnable(GL_POLYGON_OFFSET_FILL);
1641 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1642 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1643 checkGLcall("glPolygonOffset(...)");
1644 } else {
1645 glDisable(GL_POLYGON_OFFSET_FILL);
1646 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1650 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1651 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1652 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1653 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1654 } else {
1655 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1656 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1660 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1661 TRACE("Stub\n");
1662 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1663 FIXME(" Stippled Alpha not supported yet.\n");
1666 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1667 TRACE("Stub\n");
1668 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1669 FIXME(" Antialias not supported yet.\n");
1672 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1673 TRACE("Stub\n");
1674 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1675 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1678 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1679 TRACE("Stub\n");
1680 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1681 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1684 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1685 union {
1686 DWORD d;
1687 float f;
1688 } tmpvalue;
1689 tmpvalue.f = 1.0f;
1691 TRACE("Stub\n");
1692 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1694 static BOOL displayed = FALSE;
1696 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1697 if(!displayed)
1698 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1700 displayed = TRUE;
1704 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1705 TRACE("Stub\n");
1706 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1707 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1710 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1711 TRACE("Stub\n");
1712 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1713 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1716 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1717 TRACE("Stub\n");
1718 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1719 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1722 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1723 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1724 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1728 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1729 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1730 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1734 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1735 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1736 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1740 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1741 if(stateblock->renderState[WINED3DRS_ROP2]) {
1742 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1746 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1747 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1748 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1752 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1753 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1754 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1758 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1759 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1760 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1764 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1765 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1766 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1770 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1771 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1772 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1776 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1777 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1778 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1782 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1783 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1784 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1788 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1789 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1790 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1794 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1795 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1796 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1800 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1801 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1802 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1806 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1807 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1808 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1812 /* Activates the texture dimension according to the bound D3D texture.
1813 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1814 * Requires the caller to activate the correct unit before
1816 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1817 BOOL bumpmap = FALSE;
1819 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1820 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1821 bumpmap = TRUE;
1822 context->texShaderBumpMap |= (1 << stage);
1823 } else {
1824 context->texShaderBumpMap &= ~(1 << stage);
1827 if(stateblock->textures[stage]) {
1828 switch(stateblock->textureDimensions[stage]) {
1829 case GL_TEXTURE_2D:
1830 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1831 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1832 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1833 } else {
1834 glDisable(GL_TEXTURE_3D);
1835 checkGLcall("glDisable(GL_TEXTURE_3D)");
1836 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1837 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1838 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1840 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1841 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1842 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1844 glEnable(GL_TEXTURE_2D);
1845 checkGLcall("glEnable(GL_TEXTURE_2D)");
1847 break;
1848 case GL_TEXTURE_RECTANGLE_ARB:
1849 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1850 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB);
1851 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1852 } else {
1853 glDisable(GL_TEXTURE_2D);
1854 checkGLcall("glDisable(GL_TEXTURE_2D)");
1855 glDisable(GL_TEXTURE_3D);
1856 checkGLcall("glDisable(GL_TEXTURE_3D)");
1857 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1858 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1859 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1861 glEnable(GL_TEXTURE_RECTANGLE_ARB);
1862 checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
1864 break;
1865 case GL_TEXTURE_3D:
1866 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1867 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1868 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)");
1869 } else {
1870 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1871 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1872 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1874 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1875 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1876 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1878 glDisable(GL_TEXTURE_2D);
1879 checkGLcall("glDisable(GL_TEXTURE_2D)");
1880 glEnable(GL_TEXTURE_3D);
1881 checkGLcall("glEnable(GL_TEXTURE_3D)");
1883 break;
1884 case GL_TEXTURE_CUBE_MAP_ARB:
1885 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1886 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1887 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
1888 } else {
1889 glDisable(GL_TEXTURE_2D);
1890 checkGLcall("glDisable(GL_TEXTURE_2D)");
1891 glDisable(GL_TEXTURE_3D);
1892 checkGLcall("glDisable(GL_TEXTURE_3D)");
1893 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1894 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1895 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1897 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1898 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1900 break;
1902 } else {
1903 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1904 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1905 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)");
1906 } else {
1907 glEnable(GL_TEXTURE_2D);
1908 checkGLcall("glEnable(GL_TEXTURE_2D)");
1909 glDisable(GL_TEXTURE_3D);
1910 checkGLcall("glDisable(GL_TEXTURE_3D)");
1911 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1912 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1913 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1915 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1916 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1917 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1919 /* Binding textures is done by samplers. A dummy texture will be bound */
1924 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1925 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1926 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1927 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1929 TRACE("Setting color op for stage %d\n", stage);
1931 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1932 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1933 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1934 return;
1937 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1939 if (mapped_stage != -1) {
1940 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1941 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1942 FIXME("Attempt to enable unsupported stage!\n");
1943 return;
1945 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1946 checkGLcall("glActiveTextureARB");
1947 } else if (stage > 0) {
1948 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1949 return;
1953 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1954 if(stateblock->lowest_disabled_stage > 0) {
1955 glEnable(GL_REGISTER_COMBINERS_NV);
1956 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1957 } else {
1958 glDisable(GL_REGISTER_COMBINERS_NV);
1961 if(stage >= stateblock->lowest_disabled_stage) {
1962 TRACE("Stage disabled\n");
1963 if (mapped_stage != -1) {
1964 /* Disable everything here */
1965 glDisable(GL_TEXTURE_2D);
1966 checkGLcall("glDisable(GL_TEXTURE_2D)");
1967 glDisable(GL_TEXTURE_3D);
1968 checkGLcall("glDisable(GL_TEXTURE_3D)");
1969 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1970 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1971 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1973 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1974 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1975 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1977 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1978 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1981 /* All done */
1982 return;
1985 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1986 * if the sampler for this stage is dirty
1988 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1989 if (tex_used) activate_dimensions(stage, stateblock, context);
1992 /* Set the texture combiners */
1993 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1994 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1995 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1996 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1997 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1998 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1999 mapped_stage);
2001 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
2002 * thus the texture shader may have to be updated
2004 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2005 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
2006 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
2007 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
2008 if(usesBump != usedBump) {
2009 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
2010 checkGLcall("glActiveTextureARB");
2011 activate_dimensions(stage + 1, stateblock, context);
2012 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2013 checkGLcall("glActiveTextureARB");
2016 } else {
2017 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2018 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2019 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2020 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2021 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2025 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2026 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2027 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2028 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2029 DWORD op, arg1, arg2, arg0;
2031 TRACE("Setting alpha op for stage %d\n", stage);
2032 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2033 if (mapped_stage != -1) {
2034 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2035 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2036 FIXME("Attempt to enable unsupported stage!\n");
2037 return;
2039 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2040 checkGLcall("glActiveTextureARB");
2041 } else if (stage > 0) {
2042 /* We can't do anything here */
2043 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2044 return;
2048 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2049 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2050 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2051 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2053 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
2054 stateblock->textures[0] &&
2055 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
2056 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2058 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
2059 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
2061 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
2062 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
2063 * cannot remove the texture's alpha channel entirely.
2065 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
2066 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
2067 * draw things like translucent text and perform other blending effects.
2069 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
2070 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
2071 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
2072 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
2073 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
2074 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
2075 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
2076 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
2078 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
2080 if(op == WINED3DTOP_DISABLE) {
2081 arg1 = WINED3DTA_TEXTURE;
2082 op = WINED3DTOP_SELECTARG1;
2084 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
2085 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
2086 arg2 = WINED3DTA_TEXTURE;
2087 op = WINED3DTOP_MODULATE;
2089 else arg1 = WINED3DTA_TEXTURE;
2091 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
2092 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
2093 arg1 = WINED3DTA_TEXTURE;
2094 op = WINED3DTOP_MODULATE;
2096 else arg2 = WINED3DTA_TEXTURE;
2101 TRACE("Setting alpha op for stage %d\n", stage);
2102 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2103 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2104 op, arg1, arg2, arg0,
2105 mapped_stage);
2106 } else {
2107 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2108 op, arg1, arg2, arg0);
2112 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2113 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
2114 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2115 BOOL generated;
2117 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2118 if(use_vs(stateblock->wineD3DDevice) ||
2119 isStateDirty(context, STATE_VDECL)) {
2120 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
2121 return;
2124 if (mapped_stage == -1) return;
2126 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2127 if(mapped_stage >= GL_LIMITS(textures)) {
2128 return;
2130 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2131 checkGLcall("glActiveTextureARB");
2132 } else if (mapped_stage > 0) {
2133 /* We can't do anything here */
2134 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2135 return;
2137 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
2139 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
2140 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
2141 generated,
2142 context->last_was_rhw,
2143 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
2144 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
2145 WINED3DDECLTYPE_UNUSED);
2147 /* The sampler applying function calls us if this changes */
2148 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
2149 if(generated) {
2150 FIXME("Non-power2 texture being used with generated texture coords\n");
2152 TRACE("Non power two matrix multiply fixup\n");
2153 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
2157 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
2158 int texture_idx;
2160 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
2161 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2162 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2166 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2167 UINT *offset = stateblock->streamOffset;
2168 unsigned int mapped_stage = 0;
2169 unsigned int textureNo = 0;
2171 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2172 /* Abort if we don't support the extension. */
2173 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2174 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2175 return;
2178 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2179 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2181 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2182 if (mapped_stage == -1) continue;
2184 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2185 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2186 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2188 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2189 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2190 checkGLcall("glBindBufferARB");
2191 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2194 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2195 checkGLcall("glClientActiveTextureARB");
2197 /* The coords to supply depend completely on the fvf / vertex shader */
2198 glTexCoordPointer(
2199 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2200 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2201 sd->u.s.texCoords[coordIdx].dwStride,
2202 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2203 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2204 } else {
2205 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2208 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2209 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2210 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2211 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2216 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2217 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2218 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2220 if (mapped_stage == -1) {
2221 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2222 return;
2225 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2226 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2227 return;
2229 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2230 checkGLcall("glActiveTextureARB");
2231 } else if (stage > 0) {
2232 /* We can't do anything here */
2233 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2234 return;
2237 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2239 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2240 * one flag, you can still specify an index value, which the system uses to
2241 * determine the texture wrapping mode.
2242 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2243 * means use the vertex position (camera-space) as the input texture coordinates
2244 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2245 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2246 * to the TEXCOORDINDEX value
2250 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2252 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2253 case WINED3DTSS_TCI_PASSTHRU:
2254 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2255 glDisable(GL_TEXTURE_GEN_S);
2256 glDisable(GL_TEXTURE_GEN_T);
2257 glDisable(GL_TEXTURE_GEN_R);
2258 glDisable(GL_TEXTURE_GEN_Q);
2259 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2260 break;
2262 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2263 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2264 * as the input texture coordinates for this stage's texture transformation. This
2265 * equates roughly to EYE_LINEAR
2268 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2269 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2270 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2271 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2272 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2274 glMatrixMode(GL_MODELVIEW);
2275 glPushMatrix();
2276 glLoadIdentity();
2277 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2278 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2279 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2280 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2281 glPopMatrix();
2283 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2284 glEnable(GL_TEXTURE_GEN_S);
2285 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2286 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2287 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2288 glEnable(GL_TEXTURE_GEN_T);
2289 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2290 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2291 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2292 glEnable(GL_TEXTURE_GEN_R);
2293 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2294 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2295 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2297 break;
2299 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2301 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2302 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2303 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2304 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2305 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2306 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2308 glMatrixMode(GL_MODELVIEW);
2309 glPushMatrix();
2310 glLoadIdentity();
2311 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2312 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2313 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2314 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2315 glPopMatrix();
2317 glEnable(GL_TEXTURE_GEN_S);
2318 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2319 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2320 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2321 glEnable(GL_TEXTURE_GEN_T);
2322 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2323 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2324 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2325 glEnable(GL_TEXTURE_GEN_R);
2326 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2327 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2328 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2331 break;
2333 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2335 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2336 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2337 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2338 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2339 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2340 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2342 glMatrixMode(GL_MODELVIEW);
2343 glPushMatrix();
2344 glLoadIdentity();
2345 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2346 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2347 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2348 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2349 glPopMatrix();
2351 glEnable(GL_TEXTURE_GEN_S);
2352 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2353 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2354 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2355 glEnable(GL_TEXTURE_GEN_T);
2356 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2357 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2358 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2359 glEnable(GL_TEXTURE_GEN_R);
2360 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2361 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2362 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2365 break;
2367 /* Unhandled types: */
2368 default:
2369 /* Todo: */
2370 /* ? disable GL_TEXTURE_GEN_n ? */
2371 glDisable(GL_TEXTURE_GEN_S);
2372 glDisable(GL_TEXTURE_GEN_T);
2373 glDisable(GL_TEXTURE_GEN_R);
2374 glDisable(GL_TEXTURE_GEN_Q);
2375 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2376 break;
2379 /* Update the texture matrix */
2380 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2381 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2384 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2385 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2386 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2387 * and do all the things linked to it
2388 * TODO: Tidy that up to reload only the arrays of the changed unit
2390 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2392 unloadTexCoords(stateblock);
2393 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2397 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2398 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2400 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2401 * has an update pending
2403 if(isStateDirty(context, STATE_VDECL) ||
2404 isStateDirty(context, STATE_PIXELSHADER)) {
2405 return;
2408 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2411 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2412 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2413 union {
2414 DWORD d;
2415 float f;
2416 } tmpvalue;
2418 if(stateblock->pixelShader && stage != 0 &&
2419 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2420 /* The pixel shader has to know the luminance scale. Do a constants update if it
2421 * isn't scheduled anyway
2423 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2424 !isStateDirty(context, STATE_PIXELSHADER)) {
2425 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2429 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2430 if(tmpvalue.f != 0.0) {
2431 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2435 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2436 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2437 union {
2438 DWORD d;
2439 float f;
2440 } tmpvalue;
2442 if(stateblock->pixelShader && stage != 0 &&
2443 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2444 /* The pixel shader has to know the luminance offset. Do a constants update if it
2445 * isn't scheduled anyway
2447 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2448 !isStateDirty(context, STATE_PIXELSHADER)) {
2449 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2453 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2454 if(tmpvalue.f != 0.0) {
2455 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2459 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2460 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2462 if(stage >= GL_LIMITS(texture_stages)) {
2463 return;
2466 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2467 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2471 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2472 DWORD sampler = state - STATE_SAMPLER(0);
2473 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2474 union {
2475 float f;
2476 DWORD d;
2477 } tmpvalue;
2479 TRACE("Sampler: %d\n", sampler);
2480 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2481 * only has to bind textures and set the per texture states
2484 if (mapped_stage == -1) {
2485 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2486 return;
2489 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2490 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2491 return;
2493 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2494 checkGLcall("glActiveTextureARB");
2495 } else if (sampler > 0) {
2496 /* We can't do anything here */
2497 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2498 return;
2501 if(stateblock->textures[sampler]) {
2502 BOOL texIsPow2 = FALSE;
2504 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2505 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2506 * scaling is reapplied or removed, the texture matrix has to be reapplied
2508 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2509 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2510 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2511 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0 ||
2512 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[5] != 1.0 ) {
2513 texIsPow2 = TRUE;
2515 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2516 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0) {
2517 texIsPow2 = TRUE;
2521 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2522 context->lastWasPow2Texture[sampler] = texIsPow2;
2523 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2527 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
2528 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2530 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2531 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2532 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2533 GL_TEXTURE_LOD_BIAS_EXT,
2534 tmpvalue.f);
2535 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
2538 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2539 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2540 /* Using a pixel shader? Verify the sampler types */
2542 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2543 * dimensions because the shader knows from which texture type to sample from. For the sake of
2544 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2545 * dimensions. This should make wrong sampling sources visible :-)
2547 glEnable(stateblock->textureDimensions[sampler]);
2548 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2549 } else if(sampler < stateblock->lowest_disabled_stage) {
2550 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2551 activate_dimensions(sampler, stateblock, context);
2554 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2555 /* If color keying is enabled update the alpha test, it depends on the existence
2556 * of a color key in stage 0
2558 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2561 } else if(mapped_stage < GL_LIMITS(textures)) {
2562 if(sampler < stateblock->lowest_disabled_stage) {
2563 /* TODO: What should I do with pixel shaders here ??? */
2564 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2565 activate_dimensions(sampler, stateblock, context);
2568 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2569 /* If color keying is enabled update the alpha test, it depends on the existence
2570 * of a color key in stage 0
2572 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2574 } /* Otherwise tex_colorop disables the stage */
2575 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2576 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2580 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2581 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2582 BOOL use_pshader = use_ps(device);
2583 BOOL use_vshader = use_vs(device);
2584 BOOL update_fog = FALSE;
2585 int i;
2587 if (use_pshader) {
2588 if(!context->last_was_pshader) {
2589 /* Former draw without a pixel shader, some samplers
2590 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2591 * make sure to enable them
2593 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2594 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2595 sampler(STATE_SAMPLER(i), stateblock, context);
2598 update_fog = TRUE;
2599 } else {
2600 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2601 * if a different texture was bound. I don't have to do anything.
2605 /* Compile and bind the shader */
2606 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2607 } else {
2608 /* Disabled the pixel shader - color ops weren't applied
2609 * while it was enabled, so re-apply them.
2611 for(i=0; i < MAX_TEXTURES; i++) {
2612 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2613 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2616 if(context->last_was_pshader)
2617 update_fog = TRUE;
2620 if(!isStateDirty(context, FFPStateTable[STATE_VSHADER].representative)) {
2621 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2623 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2624 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2628 if(update_fog)
2629 state_fog(state, stateblock, context);
2631 context->last_was_pshader = use_pshader;
2634 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2635 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2636 float mat[2][2];
2637 if(stateblock->pixelShader && stage != 0 &&
2638 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
2639 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2640 * anyway
2642 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2643 !isStateDirty(context, STATE_PIXELSHADER)) {
2644 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2648 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2649 if(stage >= GL_LIMITS(texture_stages)) {
2650 WARN("Bump env matrix of unsupported stage set\n");
2651 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2652 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2653 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2655 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2656 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2657 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2658 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2659 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, (float *) mat));
2660 checkGLcall("glTexBumpParameterfvATI");
2661 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2662 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2663 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2664 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2665 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2666 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2668 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2670 if(mapped_stage < GL_LIMITS(textures)) {
2671 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2672 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2674 /* We can't just pass a pointer to the stateblock to GL due to the different matrix
2675 * format(column major vs row major)
2677 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2678 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2679 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2680 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2681 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *) mat);
2682 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)");
2687 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2688 /* This function is called by transform_view below if the view matrix was changed too
2690 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2691 * does not always update the world matrix, only on a switch between transformed
2692 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
2693 * draw, but that should be rather rare and cheaper in total.
2695 glMatrixMode(GL_MODELVIEW);
2696 checkGLcall("glMatrixMode");
2698 if(context->last_was_rhw) {
2699 glLoadIdentity();
2700 checkGLcall("glLoadIdentity()");
2701 } else {
2702 /* In the general case, the view matrix is the identity matrix */
2703 if (stateblock->wineD3DDevice->view_ident) {
2704 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2705 checkGLcall("glLoadMatrixf");
2706 } else {
2707 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2708 checkGLcall("glLoadMatrixf");
2709 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2710 checkGLcall("glMultMatrixf");
2715 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2716 UINT index = state - STATE_CLIPPLANE(0);
2718 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2719 return;
2722 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2723 glMatrixMode(GL_MODELVIEW);
2724 glPushMatrix();
2725 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2727 TRACE("Clipplane [%f,%f,%f,%f]\n",
2728 stateblock->clipplane[index][0],
2729 stateblock->clipplane[index][1],
2730 stateblock->clipplane[index][2],
2731 stateblock->clipplane[index][3]);
2732 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2733 checkGLcall("glClipPlane");
2735 glPopMatrix();
2738 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2739 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2740 GLenum glMat;
2741 TRACE("Setting world matrix %d\n", matrix);
2743 if(matrix >= GL_LIMITS(blends)) {
2744 WARN("Unsupported blend matrix set\n");
2745 return;
2746 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2747 return;
2750 /* GL_MODELVIEW0_ARB: 0x1700
2751 * GL_MODELVIEW1_ARB: 0x0x850a
2752 * GL_MODELVIEW2_ARB: 0x8722
2753 * GL_MODELVIEW3_ARB: 0x8723
2754 * etc
2755 * GL_MODELVIEW31_ARB: 0x873F
2757 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2758 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2760 glMatrixMode(glMat);
2761 checkGLcall("glMatrixMode(glMat)");
2763 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2764 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2766 if(stateblock->wineD3DDevice->view_ident) {
2767 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2768 checkGLcall("glLoadMatrixf")
2769 } else {
2770 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2771 checkGLcall("glLoadMatrixf")
2772 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2773 checkGLcall("glMultMatrixf")
2777 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2778 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2780 switch(val) {
2781 case WINED3DVBF_1WEIGHTS:
2782 case WINED3DVBF_2WEIGHTS:
2783 case WINED3DVBF_3WEIGHTS:
2784 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2785 glEnable(GL_VERTEX_BLEND_ARB);
2786 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2788 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2789 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2791 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2793 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2794 int i;
2795 for(i = 1; i < GL_LIMITS(blends); i++) {
2796 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2797 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2800 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2802 } else {
2803 static BOOL once = FALSE;
2804 if(!once) {
2805 once = TRUE;
2806 /* TODO: Implement vertex blending in drawStridedSlow */
2807 FIXME("Vertex blending enabled, but not supported by hardware\n");
2810 break;
2812 case WINED3DVBF_DISABLE:
2813 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2814 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2815 glDisable(GL_VERTEX_BLEND_ARB);
2816 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2817 } else {
2818 TRACE("Vertex blending disabled\n");
2820 break;
2822 case WINED3DVBF_TWEENING:
2823 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2824 * vertex weights in the vertices?
2825 * For now we don't report that as supported, so a warn should suffice
2827 WARN("Tweening not supported yet\n");
2828 break;
2832 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2833 unsigned int k;
2835 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2836 * NOTE: We have to reset the positions even if the light/plane is not currently
2837 * enabled, since the call to enable it will not reset the position.
2838 * NOTE2: Apparently texture transforms do NOT need reapplying
2841 PLIGHTINFOEL *light = NULL;
2843 glMatrixMode(GL_MODELVIEW);
2844 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2845 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2846 checkGLcall("glLoadMatrixf(...)");
2848 /* Reset lights. TODO: Call light apply func */
2849 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2850 light = stateblock->activeLights[k];
2851 if(!light) continue;
2852 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2853 checkGLcall("glLightfv posn");
2854 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2855 checkGLcall("glLightfv dirn");
2858 /* Reset Clipping Planes */
2859 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2860 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2861 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2865 if(context->last_was_rhw) {
2866 glLoadIdentity();
2867 checkGLcall("glLoadIdentity()");
2868 /* No need to update the world matrix, the identity is fine */
2869 return;
2872 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2873 * No need to do it here if the state is scheduled for update.
2875 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2876 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2879 /* Avoid looping over a number of matrices if the app never used the functionality */
2880 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2881 for(k = 1; k < GL_LIMITS(blends); k++) {
2882 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2883 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2889 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2890 glMatrixMode(GL_PROJECTION);
2891 checkGLcall("glMatrixMode(GL_PROJECTION)");
2892 glLoadIdentity();
2893 checkGLcall("glLoadIdentity");
2895 if(context->last_was_rhw) {
2896 double X, Y, height, width, minZ, maxZ;
2898 X = stateblock->viewport.X;
2899 Y = stateblock->viewport.Y;
2900 height = stateblock->viewport.Height;
2901 width = stateblock->viewport.Width;
2902 minZ = stateblock->viewport.MinZ;
2903 maxZ = stateblock->viewport.MaxZ;
2905 if(!stateblock->wineD3DDevice->untransformed) {
2906 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2907 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2908 * suppress depth clipping. This can be done because it is an orthogonal projection and
2909 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2910 * Persia 3D need this.
2912 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2913 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2914 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2915 * to the viewer.
2917 * Also note that this breaks z comparison against z values filled in with clear,
2918 * but no app depending on that and disabled clipping has been found yet. Comparing
2919 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2920 * surface removal.
2922 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2923 * but this would break Z buffer operation. Raising the range to something less than
2924 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2925 * problem either.
2927 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2928 if(stateblock->wineD3DDevice->render_offscreen) {
2929 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2930 } else {
2931 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2933 } else {
2934 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2935 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2936 * unmodified to opengl.
2938 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2939 * replacement shader.
2941 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2942 if(stateblock->wineD3DDevice->render_offscreen) {
2943 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2944 } else {
2945 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2948 checkGLcall("glOrtho");
2950 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2951 glTranslatef(0.5, 0.5, 0);
2952 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2953 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2954 * render everything upside down when rendering offscreen. */
2955 if (stateblock->wineD3DDevice->render_offscreen) {
2956 glScalef(1.0, -1.0, 1.0);
2957 checkGLcall("glScalef");
2959 } else {
2960 /* The rule is that the window coordinate 0 does not correspond to the
2961 beginning of the first pixel, but the center of the first pixel.
2962 As a consequence if you want to correctly draw one line exactly from
2963 the left to the right end of the viewport (with all matrices set to
2964 be identity), the x coords of both ends of the line would be not
2965 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2966 instead.
2968 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2969 divide by the Width/Height, so we need the half range(1.0) to translate by
2970 half a pixel.
2972 The other fun is that d3d's output z range after the transformation is [0;1],
2973 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2974 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2975 of Z buffer precision and the clear values do not match in the z test. Thus scale
2976 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2978 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2979 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2980 if (stateblock->wineD3DDevice->render_offscreen) {
2981 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2982 * render everything upside down when rendering offscreen. */
2983 glScalef(1.0, -1.0, 2.0);
2984 } else {
2985 glScalef(1.0, 1.0, 2.0);
2987 checkGLcall("glScalef");
2989 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2990 checkGLcall("glLoadMatrixf");
2994 /* This should match any arrays loaded in loadVertexData.
2995 * stateblock impl is required for GL_SUPPORT
2996 * TODO: Only load / unload arrays if we have to.
2998 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2999 glDisableClientState(GL_VERTEX_ARRAY);
3000 glDisableClientState(GL_NORMAL_ARRAY);
3001 glDisableClientState(GL_COLOR_ARRAY);
3002 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3003 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3005 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3006 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3007 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3008 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3010 unloadTexCoords(stateblock);
3013 /* This should match any arrays loaded in loadNumberedArrays
3014 * TODO: Only load / unload arrays if we have to.
3016 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
3017 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3018 GLint maxAttribs = 16;
3019 int i;
3021 /* Leave all the attribs disabled */
3022 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3023 /* MESA does not support it right not */
3024 if (glGetError() != GL_NO_ERROR)
3025 maxAttribs = 16;
3026 for (i = 0; i < maxAttribs; ++i) {
3027 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3028 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3032 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
3033 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3034 int i;
3035 UINT *offset = stateblock->streamOffset;
3036 IWineD3DVertexBufferImpl *vb;
3037 DWORD_PTR shift_index;
3039 /* Default to no instancing */
3040 stateblock->wineD3DDevice->instancedDraw = FALSE;
3042 for (i = 0; i < MAX_ATTRIBS; i++) {
3044 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
3045 continue;
3047 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3048 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3049 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3050 stateblock->wineD3DDevice->instancedDraw = TRUE;
3051 continue;
3054 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3056 if(strided->u.input[i].dwStride) {
3057 if(curVBO != strided->u.input[i].VBO) {
3058 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3059 checkGLcall("glBindBufferARB");
3060 curVBO = strided->u.input[i].VBO;
3062 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3063 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3064 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3065 * vbo we won't be load converted attributes anyway
3067 if(curVBO && vb->conv_shift) {
3068 TRACE("Loading attribute from shifted buffer\n");
3069 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
3070 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3071 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3072 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3073 shift_index = shift_index % strided->u.input[i].dwStride;
3074 GL_EXTCALL(glVertexAttribPointerARB(i,
3075 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3076 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3077 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3078 vb->conv_stride,
3080 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
3081 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3082 offset[strided->u.input[i].streamNo]));
3084 } else {
3085 GL_EXTCALL(glVertexAttribPointerARB(i,
3086 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3087 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3088 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3089 strided->u.input[i].dwStride,
3091 strided->u.input[i].lpData +
3092 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3093 offset[strided->u.input[i].streamNo]) );
3095 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3096 } else {
3097 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3098 * set up the attribute statically. But we have to figure out the system memory address.
3100 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3101 if(strided->u.input[i].VBO) {
3102 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3103 ptr += (long) vb->resource.allocatedMemory;
3105 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3107 switch(strided->u.input[i].dwType) {
3108 case WINED3DDECLTYPE_FLOAT1:
3109 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
3110 break;
3111 case WINED3DDECLTYPE_FLOAT2:
3112 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
3113 break;
3114 case WINED3DDECLTYPE_FLOAT3:
3115 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
3116 break;
3117 case WINED3DDECLTYPE_FLOAT4:
3118 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
3119 break;
3121 case WINED3DDECLTYPE_UBYTE4:
3122 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3123 break;
3124 case WINED3DDECLTYPE_UBYTE4N:
3125 case WINED3DDECLTYPE_D3DCOLOR:
3126 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3127 break;
3129 case WINED3DDECLTYPE_SHORT2:
3130 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3131 break;
3132 case WINED3DDECLTYPE_SHORT4:
3133 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3134 break;
3136 case WINED3DDECLTYPE_SHORT2N:
3138 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
3139 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3140 break;
3142 case WINED3DDECLTYPE_USHORT2N:
3144 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
3145 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3146 break;
3148 case WINED3DDECLTYPE_SHORT4N:
3149 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
3150 break;
3151 case WINED3DDECLTYPE_USHORT4N:
3152 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
3153 break;
3155 case WINED3DDECLTYPE_UDEC3:
3156 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3157 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
3158 break;
3159 case WINED3DDECLTYPE_DEC3N:
3160 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3161 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
3162 break;
3164 case WINED3DDECLTYPE_FLOAT16_2:
3165 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3166 * byte float according to the IEEE standard
3168 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3169 break;
3170 case WINED3DDECLTYPE_FLOAT16_4:
3171 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3172 break;
3174 case WINED3DDECLTYPE_UNUSED:
3175 default:
3176 ERR("Unexpected declaration in stride 0 attributes\n");
3177 break;
3182 checkGLcall("Loading numbered arrays");
3185 /* Used from 2 different functions, and too big to justify making it inlined */
3186 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3187 UINT *offset = stateblock->streamOffset;
3188 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3190 TRACE("Using fast vertex array code\n");
3192 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3193 stateblock->wineD3DDevice->instancedDraw = FALSE;
3195 /* Blend Data ---------------------------------------------- */
3196 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3197 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3199 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3200 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3201 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3203 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3204 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3206 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3208 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3209 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3210 sd->u.s.blendWeights.dwStride,
3211 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3213 if(curVBO != sd->u.s.blendWeights.VBO) {
3214 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3215 checkGLcall("glBindBufferARB");
3216 curVBO = sd->u.s.blendWeights.VBO;
3219 GL_EXTCALL(glWeightPointerARB)(
3220 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3221 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3222 sd->u.s.blendWeights.dwStride,
3223 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3225 checkGLcall("glWeightPointerARB");
3227 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3228 static BOOL showfixme = TRUE;
3229 if(showfixme){
3230 FIXME("blendMatrixIndices support\n");
3231 showfixme = FALSE;
3234 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3235 /* FIXME("TODO\n");*/
3236 #if 0
3238 GL_EXTCALL(glVertexWeightPointerEXT)(
3239 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3240 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3241 sd->u.s.blendWeights.dwStride,
3242 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3243 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3244 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3245 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3246 #endif
3248 } else {
3249 /* TODO: support blends in drawStridedSlow
3250 * No need to write a FIXME here, this is done after the general vertex decl decoding
3252 WARN("unsupported blending in openGl\n");
3254 } else {
3255 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3256 static const GLbyte one = 1;
3257 GL_EXTCALL(glWeightbvARB(1, &one));
3258 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3262 #if 0 /* FOG ----------------------------------------------*/
3263 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3264 /* TODO: fog*/
3265 if (GL_SUPPORT(EXT_FOG_COORD) {
3266 glEnableClientState(GL_FOG_COORDINATE_EXT);
3267 (GL_EXTCALL)(FogCoordPointerEXT)(
3268 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3269 sd->u.s.fog.dwStride,
3270 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3271 } else {
3272 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3273 /* FIXME: fixme once */
3274 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3276 } else {
3277 if (GL_SUPPRT(EXT_FOR_COORD) {
3278 /* make sure fog is disabled */
3279 glDisableClientState(GL_FOG_COORDINATE_EXT);
3282 #endif
3284 #if 0 /* tangents ----------------------------------------------*/
3285 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3286 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3287 /* TODO: tangents*/
3288 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3289 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3290 glEnable(GL_TANGENT_ARRAY_EXT);
3291 (GL_EXTCALL)(TangentPointerEXT)(
3292 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3293 sd->u.s.tangent.dwStride,
3294 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3295 } else {
3296 glDisable(GL_TANGENT_ARRAY_EXT);
3298 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3299 glEnable(GL_BINORMAL_ARRAY_EXT);
3300 (GL_EXTCALL)(BinormalPointerEXT)(
3301 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3302 sd->u.s.binormal.dwStride,
3303 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3304 } else{
3305 glDisable(GL_BINORMAL_ARRAY_EXT);
3308 } else {
3309 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3310 /* FIXME: fixme once */
3311 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3313 } else {
3314 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3315 /* make sure fog is disabled */
3316 glDisable(GL_TANGENT_ARRAY_EXT);
3317 glDisable(GL_BINORMAL_ARRAY_EXT);
3320 #endif
3322 /* Point Size ----------------------------------------------*/
3323 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3325 /* no such functionality in the fixed function GL pipeline */
3326 TRACE("Cannot change ptSize here in openGl\n");
3327 /* TODO: Implement this function in using shaders if they are available */
3331 /* Vertex Pointers -----------------------------------------*/
3332 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3333 /* Note dwType == float3 or float4 == 2 or 3 */
3334 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3335 sd->u.s.position.dwStride,
3336 sd->u.s.position.dwType + 1,
3337 sd->u.s.position.lpData));
3339 if(curVBO != sd->u.s.position.VBO) {
3340 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3341 checkGLcall("glBindBufferARB");
3342 curVBO = sd->u.s.position.VBO;
3345 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3346 handling for rhw mode should not impact screen position whereas in GL it does.
3347 This may result in very slightly distorted textures in rhw mode.
3348 There's always the other option of fixing the view matrix to
3349 prevent w from having any effect.
3351 This only applies to user pointer sources, in VBOs the vertices are fixed up
3353 if(sd->u.s.position.VBO == 0) {
3354 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3355 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3356 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3357 } else {
3358 glVertexPointer(
3359 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3360 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3361 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3363 checkGLcall("glVertexPointer(...)");
3364 glEnableClientState(GL_VERTEX_ARRAY);
3365 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3368 /* Normals -------------------------------------------------*/
3369 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3370 /* Note dwType == float3 or float4 == 2 or 3 */
3371 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3372 sd->u.s.normal.dwStride,
3373 sd->u.s.normal.lpData));
3374 if(curVBO != sd->u.s.normal.VBO) {
3375 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3376 checkGLcall("glBindBufferARB");
3377 curVBO = sd->u.s.normal.VBO;
3379 glNormalPointer(
3380 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3381 sd->u.s.normal.dwStride,
3382 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3383 checkGLcall("glNormalPointer(...)");
3384 glEnableClientState(GL_NORMAL_ARRAY);
3385 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3387 } else {
3388 glNormal3f(0, 0, 0);
3389 checkGLcall("glNormal3f(0, 0, 0)");
3392 /* Diffuse Colour --------------------------------------------*/
3393 /* WARNING: Data here MUST be in RGBA format, so cannot */
3394 /* go directly into fast mode from app pgm, because */
3395 /* directx requires data in BGRA format. */
3396 /* currently fixupVertices swizzles the format, but this isn't*/
3397 /* very practical when using VBOS */
3398 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3399 /* , or the user doesn't care and wants the speed advantage */
3401 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3402 /* Note dwType == float3 or float4 == 2 or 3 */
3403 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3404 sd->u.s.diffuse.dwStride,
3405 sd->u.s.diffuse.lpData));
3407 if(curVBO != sd->u.s.diffuse.VBO) {
3408 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3409 checkGLcall("glBindBufferARB");
3410 curVBO = sd->u.s.diffuse.VBO;
3413 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3414 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3415 sd->u.s.diffuse.dwStride,
3416 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3417 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3418 glEnableClientState(GL_COLOR_ARRAY);
3419 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3421 } else {
3422 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3423 checkGLcall("glColor4f(1, 1, 1, 1)");
3426 /* Specular Colour ------------------------------------------*/
3427 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3428 TRACE("setting specular colour\n");
3429 /* Note dwType == float3 or float4 == 2 or 3 */
3430 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3431 sd->u.s.specular.dwStride,
3432 sd->u.s.specular.lpData));
3433 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3434 if(curVBO != sd->u.s.specular.VBO) {
3435 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3436 checkGLcall("glBindBufferARB");
3437 curVBO = sd->u.s.specular.VBO;
3439 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3440 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3441 sd->u.s.specular.dwStride,
3442 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3443 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3444 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3445 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3446 } else {
3448 /* Missing specular color is not critical, no warnings */
3449 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3452 } else {
3453 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3454 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3455 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3456 } else {
3458 /* Missing specular color is not critical, no warnings */
3459 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3463 /* Texture coords -------------------------------------------*/
3464 loadTexCoords(stateblock, sd, &curVBO);
3467 static inline void drawPrimitiveTraceDataLocations(
3468 WineDirect3DVertexStridedData *dataLocations) {
3470 /* Dump out what parts we have supplied */
3471 TRACE("Strided Data:\n");
3472 TRACE_STRIDED((dataLocations), position);
3473 TRACE_STRIDED((dataLocations), blendWeights);
3474 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3475 TRACE_STRIDED((dataLocations), normal);
3476 TRACE_STRIDED((dataLocations), pSize);
3477 TRACE_STRIDED((dataLocations), diffuse);
3478 TRACE_STRIDED((dataLocations), specular);
3479 TRACE_STRIDED((dataLocations), texCoords[0]);
3480 TRACE_STRIDED((dataLocations), texCoords[1]);
3481 TRACE_STRIDED((dataLocations), texCoords[2]);
3482 TRACE_STRIDED((dataLocations), texCoords[3]);
3483 TRACE_STRIDED((dataLocations), texCoords[4]);
3484 TRACE_STRIDED((dataLocations), texCoords[5]);
3485 TRACE_STRIDED((dataLocations), texCoords[6]);
3486 TRACE_STRIDED((dataLocations), texCoords[7]);
3487 TRACE_STRIDED((dataLocations), position2);
3488 TRACE_STRIDED((dataLocations), normal2);
3489 TRACE_STRIDED((dataLocations), tangent);
3490 TRACE_STRIDED((dataLocations), binormal);
3491 TRACE_STRIDED((dataLocations), tessFactor);
3492 TRACE_STRIDED((dataLocations), fog);
3493 TRACE_STRIDED((dataLocations), depth);
3494 TRACE_STRIDED((dataLocations), sample);
3496 return;
3499 /* Helper for vertexdeclaration() */
3500 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3501 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3502 BOOL fixup = FALSE;
3503 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3505 if(device->up_strided) {
3506 /* Note: this is a ddraw fixed-function code path */
3507 TRACE("================ Strided Input ===================\n");
3508 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3510 if(TRACE_ON(d3d)) {
3511 drawPrimitiveTraceDataLocations(dataLocations);
3513 } else {
3514 /* Note: This is a fixed function or shader codepath.
3515 * This means it must handle both types of strided data.
3516 * Shaders must go through here to zero the strided data, even if they
3517 * don't set any declaration at all
3519 TRACE("================ Vertex Declaration ===================\n");
3520 memset(dataLocations, 0, sizeof(*dataLocations));
3521 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3522 useVertexShaderFunction, dataLocations, &fixup);
3525 if (dataLocations->u.s.position_transformed) {
3526 useVertexShaderFunction = FALSE;
3529 /* Unload the old arrays before loading the new ones to get old junk out */
3530 if(context->numberedArraysLoaded) {
3531 unloadNumberedArrays(stateblock);
3532 context->numberedArraysLoaded = FALSE;
3534 if(context->namedArraysLoaded) {
3535 unloadVertexData(stateblock);
3536 context->namedArraysLoaded = FALSE;
3539 if(useVertexShaderFunction) {
3540 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3541 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3542 device->useDrawStridedSlow = TRUE;
3543 context->numberedArraysLoaded = FALSE;
3544 } else {
3545 TRACE("Loading numbered arrays\n");
3546 loadNumberedArrays(stateblock, dataLocations);
3547 device->useDrawStridedSlow = FALSE;
3548 context->numberedArraysLoaded = TRUE;
3550 } else if (fixup ||
3551 (dataLocations->u.s.pSize.lpData == NULL &&
3552 dataLocations->u.s.diffuse.lpData == NULL &&
3553 dataLocations->u.s.specular.lpData == NULL)) {
3554 /* Load the vertex data using named arrays */
3555 TRACE("Loading vertex data\n");
3556 loadVertexData(stateblock, dataLocations);
3557 device->useDrawStridedSlow = FALSE;
3558 context->namedArraysLoaded = TRUE;
3559 } else {
3560 TRACE("Not loading vertex data\n");
3561 device->useDrawStridedSlow = TRUE;
3564 /* Generate some fixme's if unsupported functionality is being used */
3565 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3566 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3567 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3568 FIXME("Tweening is only valid with vertex shaders\n");
3570 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3571 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3573 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3574 FIXME("Extended attributes are only valid with vertex shaders\n");
3576 #undef BUFFER_OR_DATA
3579 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3580 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3581 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3582 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3583 BOOL transformed;
3584 /* Some stuff is in the device until we have per context tracking */
3585 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3586 BOOL wasrhw = context->last_was_rhw;
3588 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3589 * here simply check whether a shader was set, or the user disabled shaders
3591 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3592 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3593 useVertexShaderFunction = TRUE;
3595 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3596 updateFog = TRUE;
3598 } else if(context->last_was_foggy_shader) {
3599 updateFog = TRUE;
3602 handleStreams(stateblock, useVertexShaderFunction, context);
3604 transformed = device->strided_streams.u.s.position_transformed;
3605 if (transformed) useVertexShaderFunction = FALSE;
3607 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3608 updateFog = TRUE;
3611 /* Reapply lighting if it is not scheduled for reapplication already */
3612 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3613 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3616 if (transformed) {
3617 context->last_was_rhw = TRUE;
3618 } else {
3620 /* Untransformed, so relies on the view and projection matrices */
3621 context->last_was_rhw = FALSE;
3622 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3623 device->untransformed = TRUE;
3625 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3626 * Not needed as long as only hw shaders are supported
3629 /* This sets the shader output position correction constants.
3630 * TODO: Move to the viewport state
3632 if (useVertexShaderFunction) {
3633 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3634 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3638 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3639 * off this function will be called again anyway to make sure they're properly set
3641 if(!useVertexShaderFunction) {
3642 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3643 * or transformed / untransformed was switched
3645 if(wasrhw != context->last_was_rhw &&
3646 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3647 !isStateDirty(context, STATE_VIEWPORT)) {
3648 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3650 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3651 * mode.
3653 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3654 * this check will fail and the matrix not applied again. This is OK because a simple
3655 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3656 * needs of the vertex declaration.
3658 * World and view matrix go into the same gl matrix, so only apply them when neither is
3659 * dirty
3661 if(transformed != wasrhw &&
3662 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3663 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3664 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3667 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3668 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3671 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3672 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3674 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3675 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3677 } else {
3678 /* We compile the shader here because we need the vertex declaration
3679 * in order to determine if we need to do any swizzling for D3DCOLOR
3680 * registers. If the shader is already compiled this call will do nothing. */
3681 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3683 if(!context->last_was_vshader) {
3684 int i;
3685 static BOOL warned = FALSE;
3686 /* Disable all clip planes to get defined results on all drivers. See comment in the
3687 * state_clipping state handler
3689 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3690 glDisable(GL_CLIP_PLANE0 + i);
3691 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3694 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3695 FIXME("Clipping not supported with vertex shaders\n");
3696 warned = TRUE;
3698 if(wasrhw) {
3699 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3700 * shaders themselves do not need it, but the matrices are not reapplied automatically when
3701 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3702 * fixed function vertex processing states back in a sane state before switching to shaders
3704 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3705 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3707 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3708 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3714 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3715 * application
3717 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3718 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3720 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3721 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3725 context->last_was_vshader = useVertexShaderFunction;
3727 if(updateFog) {
3728 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3730 if(!useVertexShaderFunction) {
3731 int i;
3732 for(i = 0; i < MAX_TEXTURES; i++) {
3733 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3734 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3740 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3741 UINT width, height;
3742 IWineD3DSurfaceImpl *target;
3744 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3745 checkGLcall("glDepthRange");
3746 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3748 if(stateblock->wineD3DDevice->render_offscreen) {
3749 glViewport(stateblock->viewport.X,
3750 stateblock->viewport.Y,
3751 stateblock->viewport.Width, stateblock->viewport.Height);
3752 } else {
3753 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3754 target->get_drawable_size(target, &width, &height);
3756 glViewport(stateblock->viewport.X,
3757 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3758 stateblock->viewport.Width, stateblock->viewport.Height);
3761 checkGLcall("glViewport");
3763 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3764 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3765 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3766 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3768 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3769 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3773 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3774 UINT Index = state - STATE_ACTIVELIGHT(0);
3775 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3777 if(!lightInfo) {
3778 glDisable(GL_LIGHT0 + Index);
3779 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3780 } else {
3781 float quad_att;
3782 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3784 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3785 glMatrixMode(GL_MODELVIEW);
3786 glPushMatrix();
3787 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3789 /* Diffuse: */
3790 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3791 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3792 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3793 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3794 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3795 checkGLcall("glLightfv");
3797 /* Specular */
3798 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3799 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3800 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3801 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3802 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3803 checkGLcall("glLightfv");
3805 /* Ambient */
3806 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3807 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3808 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3809 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3810 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3811 checkGLcall("glLightfv");
3813 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3814 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3815 } else {
3816 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3819 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3820 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3821 * Attenuation0 to NaN and crashes in the gl lib
3824 switch (lightInfo->OriginalParms.Type) {
3825 case WINED3DLIGHT_POINT:
3826 /* Position */
3827 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3828 checkGLcall("glLightfv");
3829 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3830 checkGLcall("glLightf");
3831 /* Attenuation - Are these right? guessing... */
3832 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3833 checkGLcall("glLightf");
3834 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3835 checkGLcall("glLightf");
3836 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3837 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3838 checkGLcall("glLightf");
3839 /* FIXME: Range */
3840 break;
3842 case WINED3DLIGHT_SPOT:
3843 /* Position */
3844 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3845 checkGLcall("glLightfv");
3846 /* Direction */
3847 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3848 checkGLcall("glLightfv");
3849 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3850 checkGLcall("glLightf");
3851 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3852 checkGLcall("glLightf");
3853 /* Attenuation - Are these right? guessing... */
3854 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3855 checkGLcall("glLightf");
3856 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3857 checkGLcall("glLightf");
3858 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3859 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3860 checkGLcall("glLightf");
3861 /* FIXME: Range */
3862 break;
3864 case WINED3DLIGHT_DIRECTIONAL:
3865 /* Direction */
3866 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3867 checkGLcall("glLightfv");
3868 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3869 checkGLcall("glLightf");
3870 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3871 checkGLcall("glLightf");
3872 break;
3874 default:
3875 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3878 /* Restore the modelview matrix */
3879 glPopMatrix();
3881 glEnable(GL_LIGHT0 + Index);
3882 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3885 return;
3888 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3889 RECT *pRect = &stateblock->scissorRect;
3890 UINT height;
3891 UINT width;
3892 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3894 target->get_drawable_size(target, &width, &height);
3895 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3896 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3898 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3899 pRect->right - pRect->left, pRect->bottom - pRect->top);
3901 if (stateblock->wineD3DDevice->render_offscreen) {
3902 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3903 } else {
3904 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3906 checkGLcall("glScissor");
3909 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3910 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3911 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3912 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3913 } else {
3914 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3915 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3920 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3921 if(stateblock->wineD3DDevice->render_offscreen) {
3922 glFrontFace(GL_CCW);
3923 checkGLcall("glFrontFace(GL_CCW)");
3924 } else {
3925 glFrontFace(GL_CW);
3926 checkGLcall("glFrontFace(GL_CW)");
3930 const struct StateEntry FFPStateTable[] =
3932 /* State name representative, apply function */
3933 { /* 0, Undefined */ 0, state_undefined },
3934 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3935 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3936 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3937 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3938 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3939 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3940 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3941 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3942 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3943 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3944 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3945 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3946 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3947 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3948 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3949 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3950 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3951 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3952 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3953 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3954 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3955 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3956 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3957 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3958 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3959 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3960 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3961 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3962 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3963 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3964 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3965 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3966 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3967 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3968 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3969 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3970 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3971 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3972 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3973 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3974 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3975 { /* 42, undefined */ 0, state_undefined },
3976 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3977 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3978 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3979 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3980 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3981 { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog },
3982 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3983 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3984 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3985 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3986 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3987 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3988 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3989 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3990 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3991 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3992 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3993 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3994 { /* 61, Undefined */ 0, state_undefined },
3995 { /* 62, Undefined */ 0, state_undefined },
3996 { /* 63, Undefined */ 0, state_undefined },
3997 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3998 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3999 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4000 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4001 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4002 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4003 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4004 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4005 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4006 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4007 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4008 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4009 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4010 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4011 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4012 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4013 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4014 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4015 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4016 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4017 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4018 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4019 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4020 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4021 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4022 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4023 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4024 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4025 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4026 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4027 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4028 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4029 { /* 96, Undefined */ 0, state_undefined },
4030 { /* 97, Undefined */ 0, state_undefined },
4031 { /* 98, Undefined */ 0, state_undefined },
4032 { /* 99, Undefined */ 0, state_undefined },
4033 { /*100, Undefined */ 0, state_undefined },
4034 { /*101, Undefined */ 0, state_undefined },
4035 { /*102, Undefined */ 0, state_undefined },
4036 { /*103, Undefined */ 0, state_undefined },
4037 { /*104, Undefined */ 0, state_undefined },
4038 { /*105, Undefined */ 0, state_undefined },
4039 { /*106, Undefined */ 0, state_undefined },
4040 { /*107, Undefined */ 0, state_undefined },
4041 { /*108, Undefined */ 0, state_undefined },
4042 { /*109, Undefined */ 0, state_undefined },
4043 { /*110, Undefined */ 0, state_undefined },
4044 { /*111, Undefined */ 0, state_undefined },
4045 { /*112, Undefined */ 0, state_undefined },
4046 { /*113, Undefined */ 0, state_undefined },
4047 { /*114, Undefined */ 0, state_undefined },
4048 { /*115, Undefined */ 0, state_undefined },
4049 { /*116, Undefined */ 0, state_undefined },
4050 { /*117, Undefined */ 0, state_undefined },
4051 { /*118, Undefined */ 0, state_undefined },
4052 { /*119, Undefined */ 0, state_undefined },
4053 { /*120, Undefined */ 0, state_undefined },
4054 { /*121, Undefined */ 0, state_undefined },
4055 { /*122, Undefined */ 0, state_undefined },
4056 { /*123, Undefined */ 0, state_undefined },
4057 { /*124, Undefined */ 0, state_undefined },
4058 { /*125, Undefined */ 0, state_undefined },
4059 { /*126, Undefined */ 0, state_undefined },
4060 { /*127, Undefined */ 0, state_undefined },
4061 /* Big hole ends */
4062 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4063 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4064 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4065 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4066 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4067 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4068 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4069 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4070 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
4071 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
4072 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
4073 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
4074 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
4075 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4076 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
4077 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
4078 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
4079 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4080 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4081 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4082 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4083 { /*149, Undefined */ 0, state_undefined },
4084 { /*150, Undefined */ 0, state_undefined },
4085 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
4086 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
4087 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
4088 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4089 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
4090 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
4091 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4092 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4093 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4094 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4095 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
4096 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
4097 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
4098 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
4099 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
4100 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
4101 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
4102 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4103 { /*169, Undefined */ 0, state_undefined },
4104 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
4105 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
4106 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
4107 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
4108 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
4109 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
4110 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
4111 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
4112 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4113 { /*177, undefined */ 0, state_undefined },
4114 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4115 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4116 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4117 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4118 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4119 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4120 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4121 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4122 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4123 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4124 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4125 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4126 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4127 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4128 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4129 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
4130 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_PIXELSHADER, pixelshader },
4131 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
4132 { /*196, undefined */ 0, state_undefined },
4133 { /*197, undefined */ 0, state_undefined },
4134 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4135 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4136 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4137 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4138 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4139 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4140 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4141 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4142 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4143 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4144 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4145 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blendop },
4146 /* Texture stage states */
4147 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4148 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4149 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4150 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4151 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4152 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4153 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4154 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4155 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4156 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4157 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4158 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4159 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4160 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4161 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4162 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4163 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4164 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4165 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4166 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4167 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4168 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4169 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4170 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4171 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4172 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4173 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4174 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
4175 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4176 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4177 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4178 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4180 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4181 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4182 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4183 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4184 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4185 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4186 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4187 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4188 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4189 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4190 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4191 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4192 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4193 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4194 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4195 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4196 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4197 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4198 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4199 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4200 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4201 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4202 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4203 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4204 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4205 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4206 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4207 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
4208 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4209 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4210 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4211 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4213 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4214 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4215 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4216 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4217 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4218 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4219 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4220 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4221 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4222 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4223 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4224 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4225 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4226 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4227 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4228 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4229 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4230 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4231 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4232 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4233 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4234 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4235 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4236 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4237 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4238 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4239 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4240 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
4241 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4242 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4243 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4244 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4246 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4247 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4248 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4249 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4250 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4251 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4252 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4253 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4254 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4255 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4256 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4257 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4258 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4259 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4260 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4261 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4262 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4263 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4264 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4265 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4266 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4267 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4268 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4269 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4270 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4271 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4272 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4273 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
4274 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4275 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4276 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4277 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4279 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4280 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4281 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4282 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4283 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4284 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4285 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4286 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4287 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4288 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4289 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4290 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4291 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4292 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4293 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4294 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4295 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4296 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4297 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4298 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4299 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4300 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4301 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4302 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4303 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4304 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4305 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4306 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
4307 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4308 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4309 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4310 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4312 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4313 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4314 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4315 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4316 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4317 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4318 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4319 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4320 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4321 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4322 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4323 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4324 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4325 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4326 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4327 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4328 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4329 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4330 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4331 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4332 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4333 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4334 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4335 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4336 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4337 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4338 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4339 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
4340 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4341 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4342 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4343 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4345 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4346 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4347 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4348 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4349 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4350 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4351 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4352 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4353 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4354 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4355 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4356 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4357 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4358 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4359 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4360 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4361 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4362 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4363 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4364 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4365 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4366 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4367 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4368 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4369 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4370 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4371 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4372 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
4373 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4374 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4375 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4376 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4378 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4379 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4380 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4381 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4382 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4383 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4384 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4385 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4386 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4387 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4388 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4389 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4390 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4391 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4392 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4393 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4394 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4395 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4396 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4397 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4398 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4399 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4400 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4401 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4402 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4403 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4404 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4405 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
4406 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4407 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4408 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4409 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4410 /* Sampler states */
4411 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
4412 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
4413 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
4414 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
4415 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
4416 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
4417 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
4418 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
4419 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
4420 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
4421 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
4422 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
4423 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
4424 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
4425 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
4426 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
4427 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
4428 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
4429 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
4430 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
4431 /* Pixel shader */
4432 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
4433 /* Transform states follow */
4434 { /* 1, undefined */ 0, state_undefined },
4435 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
4436 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
4437 { /* 4, undefined */ 0, state_undefined },
4438 { /* 5, undefined */ 0, state_undefined },
4439 { /* 6, undefined */ 0, state_undefined },
4440 { /* 7, undefined */ 0, state_undefined },
4441 { /* 8, undefined */ 0, state_undefined },
4442 { /* 9, undefined */ 0, state_undefined },
4443 { /* 10, undefined */ 0, state_undefined },
4444 { /* 11, undefined */ 0, state_undefined },
4445 { /* 12, undefined */ 0, state_undefined },
4446 { /* 13, undefined */ 0, state_undefined },
4447 { /* 14, undefined */ 0, state_undefined },
4448 { /* 15, undefined */ 0, state_undefined },
4449 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4450 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4451 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4452 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4453 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4454 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4455 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4456 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4457 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
4458 { /* 24, undefined */ 0, state_undefined },
4459 { /* 25, undefined */ 0, state_undefined },
4460 { /* 26, undefined */ 0, state_undefined },
4461 { /* 27, undefined */ 0, state_undefined },
4462 { /* 28, undefined */ 0, state_undefined },
4463 { /* 29, undefined */ 0, state_undefined },
4464 { /* 30, undefined */ 0, state_undefined },
4465 { /* 31, undefined */ 0, state_undefined },
4466 { /* 32, undefined */ 0, state_undefined },
4467 { /* 33, undefined */ 0, state_undefined },
4468 { /* 34, undefined */ 0, state_undefined },
4469 { /* 35, undefined */ 0, state_undefined },
4470 { /* 36, undefined */ 0, state_undefined },
4471 { /* 37, undefined */ 0, state_undefined },
4472 { /* 38, undefined */ 0, state_undefined },
4473 { /* 39, undefined */ 0, state_undefined },
4474 { /* 40, undefined */ 0, state_undefined },
4475 { /* 41, undefined */ 0, state_undefined },
4476 { /* 42, undefined */ 0, state_undefined },
4477 { /* 43, undefined */ 0, state_undefined },
4478 { /* 44, undefined */ 0, state_undefined },
4479 { /* 45, undefined */ 0, state_undefined },
4480 { /* 46, undefined */ 0, state_undefined },
4481 { /* 47, undefined */ 0, state_undefined },
4482 { /* 48, undefined */ 0, state_undefined },
4483 { /* 49, undefined */ 0, state_undefined },
4484 { /* 50, undefined */ 0, state_undefined },
4485 { /* 51, undefined */ 0, state_undefined },
4486 { /* 52, undefined */ 0, state_undefined },
4487 { /* 53, undefined */ 0, state_undefined },
4488 { /* 54, undefined */ 0, state_undefined },
4489 { /* 55, undefined */ 0, state_undefined },
4490 { /* 56, undefined */ 0, state_undefined },
4491 { /* 57, undefined */ 0, state_undefined },
4492 { /* 58, undefined */ 0, state_undefined },
4493 { /* 59, undefined */ 0, state_undefined },
4494 { /* 60, undefined */ 0, state_undefined },
4495 { /* 61, undefined */ 0, state_undefined },
4496 { /* 62, undefined */ 0, state_undefined },
4497 { /* 63, undefined */ 0, state_undefined },
4498 { /* 64, undefined */ 0, state_undefined },
4499 { /* 65, undefined */ 0, state_undefined },
4500 { /* 66, undefined */ 0, state_undefined },
4501 { /* 67, undefined */ 0, state_undefined },
4502 { /* 68, undefined */ 0, state_undefined },
4503 { /* 69, undefined */ 0, state_undefined },
4504 { /* 70, undefined */ 0, state_undefined },
4505 { /* 71, undefined */ 0, state_undefined },
4506 { /* 72, undefined */ 0, state_undefined },
4507 { /* 73, undefined */ 0, state_undefined },
4508 { /* 74, undefined */ 0, state_undefined },
4509 { /* 75, undefined */ 0, state_undefined },
4510 { /* 76, undefined */ 0, state_undefined },
4511 { /* 77, undefined */ 0, state_undefined },
4512 { /* 78, undefined */ 0, state_undefined },
4513 { /* 79, undefined */ 0, state_undefined },
4514 { /* 80, undefined */ 0, state_undefined },
4515 { /* 81, undefined */ 0, state_undefined },
4516 { /* 82, undefined */ 0, state_undefined },
4517 { /* 83, undefined */ 0, state_undefined },
4518 { /* 84, undefined */ 0, state_undefined },
4519 { /* 85, undefined */ 0, state_undefined },
4520 { /* 86, undefined */ 0, state_undefined },
4521 { /* 87, undefined */ 0, state_undefined },
4522 { /* 88, undefined */ 0, state_undefined },
4523 { /* 89, undefined */ 0, state_undefined },
4524 { /* 90, undefined */ 0, state_undefined },
4525 { /* 91, undefined */ 0, state_undefined },
4526 { /* 92, undefined */ 0, state_undefined },
4527 { /* 93, undefined */ 0, state_undefined },
4528 { /* 94, undefined */ 0, state_undefined },
4529 { /* 95, undefined */ 0, state_undefined },
4530 { /* 96, undefined */ 0, state_undefined },
4531 { /* 97, undefined */ 0, state_undefined },
4532 { /* 98, undefined */ 0, state_undefined },
4533 { /* 99, undefined */ 0, state_undefined },
4534 { /*100, undefined */ 0, state_undefined },
4535 { /*101, undefined */ 0, state_undefined },
4536 { /*102, undefined */ 0, state_undefined },
4537 { /*103, undefined */ 0, state_undefined },
4538 { /*104, undefined */ 0, state_undefined },
4539 { /*105, undefined */ 0, state_undefined },
4540 { /*106, undefined */ 0, state_undefined },
4541 { /*107, undefined */ 0, state_undefined },
4542 { /*108, undefined */ 0, state_undefined },
4543 { /*109, undefined */ 0, state_undefined },
4544 { /*110, undefined */ 0, state_undefined },
4545 { /*111, undefined */ 0, state_undefined },
4546 { /*112, undefined */ 0, state_undefined },
4547 { /*113, undefined */ 0, state_undefined },
4548 { /*114, undefined */ 0, state_undefined },
4549 { /*115, undefined */ 0, state_undefined },
4550 { /*116, undefined */ 0, state_undefined },
4551 { /*117, undefined */ 0, state_undefined },
4552 { /*118, undefined */ 0, state_undefined },
4553 { /*119, undefined */ 0, state_undefined },
4554 { /*120, undefined */ 0, state_undefined },
4555 { /*121, undefined */ 0, state_undefined },
4556 { /*122, undefined */ 0, state_undefined },
4557 { /*123, undefined */ 0, state_undefined },
4558 { /*124, undefined */ 0, state_undefined },
4559 { /*125, undefined */ 0, state_undefined },
4560 { /*126, undefined */ 0, state_undefined },
4561 { /*127, undefined */ 0, state_undefined },
4562 { /*128, undefined */ 0, state_undefined },
4563 { /*129, undefined */ 0, state_undefined },
4564 { /*130, undefined */ 0, state_undefined },
4565 { /*131, undefined */ 0, state_undefined },
4566 { /*132, undefined */ 0, state_undefined },
4567 { /*133, undefined */ 0, state_undefined },
4568 { /*134, undefined */ 0, state_undefined },
4569 { /*135, undefined */ 0, state_undefined },
4570 { /*136, undefined */ 0, state_undefined },
4571 { /*137, undefined */ 0, state_undefined },
4572 { /*138, undefined */ 0, state_undefined },
4573 { /*139, undefined */ 0, state_undefined },
4574 { /*140, undefined */ 0, state_undefined },
4575 { /*141, undefined */ 0, state_undefined },
4576 { /*142, undefined */ 0, state_undefined },
4577 { /*143, undefined */ 0, state_undefined },
4578 { /*144, undefined */ 0, state_undefined },
4579 { /*145, undefined */ 0, state_undefined },
4580 { /*146, undefined */ 0, state_undefined },
4581 { /*147, undefined */ 0, state_undefined },
4582 { /*148, undefined */ 0, state_undefined },
4583 { /*149, undefined */ 0, state_undefined },
4584 { /*150, undefined */ 0, state_undefined },
4585 { /*151, undefined */ 0, state_undefined },
4586 { /*152, undefined */ 0, state_undefined },
4587 { /*153, undefined */ 0, state_undefined },
4588 { /*154, undefined */ 0, state_undefined },
4589 { /*155, undefined */ 0, state_undefined },
4590 { /*156, undefined */ 0, state_undefined },
4591 { /*157, undefined */ 0, state_undefined },
4592 { /*158, undefined */ 0, state_undefined },
4593 { /*159, undefined */ 0, state_undefined },
4594 { /*160, undefined */ 0, state_undefined },
4595 { /*161, undefined */ 0, state_undefined },
4596 { /*162, undefined */ 0, state_undefined },
4597 { /*163, undefined */ 0, state_undefined },
4598 { /*164, undefined */ 0, state_undefined },
4599 { /*165, undefined */ 0, state_undefined },
4600 { /*166, undefined */ 0, state_undefined },
4601 { /*167, undefined */ 0, state_undefined },
4602 { /*168, undefined */ 0, state_undefined },
4603 { /*169, undefined */ 0, state_undefined },
4604 { /*170, undefined */ 0, state_undefined },
4605 { /*171, undefined */ 0, state_undefined },
4606 { /*172, undefined */ 0, state_undefined },
4607 { /*173, undefined */ 0, state_undefined },
4608 { /*174, undefined */ 0, state_undefined },
4609 { /*175, undefined */ 0, state_undefined },
4610 { /*176, undefined */ 0, state_undefined },
4611 { /*177, undefined */ 0, state_undefined },
4612 { /*178, undefined */ 0, state_undefined },
4613 { /*179, undefined */ 0, state_undefined },
4614 { /*180, undefined */ 0, state_undefined },
4615 { /*181, undefined */ 0, state_undefined },
4616 { /*182, undefined */ 0, state_undefined },
4617 { /*183, undefined */ 0, state_undefined },
4618 { /*184, undefined */ 0, state_undefined },
4619 { /*185, undefined */ 0, state_undefined },
4620 { /*186, undefined */ 0, state_undefined },
4621 { /*187, undefined */ 0, state_undefined },
4622 { /*188, undefined */ 0, state_undefined },
4623 { /*189, undefined */ 0, state_undefined },
4624 { /*190, undefined */ 0, state_undefined },
4625 { /*191, undefined */ 0, state_undefined },
4626 { /*192, undefined */ 0, state_undefined },
4627 { /*193, undefined */ 0, state_undefined },
4628 { /*194, undefined */ 0, state_undefined },
4629 { /*195, undefined */ 0, state_undefined },
4630 { /*196, undefined */ 0, state_undefined },
4631 { /*197, undefined */ 0, state_undefined },
4632 { /*198, undefined */ 0, state_undefined },
4633 { /*199, undefined */ 0, state_undefined },
4634 { /*200, undefined */ 0, state_undefined },
4635 { /*201, undefined */ 0, state_undefined },
4636 { /*202, undefined */ 0, state_undefined },
4637 { /*203, undefined */ 0, state_undefined },
4638 { /*204, undefined */ 0, state_undefined },
4639 { /*205, undefined */ 0, state_undefined },
4640 { /*206, undefined */ 0, state_undefined },
4641 { /*207, undefined */ 0, state_undefined },
4642 { /*208, undefined */ 0, state_undefined },
4643 { /*209, undefined */ 0, state_undefined },
4644 { /*210, undefined */ 0, state_undefined },
4645 { /*211, undefined */ 0, state_undefined },
4646 { /*212, undefined */ 0, state_undefined },
4647 { /*213, undefined */ 0, state_undefined },
4648 { /*214, undefined */ 0, state_undefined },
4649 { /*215, undefined */ 0, state_undefined },
4650 { /*216, undefined */ 0, state_undefined },
4651 { /*217, undefined */ 0, state_undefined },
4652 { /*218, undefined */ 0, state_undefined },
4653 { /*219, undefined */ 0, state_undefined },
4654 { /*220, undefined */ 0, state_undefined },
4655 { /*221, undefined */ 0, state_undefined },
4656 { /*222, undefined */ 0, state_undefined },
4657 { /*223, undefined */ 0, state_undefined },
4658 { /*224, undefined */ 0, state_undefined },
4659 { /*225, undefined */ 0, state_undefined },
4660 { /*226, undefined */ 0, state_undefined },
4661 { /*227, undefined */ 0, state_undefined },
4662 { /*228, undefined */ 0, state_undefined },
4663 { /*229, undefined */ 0, state_undefined },
4664 { /*230, undefined */ 0, state_undefined },
4665 { /*231, undefined */ 0, state_undefined },
4666 { /*232, undefined */ 0, state_undefined },
4667 { /*233, undefined */ 0, state_undefined },
4668 { /*234, undefined */ 0, state_undefined },
4669 { /*235, undefined */ 0, state_undefined },
4670 { /*236, undefined */ 0, state_undefined },
4671 { /*237, undefined */ 0, state_undefined },
4672 { /*238, undefined */ 0, state_undefined },
4673 { /*239, undefined */ 0, state_undefined },
4674 { /*240, undefined */ 0, state_undefined },
4675 { /*241, undefined */ 0, state_undefined },
4676 { /*242, undefined */ 0, state_undefined },
4677 { /*243, undefined */ 0, state_undefined },
4678 { /*244, undefined */ 0, state_undefined },
4679 { /*245, undefined */ 0, state_undefined },
4680 { /*246, undefined */ 0, state_undefined },
4681 { /*247, undefined */ 0, state_undefined },
4682 { /*248, undefined */ 0, state_undefined },
4683 { /*249, undefined */ 0, state_undefined },
4684 { /*250, undefined */ 0, state_undefined },
4685 { /*251, undefined */ 0, state_undefined },
4686 { /*252, undefined */ 0, state_undefined },
4687 { /*253, undefined */ 0, state_undefined },
4688 { /*254, undefined */ 0, state_undefined },
4689 { /*255, undefined */ 0, state_undefined },
4690 /* End huge gap */
4691 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4692 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4693 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4694 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4695 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4696 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4697 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4698 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4699 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4700 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4701 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4702 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4703 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4704 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4705 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4706 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4707 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4708 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4709 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4710 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4711 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4712 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4713 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4714 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4715 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4716 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4717 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4718 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4719 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4720 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4721 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4722 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4723 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4724 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4725 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4726 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4727 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4728 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4729 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4730 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4731 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4732 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4733 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4734 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4735 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4736 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4737 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4738 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4739 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4740 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4741 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4742 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4743 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4744 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4745 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4746 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4747 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4748 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4749 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4750 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4751 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4752 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4753 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4754 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4755 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4756 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4757 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4758 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4759 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4760 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4761 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4762 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4763 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4764 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4765 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4766 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4767 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4768 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4769 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4770 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4771 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4772 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4773 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4774 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4775 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4776 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4777 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4778 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4779 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4780 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4781 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4782 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4783 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4784 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4785 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4786 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4787 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4788 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4789 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4790 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4791 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4792 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4793 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4794 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4795 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4796 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4797 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4798 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4799 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4800 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4801 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4802 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4803 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4804 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4805 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4806 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4807 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4808 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4809 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4810 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4811 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4812 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4813 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4814 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4815 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4816 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4817 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4818 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4819 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4820 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4821 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4822 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4823 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4824 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4825 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4826 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4827 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4828 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4829 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4830 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4831 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4832 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4833 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4834 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4835 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4836 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4837 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4838 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4839 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4840 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4841 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4842 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4843 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4844 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4845 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4846 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4847 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4848 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4849 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4850 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4851 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4852 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4853 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4854 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4855 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4856 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4857 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4858 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4859 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4860 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4861 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4862 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4863 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4864 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4865 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4866 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4867 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4868 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4869 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4870 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4871 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4872 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4873 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4874 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4875 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4876 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4877 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4878 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4879 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4880 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4881 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4882 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4883 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4884 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4885 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4886 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4887 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4888 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4889 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4890 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4891 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4892 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4893 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4894 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4895 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4896 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4897 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4898 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4899 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4900 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4901 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4902 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4903 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4904 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4905 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4906 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4907 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4908 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4909 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4910 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4911 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4912 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4913 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4914 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4915 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4916 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4917 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4918 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4919 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4920 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4921 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4922 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4923 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4924 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4925 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4926 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4927 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4928 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4929 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4930 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4931 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4932 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4933 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4934 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4935 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4936 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4937 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4938 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4939 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4940 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4941 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4942 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4943 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4944 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4945 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4946 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4947 /* Various Vertex states follow */
4948 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4949 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4950 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4951 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4952 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4953 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4954 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4955 /* Lights */
4956 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4957 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4958 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4959 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4960 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4961 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4962 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4963 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4965 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4966 /* Clip planes */
4967 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4968 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4969 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4970 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4971 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4972 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4973 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4974 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4975 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4976 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4977 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4978 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4979 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4980 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4981 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4982 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4983 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4984 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4985 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4986 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4987 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4988 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4989 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4990 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4991 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4992 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4993 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4994 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4995 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4996 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4997 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4998 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
5000 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
5001 { /* STATE_FRONTFACE */ STATE_FRONTFACE, frontface },