wined3d: In tex_colorop() & tex_alphaop(), only check the mapped stage against GL_LIM...
[wine/multimedia.git] / dlls / wined3d / state.c
blobfbd0cd3b04e9035b5f2e2b505a880e884987ccbe
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_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
40 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
41 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
43 if(STATE_IS_RENDER(state)) {
44 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
45 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
46 } else {
47 /* Shouldn't have an unknown type here */
48 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
52 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
53 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
54 * list without causing confusing terminal output. Deliberately no special debug name here
55 * because its undefined.
57 WARN("undefined state %d\n", state);
60 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
61 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
63 switch(Value) {
64 case WINED3DFILL_POINT:
65 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
66 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
67 break;
68 case WINED3DFILL_WIREFRAME:
69 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
70 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
71 break;
72 case WINED3DFILL_SOLID:
73 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
74 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
75 break;
76 default:
77 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
81 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
82 BOOL transformed;
84 /* Lighting is not enabled if transformed vertices are drawn
85 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
86 * This state reads the decoded vertex decl, so if it is dirty don't do anything. The
87 * vertex declaration appplying function calls this function for updating
90 if(isStateDirty(context, STATE_VDECL)) {
91 return;
94 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
95 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
96 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
98 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
99 glEnable(GL_LIGHTING);
100 checkGLcall("glEnable GL_LIGHTING");
101 } else {
102 glDisable(GL_LIGHTING);
103 checkGLcall("glDisable GL_LIGHTING");
107 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
108 /* No z test without depth stencil buffers */
109 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
110 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
111 checkGLcall("glDisable GL_DEPTH_TEST");
112 return;
115 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
116 case WINED3DZB_FALSE:
117 glDisable(GL_DEPTH_TEST);
118 checkGLcall("glDisable GL_DEPTH_TEST");
119 break;
120 case WINED3DZB_TRUE:
121 glEnable(GL_DEPTH_TEST);
122 checkGLcall("glEnable GL_DEPTH_TEST");
123 break;
124 case WINED3DZB_USEW:
125 glEnable(GL_DEPTH_TEST);
126 checkGLcall("glEnable GL_DEPTH_TEST");
127 FIXME("W buffer is not well handled\n");
128 break;
129 default:
130 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
134 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
135 /* TODO: Put this into the offscreen / onscreen rendering block due to device->render_offscreen */
137 /* If we are culling "back faces with clockwise vertices" then
138 set front faces to be counter clockwise and enable culling
139 of back faces */
140 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
141 case WINED3DCULL_NONE:
142 glDisable(GL_CULL_FACE);
143 checkGLcall("glDisable GL_CULL_FACE");
144 break;
145 case WINED3DCULL_CW:
146 glEnable(GL_CULL_FACE);
147 checkGLcall("glEnable GL_CULL_FACE");
148 if (stateblock->wineD3DDevice->render_offscreen) {
149 glFrontFace(GL_CW);
150 checkGLcall("glFrontFace GL_CW");
151 } else {
152 glFrontFace(GL_CCW);
153 checkGLcall("glFrontFace GL_CCW");
155 glCullFace(GL_BACK);
156 break;
157 case WINED3DCULL_CCW:
158 glEnable(GL_CULL_FACE);
159 checkGLcall("glEnable GL_CULL_FACE");
160 if (stateblock->wineD3DDevice->render_offscreen) {
161 glFrontFace(GL_CCW);
162 checkGLcall("glFrontFace GL_CCW");
163 } else {
164 glFrontFace(GL_CW);
165 checkGLcall("glFrontFace GL_CW");
167 glCullFace(GL_BACK);
168 break;
169 default:
170 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
174 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
175 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
176 case WINED3DSHADE_FLAT:
177 glShadeModel(GL_FLAT);
178 checkGLcall("glShadeModel(GL_FLAT)");
179 break;
180 case WINED3DSHADE_GOURAUD:
181 glShadeModel(GL_SMOOTH);
182 checkGLcall("glShadeModel(GL_SMOOTH)");
183 break;
184 case WINED3DSHADE_PHONG:
185 FIXME("WINED3DSHADE_PHONG isn't supported\n");
186 break;
187 default:
188 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
192 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
193 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
194 glEnable(GL_DITHER);
195 checkGLcall("glEnable GL_DITHER");
196 } else {
197 glDisable(GL_DITHER);
198 checkGLcall("glDisable GL_DITHER");
202 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
203 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
204 * this has to be merged with ZENABLE and ZFUNC
206 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
207 glDepthMask(1);
208 checkGLcall("glDepthMask(1)");
209 } else {
210 glDepthMask(0);
211 checkGLcall("glDepthMask(0)");
215 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
216 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
218 if(glParm) {
219 glDepthFunc(glParm);
220 checkGLcall("glDepthFunc");
224 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
225 float col[4];
226 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
228 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
229 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
230 checkGLcall("glLightModel for MODEL_AMBIENT");
233 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
234 int srcBlend = GL_ZERO;
235 int dstBlend = GL_ZERO;
237 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
238 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
239 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
240 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
241 glEnable(GL_BLEND);
242 checkGLcall("glEnable GL_BLEND");
243 } else {
244 glDisable(GL_BLEND);
245 checkGLcall("glDisable GL_BLEND");
246 /* Nothing more to do - get out */
247 return;
250 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
251 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
252 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
253 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
254 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
255 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
256 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
257 case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
258 case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
259 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
260 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
261 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
263 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
264 dstBlend = GL_SRC_ALPHA;
265 break;
267 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
268 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
269 break;
271 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
272 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
273 default:
274 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
277 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
278 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
279 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
280 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
281 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
282 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
283 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
284 case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
285 case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
286 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
287 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
288 case WINED3DBLEND_SRCALPHASAT : dstBlend = GL_SRC_ALPHA_SATURATE; break;
290 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
291 srcBlend = GL_SRC_ALPHA;
292 break;
294 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
295 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
296 break;
298 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
299 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
300 default:
301 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
304 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
305 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
306 glEnable(GL_LINE_SMOOTH);
307 checkGLcall("glEnable(GL_LINE_SMOOTH)");
308 if(srcBlend != GL_SRC_ALPHA) {
309 FIXME("WINED3DRS_EDGEANTIALIAS enabled, but incompatible src blending param - what to do?\n");
310 srcBlend = GL_SRC_ALPHA;
312 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA) {
313 FIXME("WINED3DRS_EDGEANTIALIAS enabled, but incompatible dst blending param - what to do?\n");
314 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
316 } else {
317 glDisable(GL_LINE_SMOOTH);
318 checkGLcall("glDisable(GL_LINE_SMOOTH)");
321 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
322 glBlendFunc(srcBlend, dstBlend);
323 checkGLcall("glBlendFunc");
326 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
327 float col[4];
329 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
330 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
331 glBlendColor (col[0],col[1],col[2],col[3]);
332 checkGLcall("glBlendColor");
335 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
336 int glParm = 0;
337 float ref;
338 BOOL enable_ckey = FALSE;
340 IWineD3DSurfaceImpl *surf;
342 /* Find out if the texture on the first stage has a ckey set
343 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
344 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
345 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
346 * in case it finds some texture+colorkeyenable combination which needs extra care.
348 if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
349 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
351 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
352 const PixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format);
353 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
354 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
355 * surface has alpha bits
357 if(fmt->alphaMask == 0x00000000) {
358 enable_ckey = TRUE;
363 if(enable_ckey || context->last_was_ckey) {
364 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
366 context->last_was_ckey = enable_ckey;
368 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
369 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
370 glEnable(GL_ALPHA_TEST);
371 checkGLcall("glEnable GL_ALPHA_TEST");
372 } else {
373 glDisable(GL_ALPHA_TEST);
374 checkGLcall("glDisable GL_ALPHA_TEST");
375 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
376 * enable call
378 return;
381 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
382 glParm = GL_NOTEQUAL;
383 ref = 0.0;
384 } else {
385 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
386 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
388 if(glParm) {
389 glAlphaFunc(glParm, ref);
390 checkGLcall("glAlphaFunc");
394 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
395 DWORD enable = 0xFFFFFFFF;
396 DWORD disable = 0x00000000;
398 if (use_vs(stateblock->wineD3DDevice)) {
399 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
400 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
401 * contitions I got sick of tracking down. The shader state handler disables all clip planes because
402 * of that - don't do anything here and keep them disabled
404 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
405 static BOOL warned = FALSE;
406 if(!warned) {
407 FIXME("Clipping not supported with vertex shaders\n");
408 warned = TRUE;
411 return;
414 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
415 * of already set values
418 /* If enabling / disabling all
419 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
421 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
422 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
423 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
424 } else {
425 disable = 0xffffffff;
426 enable = 0x00;
429 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
430 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
431 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
432 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
433 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
434 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
436 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
437 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
438 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
439 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
440 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
441 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
443 /** update clipping status */
444 if (enable) {
445 stateblock->clip_status.ClipUnion = 0;
446 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
447 } else {
448 stateblock->clip_status.ClipUnion = 0;
449 stateblock->clip_status.ClipIntersection = 0;
453 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
454 int glParm = GL_FUNC_ADD;
456 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
457 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
458 return;
461 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
462 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
463 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
464 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
465 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
466 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
467 default:
468 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
471 TRACE("glBlendEquation(%x)\n", glParm);
472 GL_EXTCALL(glBlendEquation(glParm));
473 checkGLcall("glBlendEquation");
476 static void
477 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
478 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
479 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
480 * specular color. This is wrong:
481 * Separate specular color means the specular colour is maintained separately, whereas
482 * single color means it is merged in. However in both cases they are being used to
483 * some extent.
484 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
485 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
486 * running 1.4 yet!
489 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
490 * Instead, we need to setup the FinalCombiner properly.
492 * The default setup for the FinalCombiner is:
494 * <variable> <input> <mapping> <usage>
495 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
496 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
497 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
498 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
499 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
500 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
501 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
503 * That's pretty much fine as it is, except for variable B, which needs to take
504 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
505 * whether WINED3DRS_SPECULARENABLE is enabled or not.
508 TRACE("Setting specular enable state and materials\n");
509 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
510 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
511 checkGLcall("glMaterialfv");
513 if(stateblock->material.Power > 128.0) {
514 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
515 * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
516 * them, since 128 results in a hardly visible specular highlight, so it should be safe to
517 * to clamp to 128
519 WARN("Material power > 128\n");
520 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
521 } else {
522 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
524 checkGLcall("glMaterialf(GL_SHININESS");
526 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
527 glEnable(GL_COLOR_SUM_EXT);
528 } else {
529 TRACE("Specular colors cannot be enabled in this version of opengl\n");
531 checkGLcall("glEnable(GL_COLOR_SUM)");
533 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
534 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
535 checkGLcall("glFinalCombinerInputNV()");
537 } else {
538 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
540 /* for the case of enabled lighting: */
541 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
542 checkGLcall("glMaterialfv");
544 /* for the case of disabled lighting: */
545 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
546 glDisable(GL_COLOR_SUM_EXT);
547 } else {
548 TRACE("Specular colors cannot be disabled in this version of opengl\n");
550 checkGLcall("glDisable(GL_COLOR_SUM)");
552 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
553 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
554 checkGLcall("glFinalCombinerInputNV()");
558 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
559 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
560 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
561 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
562 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
563 stateblock->material.Specular.b, stateblock->material.Specular.a);
564 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
565 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
567 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
568 checkGLcall("glMaterialfv(GL_AMBIENT)");
569 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
570 checkGLcall("glMaterialfv(GL_DIFFUSE)");
571 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
572 checkGLcall("glMaterialfv(GL_EMISSION)");
575 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
576 unsigned int i;
578 /* Note the texture color applies to all textures whereas
579 * GL_TEXTURE_ENV_COLOR applies to active only
581 float col[4];
582 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
584 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
585 /* And now the default texture color as well */
586 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
587 /* Note the WINED3DRS value applies to all textures, but GL has one
588 * per texture, so apply it now ready to be used!
590 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
591 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
592 checkGLcall("glActiveTextureARB");
593 } else if (i>0) {
594 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
597 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
598 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
600 } else {
601 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
605 static void
606 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
607 #if 0 /* Don't use OpenGL 2.0 calls for now */
608 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
609 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
610 checkGLcall("glStencilFuncSeparate(...)");
611 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
612 checkGLcall("glStencilOpSeparate(...)");
614 else
615 #endif
616 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
617 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
618 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
619 GL_EXTCALL(glActiveStencilFaceEXT(face));
620 checkGLcall("glActiveStencilFaceEXT(...)");
621 glStencilFunc(func, ref, mask);
622 checkGLcall("glStencilFunc(...)");
623 glStencilOp(stencilFail, depthFail, stencilPass);
624 checkGLcall("glStencilOp(...)");
625 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
626 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
627 checkGLcall("glStencilFuncSeparateATI(...)");
628 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
629 checkGLcall("glStencilOpSeparateATI(...)");
630 } else {
631 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
635 static void
636 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
637 DWORD onesided_enable = FALSE;
638 DWORD twosided_enable = FALSE;
639 GLint func = GL_ALWAYS;
640 GLint func_ccw = GL_ALWAYS;
641 GLint ref = 0;
642 GLuint mask = 0;
643 GLint stencilFail = GL_KEEP;
644 GLint depthFail = GL_KEEP;
645 GLint stencilPass = GL_KEEP;
646 GLint stencilFail_ccw = GL_KEEP;
647 GLint depthFail_ccw = GL_KEEP;
648 GLint stencilPass_ccw = GL_KEEP;
650 /* No stencil test without a stencil buffer */
651 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
652 glDisable(GL_STENCIL_TEST);
653 checkGLcall("glDisable GL_STENCIL_TEST");
654 return;
657 if( stateblock->set.renderState[WINED3DRS_STENCILENABLE] )
658 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
659 if( stateblock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
660 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
661 if( stateblock->set.renderState[WINED3DRS_STENCILFUNC] )
662 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
663 func = GL_ALWAYS;
664 if( stateblock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
665 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
666 func = GL_ALWAYS;
667 if( stateblock->set.renderState[WINED3DRS_STENCILREF] )
668 ref = stateblock->renderState[WINED3DRS_STENCILREF];
669 if( stateblock->set.renderState[WINED3DRS_STENCILMASK] )
670 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
671 if( stateblock->set.renderState[WINED3DRS_STENCILFAIL] )
672 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
673 if( stateblock->set.renderState[WINED3DRS_STENCILZFAIL] )
674 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
675 if( stateblock->set.renderState[WINED3DRS_STENCILPASS] )
676 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
677 if( stateblock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
678 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
679 if( stateblock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
680 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
681 if( stateblock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
682 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
684 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
685 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
686 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
687 onesided_enable, twosided_enable, ref, mask,
688 func, stencilFail, depthFail, stencilPass,
689 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
691 if (twosided_enable) {
692 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
693 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
694 } else {
695 if (onesided_enable) {
696 glEnable(GL_STENCIL_TEST);
697 checkGLcall("glEnable GL_STENCIL_TEST");
698 glStencilFunc(func, ref, mask);
699 checkGLcall("glStencilFunc(...)");
700 glStencilOp(stencilFail, depthFail, stencilPass);
701 checkGLcall("glStencilOp(...)");
702 } else {
703 glDisable(GL_STENCIL_TEST);
704 checkGLcall("glDisable GL_STENCIL_TEST");
709 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
710 if(stateblock->wineD3DDevice->stencilBufferTarget) {
711 glStencilMask(stateblock->renderState[WINED3DRS_STENCILWRITEMASK]);
712 } else {
713 glStencilMask(0);
715 checkGLcall("glStencilMask");
718 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
719 /* TODO: Put this into the vertex type block once that is in the state table */
720 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
721 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
722 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
723 float fogstart, fogend;
725 union {
726 DWORD d;
727 float f;
728 } tmpvalue;
730 if (!fogenable) {
731 /* No fog? Disable it, and we're done :-) */
732 glDisable(GL_FOG);
733 checkGLcall("glDisable GL_FOG");
734 if( use_ps(stateblock->wineD3DDevice)
735 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
736 /* disable fog in the pixel shader
737 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
738 * -1/(e-s) and e/(e-s) respectively.
740 glFogf(GL_FOG_START, 0.0f);
741 checkGLcall("glFogf(GL_FOG_START, fogstart");
742 glFogf(GL_FOG_END, 1.0f);
743 checkGLcall("glFogf(GL_FOG_END, fogend");
745 return;
748 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
749 fogstart = tmpvalue.f;
750 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
751 fogend = tmpvalue.f;
753 /* Fog Rules:
755 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
756 * It can use the Z value of the vertex, or the alpha component of the specular color.
757 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
758 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
759 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
761 * FOGTABLEMODE != NONE:
762 * The Z value is used, with the equation specified, no matter what vertex type.
764 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
765 * Per vertex fog is calculated using the specified fog equation and the parameters
767 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
768 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
769 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
772 * Rules for vertex fog with shaders:
774 * When mixing fixed function functionality with the programmable pipeline, D3D expects
775 * the fog computation to happen during transformation while openGL expects it to happen
776 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
777 * the pixel shader while openGL always expects the pixel shader to handle the blending.
778 * To solve this problem, WineD3D does:
779 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
780 * shader,
781 * and 2) disables the fog computation (in either the fixed function or programmable
782 * rasterizer) if using a vertex program.
785 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
786 * without shaders).
789 if( is_ps3 ) {
790 if( !use_vs(stateblock->wineD3DDevice)
791 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
792 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
796 if (use_vs(stateblock->wineD3DDevice)
797 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
798 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
799 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
800 /* Disable fog */
801 fogenable = FALSE;
802 } else {
803 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
804 glFogi(GL_FOG_MODE, GL_LINEAR);
805 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
806 fogstart = 1.0;
807 fogend = 0.0;
809 context->last_was_foggy_shader = TRUE;
811 else if( use_ps(stateblock->wineD3DDevice) ) {
812 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
813 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
815 WINED3DFOGMODE mode;
816 context->last_was_foggy_shader = FALSE;
818 /* If both fogmodes are set use the table fog mode */
819 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
820 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
821 else
822 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
824 switch (mode) {
825 case WINED3DFOG_EXP:
826 case WINED3DFOG_EXP2:
827 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
828 /* Disable fog */
829 fogenable = FALSE;
830 break;
832 case WINED3DFOG_LINEAR:
833 fogstart = -1.0f/(fogend-fogstart);
834 fogend *= -fogstart;
835 break;
837 case WINED3DFOG_NONE:
838 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
839 /* Disable fog */
840 fogenable = FALSE;
841 break;
842 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
845 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
846 * the system will apply only pixel(=table) fog effects."
848 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
849 glHint(GL_FOG_HINT, GL_FASTEST);
850 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
851 context->last_was_foggy_shader = FALSE;
853 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
854 /* If processed vertices are used, fall through to the NONE case */
855 case WINED3DFOG_EXP: {
856 if(!context->last_was_rhw) {
857 glFogi(GL_FOG_MODE, GL_EXP);
858 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
859 if(GL_SUPPORT(EXT_FOG_COORD)) {
860 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
861 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
863 break;
866 case WINED3DFOG_EXP2: {
867 if(!context->last_was_rhw) {
868 glFogi(GL_FOG_MODE, GL_EXP2);
869 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
870 if(GL_SUPPORT(EXT_FOG_COORD)) {
871 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
872 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
874 break;
877 case WINED3DFOG_LINEAR: {
878 if(!context->last_was_rhw) {
879 glFogi(GL_FOG_MODE, GL_LINEAR);
880 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
881 if(GL_SUPPORT(EXT_FOG_COORD)) {
882 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
883 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
885 break;
888 case WINED3DFOG_NONE: {
889 /* Both are none? According to msdn the alpha channel of the specular
890 * color contains a fog factor. Set it in drawStridedSlow.
891 * Same happens with Vertexfog on transformed vertices
893 if(GL_SUPPORT(EXT_FOG_COORD)) {
894 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
895 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
896 glFogi(GL_FOG_MODE, GL_LINEAR);
897 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
898 fogstart = 0xff;
899 fogend = 0x0;
900 } else {
901 /* Disable GL fog, handle this in software in drawStridedSlow */
902 fogenable = FALSE;
904 break;
906 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
908 } else {
909 glHint(GL_FOG_HINT, GL_NICEST);
910 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
911 context->last_was_foggy_shader = FALSE;
913 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
914 case WINED3DFOG_EXP:
915 glFogi(GL_FOG_MODE, GL_EXP);
916 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
917 if(GL_SUPPORT(EXT_FOG_COORD)) {
918 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
919 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
921 break;
923 case WINED3DFOG_EXP2:
924 glFogi(GL_FOG_MODE, GL_EXP2);
925 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
926 if(GL_SUPPORT(EXT_FOG_COORD)) {
927 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
928 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
930 break;
932 case WINED3DFOG_LINEAR:
933 glFogi(GL_FOG_MODE, GL_LINEAR);
934 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
935 if(GL_SUPPORT(EXT_FOG_COORD)) {
936 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
937 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
939 break;
941 case WINED3DFOG_NONE: /* Won't happen */
942 default:
943 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
947 if(fogenable) {
948 glEnable(GL_FOG);
949 checkGLcall("glEnable GL_FOG");
951 glFogfv(GL_FOG_START, &fogstart);
952 checkGLcall("glFogf(GL_FOG_START, fogstart");
953 TRACE("Fog Start == %f\n", fogstart);
955 glFogfv(GL_FOG_END, &fogend);
956 checkGLcall("glFogf(GL_FOG_END, fogend");
957 TRACE("Fog End == %f\n", fogend);
958 } else {
959 glDisable(GL_FOG);
960 checkGLcall("glDisable GL_FOG");
961 if( use_ps(stateblock->wineD3DDevice) ) {
962 /* disable fog in the pixel shader
963 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
964 * -1/(e-s) and e/(e-s) respectively.
966 glFogf(GL_FOG_START, 0.0f);
967 checkGLcall("glFogf(GL_FOG_START, fogstart");
968 glFogf(GL_FOG_END, 1.0f);
969 checkGLcall("glFogf(GL_FOG_END, fogend");
973 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
974 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
978 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
979 float col[4];
980 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
981 glFogfv(GL_FOG_COLOR, &col[0]);
982 checkGLcall("glFog GL_FOG_COLOR");
985 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
986 union {
987 DWORD d;
988 float f;
989 } tmpvalue;
990 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
991 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
992 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
995 /* TODO: Merge with primitive type + init_materials()!! */
996 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
997 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice;
998 GLenum Parm = 0;
999 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1000 BOOL isDiffuseSupplied;
1002 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1003 * The vertex declaration will call this function if the fixed function pipeline is used.
1006 if(isStateDirty(context, STATE_VDECL)) {
1007 return;
1010 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1012 context->num_untracked_materials = 0;
1013 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1014 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1015 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1016 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1017 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1018 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1020 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1021 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1022 Parm = GL_AMBIENT_AND_DIFFUSE;
1023 } else {
1024 Parm = GL_DIFFUSE;
1026 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1027 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1028 context->num_untracked_materials++;
1030 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1031 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1032 context->num_untracked_materials++;
1034 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1035 Parm = GL_AMBIENT;
1036 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1037 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1038 context->num_untracked_materials++;
1040 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1041 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1042 context->num_untracked_materials++;
1044 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1045 Parm = GL_EMISSION;
1046 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1047 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1048 context->num_untracked_materials++;
1050 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1051 Parm = GL_SPECULAR;
1055 /* Nothing changed, return. */
1056 if (Parm == context->tracking_parm) return;
1058 if(!Parm) {
1059 glDisable(GL_COLOR_MATERIAL);
1060 checkGLcall("glDisable GL_COLOR_MATERIAL");
1061 } else {
1062 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1063 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1064 glEnable(GL_COLOR_MATERIAL);
1065 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1068 /* Apparently calls to glMaterialfv are ignored for properties we're
1069 * tracking with glColorMaterial, so apply those here. */
1070 switch (context->tracking_parm) {
1071 case GL_AMBIENT_AND_DIFFUSE:
1072 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1073 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1074 checkGLcall("glMaterialfv");
1075 break;
1077 case GL_DIFFUSE:
1078 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1079 checkGLcall("glMaterialfv");
1080 break;
1082 case GL_AMBIENT:
1083 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1084 checkGLcall("glMaterialfv");
1085 break;
1087 case GL_EMISSION:
1088 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1089 checkGLcall("glMaterialfv");
1090 break;
1092 case GL_SPECULAR:
1093 /* Only change material color if specular is enabled, otherwise it is set to black */
1094 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1095 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1096 checkGLcall("glMaterialfv");
1097 } else {
1098 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1099 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1100 checkGLcall("glMaterialfv");
1102 break;
1105 context->tracking_parm = Parm;
1108 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1109 union {
1110 DWORD d;
1111 WINED3DLINEPATTERN lp;
1112 } tmppattern;
1113 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1115 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1117 if (tmppattern.lp.wRepeatFactor) {
1118 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1119 checkGLcall("glLineStipple(repeat, linepattern)");
1120 glEnable(GL_LINE_STIPPLE);
1121 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1122 } else {
1123 glDisable(GL_LINE_STIPPLE);
1124 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1128 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1129 union {
1130 DWORD d;
1131 float f;
1132 } tmpvalue;
1134 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1135 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1136 TRACE("ZBias value %f\n", tmpvalue.f);
1137 glPolygonOffset(0, -tmpvalue.f);
1138 checkGLcall("glPolygonOffset(0, -Value)");
1139 glEnable(GL_POLYGON_OFFSET_FILL);
1140 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1141 glEnable(GL_POLYGON_OFFSET_LINE);
1142 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1143 glEnable(GL_POLYGON_OFFSET_POINT);
1144 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1145 } else {
1146 glDisable(GL_POLYGON_OFFSET_FILL);
1147 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1148 glDisable(GL_POLYGON_OFFSET_LINE);
1149 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1150 glDisable(GL_POLYGON_OFFSET_POINT);
1151 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1156 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1157 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]) {
1158 glEnable(GL_NORMALIZE);
1159 checkGLcall("glEnable(GL_NORMALIZE);");
1160 } else {
1161 glDisable(GL_NORMALIZE);
1162 checkGLcall("glDisable(GL_NORMALIZE);");
1166 static void state_psize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1167 union {
1168 DWORD d;
1169 float f;
1170 } tmpvalue;
1172 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
1173 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1174 TRACE("Set point size to %f\n", tmpvalue.f);
1175 glPointSize(tmpvalue.f);
1176 checkGLcall("glPointSize(...);");
1179 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1180 union {
1181 DWORD d;
1182 float f;
1183 } tmpvalue;
1185 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1186 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1187 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1188 checkGLcall("glPointParameterfARB(...");
1190 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1191 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1192 checkGLcall("glPointParameterfEXT(...);");
1193 } else if(tmpvalue.f != 1.0) {
1194 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1198 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1199 union {
1200 DWORD d;
1201 float f;
1202 } tmpvalue;
1204 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1205 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1206 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1207 checkGLcall("glPointParameterfARB(...");
1209 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1210 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1211 checkGLcall("glPointParameterfEXT(...);");
1212 } else if(tmpvalue.f != 64.0) {
1213 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1217 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1218 /* TODO: Group this with the viewport */
1220 * POINTSCALEENABLE controls how point size value is treated. If set to
1221 * true, the point size is scaled with respect to height of viewport.
1222 * When set to false point size is in pixels.
1224 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
1227 /* Default values */
1228 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1231 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
1232 * This means that OpenGL will clamp really small point sizes to 1.0f.
1233 * To correct for this we need to multiply by the scale factor when sizes
1234 * are less than 1.0f. scale_factor = 1.0f / point_size.
1236 GLfloat pointSize = *((float*)&stateblock->renderState[WINED3DRS_POINTSIZE]);
1237 if(pointSize > 0.0f) {
1238 GLfloat scaleFactor;
1240 if(pointSize < 1.0f) {
1241 scaleFactor = pointSize * pointSize;
1242 } else {
1243 scaleFactor = 1.0f;
1246 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1247 att[0] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_A]) /
1248 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1249 att[1] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_B]) /
1250 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1251 att[2] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_C]) /
1252 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1256 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1257 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1258 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
1260 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1261 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1262 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
1263 } else {
1264 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
1268 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1269 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1271 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1272 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1273 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1274 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1275 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1276 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1277 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1278 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1279 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1280 checkGLcall("glColorMask(...)");
1282 /* depends on WINED3DRS_COLORWRITEENABLE. */
1283 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1284 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1285 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1286 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1287 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1288 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1289 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1293 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1294 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1295 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1296 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1297 } else {
1298 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1299 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1303 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1304 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1305 TRACE("Last Pixel Drawing Enabled\n");
1306 } else {
1307 static BOOL first = TRUE;
1308 if(first) {
1309 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1310 first = FALSE;
1311 } else {
1312 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1317 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1318 /* TODO: NV_POINT_SPRITE */
1319 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1320 TRACE("Point sprites not supported\n");
1321 return;
1324 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1325 glEnable(GL_POINT_SPRITE_ARB);
1326 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n");
1327 } else {
1328 glDisable(GL_POINT_SPRITE_ARB);
1329 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n");
1333 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1335 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1336 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
1337 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1338 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
1339 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1341 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1343 TRACE("Stub\n");
1344 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1345 stateblock->renderState[WINED3DRS_WRAP1] ||
1346 stateblock->renderState[WINED3DRS_WRAP2] ||
1347 stateblock->renderState[WINED3DRS_WRAP3] ||
1348 stateblock->renderState[WINED3DRS_WRAP4] ||
1349 stateblock->renderState[WINED3DRS_WRAP5] ||
1350 stateblock->renderState[WINED3DRS_WRAP6] ||
1351 stateblock->renderState[WINED3DRS_WRAP7] ||
1352 stateblock->renderState[WINED3DRS_WRAP8] ||
1353 stateblock->renderState[WINED3DRS_WRAP9] ||
1354 stateblock->renderState[WINED3DRS_WRAP10] ||
1355 stateblock->renderState[WINED3DRS_WRAP11] ||
1356 stateblock->renderState[WINED3DRS_WRAP12] ||
1357 stateblock->renderState[WINED3DRS_WRAP13] ||
1358 stateblock->renderState[WINED3DRS_WRAP14] ||
1359 stateblock->renderState[WINED3DRS_WRAP15] ) {
1360 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1364 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1365 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1366 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1367 glEnable(GL_MULTISAMPLE_ARB);
1368 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1369 } else {
1370 glDisable(GL_MULTISAMPLE_ARB);
1371 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1373 } else {
1374 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1375 ERR("Multisample antialiasing not supported by gl\n");
1380 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1381 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1382 glEnable(GL_SCISSOR_TEST);
1383 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1384 } else {
1385 glDisable(GL_SCISSOR_TEST);
1386 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1390 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1391 union {
1392 DWORD d;
1393 float f;
1394 } tmpvalue;
1396 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1397 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1398 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1399 glEnable(GL_POLYGON_OFFSET_FILL);
1400 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1401 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1402 checkGLcall("glPolygonOffset(...)");
1403 } else {
1404 glDisable(GL_POLYGON_OFFSET_FILL);
1405 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1409 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1410 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1411 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1412 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1413 } else {
1414 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1415 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1419 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1420 TRACE("Stub\n");
1421 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1422 FIXME(" Stippled Alpha not supported yet.\n");
1425 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1426 TRACE("Stub\n");
1427 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1428 FIXME(" Antialias not supported yet.\n");
1431 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1432 TRACE("Stub\n");
1433 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1434 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1437 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1438 TRACE("Stub\n");
1439 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1440 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1443 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1444 union {
1445 DWORD d;
1446 float f;
1447 } tmpvalue;
1448 tmpvalue.f = 1.0f;
1450 TRACE("Stub\n");
1451 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1453 static BOOL displayed = FALSE;
1455 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1456 if(!displayed)
1457 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1459 displayed = TRUE;
1463 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1464 TRACE("Stub\n");
1465 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1466 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1469 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1470 TRACE("Stub\n");
1471 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1472 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1475 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1476 TRACE("Stub\n");
1477 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1478 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1482 static void state_srgbwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1483 if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE])
1484 FIXME("Render state WINED3DRS_SRGBWRITEENABLE not yet implemented\n");
1487 static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1488 TRACE("Stub\n");
1489 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
1490 FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
1493 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1494 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1495 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1499 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1500 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1501 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1505 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1506 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1507 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1511 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1512 if(stateblock->renderState[WINED3DRS_ROP2]) {
1513 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1517 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1518 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1519 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1523 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1524 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1525 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1529 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1530 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1531 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1535 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1536 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1537 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1541 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1542 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1543 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1547 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1548 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1549 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1553 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1554 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1555 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1559 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1560 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1561 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1565 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1566 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1567 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1571 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1572 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1573 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1577 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1578 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1579 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1583 /* Activates the texture dimension according to the bound D3D texture.
1584 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1585 * Requires the caller to activate the correct unit before
1587 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1588 BOOL bumpmap = FALSE;
1590 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1591 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1592 bumpmap = TRUE;
1593 context->texShaderBumpMap |= (1 << stage);
1594 } else {
1595 context->texShaderBumpMap &= ~(1 << stage);
1598 if(stateblock->textures[stage]) {
1599 switch(stateblock->textureDimensions[stage]) {
1600 case GL_TEXTURE_2D:
1601 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1602 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1603 } else {
1604 glDisable(GL_TEXTURE_3D);
1605 checkGLcall("glDisable(GL_TEXTURE_3D)");
1606 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1607 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1608 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1610 glEnable(GL_TEXTURE_2D);
1611 checkGLcall("glEnable(GL_TEXTURE_2D)");
1613 break;
1614 case GL_TEXTURE_3D:
1615 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1616 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1617 } else {
1618 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1619 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1620 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1622 glDisable(GL_TEXTURE_2D);
1623 checkGLcall("glDisable(GL_TEXTURE_2D)");
1624 glEnable(GL_TEXTURE_3D);
1625 checkGLcall("glEnable(GL_TEXTURE_3D)");
1627 break;
1628 case GL_TEXTURE_CUBE_MAP_ARB:
1629 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1630 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1631 } else {
1632 glDisable(GL_TEXTURE_2D);
1633 checkGLcall("glDisable(GL_TEXTURE_2D)");
1634 glDisable(GL_TEXTURE_3D);
1635 checkGLcall("glDisable(GL_TEXTURE_3D)");
1636 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1637 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1639 break;
1641 } else {
1642 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1643 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1644 } else {
1645 glEnable(GL_TEXTURE_2D);
1646 checkGLcall("glEnable(GL_TEXTURE_2D)");
1647 glDisable(GL_TEXTURE_3D);
1648 checkGLcall("glDisable(GL_TEXTURE_3D)");
1649 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1650 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1651 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1653 /* Binding textures is done by samplers. A dummy texture will be bound */
1658 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1659 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1660 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1661 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1663 TRACE("Setting color op for stage %d\n", stage);
1665 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1666 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1667 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1668 return;
1671 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1673 if (mapped_stage != -1) {
1674 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1675 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1676 FIXME("Attempt to enable unsupported stage!\n");
1677 return;
1679 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1680 checkGLcall("glActiveTextureARB");
1681 } else if (stage > 0) {
1682 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1683 return;
1687 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1688 if(stateblock->lowest_disabled_stage > 0) {
1689 glEnable(GL_REGISTER_COMBINERS_NV);
1690 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1691 } else {
1692 glDisable(GL_REGISTER_COMBINERS_NV);
1695 if(stage >= stateblock->lowest_disabled_stage) {
1696 TRACE("Stage disabled\n");
1697 if (mapped_stage != -1) {
1698 /* Disable everything here */
1699 glDisable(GL_TEXTURE_2D);
1700 checkGLcall("glDisable(GL_TEXTURE_2D)");
1701 glDisable(GL_TEXTURE_3D);
1702 checkGLcall("glDisable(GL_TEXTURE_3D)");
1703 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1704 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1705 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1707 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1708 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1711 /* All done */
1712 return;
1715 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1716 * if the sampler for this stage is dirty
1718 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1719 if (tex_used) activate_dimensions(stage, stateblock, context);
1722 /* Set the texture combiners */
1723 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1724 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1725 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1726 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1727 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1728 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1729 mapped_stage);
1731 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1732 * thus the texture shader may have to be updated
1734 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1735 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1736 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1737 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1738 if(usesBump != usedBump) {
1739 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1740 checkGLcall("glActiveTextureARB");
1741 activate_dimensions(stage + 1, stateblock, context);
1742 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1743 checkGLcall("glActiveTextureARB");
1746 } else {
1747 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1748 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1749 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1750 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1751 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1755 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1756 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1757 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1758 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1759 DWORD op, arg1, arg2, arg0;
1761 TRACE("Setting alpha op for stage %d\n", stage);
1762 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1763 if (mapped_stage != -1) {
1764 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1765 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1766 FIXME("Attempt to enable unsupported stage!\n");
1767 return;
1769 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1770 checkGLcall("glActiveTextureARB");
1771 } else if (stage > 0) {
1772 /* We can't do anything here */
1773 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1774 return;
1778 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1779 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1780 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1781 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1783 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1784 stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
1785 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1787 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1788 getFormatDescEntry(surf->resource.format)->alphaMask == 0x00000000) {
1790 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1791 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1792 * cannot remove the texture's alpha channel entirely.
1794 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1795 * on color keyed surfaces.
1797 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1799 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1800 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1801 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1805 TRACE("Setting alpha op for stage %d\n", stage);
1806 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1807 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1808 op, arg1, arg2, arg0,
1809 mapped_stage);
1810 } else {
1811 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1812 op, arg1, arg2, arg0);
1816 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1817 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1818 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1820 if (mapped_stage < 0) return;
1822 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1823 if(mapped_stage >= GL_LIMITS(textures)) {
1824 return;
1826 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1827 checkGLcall("glActiveTextureARB");
1828 } else if (mapped_stage > 0) {
1829 /* We can't do anything here */
1830 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1831 return;
1834 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1835 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1836 (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
1840 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1841 int texture_idx;
1843 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1844 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1845 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1849 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
1850 UINT *offset = stateblock->streamOffset;
1851 unsigned int mapped_stage = 0;
1852 unsigned int textureNo = 0;
1854 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1855 /* Abort if we don't support the extension. */
1856 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1857 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1858 return;
1861 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1862 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1864 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
1865 if (mapped_stage == -1) continue;
1867 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
1868 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1869 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1871 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1872 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1873 checkGLcall("glBindBufferARB");
1874 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
1877 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1878 checkGLcall("glClientActiveTextureARB");
1880 /* The coords to supply depend completely on the fvf / vertex shader */
1881 glTexCoordPointer(
1882 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1883 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1884 sd->u.s.texCoords[coordIdx].dwStride,
1885 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
1886 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1887 } else {
1888 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
1891 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1892 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
1893 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
1894 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1899 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1900 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1901 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1903 if (mapped_stage == -1) {
1904 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
1905 return;
1908 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1909 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
1910 return;
1912 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1913 checkGLcall("glActiveTextureARB");
1914 } else if (stage > 0) {
1915 /* We can't do anything here */
1916 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1917 return;
1920 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
1922 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
1923 * one flag, you can still specify an index value, which the system uses to
1924 * determine the texture wrapping mode.
1925 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
1926 * means use the vertex position (camera-space) as the input texture coordinates
1927 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
1928 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
1929 * to the TEXCOORDINDEX value
1933 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
1935 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
1936 case WINED3DTSS_TCI_PASSTHRU:
1937 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
1938 glDisable(GL_TEXTURE_GEN_S);
1939 glDisable(GL_TEXTURE_GEN_T);
1940 glDisable(GL_TEXTURE_GEN_R);
1941 glDisable(GL_TEXTURE_GEN_Q);
1942 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
1943 break;
1945 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
1946 /* CameraSpacePosition means use the vertex position, transformed to camera space,
1947 * as the input texture coordinates for this stage's texture transformation. This
1948 * equates roughly to EYE_LINEAR
1951 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1952 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1953 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1954 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1955 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
1957 glMatrixMode(GL_MODELVIEW);
1958 glPushMatrix();
1959 glLoadIdentity();
1960 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
1961 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
1962 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
1963 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
1964 glPopMatrix();
1966 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
1967 glEnable(GL_TEXTURE_GEN_S);
1968 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
1969 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1970 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1971 glEnable(GL_TEXTURE_GEN_T);
1972 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
1973 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1974 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1975 glEnable(GL_TEXTURE_GEN_R);
1976 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
1977 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1978 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1980 break;
1982 case WINED3DTSS_TCI_CAMERASPACENORMAL:
1984 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
1985 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1986 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1987 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1988 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1989 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
1991 glMatrixMode(GL_MODELVIEW);
1992 glPushMatrix();
1993 glLoadIdentity();
1994 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
1995 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
1996 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
1997 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
1998 glPopMatrix();
2000 glEnable(GL_TEXTURE_GEN_S);
2001 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2002 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2003 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2004 glEnable(GL_TEXTURE_GEN_T);
2005 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2006 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2007 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2008 glEnable(GL_TEXTURE_GEN_R);
2009 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2010 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2011 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2014 break;
2016 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2018 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2019 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2020 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2021 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2022 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2023 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2025 glMatrixMode(GL_MODELVIEW);
2026 glPushMatrix();
2027 glLoadIdentity();
2028 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2029 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2030 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2031 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2032 glPopMatrix();
2034 glEnable(GL_TEXTURE_GEN_S);
2035 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2036 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2037 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2038 glEnable(GL_TEXTURE_GEN_T);
2039 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2040 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2041 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2042 glEnable(GL_TEXTURE_GEN_R);
2043 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2044 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2045 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2048 break;
2050 /* Unhandled types: */
2051 default:
2052 /* Todo: */
2053 /* ? disable GL_TEXTURE_GEN_n ? */
2054 glDisable(GL_TEXTURE_GEN_S);
2055 glDisable(GL_TEXTURE_GEN_T);
2056 glDisable(GL_TEXTURE_GEN_R);
2057 glDisable(GL_TEXTURE_GEN_Q);
2058 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2059 break;
2062 /* Update the texture matrix */
2063 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2064 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2067 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2068 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2069 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2070 * and do all the things linked to it
2071 * TODO: Tidy that up to reload only the arrays of the changed unit
2073 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2075 unloadTexCoords(stateblock);
2076 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2080 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2081 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2082 union {
2083 DWORD d;
2084 float f;
2085 } tmpvalue;
2087 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2088 if(tmpvalue.f != 0.0) {
2089 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2093 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2094 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2095 union {
2096 DWORD d;
2097 float f;
2098 } tmpvalue;
2100 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2101 if(tmpvalue.f != 0.0) {
2102 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2106 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2107 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2109 if(stage >= GL_LIMITS(texture_stages)) {
2110 return;
2113 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2114 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2118 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2119 DWORD sampler = state - STATE_SAMPLER(0);
2120 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2121 union {
2122 float f;
2123 DWORD d;
2124 } tmpvalue;
2126 TRACE("Sampler: %d\n", sampler);
2127 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2128 * only has to bind textures and set the per texture states
2131 if (mapped_stage == -1) {
2132 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2133 return;
2136 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2137 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2138 return;
2140 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2141 checkGLcall("glActiveTextureARB");
2142 } else if (sampler > 0) {
2143 /* We can't do anything here */
2144 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2145 return;
2148 if(stateblock->textures[sampler]) {
2149 BOOL texIsPow2 = FALSE;
2151 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2152 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2153 * scaling is reapplied or removed, the texture matrix has to be reapplied
2155 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2156 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
2157 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
2158 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {
2159 texIsPow2 = TRUE;
2161 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2162 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->pow2scalingFactor != 1.0) {
2163 texIsPow2 = TRUE;
2167 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2168 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2169 context->lastWasPow2Texture[sampler] = texIsPow2;
2173 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2174 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2176 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2177 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2178 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2179 GL_TEXTURE_LOD_BIAS_EXT,
2180 tmpvalue.f);
2181 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2184 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2185 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2186 /* Using a pixel shader? Verify the sampler types */
2188 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2189 * dimensions because the shader knows from which texture type to sample from. For the sake of
2190 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2191 * dimensions. This should make wrong sampling sources visible :-)
2193 glEnable(stateblock->textureDimensions[sampler]);
2194 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2195 } else if(sampler < stateblock->lowest_disabled_stage) {
2196 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2197 activate_dimensions(sampler, stateblock, context);
2200 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2201 /* If color keying is enabled update the alpha test, it depends on the existence
2202 * of a color key in stage 0
2204 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2207 } else if(sampler < GL_LIMITS(texture_stages)) {
2208 if(sampler < stateblock->lowest_disabled_stage) {
2209 /* TODO: What should I do with pixel shaders here ??? */
2210 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2211 activate_dimensions(sampler, stateblock, context);
2213 } /* Otherwise tex_colorop disables the stage */
2214 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2215 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2219 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2220 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2222 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2223 * has an update pending
2225 if(isStateDirty(context, STATE_VDECL) ||
2226 isStateDirty(context, STATE_PIXELSHADER)) {
2227 return;
2230 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2233 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2234 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2235 BOOL use_pshader = use_ps(device);
2236 BOOL use_vshader = use_vs(device);
2237 BOOL update_fog = FALSE;
2238 int i;
2240 if (use_pshader) {
2241 if(!context->last_was_pshader) {
2242 /* Former draw without a pixel shader, some samplers
2243 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2244 * make sure to enable them
2246 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2247 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2248 sampler(STATE_SAMPLER(i), stateblock, context);
2251 update_fog = TRUE;
2252 } else {
2253 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2254 * if a different texture was bound. I don't have to do anything.
2258 /* Compile and bind the shader */
2259 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2260 } else {
2261 /* Disabled the pixel shader - color ops weren't applied
2262 * while it was enabled, so re-apply them.
2264 for(i=0; i < MAX_TEXTURES; i++) {
2265 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2266 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2269 if(context->last_was_pshader)
2270 update_fog = TRUE;
2273 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2274 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2276 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2277 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2281 if(update_fog)
2282 state_fog(state, stateblock, context);
2284 context->last_was_pshader = use_pshader;
2287 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2288 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2290 if(stateblock->pixelShader && stage != 0 &&
2291 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2292 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2293 * anyway
2295 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2296 !isStateDirty(context, STATE_PIXELSHADER)) {
2297 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2301 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2302 if(stage >= GL_LIMITS(texture_stages)) {
2303 WARN("Bump env matrix of unsupported stage set\n");
2304 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2305 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2306 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2308 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2309 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2310 checkGLcall("glTexBumpParameterfvATI");
2312 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2313 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2314 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2315 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2316 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2317 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2319 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2321 if(mapped_stage < GL_LIMITS(textures)) {
2322 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2323 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2325 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2326 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2327 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2332 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2333 /* This function is called by transform_view below if the view matrix was changed too
2335 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2336 * does not always update the world matrix, only on a switch between transformed
2337 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2338 * draw, but that should be rather rare and cheaper in total.
2340 glMatrixMode(GL_MODELVIEW);
2341 checkGLcall("glMatrixMode");
2343 if(context->last_was_rhw) {
2344 glLoadIdentity();
2345 checkGLcall("glLoadIdentity()");
2346 } else {
2347 /* In the general case, the view matrix is the identity matrix */
2348 if (stateblock->wineD3DDevice->view_ident) {
2349 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2350 checkGLcall("glLoadMatrixf");
2351 } else {
2352 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2353 checkGLcall("glLoadMatrixf");
2354 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2355 checkGLcall("glMultMatrixf");
2360 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2361 UINT index = state - STATE_CLIPPLANE(0);
2363 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2364 return;
2367 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2368 glMatrixMode(GL_MODELVIEW);
2369 glPushMatrix();
2370 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2372 TRACE("Clipplane [%f,%f,%f,%f]\n",
2373 stateblock->clipplane[index][0],
2374 stateblock->clipplane[index][1],
2375 stateblock->clipplane[index][2],
2376 stateblock->clipplane[index][3]);
2377 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2378 checkGLcall("glClipPlane");
2380 glPopMatrix();
2383 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2384 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2385 GLenum glMat;
2386 TRACE("Setting world matrix %d\n", matrix);
2388 if(matrix >= GL_LIMITS(blends)) {
2389 WARN("Unsupported blend matrix set\n");
2390 return;
2391 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2392 return;
2395 /* GL_MODELVIEW0_ARB: 0x1700
2396 * GL_MODELVIEW1_ARB: 0x0x850a
2397 * GL_MODELVIEW2_ARB: 0x8722
2398 * GL_MODELVIEW3_ARB: 0x8723
2399 * etc
2400 * GL_MODELVIEW31_ARB: 0x873F
2402 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2403 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2405 glMatrixMode(glMat);
2406 checkGLcall("glMatrixMode(glMat)");
2408 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2409 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2411 if(stateblock->wineD3DDevice->view_ident) {
2412 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2413 checkGLcall("glLoadMatrixf")
2414 } else {
2415 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2416 checkGLcall("glLoadMatrixf")
2417 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2418 checkGLcall("glMultMatrixf")
2422 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2423 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2425 switch(val) {
2426 case WINED3DVBF_1WEIGHTS:
2427 case WINED3DVBF_2WEIGHTS:
2428 case WINED3DVBF_3WEIGHTS:
2429 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2430 glEnable(GL_VERTEX_BLEND_ARB);
2431 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2433 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2434 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2436 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2438 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2439 int i;
2440 for(i = 1; i < GL_LIMITS(blends); i++) {
2441 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2442 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2445 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2447 } else {
2448 /* TODO: Implement vertex blending in drawStridedSlow */
2449 FIXME("Vertex blending enabled, but not supported by hardware\n");
2451 break;
2453 case WINED3DVBF_DISABLE:
2454 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2455 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2456 glDisable(GL_VERTEX_BLEND_ARB);
2457 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2458 } else {
2459 TRACE("Vertex blending disabled\n");
2461 break;
2463 case WINED3DVBF_TWEENING:
2464 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2465 * vertex weights in the vertices?
2466 * For now we don't report that as supported, so a warn should suffice
2468 WARN("Tweening not supported yet\n");
2469 break;
2473 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2474 unsigned int k;
2476 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2477 * NOTE: We have to reset the positions even if the light/plane is not currently
2478 * enabled, since the call to enable it will not reset the position.
2479 * NOTE2: Apparently texture transforms do NOT need reapplying
2482 PLIGHTINFOEL *light = NULL;
2484 glMatrixMode(GL_MODELVIEW);
2485 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2486 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2487 checkGLcall("glLoadMatrixf(...)");
2489 /* Reset lights. TODO: Call light apply func */
2490 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2491 light = stateblock->activeLights[k];
2492 if(!light) continue;
2493 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2494 checkGLcall("glLightfv posn");
2495 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2496 checkGLcall("glLightfv dirn");
2499 /* Reset Clipping Planes */
2500 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2501 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2502 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2506 if(context->last_was_rhw) {
2507 glLoadIdentity();
2508 checkGLcall("glLoadIdentity()");
2509 /* No need to update the world matrix, the identity is fine */
2510 return;
2513 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2514 * No need to do it here if the state is scheduled for update.
2516 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2517 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2520 /* Avoid looping over a number of matrices if the app never used the functionality */
2521 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2522 for(k = 1; k < GL_LIMITS(blends); k++) {
2523 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2524 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2530 static const GLfloat invymat[16] = {
2531 1.0f, 0.0f, 0.0f, 0.0f,
2532 0.0f, -1.0f, 0.0f, 0.0f,
2533 0.0f, 0.0f, 1.0f, 0.0f,
2534 0.0f, 0.0f, 0.0f, 1.0f};
2536 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2537 glMatrixMode(GL_PROJECTION);
2538 checkGLcall("glMatrixMode(GL_PROJECTION)");
2539 glLoadIdentity();
2540 checkGLcall("glLoadIdentity");
2542 if(context->last_was_rhw) {
2543 double X, Y, height, width, minZ, maxZ;
2545 X = stateblock->viewport.X;
2546 Y = stateblock->viewport.Y;
2547 height = stateblock->viewport.Height;
2548 width = stateblock->viewport.Width;
2549 minZ = stateblock->viewport.MinZ;
2550 maxZ = stateblock->viewport.MaxZ;
2552 if(!stateblock->wineD3DDevice->untransformed) {
2553 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2554 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2555 * suppress depth clipping. This can be done because it is an orthogonal projection and
2556 * the Z coordinate does not affect the size of the primitives
2558 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2559 if(stateblock->wineD3DDevice->render_offscreen) {
2560 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2561 } else {
2562 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2564 } else {
2565 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2566 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2567 * unmodified to opengl.
2569 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2570 * replacement shader.
2572 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2573 if(stateblock->wineD3DDevice->render_offscreen) {
2574 glOrtho(X, X + width, -Y, -Y - height, 1.0, -1.0);
2575 } else {
2576 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
2579 checkGLcall("glOrtho");
2581 /* Window Coord 0 is the middle of the first pixel, so translate by 3/8 pixels */
2582 glTranslatef(0.375, 0.375, 0);
2583 checkGLcall("glTranslatef(0.375, 0.375, 0)");
2584 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2585 * render everything upside down when rendering offscreen. */
2586 if (stateblock->wineD3DDevice->render_offscreen) {
2587 glMultMatrixf(invymat);
2588 checkGLcall("glMultMatrixf(invymat)");
2590 } else {
2591 /* The rule is that the window coordinate 0 does not correspond to the
2592 beginning of the first pixel, but the center of the first pixel.
2593 As a consequence if you want to correctly draw one line exactly from
2594 the left to the right end of the viewport (with all matrices set to
2595 be identity), the x coords of both ends of the line would be not
2596 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2597 instead. */
2598 glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
2599 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
2601 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2602 * render everything upside down when rendering offscreen. */
2603 if (stateblock->wineD3DDevice->render_offscreen) {
2604 glMultMatrixf(invymat);
2605 checkGLcall("glMultMatrixf(invymat)");
2607 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2608 checkGLcall("glLoadMatrixf");
2612 /* This should match any arrays loaded in loadVertexData.
2613 * stateblock impl is required for GL_SUPPORT
2614 * TODO: Only load / unload arrays if we have to.
2616 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2617 glDisableClientState(GL_VERTEX_ARRAY);
2618 glDisableClientState(GL_NORMAL_ARRAY);
2619 glDisableClientState(GL_COLOR_ARRAY);
2620 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2621 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2623 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2624 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2625 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2626 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2628 unloadTexCoords(stateblock);
2631 /* This should match any arrays loaded in loadNumberedArrays
2632 * TODO: Only load / unload arrays if we have to.
2634 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2635 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2636 GLint maxAttribs;
2637 int i;
2639 /* Leave all the attribs disabled */
2640 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2641 /* MESA does not support it right not */
2642 if (glGetError() != GL_NO_ERROR)
2643 maxAttribs = 16;
2644 for (i = 0; i < maxAttribs; ++i) {
2645 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2646 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2650 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2651 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2652 int i;
2653 UINT *offset = stateblock->streamOffset;
2655 /* Default to no instancing */
2656 stateblock->wineD3DDevice->instancedDraw = FALSE;
2658 for (i = 0; i < MAX_ATTRIBS; i++) {
2660 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2661 continue;
2663 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2664 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2665 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2666 stateblock->wineD3DDevice->instancedDraw = TRUE;
2667 continue;
2670 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2672 if(strided->u.input[i].dwStride) {
2673 if(curVBO != strided->u.input[i].VBO) {
2674 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2675 checkGLcall("glBindBufferARB");
2676 curVBO = strided->u.input[i].VBO;
2678 GL_EXTCALL(glVertexAttribPointerARB(i,
2679 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2680 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2681 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2682 strided->u.input[i].dwStride,
2683 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2684 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2685 } else {
2686 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2687 * set up the attribute statically. But we have to figure out the system memory address.
2689 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2690 if(strided->u.input[i].VBO) {
2691 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2692 ptr += (long) vb->resource.allocatedMemory;
2694 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2696 switch(strided->u.input[i].dwType) {
2697 case WINED3DDECLTYPE_FLOAT1:
2698 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2699 break;
2700 case WINED3DDECLTYPE_FLOAT2:
2701 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2702 break;
2703 case WINED3DDECLTYPE_FLOAT3:
2704 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2705 break;
2706 case WINED3DDECLTYPE_FLOAT4:
2707 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2708 break;
2710 case WINED3DDECLTYPE_UBYTE4:
2711 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2712 break;
2713 case WINED3DDECLTYPE_UBYTE4N:
2714 case WINED3DDECLTYPE_D3DCOLOR:
2715 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2716 break;
2718 case WINED3DDECLTYPE_SHORT2:
2719 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2720 break;
2721 case WINED3DDECLTYPE_SHORT4:
2722 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2723 break;
2725 case WINED3DDECLTYPE_SHORT2N:
2727 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2728 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2729 break;
2731 case WINED3DDECLTYPE_USHORT2N:
2733 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2734 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2735 break;
2737 case WINED3DDECLTYPE_SHORT4N:
2738 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2739 break;
2740 case WINED3DDECLTYPE_USHORT4N:
2741 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2742 break;
2744 case WINED3DDECLTYPE_UDEC3:
2745 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2746 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2747 break;
2748 case WINED3DDECLTYPE_DEC3N:
2749 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2750 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2751 break;
2753 case WINED3DDECLTYPE_FLOAT16_2:
2754 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2755 * byte float according to the IEEE standard
2757 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2758 break;
2759 case WINED3DDECLTYPE_FLOAT16_4:
2760 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2761 break;
2763 case WINED3DDECLTYPE_UNUSED:
2764 default:
2765 ERR("Unexpected declaration in stride 0 attributes\n");
2766 break;
2773 /* Used from 2 different functions, and too big to justify making it inlined */
2774 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2775 UINT *offset = stateblock->streamOffset;
2776 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2778 TRACE("Using fast vertex array code\n");
2780 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2781 stateblock->wineD3DDevice->instancedDraw = FALSE;
2783 /* Blend Data ---------------------------------------------- */
2784 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2785 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2787 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2788 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2789 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2791 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
2792 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
2794 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
2796 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
2797 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
2798 sd->u.s.blendWeights.dwStride,
2799 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
2801 if(curVBO != sd->u.s.blendWeights.VBO) {
2802 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
2803 checkGLcall("glBindBufferARB");
2804 curVBO = sd->u.s.blendWeights.VBO;
2807 GL_EXTCALL(glWeightPointerARB)(
2808 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2809 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2810 sd->u.s.blendWeights.dwStride,
2811 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2813 checkGLcall("glWeightPointerARB");
2815 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
2816 static BOOL showfixme = TRUE;
2817 if(showfixme){
2818 FIXME("blendMatrixIndices support\n");
2819 showfixme = FALSE;
2822 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2823 /* FIXME("TODO\n");*/
2824 #if 0
2826 GL_EXTCALL(glVertexWeightPointerEXT)(
2827 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2828 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2829 sd->u.s.blendWeights.dwStride,
2830 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
2831 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
2832 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2833 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
2834 #endif
2836 } else {
2837 /* TODO: support blends in drawStridedSlow
2838 * No need to write a FIXME here, this is done after the general vertex decl decoding
2840 WARN("unsupported blending in openGl\n");
2842 } else {
2843 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2844 static const GLbyte one = 1;
2845 GL_EXTCALL(glWeightbvARB(1, &one));
2846 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
2850 #if 0 /* FOG ----------------------------------------------*/
2851 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
2852 /* TODO: fog*/
2853 if (GL_SUPPORT(EXT_FOG_COORD) {
2854 glEnableClientState(GL_FOG_COORDINATE_EXT);
2855 (GL_EXTCALL)(FogCoordPointerEXT)(
2856 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
2857 sd->u.s.fog.dwStride,
2858 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
2859 } else {
2860 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
2861 /* FIXME: fixme once */
2862 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
2864 } else {
2865 if (GL_SUPPRT(EXT_FOR_COORD) {
2866 /* make sure fog is disabled */
2867 glDisableClientState(GL_FOG_COORDINATE_EXT);
2870 #endif
2872 #if 0 /* tangents ----------------------------------------------*/
2873 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
2874 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2875 /* TODO: tangents*/
2876 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2877 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
2878 glEnable(GL_TANGENT_ARRAY_EXT);
2879 (GL_EXTCALL)(TangentPointerEXT)(
2880 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
2881 sd->u.s.tangent.dwStride,
2882 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
2883 } else {
2884 glDisable(GL_TANGENT_ARRAY_EXT);
2886 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2887 glEnable(GL_BINORMAL_ARRAY_EXT);
2888 (GL_EXTCALL)(BinormalPointerEXT)(
2889 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
2890 sd->u.s.binormal.dwStride,
2891 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
2892 } else{
2893 glDisable(GL_BINORMAL_ARRAY_EXT);
2896 } else {
2897 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
2898 /* FIXME: fixme once */
2899 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
2901 } else {
2902 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2903 /* make sure fog is disabled */
2904 glDisable(GL_TANGENT_ARRAY_EXT);
2905 glDisable(GL_BINORMAL_ARRAY_EXT);
2908 #endif
2910 /* Point Size ----------------------------------------------*/
2911 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
2913 /* no such functionality in the fixed function GL pipeline */
2914 TRACE("Cannot change ptSize here in openGl\n");
2915 /* TODO: Implement this function in using shaders if they are available */
2919 /* Vertex Pointers -----------------------------------------*/
2920 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
2921 /* Note dwType == float3 or float4 == 2 or 3 */
2922 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
2923 sd->u.s.position.dwStride,
2924 sd->u.s.position.dwType + 1,
2925 sd->u.s.position.lpData));
2927 if(curVBO != sd->u.s.position.VBO) {
2928 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
2929 checkGLcall("glBindBufferARB");
2930 curVBO = sd->u.s.position.VBO;
2933 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
2934 handling for rhw mode should not impact screen position whereas in GL it does.
2935 This may result in very slightly distored textures in rhw mode, but
2936 a very minimal different. There's always the other option of
2937 fixing the view matrix to prevent w from having any effect
2939 This only applies to user pointer sources, in VBOs the vertices are fixed up
2941 if(sd->u.s.position.VBO == 0) {
2942 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
2943 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2944 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2945 } else {
2946 glVertexPointer(
2947 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
2948 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2949 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2951 checkGLcall("glVertexPointer(...)");
2952 glEnableClientState(GL_VERTEX_ARRAY);
2953 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
2956 /* Normals -------------------------------------------------*/
2957 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
2958 /* Note dwType == float3 or float4 == 2 or 3 */
2959 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
2960 sd->u.s.normal.dwStride,
2961 sd->u.s.normal.lpData));
2962 if(curVBO != sd->u.s.normal.VBO) {
2963 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
2964 checkGLcall("glBindBufferARB");
2965 curVBO = sd->u.s.normal.VBO;
2967 glNormalPointer(
2968 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
2969 sd->u.s.normal.dwStride,
2970 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
2971 checkGLcall("glNormalPointer(...)");
2972 glEnableClientState(GL_NORMAL_ARRAY);
2973 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
2975 } else {
2976 glNormal3f(0, 0, 1);
2977 checkGLcall("glNormal3f(0, 0, 1)");
2980 /* Diffuse Colour --------------------------------------------*/
2981 /* WARNING: Data here MUST be in RGBA format, so cannot */
2982 /* go directly into fast mode from app pgm, because */
2983 /* directx requires data in BGRA format. */
2984 /* currently fixupVertices swizels the format, but this isn't */
2985 /* very practical when using VBOS */
2986 /* NOTE: Unless we write a vertex shader to swizel the colour */
2987 /* , or the user doesn't care and wants the speed advantage */
2989 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
2990 /* Note dwType == float3 or float4 == 2 or 3 */
2991 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
2992 sd->u.s.diffuse.dwStride,
2993 sd->u.s.diffuse.lpData));
2995 if(curVBO != sd->u.s.diffuse.VBO) {
2996 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
2997 checkGLcall("glBindBufferARB");
2998 curVBO = sd->u.s.diffuse.VBO;
3000 glColorPointer(4, GL_UNSIGNED_BYTE,
3001 sd->u.s.diffuse.dwStride,
3002 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3003 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3004 glEnableClientState(GL_COLOR_ARRAY);
3005 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3007 } else {
3008 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3009 checkGLcall("glColor4f(1, 1, 1, 1)");
3012 /* Specular Colour ------------------------------------------*/
3013 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3014 TRACE("setting specular colour\n");
3015 /* Note dwType == float3 or float4 == 2 or 3 */
3016 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3017 sd->u.s.specular.dwStride,
3018 sd->u.s.specular.lpData));
3019 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3020 if(curVBO != sd->u.s.specular.VBO) {
3021 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3022 checkGLcall("glBindBufferARB");
3023 curVBO = sd->u.s.specular.VBO;
3025 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3026 sd->u.s.specular.dwStride,
3027 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3028 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3029 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3030 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3031 } else {
3033 /* Missing specular color is not critical, no warnings */
3034 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3037 } else {
3038 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3039 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3040 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3041 } else {
3043 /* Missing specular color is not critical, no warnings */
3044 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3048 /* Texture coords -------------------------------------------*/
3049 loadTexCoords(stateblock, sd, &curVBO);
3052 static inline void drawPrimitiveTraceDataLocations(
3053 WineDirect3DVertexStridedData *dataLocations) {
3055 /* Dump out what parts we have supplied */
3056 TRACE("Strided Data:\n");
3057 TRACE_STRIDED((dataLocations), position);
3058 TRACE_STRIDED((dataLocations), blendWeights);
3059 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3060 TRACE_STRIDED((dataLocations), normal);
3061 TRACE_STRIDED((dataLocations), pSize);
3062 TRACE_STRIDED((dataLocations), diffuse);
3063 TRACE_STRIDED((dataLocations), specular);
3064 TRACE_STRIDED((dataLocations), texCoords[0]);
3065 TRACE_STRIDED((dataLocations), texCoords[1]);
3066 TRACE_STRIDED((dataLocations), texCoords[2]);
3067 TRACE_STRIDED((dataLocations), texCoords[3]);
3068 TRACE_STRIDED((dataLocations), texCoords[4]);
3069 TRACE_STRIDED((dataLocations), texCoords[5]);
3070 TRACE_STRIDED((dataLocations), texCoords[6]);
3071 TRACE_STRIDED((dataLocations), texCoords[7]);
3072 TRACE_STRIDED((dataLocations), position2);
3073 TRACE_STRIDED((dataLocations), normal2);
3074 TRACE_STRIDED((dataLocations), tangent);
3075 TRACE_STRIDED((dataLocations), binormal);
3076 TRACE_STRIDED((dataLocations), tessFactor);
3077 TRACE_STRIDED((dataLocations), fog);
3078 TRACE_STRIDED((dataLocations), depth);
3079 TRACE_STRIDED((dataLocations), sample);
3081 return;
3084 /* Helper for vertexdeclaration() */
3085 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3086 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3087 BOOL fixup = FALSE;
3088 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3090 if(device->up_strided) {
3091 /* Note: this is a ddraw fixed-function code path */
3092 TRACE("================ Strided Input ===================\n");
3093 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3095 if(TRACE_ON(d3d)) {
3096 drawPrimitiveTraceDataLocations(dataLocations);
3098 } else {
3099 /* Note: This is a fixed function or shader codepath.
3100 * This means it must handle both types of strided data.
3101 * Shaders must go through here to zero the strided data, even if they
3102 * don't set any declaration at all
3104 TRACE("================ Vertex Declaration ===================\n");
3105 memset(dataLocations, 0, sizeof(*dataLocations));
3106 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3107 useVertexShaderFunction, dataLocations, &fixup);
3110 if (dataLocations->u.s.position_transformed) {
3111 useVertexShaderFunction = FALSE;
3114 /* Unload the old arrays before loading the new ones to get old junk out */
3115 if(context->numberedArraysLoaded) {
3116 unloadNumberedArrays(stateblock);
3117 context->numberedArraysLoaded = FALSE;
3119 if(context->namedArraysLoaded) {
3120 unloadVertexData(stateblock);
3121 context->namedArraysLoaded = FALSE;
3124 if(useVertexShaderFunction) {
3125 TRACE("Loading numbered arrays\n");
3126 loadNumberedArrays(stateblock, dataLocations);
3127 device->useDrawStridedSlow = FALSE;
3128 context->numberedArraysLoaded = TRUE;
3129 } else if (fixup ||
3130 (dataLocations->u.s.pSize.lpData == NULL &&
3131 dataLocations->u.s.diffuse.lpData == NULL &&
3132 dataLocations->u.s.specular.lpData == NULL)) {
3133 /* Load the vertex data using named arrays */
3134 TRACE("Loading vertex data\n");
3135 loadVertexData(stateblock, dataLocations);
3136 device->useDrawStridedSlow = FALSE;
3137 context->namedArraysLoaded = TRUE;
3138 } else {
3139 TRACE("Not loading vertex data\n");
3140 device->useDrawStridedSlow = TRUE;
3143 /* Generate some fixme's if unsupported functionality is being used */
3144 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3145 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3146 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3147 FIXME("Tweening is only valid with vertex shaders\n");
3149 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3150 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3152 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3153 FIXME("Extended attributes are only valid with vertex shaders\n");
3155 #undef BUFFER_OR_DATA
3158 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3159 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3160 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3161 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3162 BOOL transformed;
3163 /* Some stuff is in the device until we have per context tracking */
3164 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3165 BOOL wasrhw = context->last_was_rhw;
3167 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3168 * here simply check whether a shader was set, or the user disabled shaders
3170 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3171 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3172 useVertexShaderFunction = TRUE;
3174 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3175 updateFog = TRUE;
3177 } else if(context->last_was_foggy_shader) {
3178 updateFog = TRUE;
3181 handleStreams(stateblock, useVertexShaderFunction, context);
3183 transformed = device->strided_streams.u.s.position_transformed;
3184 if (transformed) useVertexShaderFunction = FALSE;
3186 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3187 updateFog = TRUE;
3190 /* Reapply lighting if it is not scheduled for reapplication already */
3191 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3192 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3195 if (transformed) {
3196 context->last_was_rhw = TRUE;
3197 } else {
3199 /* Untransformed, so relies on the view and projection matrices */
3200 context->last_was_rhw = FALSE;
3201 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3202 device->untransformed = TRUE;
3204 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3205 * Not needed as long as only hw shaders are supported
3208 /* This sets the shader output position correction constants.
3209 * TODO: Move to the viewport state
3211 if (useVertexShaderFunction) {
3212 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3216 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3217 * off this function will be called again anyway to make sure they're properly set
3219 if(!useVertexShaderFunction) {
3220 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3221 * or transformed / untransformed was switched
3223 if(wasrhw != context->last_was_rhw &&
3224 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3225 !isStateDirty(context, STATE_VIEWPORT)) {
3226 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3228 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3229 * mode.
3231 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3232 * this check will fail and the matrix not applied again. This is OK because a simple
3233 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3234 * needs of the vertex declaration.
3236 * World and view matrix go into the same gl matrix, so only apply them when neither is
3237 * dirty
3239 if(transformed != wasrhw &&
3240 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3241 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3242 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3245 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3246 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3249 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3250 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3252 } else {
3253 /* We compile the shader here because we need the vertex declaration
3254 * in order to determine if we need to do any swizzling for D3DCOLOR
3255 * registers. If the shader is already compiled this call will do nothing. */
3256 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3258 if(!context->last_was_vshader) {
3259 int i;
3260 static BOOL warned = FALSE;
3261 /* Disable all clip planes to get defined results on all drivers. See comment in the
3262 * state_clipping state handler
3264 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3265 glDisable(GL_CLIP_PLANE0 + i);
3266 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3269 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3270 FIXME("Clipping not supported with vertex shaders\n");
3271 warned = TRUE;
3276 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3277 * application
3279 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3280 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3282 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3283 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3287 context->last_was_vshader = useVertexShaderFunction;
3289 if(updateFog) {
3290 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3294 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3295 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3296 checkGLcall("glDepthRange");
3297 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3299 if(stateblock->wineD3DDevice->render_offscreen) {
3300 glViewport(stateblock->viewport.X,
3301 stateblock->viewport.Y,
3302 stateblock->viewport.Width, stateblock->viewport.Height);
3303 } else {
3304 glViewport(stateblock->viewport.X,
3305 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3306 stateblock->viewport.Width, stateblock->viewport.Height);
3309 checkGLcall("glViewport");
3311 stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
3312 stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
3313 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3314 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3319 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3320 UINT Index = state - STATE_ACTIVELIGHT(0);
3321 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3323 if(!lightInfo) {
3324 glDisable(GL_LIGHT0 + Index);
3325 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3326 } else {
3327 float quad_att;
3328 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3330 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3331 glMatrixMode(GL_MODELVIEW);
3332 glPushMatrix();
3333 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3335 /* Diffuse: */
3336 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3337 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3338 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3339 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3340 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3341 checkGLcall("glLightfv");
3343 /* Specular */
3344 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3345 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3346 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3347 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3348 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3349 checkGLcall("glLightfv");
3351 /* Ambient */
3352 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3353 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3354 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3355 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3356 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3357 checkGLcall("glLightfv");
3359 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3360 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3361 } else {
3362 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3365 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3366 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3367 * Attenuation0 to NaN and crashes in the gl lib
3370 switch (lightInfo->OriginalParms.Type) {
3371 case WINED3DLIGHT_POINT:
3372 /* Position */
3373 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3374 checkGLcall("glLightfv");
3375 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3376 checkGLcall("glLightf");
3377 /* Attenuation - Are these right? guessing... */
3378 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3379 checkGLcall("glLightf");
3380 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3381 checkGLcall("glLightf");
3382 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3383 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3384 checkGLcall("glLightf");
3385 /* FIXME: Range */
3386 break;
3388 case WINED3DLIGHT_SPOT:
3389 /* Position */
3390 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3391 checkGLcall("glLightfv");
3392 /* Direction */
3393 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3394 checkGLcall("glLightfv");
3395 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3396 checkGLcall("glLightf");
3397 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3398 checkGLcall("glLightf");
3399 /* Attenuation - Are these right? guessing... */
3400 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3401 checkGLcall("glLightf");
3402 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3403 checkGLcall("glLightf");
3404 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3405 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3406 checkGLcall("glLightf");
3407 /* FIXME: Range */
3408 break;
3410 case WINED3DLIGHT_DIRECTIONAL:
3411 /* Direction */
3412 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3413 checkGLcall("glLightfv");
3414 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3415 checkGLcall("glLightf");
3416 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3417 checkGLcall("glLightf");
3418 break;
3420 default:
3421 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3424 /* Restore the modelview matrix */
3425 glPopMatrix();
3427 glEnable(GL_LIGHT0 + Index);
3428 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3431 return;
3434 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3435 IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) stateblock->wineD3DDevice->swapchains[0];
3436 RECT *pRect = &stateblock->scissorRect;
3437 RECT windowRect;
3438 UINT winHeight;
3440 GetClientRect(swapchain->win_handle, &windowRect);
3441 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3442 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3444 winHeight = windowRect.bottom - windowRect.top;
3445 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3446 pRect->right - pRect->left, pRect->bottom - pRect->top);
3447 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3448 checkGLcall("glScissor");
3451 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3452 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3453 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3454 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3455 } else {
3456 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3457 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3462 const struct StateEntry StateTable[] =
3464 /* State name representative, apply function */
3465 { /* 0, Undefined */ 0, state_undefined },
3466 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3467 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3468 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3469 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3470 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3471 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3472 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3473 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3474 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3475 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3476 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3477 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3478 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3479 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3480 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3481 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3482 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3483 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3484 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3485 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3486 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3487 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3488 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3489 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3490 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3491 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3492 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3493 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3494 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3495 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3496 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3497 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3498 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3499 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3500 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3501 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3502 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3503 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3504 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3505 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3506 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3507 { /* 42, undefined */ 0, state_undefined },
3508 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3509 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3510 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3511 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3512 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3513 { /* 48, WINED3DRS_RANGEFOGENABLE */ 0, state_nogl },
3514 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3515 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3516 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3517 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3518 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3519 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3520 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3521 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3522 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3523 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3524 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3525 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3526 { /* 61, Undefined */ 0, state_undefined },
3527 { /* 62, Undefined */ 0, state_undefined },
3528 { /* 63, Undefined */ 0, state_undefined },
3529 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3530 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3531 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3532 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3533 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3534 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3535 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3536 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3537 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3538 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3539 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3540 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3541 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3542 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3543 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3544 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3545 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3546 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3547 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3548 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3549 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3550 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3551 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3552 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3553 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3554 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3555 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3556 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3557 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3558 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3559 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3560 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3561 { /* 96, Undefined */ 0, state_undefined },
3562 { /* 97, Undefined */ 0, state_undefined },
3563 { /* 98, Undefined */ 0, state_undefined },
3564 { /* 99, Undefined */ 0, state_undefined },
3565 { /*100, Undefined */ 0, state_undefined },
3566 { /*101, Undefined */ 0, state_undefined },
3567 { /*102, Undefined */ 0, state_undefined },
3568 { /*103, Undefined */ 0, state_undefined },
3569 { /*104, Undefined */ 0, state_undefined },
3570 { /*105, Undefined */ 0, state_undefined },
3571 { /*106, Undefined */ 0, state_undefined },
3572 { /*107, Undefined */ 0, state_undefined },
3573 { /*108, Undefined */ 0, state_undefined },
3574 { /*109, Undefined */ 0, state_undefined },
3575 { /*110, Undefined */ 0, state_undefined },
3576 { /*111, Undefined */ 0, state_undefined },
3577 { /*112, Undefined */ 0, state_undefined },
3578 { /*113, Undefined */ 0, state_undefined },
3579 { /*114, Undefined */ 0, state_undefined },
3580 { /*115, Undefined */ 0, state_undefined },
3581 { /*116, Undefined */ 0, state_undefined },
3582 { /*117, Undefined */ 0, state_undefined },
3583 { /*118, Undefined */ 0, state_undefined },
3584 { /*119, Undefined */ 0, state_undefined },
3585 { /*120, Undefined */ 0, state_undefined },
3586 { /*121, Undefined */ 0, state_undefined },
3587 { /*122, Undefined */ 0, state_undefined },
3588 { /*123, Undefined */ 0, state_undefined },
3589 { /*124, Undefined */ 0, state_undefined },
3590 { /*125, Undefined */ 0, state_undefined },
3591 { /*126, Undefined */ 0, state_undefined },
3592 { /*127, Undefined */ 0, state_undefined },
3593 /* Big hole ends */
3594 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3595 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3596 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3597 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3598 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3599 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3600 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3601 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3602 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3603 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3604 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3605 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3606 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3607 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3608 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3609 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3610 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3611 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3612 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3613 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3614 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3615 { /*149, Undefined */ 0, state_undefined },
3616 { /*150, Undefined */ 0, state_undefined },
3617 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3618 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3619 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3620 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
3621 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3622 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3623 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3624 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3625 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3626 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3627 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3628 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3629 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3630 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3631 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3632 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3633 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3634 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3635 { /*169, Undefined */ 0, state_undefined },
3636 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3637 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3638 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3639 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3640 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3641 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3642 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3643 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3644 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3645 { /*177, undefined */ 0, state_undefined },
3646 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3647 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3648 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3649 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3650 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3651 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3652 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3653 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3654 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3655 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3656 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3657 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3658 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3659 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3660 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3661 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3662 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite },
3663 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3664 { /*196, undefined */ 0, state_undefined },
3665 { /*197, undefined */ 0, state_undefined },
3666 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3667 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3668 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3669 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3670 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3671 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3672 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3673 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3674 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3675 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3676 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3677 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3678 /* Texture stage states */
3679 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3680 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3681 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3682 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3683 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3684 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3685 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3686 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3687 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3688 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3689 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3690 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3691 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3692 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3693 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3694 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3695 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3696 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3697 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3698 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3699 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3700 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3701 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3702 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3703 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3704 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3705 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3706 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3707 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3708 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3709 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3710 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3712 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3713 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3714 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3715 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3716 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3717 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3718 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3719 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3720 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3721 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3722 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3723 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3724 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3725 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3726 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3727 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3728 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3729 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3730 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3731 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3732 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3733 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3734 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3735 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3736 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3737 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3738 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3739 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3740 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3741 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3742 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3743 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3745 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3746 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3747 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3748 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3749 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3750 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3751 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3752 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3753 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3754 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3755 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3756 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3757 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3758 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3759 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3760 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3761 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3762 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3763 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3764 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3765 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3766 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3767 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3768 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3769 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3770 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3771 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3772 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
3773 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3774 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3775 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3776 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3778 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3779 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3780 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3781 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3782 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3783 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3784 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3785 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3786 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3787 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3788 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3789 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3790 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3791 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3792 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3793 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3794 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3795 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3796 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3797 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3798 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3799 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3800 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3801 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3802 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3803 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3804 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3805 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
3806 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3807 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3808 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3809 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3811 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3812 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3813 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3814 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3815 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3816 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3817 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3818 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3819 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3820 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3821 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3822 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3823 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3824 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3825 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3826 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3827 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3828 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3829 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3830 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3831 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3832 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3833 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3834 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3835 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3836 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3837 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3838 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
3839 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3840 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3841 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3842 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3844 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3845 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3846 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3847 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3848 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3849 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3850 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3851 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3852 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3853 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3854 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3855 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3856 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3857 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3858 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3859 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3860 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3861 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3862 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3863 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3864 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3865 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3866 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3867 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3868 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3869 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3870 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3871 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
3872 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3873 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3874 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3875 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3877 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3878 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3879 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3880 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3881 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3882 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3883 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3884 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3885 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3886 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3887 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3888 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3889 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3890 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3891 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3892 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3893 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3894 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3895 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3896 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3897 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3898 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3899 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3900 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3901 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3902 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3903 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3904 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
3905 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3906 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3907 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3908 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3910 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3911 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3912 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3913 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3914 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3915 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3916 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3917 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3918 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3919 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3920 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3921 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3922 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3923 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3924 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3925 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3926 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3927 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3928 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3929 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3930 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3931 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3932 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3933 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3934 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3935 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3936 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3937 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
3938 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3939 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3940 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3941 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3942 /* Sampler states */
3943 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
3944 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
3945 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
3946 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
3947 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
3948 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
3949 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
3950 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
3951 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
3952 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
3953 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
3954 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
3955 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
3956 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
3957 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
3958 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
3959 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
3960 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
3961 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
3962 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
3963 /* Pixel shader */
3964 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
3965 /* Transform states follow */
3966 { /* 1, undefined */ 0, state_undefined },
3967 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
3968 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
3969 { /* 4, undefined */ 0, state_undefined },
3970 { /* 5, undefined */ 0, state_undefined },
3971 { /* 6, undefined */ 0, state_undefined },
3972 { /* 7, undefined */ 0, state_undefined },
3973 { /* 8, undefined */ 0, state_undefined },
3974 { /* 9, undefined */ 0, state_undefined },
3975 { /* 10, undefined */ 0, state_undefined },
3976 { /* 11, undefined */ 0, state_undefined },
3977 { /* 12, undefined */ 0, state_undefined },
3978 { /* 13, undefined */ 0, state_undefined },
3979 { /* 14, undefined */ 0, state_undefined },
3980 { /* 15, undefined */ 0, state_undefined },
3981 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3982 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3983 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3984 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3985 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3986 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3987 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3988 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3989 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
3990 { /* 24, undefined */ 0, state_undefined },
3991 { /* 25, undefined */ 0, state_undefined },
3992 { /* 26, undefined */ 0, state_undefined },
3993 { /* 27, undefined */ 0, state_undefined },
3994 { /* 28, undefined */ 0, state_undefined },
3995 { /* 29, undefined */ 0, state_undefined },
3996 { /* 30, undefined */ 0, state_undefined },
3997 { /* 31, undefined */ 0, state_undefined },
3998 { /* 32, undefined */ 0, state_undefined },
3999 { /* 33, undefined */ 0, state_undefined },
4000 { /* 34, undefined */ 0, state_undefined },
4001 { /* 35, undefined */ 0, state_undefined },
4002 { /* 36, undefined */ 0, state_undefined },
4003 { /* 37, undefined */ 0, state_undefined },
4004 { /* 38, undefined */ 0, state_undefined },
4005 { /* 39, undefined */ 0, state_undefined },
4006 { /* 40, undefined */ 0, state_undefined },
4007 { /* 41, undefined */ 0, state_undefined },
4008 { /* 42, undefined */ 0, state_undefined },
4009 { /* 43, undefined */ 0, state_undefined },
4010 { /* 44, undefined */ 0, state_undefined },
4011 { /* 45, undefined */ 0, state_undefined },
4012 { /* 46, undefined */ 0, state_undefined },
4013 { /* 47, undefined */ 0, state_undefined },
4014 { /* 48, undefined */ 0, state_undefined },
4015 { /* 49, undefined */ 0, state_undefined },
4016 { /* 50, undefined */ 0, state_undefined },
4017 { /* 51, undefined */ 0, state_undefined },
4018 { /* 52, undefined */ 0, state_undefined },
4019 { /* 53, undefined */ 0, state_undefined },
4020 { /* 54, undefined */ 0, state_undefined },
4021 { /* 55, undefined */ 0, state_undefined },
4022 { /* 56, undefined */ 0, state_undefined },
4023 { /* 57, undefined */ 0, state_undefined },
4024 { /* 58, undefined */ 0, state_undefined },
4025 { /* 59, undefined */ 0, state_undefined },
4026 { /* 60, undefined */ 0, state_undefined },
4027 { /* 61, undefined */ 0, state_undefined },
4028 { /* 62, undefined */ 0, state_undefined },
4029 { /* 63, undefined */ 0, state_undefined },
4030 { /* 64, undefined */ 0, state_undefined },
4031 { /* 65, undefined */ 0, state_undefined },
4032 { /* 66, undefined */ 0, state_undefined },
4033 { /* 67, undefined */ 0, state_undefined },
4034 { /* 68, undefined */ 0, state_undefined },
4035 { /* 69, undefined */ 0, state_undefined },
4036 { /* 70, undefined */ 0, state_undefined },
4037 { /* 71, undefined */ 0, state_undefined },
4038 { /* 72, undefined */ 0, state_undefined },
4039 { /* 73, undefined */ 0, state_undefined },
4040 { /* 74, undefined */ 0, state_undefined },
4041 { /* 75, undefined */ 0, state_undefined },
4042 { /* 76, undefined */ 0, state_undefined },
4043 { /* 77, undefined */ 0, state_undefined },
4044 { /* 78, undefined */ 0, state_undefined },
4045 { /* 79, undefined */ 0, state_undefined },
4046 { /* 80, undefined */ 0, state_undefined },
4047 { /* 81, undefined */ 0, state_undefined },
4048 { /* 82, undefined */ 0, state_undefined },
4049 { /* 83, undefined */ 0, state_undefined },
4050 { /* 84, undefined */ 0, state_undefined },
4051 { /* 85, undefined */ 0, state_undefined },
4052 { /* 86, undefined */ 0, state_undefined },
4053 { /* 87, undefined */ 0, state_undefined },
4054 { /* 88, undefined */ 0, state_undefined },
4055 { /* 89, undefined */ 0, state_undefined },
4056 { /* 90, undefined */ 0, state_undefined },
4057 { /* 91, undefined */ 0, state_undefined },
4058 { /* 92, undefined */ 0, state_undefined },
4059 { /* 93, undefined */ 0, state_undefined },
4060 { /* 94, undefined */ 0, state_undefined },
4061 { /* 95, undefined */ 0, state_undefined },
4062 { /* 96, undefined */ 0, state_undefined },
4063 { /* 97, undefined */ 0, state_undefined },
4064 { /* 98, undefined */ 0, state_undefined },
4065 { /* 99, undefined */ 0, state_undefined },
4066 { /*100, undefined */ 0, state_undefined },
4067 { /*101, undefined */ 0, state_undefined },
4068 { /*102, undefined */ 0, state_undefined },
4069 { /*103, undefined */ 0, state_undefined },
4070 { /*104, undefined */ 0, state_undefined },
4071 { /*105, undefined */ 0, state_undefined },
4072 { /*106, undefined */ 0, state_undefined },
4073 { /*107, undefined */ 0, state_undefined },
4074 { /*108, undefined */ 0, state_undefined },
4075 { /*109, undefined */ 0, state_undefined },
4076 { /*110, undefined */ 0, state_undefined },
4077 { /*111, undefined */ 0, state_undefined },
4078 { /*112, undefined */ 0, state_undefined },
4079 { /*113, undefined */ 0, state_undefined },
4080 { /*114, undefined */ 0, state_undefined },
4081 { /*115, undefined */ 0, state_undefined },
4082 { /*116, undefined */ 0, state_undefined },
4083 { /*117, undefined */ 0, state_undefined },
4084 { /*118, undefined */ 0, state_undefined },
4085 { /*119, undefined */ 0, state_undefined },
4086 { /*120, undefined */ 0, state_undefined },
4087 { /*121, undefined */ 0, state_undefined },
4088 { /*122, undefined */ 0, state_undefined },
4089 { /*123, undefined */ 0, state_undefined },
4090 { /*124, undefined */ 0, state_undefined },
4091 { /*125, undefined */ 0, state_undefined },
4092 { /*126, undefined */ 0, state_undefined },
4093 { /*127, undefined */ 0, state_undefined },
4094 { /*128, undefined */ 0, state_undefined },
4095 { /*129, undefined */ 0, state_undefined },
4096 { /*130, undefined */ 0, state_undefined },
4097 { /*131, undefined */ 0, state_undefined },
4098 { /*132, undefined */ 0, state_undefined },
4099 { /*133, undefined */ 0, state_undefined },
4100 { /*134, undefined */ 0, state_undefined },
4101 { /*135, undefined */ 0, state_undefined },
4102 { /*136, undefined */ 0, state_undefined },
4103 { /*137, undefined */ 0, state_undefined },
4104 { /*138, undefined */ 0, state_undefined },
4105 { /*139, undefined */ 0, state_undefined },
4106 { /*140, undefined */ 0, state_undefined },
4107 { /*141, undefined */ 0, state_undefined },
4108 { /*142, undefined */ 0, state_undefined },
4109 { /*143, undefined */ 0, state_undefined },
4110 { /*144, undefined */ 0, state_undefined },
4111 { /*145, undefined */ 0, state_undefined },
4112 { /*146, undefined */ 0, state_undefined },
4113 { /*147, undefined */ 0, state_undefined },
4114 { /*148, undefined */ 0, state_undefined },
4115 { /*149, undefined */ 0, state_undefined },
4116 { /*150, undefined */ 0, state_undefined },
4117 { /*151, undefined */ 0, state_undefined },
4118 { /*152, undefined */ 0, state_undefined },
4119 { /*153, undefined */ 0, state_undefined },
4120 { /*154, undefined */ 0, state_undefined },
4121 { /*155, undefined */ 0, state_undefined },
4122 { /*156, undefined */ 0, state_undefined },
4123 { /*157, undefined */ 0, state_undefined },
4124 { /*158, undefined */ 0, state_undefined },
4125 { /*159, undefined */ 0, state_undefined },
4126 { /*160, undefined */ 0, state_undefined },
4127 { /*161, undefined */ 0, state_undefined },
4128 { /*162, undefined */ 0, state_undefined },
4129 { /*163, undefined */ 0, state_undefined },
4130 { /*164, undefined */ 0, state_undefined },
4131 { /*165, undefined */ 0, state_undefined },
4132 { /*166, undefined */ 0, state_undefined },
4133 { /*167, undefined */ 0, state_undefined },
4134 { /*168, undefined */ 0, state_undefined },
4135 { /*169, undefined */ 0, state_undefined },
4136 { /*170, undefined */ 0, state_undefined },
4137 { /*171, undefined */ 0, state_undefined },
4138 { /*172, undefined */ 0, state_undefined },
4139 { /*173, undefined */ 0, state_undefined },
4140 { /*174, undefined */ 0, state_undefined },
4141 { /*175, undefined */ 0, state_undefined },
4142 { /*176, undefined */ 0, state_undefined },
4143 { /*177, undefined */ 0, state_undefined },
4144 { /*178, undefined */ 0, state_undefined },
4145 { /*179, undefined */ 0, state_undefined },
4146 { /*180, undefined */ 0, state_undefined },
4147 { /*181, undefined */ 0, state_undefined },
4148 { /*182, undefined */ 0, state_undefined },
4149 { /*183, undefined */ 0, state_undefined },
4150 { /*184, undefined */ 0, state_undefined },
4151 { /*185, undefined */ 0, state_undefined },
4152 { /*186, undefined */ 0, state_undefined },
4153 { /*187, undefined */ 0, state_undefined },
4154 { /*188, undefined */ 0, state_undefined },
4155 { /*189, undefined */ 0, state_undefined },
4156 { /*190, undefined */ 0, state_undefined },
4157 { /*191, undefined */ 0, state_undefined },
4158 { /*192, undefined */ 0, state_undefined },
4159 { /*193, undefined */ 0, state_undefined },
4160 { /*194, undefined */ 0, state_undefined },
4161 { /*195, undefined */ 0, state_undefined },
4162 { /*196, undefined */ 0, state_undefined },
4163 { /*197, undefined */ 0, state_undefined },
4164 { /*198, undefined */ 0, state_undefined },
4165 { /*199, undefined */ 0, state_undefined },
4166 { /*200, undefined */ 0, state_undefined },
4167 { /*201, undefined */ 0, state_undefined },
4168 { /*202, undefined */ 0, state_undefined },
4169 { /*203, undefined */ 0, state_undefined },
4170 { /*204, undefined */ 0, state_undefined },
4171 { /*205, undefined */ 0, state_undefined },
4172 { /*206, undefined */ 0, state_undefined },
4173 { /*207, undefined */ 0, state_undefined },
4174 { /*208, undefined */ 0, state_undefined },
4175 { /*209, undefined */ 0, state_undefined },
4176 { /*210, undefined */ 0, state_undefined },
4177 { /*211, undefined */ 0, state_undefined },
4178 { /*212, undefined */ 0, state_undefined },
4179 { /*213, undefined */ 0, state_undefined },
4180 { /*214, undefined */ 0, state_undefined },
4181 { /*215, undefined */ 0, state_undefined },
4182 { /*216, undefined */ 0, state_undefined },
4183 { /*217, undefined */ 0, state_undefined },
4184 { /*218, undefined */ 0, state_undefined },
4185 { /*219, undefined */ 0, state_undefined },
4186 { /*220, undefined */ 0, state_undefined },
4187 { /*221, undefined */ 0, state_undefined },
4188 { /*222, undefined */ 0, state_undefined },
4189 { /*223, undefined */ 0, state_undefined },
4190 { /*224, undefined */ 0, state_undefined },
4191 { /*225, undefined */ 0, state_undefined },
4192 { /*226, undefined */ 0, state_undefined },
4193 { /*227, undefined */ 0, state_undefined },
4194 { /*228, undefined */ 0, state_undefined },
4195 { /*229, undefined */ 0, state_undefined },
4196 { /*230, undefined */ 0, state_undefined },
4197 { /*231, undefined */ 0, state_undefined },
4198 { /*232, undefined */ 0, state_undefined },
4199 { /*233, undefined */ 0, state_undefined },
4200 { /*234, undefined */ 0, state_undefined },
4201 { /*235, undefined */ 0, state_undefined },
4202 { /*236, undefined */ 0, state_undefined },
4203 { /*237, undefined */ 0, state_undefined },
4204 { /*238, undefined */ 0, state_undefined },
4205 { /*239, undefined */ 0, state_undefined },
4206 { /*240, undefined */ 0, state_undefined },
4207 { /*241, undefined */ 0, state_undefined },
4208 { /*242, undefined */ 0, state_undefined },
4209 { /*243, undefined */ 0, state_undefined },
4210 { /*244, undefined */ 0, state_undefined },
4211 { /*245, undefined */ 0, state_undefined },
4212 { /*246, undefined */ 0, state_undefined },
4213 { /*247, undefined */ 0, state_undefined },
4214 { /*248, undefined */ 0, state_undefined },
4215 { /*249, undefined */ 0, state_undefined },
4216 { /*250, undefined */ 0, state_undefined },
4217 { /*251, undefined */ 0, state_undefined },
4218 { /*252, undefined */ 0, state_undefined },
4219 { /*253, undefined */ 0, state_undefined },
4220 { /*254, undefined */ 0, state_undefined },
4221 { /*255, undefined */ 0, state_undefined },
4222 /* End huge gap */
4223 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4224 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4225 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4226 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4227 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4228 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4229 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4230 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4231 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4232 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4233 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4234 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4235 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4236 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4237 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4238 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4239 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4240 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4241 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4242 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4243 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4244 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4245 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4246 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4247 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4248 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4249 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4250 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4251 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4252 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4253 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4254 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4255 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4256 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4257 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4258 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4259 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4260 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4261 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4262 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4263 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4264 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4265 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4266 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4267 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4268 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4269 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4270 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4271 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4272 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4273 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4274 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4275 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4276 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4277 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4278 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4279 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4280 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4281 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4282 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4283 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4284 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4285 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4286 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4287 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4288 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4289 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4290 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4291 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4292 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4293 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4294 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4295 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4296 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4297 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4298 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4299 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4300 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4301 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4302 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4303 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4304 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4305 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4306 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4307 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4308 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4309 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4310 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4311 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4312 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4313 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4314 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4315 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4316 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4317 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4318 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4319 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4320 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4321 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4322 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4323 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4324 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4325 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4326 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4327 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4328 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4329 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4330 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4331 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4332 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4333 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4334 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4335 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4336 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4337 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4338 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4339 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4340 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4341 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4342 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4343 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4344 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4345 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4346 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4347 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4348 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4349 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4350 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4351 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4352 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4353 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4354 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4355 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4356 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4357 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4358 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4359 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4360 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4361 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4362 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4363 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4364 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4365 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4366 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4367 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4368 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4369 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4370 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4371 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4372 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4373 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4374 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4375 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4376 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4377 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4378 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4379 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4380 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4381 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4382 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4383 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4384 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4385 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4386 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4387 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4388 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4389 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4390 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4391 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4392 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4393 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4394 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4395 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4396 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4397 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4398 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4399 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4400 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4401 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4402 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4403 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4404 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4405 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4406 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4407 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4408 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4409 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4410 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4411 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4412 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4413 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4414 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4415 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4416 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4417 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4418 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4419 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4420 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4421 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4422 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4423 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4424 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4425 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4426 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4427 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4428 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4429 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4430 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4431 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4432 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4433 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4434 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4435 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4436 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4437 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4438 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4439 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4440 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4441 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4442 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4443 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4444 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4445 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4446 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4447 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4448 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4449 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4450 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4451 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4452 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4453 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4454 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4455 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4456 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4457 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4458 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4459 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4460 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4461 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4462 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4463 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4464 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4465 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4466 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4467 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4468 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4469 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4470 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4471 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4472 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4473 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4474 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4475 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4476 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4477 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4478 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4479 /* Various Vertex states follow */
4480 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4481 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4482 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4483 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4484 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4485 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4486 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4487 /* Lights */
4488 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4489 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4490 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4491 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4492 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4493 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4494 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4495 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4497 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4498 /* Clip planes */
4499 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4500 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4501 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4502 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4503 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4504 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4505 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4506 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4507 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4508 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4509 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4510 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4511 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4512 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4513 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4514 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4515 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4516 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4517 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4518 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4519 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4520 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4521 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4522 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4523 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4524 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4525 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4526 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4527 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4528 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4529 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4530 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4532 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},