wined3d: Only call activate_dimensions() if the texture is used.
[wine/gsoc_dplay.git] / dlls / wined3d / state.c
blobbdb4d5b3cc2fb072af5d9ae60ecd65bcd40999cd
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 (mapped_stage >= GL_LIMITS(textures)) {
1676 if (stateblock->textureState[stage][WINED3DTSS_COLOROP] != WINED3DTOP_DISABLE &&
1677 stateblock->textureState[stage][WINED3DTSS_COLOROP] != 0) {
1678 FIXME("Attempt to enable unsupported stage!\n");
1680 return;
1682 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1683 checkGLcall("glActiveTextureARB");
1684 } else if (stage > 0) {
1685 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1686 return;
1690 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1691 if(stateblock->lowest_disabled_stage > 0) {
1692 glEnable(GL_REGISTER_COMBINERS_NV);
1693 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1694 } else {
1695 glDisable(GL_REGISTER_COMBINERS_NV);
1698 if(stage >= stateblock->lowest_disabled_stage) {
1699 TRACE("Stage disabled\n");
1700 if (mapped_stage != -1) {
1701 /* Disable everything here */
1702 glDisable(GL_TEXTURE_2D);
1703 checkGLcall("glDisable(GL_TEXTURE_2D)");
1704 glDisable(GL_TEXTURE_3D);
1705 checkGLcall("glDisable(GL_TEXTURE_3D)");
1706 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1707 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1708 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1710 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1711 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1714 /* All done */
1715 return;
1718 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1719 * if the sampler for this stage is dirty
1721 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1722 if (tex_used) activate_dimensions(stage, stateblock, context);
1725 /* Set the texture combiners */
1726 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1727 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1728 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1729 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1730 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1731 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1732 mapped_stage);
1734 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1735 * thus the texture shader may have to be updated
1737 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1738 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1739 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1740 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1741 if(usesBump != usedBump) {
1742 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1743 checkGLcall("glActiveTextureARB");
1744 activate_dimensions(stage + 1, stateblock, context);
1745 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1746 checkGLcall("glActiveTextureARB");
1749 } else {
1750 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1751 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1752 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1753 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1754 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1758 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1759 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1760 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1761 DWORD op, arg1, arg2, arg0;
1763 TRACE("Setting alpha op for stage %d\n", stage);
1764 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1765 if (mapped_stage != -1) {
1766 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1767 if (stage >= GL_LIMITS(textures)) {
1768 if (stateblock->textureState[stage][WINED3DTSS_COLOROP] != WINED3DTOP_DISABLE &&
1769 stateblock->textureState[stage][WINED3DTSS_COLOROP] != 0) {
1770 FIXME("Attempt to enable unsupported stage!\n");
1772 return;
1774 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1775 checkGLcall("glActiveTextureARB");
1776 } else if (stage > 0) {
1777 /* We can't do anything here */
1778 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1779 return;
1783 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1784 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1785 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1786 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1788 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1789 stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
1790 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1792 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1793 getFormatDescEntry(surf->resource.format)->alphaMask == 0x00000000) {
1795 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1796 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1797 * cannot remove the texture's alpha channel entirely.
1799 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1800 * on color keyed surfaces.
1802 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1804 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1805 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1806 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1810 TRACE("Setting alpha op for stage %d\n", stage);
1811 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1812 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1813 op, arg1, arg2, arg0,
1814 mapped_stage);
1815 } else {
1816 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1817 op, arg1, arg2, arg0);
1821 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1822 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1823 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1825 if (mapped_stage < 0) return;
1827 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1828 if(mapped_stage >= GL_LIMITS(textures)) {
1829 return;
1831 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1832 checkGLcall("glActiveTextureARB");
1833 } else if (mapped_stage > 0) {
1834 /* We can't do anything here */
1835 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1836 return;
1839 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1840 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1841 (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
1845 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1846 int texture_idx;
1848 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1849 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1850 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1854 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
1855 UINT *offset = stateblock->streamOffset;
1856 unsigned int mapped_stage = 0;
1857 unsigned int textureNo = 0;
1859 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1860 /* Abort if we don't support the extension. */
1861 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1862 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1863 return;
1866 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1867 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1869 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
1870 if (mapped_stage == -1) continue;
1872 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
1873 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1874 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1876 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1877 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1878 checkGLcall("glBindBufferARB");
1879 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
1882 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1883 checkGLcall("glClientActiveTextureARB");
1885 /* The coords to supply depend completely on the fvf / vertex shader */
1886 glTexCoordPointer(
1887 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1888 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1889 sd->u.s.texCoords[coordIdx].dwStride,
1890 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
1891 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1892 } else {
1893 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
1896 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1897 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
1898 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
1899 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1904 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1905 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1906 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1908 if (mapped_stage == -1) {
1909 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
1910 return;
1913 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1914 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
1915 return;
1917 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1918 checkGLcall("glActiveTextureARB");
1919 } else if (stage > 0) {
1920 /* We can't do anything here */
1921 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1922 return;
1925 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
1927 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
1928 * one flag, you can still specify an index value, which the system uses to
1929 * determine the texture wrapping mode.
1930 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
1931 * means use the vertex position (camera-space) as the input texture coordinates
1932 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
1933 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
1934 * to the TEXCOORDINDEX value
1938 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
1940 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
1941 case WINED3DTSS_TCI_PASSTHRU:
1942 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
1943 glDisable(GL_TEXTURE_GEN_S);
1944 glDisable(GL_TEXTURE_GEN_T);
1945 glDisable(GL_TEXTURE_GEN_R);
1946 glDisable(GL_TEXTURE_GEN_Q);
1947 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
1948 break;
1950 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
1951 /* CameraSpacePosition means use the vertex position, transformed to camera space,
1952 * as the input texture coordinates for this stage's texture transformation. This
1953 * equates roughly to EYE_LINEAR
1956 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1957 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1958 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1959 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1960 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
1962 glMatrixMode(GL_MODELVIEW);
1963 glPushMatrix();
1964 glLoadIdentity();
1965 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
1966 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
1967 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
1968 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
1969 glPopMatrix();
1971 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
1972 glEnable(GL_TEXTURE_GEN_S);
1973 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
1974 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1975 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1976 glEnable(GL_TEXTURE_GEN_T);
1977 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
1978 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1979 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1980 glEnable(GL_TEXTURE_GEN_R);
1981 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
1982 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1983 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1985 break;
1987 case WINED3DTSS_TCI_CAMERASPACENORMAL:
1989 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
1990 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1991 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1992 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1993 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1994 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
1996 glMatrixMode(GL_MODELVIEW);
1997 glPushMatrix();
1998 glLoadIdentity();
1999 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2000 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2001 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2002 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2003 glPopMatrix();
2005 glEnable(GL_TEXTURE_GEN_S);
2006 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2007 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2008 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2009 glEnable(GL_TEXTURE_GEN_T);
2010 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2011 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2012 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2013 glEnable(GL_TEXTURE_GEN_R);
2014 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2015 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2016 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2019 break;
2021 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2023 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2024 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2025 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2026 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2027 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2028 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2030 glMatrixMode(GL_MODELVIEW);
2031 glPushMatrix();
2032 glLoadIdentity();
2033 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2034 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2035 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2036 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2037 glPopMatrix();
2039 glEnable(GL_TEXTURE_GEN_S);
2040 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2041 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2042 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2043 glEnable(GL_TEXTURE_GEN_T);
2044 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2045 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2046 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2047 glEnable(GL_TEXTURE_GEN_R);
2048 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2049 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2050 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2053 break;
2055 /* Unhandled types: */
2056 default:
2057 /* Todo: */
2058 /* ? disable GL_TEXTURE_GEN_n ? */
2059 glDisable(GL_TEXTURE_GEN_S);
2060 glDisable(GL_TEXTURE_GEN_T);
2061 glDisable(GL_TEXTURE_GEN_R);
2062 glDisable(GL_TEXTURE_GEN_Q);
2063 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2064 break;
2067 /* Update the texture matrix */
2068 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2069 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2072 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2073 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2074 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2075 * and do all the things linked to it
2076 * TODO: Tidy that up to reload only the arrays of the changed unit
2078 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2080 unloadTexCoords(stateblock);
2081 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2085 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2086 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2087 union {
2088 DWORD d;
2089 float f;
2090 } tmpvalue;
2092 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2093 if(tmpvalue.f != 0.0) {
2094 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2098 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2099 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2100 union {
2101 DWORD d;
2102 float f;
2103 } tmpvalue;
2105 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2106 if(tmpvalue.f != 0.0) {
2107 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2111 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2112 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2114 if(stage >= GL_LIMITS(texture_stages)) {
2115 return;
2118 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2119 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2123 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2124 DWORD sampler = state - STATE_SAMPLER(0);
2125 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2126 union {
2127 float f;
2128 DWORD d;
2129 } tmpvalue;
2131 TRACE("Sampler: %d\n", sampler);
2132 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2133 * only has to bind textures and set the per texture states
2136 if (mapped_stage == -1) {
2137 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2138 return;
2141 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2142 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2143 return;
2145 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2146 checkGLcall("glActiveTextureARB");
2147 } else if (sampler > 0) {
2148 /* We can't do anything here */
2149 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2150 return;
2153 if(stateblock->textures[sampler]) {
2154 BOOL texIsPow2 = FALSE;
2156 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2157 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2158 * scaling is reapplied or removed, the texture matrix has to be reapplied
2160 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2161 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
2162 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
2163 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {
2164 texIsPow2 = TRUE;
2166 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2167 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->pow2scalingFactor != 1.0) {
2168 texIsPow2 = TRUE;
2172 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2173 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2174 context->lastWasPow2Texture[sampler] = texIsPow2;
2178 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2179 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2181 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2182 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2183 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2184 GL_TEXTURE_LOD_BIAS_EXT,
2185 tmpvalue.f);
2186 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2189 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2190 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2191 /* Using a pixel shader? Verify the sampler types */
2193 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2194 * dimensions because the shader knows from which texture type to sample from. For the sake of
2195 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2196 * dimensions. This should make wrong sampling sources visible :-)
2198 glEnable(stateblock->textureDimensions[sampler]);
2199 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2200 } else if(sampler < stateblock->lowest_disabled_stage) {
2201 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2202 activate_dimensions(sampler, stateblock, context);
2205 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2206 /* If color keying is enabled update the alpha test, it depends on the existence
2207 * of a color key in stage 0
2209 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2212 } else if(sampler < GL_LIMITS(texture_stages)) {
2213 if(sampler < stateblock->lowest_disabled_stage) {
2214 /* TODO: What should I do with pixel shaders here ??? */
2215 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2216 activate_dimensions(sampler, stateblock, context);
2218 } /* Otherwise tex_colorop disables the stage */
2219 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2220 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2224 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2225 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2227 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2228 * has an update pending
2230 if(isStateDirty(context, STATE_VDECL) ||
2231 isStateDirty(context, STATE_PIXELSHADER)) {
2232 return;
2235 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2238 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2239 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2240 BOOL use_pshader = use_ps(device);
2241 BOOL use_vshader = use_vs(device);
2242 BOOL update_fog = FALSE;
2243 int i;
2245 if (use_pshader) {
2246 if(!context->last_was_pshader) {
2247 /* Former draw without a pixel shader, some samplers
2248 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2249 * make sure to enable them
2251 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2252 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2253 sampler(STATE_SAMPLER(i), stateblock, context);
2256 update_fog = TRUE;
2257 } else {
2258 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2259 * if a different texture was bound. I don't have to do anything.
2263 /* Compile and bind the shader */
2264 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2265 } else {
2266 /* Disabled the pixel shader - color ops weren't applied
2267 * while it was enabled, so re-apply them.
2269 for(i=0; i < MAX_TEXTURES; i++) {
2270 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2271 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2274 if(context->last_was_pshader)
2275 update_fog = TRUE;
2278 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2279 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2281 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2282 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2286 if(update_fog)
2287 state_fog(state, stateblock, context);
2289 context->last_was_pshader = use_pshader;
2292 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2293 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2295 if(stateblock->pixelShader && stage != 0 &&
2296 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2297 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2298 * anyway
2300 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2301 !isStateDirty(context, STATE_PIXELSHADER)) {
2302 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2306 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2307 if(stage >= GL_LIMITS(texture_stages)) {
2308 WARN("Bump env matrix of unsupported stage set\n");
2309 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2310 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2311 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2313 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2314 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2315 checkGLcall("glTexBumpParameterfvATI");
2317 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2318 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2319 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2320 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2321 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2322 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2324 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2326 if(mapped_stage < GL_LIMITS(textures)) {
2327 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2328 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2330 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2331 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2332 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2337 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2338 /* This function is called by transform_view below if the view matrix was changed too
2340 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2341 * does not always update the world matrix, only on a switch between transformed
2342 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2343 * draw, but that should be rather rare and cheaper in total.
2345 glMatrixMode(GL_MODELVIEW);
2346 checkGLcall("glMatrixMode");
2348 if(context->last_was_rhw) {
2349 glLoadIdentity();
2350 checkGLcall("glLoadIdentity()");
2351 } else {
2352 /* In the general case, the view matrix is the identity matrix */
2353 if (stateblock->wineD3DDevice->view_ident) {
2354 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2355 checkGLcall("glLoadMatrixf");
2356 } else {
2357 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2358 checkGLcall("glLoadMatrixf");
2359 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2360 checkGLcall("glMultMatrixf");
2365 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2366 UINT index = state - STATE_CLIPPLANE(0);
2368 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2369 return;
2372 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2373 glMatrixMode(GL_MODELVIEW);
2374 glPushMatrix();
2375 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2377 TRACE("Clipplane [%f,%f,%f,%f]\n",
2378 stateblock->clipplane[index][0],
2379 stateblock->clipplane[index][1],
2380 stateblock->clipplane[index][2],
2381 stateblock->clipplane[index][3]);
2382 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2383 checkGLcall("glClipPlane");
2385 glPopMatrix();
2388 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2389 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2390 GLenum glMat;
2391 TRACE("Setting world matrix %d\n", matrix);
2393 if(matrix >= GL_LIMITS(blends)) {
2394 WARN("Unsupported blend matrix set\n");
2395 return;
2396 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2397 return;
2400 /* GL_MODELVIEW0_ARB: 0x1700
2401 * GL_MODELVIEW1_ARB: 0x0x850a
2402 * GL_MODELVIEW2_ARB: 0x8722
2403 * GL_MODELVIEW3_ARB: 0x8723
2404 * etc
2405 * GL_MODELVIEW31_ARB: 0x873F
2407 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2408 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2410 glMatrixMode(glMat);
2411 checkGLcall("glMatrixMode(glMat)");
2413 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2414 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2416 if(stateblock->wineD3DDevice->view_ident) {
2417 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2418 checkGLcall("glLoadMatrixf")
2419 } else {
2420 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2421 checkGLcall("glLoadMatrixf")
2422 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2423 checkGLcall("glMultMatrixf")
2427 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2428 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2430 switch(val) {
2431 case WINED3DVBF_1WEIGHTS:
2432 case WINED3DVBF_2WEIGHTS:
2433 case WINED3DVBF_3WEIGHTS:
2434 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2435 glEnable(GL_VERTEX_BLEND_ARB);
2436 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2438 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2439 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2441 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2443 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2444 int i;
2445 for(i = 1; i < GL_LIMITS(blends); i++) {
2446 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2447 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2450 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2452 } else {
2453 /* TODO: Implement vertex blending in drawStridedSlow */
2454 FIXME("Vertex blending enabled, but not supported by hardware\n");
2456 break;
2458 case WINED3DVBF_DISABLE:
2459 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2460 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2461 glDisable(GL_VERTEX_BLEND_ARB);
2462 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2463 } else {
2464 TRACE("Vertex blending disabled\n");
2466 break;
2468 case WINED3DVBF_TWEENING:
2469 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2470 * vertex weights in the vertices?
2471 * For now we don't report that as supported, so a warn should suffice
2473 WARN("Tweening not supported yet\n");
2474 break;
2478 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2479 unsigned int k;
2481 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2482 * NOTE: We have to reset the positions even if the light/plane is not currently
2483 * enabled, since the call to enable it will not reset the position.
2484 * NOTE2: Apparently texture transforms do NOT need reapplying
2487 PLIGHTINFOEL *light = NULL;
2489 glMatrixMode(GL_MODELVIEW);
2490 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2491 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2492 checkGLcall("glLoadMatrixf(...)");
2494 /* Reset lights. TODO: Call light apply func */
2495 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2496 light = stateblock->activeLights[k];
2497 if(!light) continue;
2498 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2499 checkGLcall("glLightfv posn");
2500 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2501 checkGLcall("glLightfv dirn");
2504 /* Reset Clipping Planes */
2505 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2506 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2507 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2511 if(context->last_was_rhw) {
2512 glLoadIdentity();
2513 checkGLcall("glLoadIdentity()");
2514 /* No need to update the world matrix, the identity is fine */
2515 return;
2518 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2519 * No need to do it here if the state is scheduled for update.
2521 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2522 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2525 /* Avoid looping over a number of matrices if the app never used the functionality */
2526 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2527 for(k = 1; k < GL_LIMITS(blends); k++) {
2528 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2529 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2535 static const GLfloat invymat[16] = {
2536 1.0f, 0.0f, 0.0f, 0.0f,
2537 0.0f, -1.0f, 0.0f, 0.0f,
2538 0.0f, 0.0f, 1.0f, 0.0f,
2539 0.0f, 0.0f, 0.0f, 1.0f};
2541 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2542 glMatrixMode(GL_PROJECTION);
2543 checkGLcall("glMatrixMode(GL_PROJECTION)");
2544 glLoadIdentity();
2545 checkGLcall("glLoadIdentity");
2547 if(context->last_was_rhw) {
2548 double X, Y, height, width, minZ, maxZ;
2550 X = stateblock->viewport.X;
2551 Y = stateblock->viewport.Y;
2552 height = stateblock->viewport.Height;
2553 width = stateblock->viewport.Width;
2554 minZ = stateblock->viewport.MinZ;
2555 maxZ = stateblock->viewport.MaxZ;
2557 if(!stateblock->wineD3DDevice->untransformed) {
2558 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2559 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2560 * suppress depth clipping. This can be done because it is an orthogonal projection and
2561 * the Z coordinate does not affect the size of the primitives
2563 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2564 if(stateblock->wineD3DDevice->render_offscreen) {
2565 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2566 } else {
2567 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2569 } else {
2570 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2571 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2572 * unmodified to opengl.
2574 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2575 * replacement shader.
2577 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2578 if(stateblock->wineD3DDevice->render_offscreen) {
2579 glOrtho(X, X + width, -Y, -Y - height, 1.0, -1.0);
2580 } else {
2581 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
2584 checkGLcall("glOrtho");
2586 /* Window Coord 0 is the middle of the first pixel, so translate by 3/8 pixels */
2587 glTranslatef(0.375, 0.375, 0);
2588 checkGLcall("glTranslatef(0.375, 0.375, 0)");
2589 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2590 * render everything upside down when rendering offscreen. */
2591 if (stateblock->wineD3DDevice->render_offscreen) {
2592 glMultMatrixf(invymat);
2593 checkGLcall("glMultMatrixf(invymat)");
2595 } else {
2596 /* The rule is that the window coordinate 0 does not correspond to the
2597 beginning of the first pixel, but the center of the first pixel.
2598 As a consequence if you want to correctly draw one line exactly from
2599 the left to the right end of the viewport (with all matrices set to
2600 be identity), the x coords of both ends of the line would be not
2601 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2602 instead. */
2603 glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
2604 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
2606 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2607 * render everything upside down when rendering offscreen. */
2608 if (stateblock->wineD3DDevice->render_offscreen) {
2609 glMultMatrixf(invymat);
2610 checkGLcall("glMultMatrixf(invymat)");
2612 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2613 checkGLcall("glLoadMatrixf");
2617 /* This should match any arrays loaded in loadVertexData.
2618 * stateblock impl is required for GL_SUPPORT
2619 * TODO: Only load / unload arrays if we have to.
2621 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2622 glDisableClientState(GL_VERTEX_ARRAY);
2623 glDisableClientState(GL_NORMAL_ARRAY);
2624 glDisableClientState(GL_COLOR_ARRAY);
2625 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2626 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2628 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2629 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2630 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2631 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2633 unloadTexCoords(stateblock);
2636 /* This should match any arrays loaded in loadNumberedArrays
2637 * TODO: Only load / unload arrays if we have to.
2639 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2640 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2641 GLint maxAttribs;
2642 int i;
2644 /* Leave all the attribs disabled */
2645 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2646 /* MESA does not support it right not */
2647 if (glGetError() != GL_NO_ERROR)
2648 maxAttribs = 16;
2649 for (i = 0; i < maxAttribs; ++i) {
2650 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2651 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2655 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2656 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2657 int i;
2658 UINT *offset = stateblock->streamOffset;
2660 /* Default to no instancing */
2661 stateblock->wineD3DDevice->instancedDraw = FALSE;
2663 for (i = 0; i < MAX_ATTRIBS; i++) {
2665 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2666 continue;
2668 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2669 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2670 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2671 stateblock->wineD3DDevice->instancedDraw = TRUE;
2672 continue;
2675 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2677 if(strided->u.input[i].dwStride) {
2678 if(curVBO != strided->u.input[i].VBO) {
2679 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2680 checkGLcall("glBindBufferARB");
2681 curVBO = strided->u.input[i].VBO;
2683 GL_EXTCALL(glVertexAttribPointerARB(i,
2684 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2685 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2686 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2687 strided->u.input[i].dwStride,
2688 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2689 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2690 } else {
2691 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2692 * set up the attribute statically. But we have to figure out the system memory address.
2694 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2695 if(strided->u.input[i].VBO) {
2696 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2697 ptr += (long) vb->resource.allocatedMemory;
2699 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2701 switch(strided->u.input[i].dwType) {
2702 case WINED3DDECLTYPE_FLOAT1:
2703 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2704 break;
2705 case WINED3DDECLTYPE_FLOAT2:
2706 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2707 break;
2708 case WINED3DDECLTYPE_FLOAT3:
2709 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2710 break;
2711 case WINED3DDECLTYPE_FLOAT4:
2712 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2713 break;
2715 case WINED3DDECLTYPE_UBYTE4:
2716 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2717 break;
2718 case WINED3DDECLTYPE_UBYTE4N:
2719 case WINED3DDECLTYPE_D3DCOLOR:
2720 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2721 break;
2723 case WINED3DDECLTYPE_SHORT2:
2724 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2725 break;
2726 case WINED3DDECLTYPE_SHORT4:
2727 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2728 break;
2730 case WINED3DDECLTYPE_SHORT2N:
2732 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2733 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2734 break;
2736 case WINED3DDECLTYPE_USHORT2N:
2738 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2739 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2740 break;
2742 case WINED3DDECLTYPE_SHORT4N:
2743 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2744 break;
2745 case WINED3DDECLTYPE_USHORT4N:
2746 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2747 break;
2749 case WINED3DDECLTYPE_UDEC3:
2750 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2751 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2752 break;
2753 case WINED3DDECLTYPE_DEC3N:
2754 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2755 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2756 break;
2758 case WINED3DDECLTYPE_FLOAT16_2:
2759 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2760 * byte float according to the IEEE standard
2762 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2763 break;
2764 case WINED3DDECLTYPE_FLOAT16_4:
2765 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2766 break;
2768 case WINED3DDECLTYPE_UNUSED:
2769 default:
2770 ERR("Unexpected declaration in stride 0 attributes\n");
2771 break;
2778 /* Used from 2 different functions, and too big to justify making it inlined */
2779 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2780 UINT *offset = stateblock->streamOffset;
2781 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2783 TRACE("Using fast vertex array code\n");
2785 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2786 stateblock->wineD3DDevice->instancedDraw = FALSE;
2788 /* Blend Data ---------------------------------------------- */
2789 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2790 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2792 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2793 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2794 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2796 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
2797 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
2799 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
2801 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
2802 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
2803 sd->u.s.blendWeights.dwStride,
2804 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
2806 if(curVBO != sd->u.s.blendWeights.VBO) {
2807 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
2808 checkGLcall("glBindBufferARB");
2809 curVBO = sd->u.s.blendWeights.VBO;
2812 GL_EXTCALL(glWeightPointerARB)(
2813 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2814 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2815 sd->u.s.blendWeights.dwStride,
2816 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2818 checkGLcall("glWeightPointerARB");
2820 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
2821 static BOOL showfixme = TRUE;
2822 if(showfixme){
2823 FIXME("blendMatrixIndices support\n");
2824 showfixme = FALSE;
2827 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2828 /* FIXME("TODO\n");*/
2829 #if 0
2831 GL_EXTCALL(glVertexWeightPointerEXT)(
2832 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2833 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2834 sd->u.s.blendWeights.dwStride,
2835 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
2836 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
2837 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2838 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
2839 #endif
2841 } else {
2842 /* TODO: support blends in drawStridedSlow
2843 * No need to write a FIXME here, this is done after the general vertex decl decoding
2845 WARN("unsupported blending in openGl\n");
2847 } else {
2848 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2849 static const GLbyte one = 1;
2850 GL_EXTCALL(glWeightbvARB(1, &one));
2851 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
2855 #if 0 /* FOG ----------------------------------------------*/
2856 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
2857 /* TODO: fog*/
2858 if (GL_SUPPORT(EXT_FOG_COORD) {
2859 glEnableClientState(GL_FOG_COORDINATE_EXT);
2860 (GL_EXTCALL)(FogCoordPointerEXT)(
2861 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
2862 sd->u.s.fog.dwStride,
2863 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
2864 } else {
2865 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
2866 /* FIXME: fixme once */
2867 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
2869 } else {
2870 if (GL_SUPPRT(EXT_FOR_COORD) {
2871 /* make sure fog is disabled */
2872 glDisableClientState(GL_FOG_COORDINATE_EXT);
2875 #endif
2877 #if 0 /* tangents ----------------------------------------------*/
2878 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
2879 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2880 /* TODO: tangents*/
2881 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2882 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
2883 glEnable(GL_TANGENT_ARRAY_EXT);
2884 (GL_EXTCALL)(TangentPointerEXT)(
2885 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
2886 sd->u.s.tangent.dwStride,
2887 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
2888 } else {
2889 glDisable(GL_TANGENT_ARRAY_EXT);
2891 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2892 glEnable(GL_BINORMAL_ARRAY_EXT);
2893 (GL_EXTCALL)(BinormalPointerEXT)(
2894 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
2895 sd->u.s.binormal.dwStride,
2896 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
2897 } else{
2898 glDisable(GL_BINORMAL_ARRAY_EXT);
2901 } else {
2902 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
2903 /* FIXME: fixme once */
2904 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
2906 } else {
2907 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2908 /* make sure fog is disabled */
2909 glDisable(GL_TANGENT_ARRAY_EXT);
2910 glDisable(GL_BINORMAL_ARRAY_EXT);
2913 #endif
2915 /* Point Size ----------------------------------------------*/
2916 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
2918 /* no such functionality in the fixed function GL pipeline */
2919 TRACE("Cannot change ptSize here in openGl\n");
2920 /* TODO: Implement this function in using shaders if they are available */
2924 /* Vertex Pointers -----------------------------------------*/
2925 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
2926 /* Note dwType == float3 or float4 == 2 or 3 */
2927 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
2928 sd->u.s.position.dwStride,
2929 sd->u.s.position.dwType + 1,
2930 sd->u.s.position.lpData));
2932 if(curVBO != sd->u.s.position.VBO) {
2933 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
2934 checkGLcall("glBindBufferARB");
2935 curVBO = sd->u.s.position.VBO;
2938 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
2939 handling for rhw mode should not impact screen position whereas in GL it does.
2940 This may result in very slightly distored textures in rhw mode, but
2941 a very minimal different. There's always the other option of
2942 fixing the view matrix to prevent w from having any effect
2944 This only applies to user pointer sources, in VBOs the vertices are fixed up
2946 if(sd->u.s.position.VBO == 0) {
2947 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
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]);
2950 } else {
2951 glVertexPointer(
2952 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
2953 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2954 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2956 checkGLcall("glVertexPointer(...)");
2957 glEnableClientState(GL_VERTEX_ARRAY);
2958 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
2961 /* Normals -------------------------------------------------*/
2962 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
2963 /* Note dwType == float3 or float4 == 2 or 3 */
2964 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
2965 sd->u.s.normal.dwStride,
2966 sd->u.s.normal.lpData));
2967 if(curVBO != sd->u.s.normal.VBO) {
2968 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
2969 checkGLcall("glBindBufferARB");
2970 curVBO = sd->u.s.normal.VBO;
2972 glNormalPointer(
2973 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
2974 sd->u.s.normal.dwStride,
2975 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
2976 checkGLcall("glNormalPointer(...)");
2977 glEnableClientState(GL_NORMAL_ARRAY);
2978 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
2980 } else {
2981 glNormal3f(0, 0, 1);
2982 checkGLcall("glNormal3f(0, 0, 1)");
2985 /* Diffuse Colour --------------------------------------------*/
2986 /* WARNING: Data here MUST be in RGBA format, so cannot */
2987 /* go directly into fast mode from app pgm, because */
2988 /* directx requires data in BGRA format. */
2989 /* currently fixupVertices swizels the format, but this isn't */
2990 /* very practical when using VBOS */
2991 /* NOTE: Unless we write a vertex shader to swizel the colour */
2992 /* , or the user doesn't care and wants the speed advantage */
2994 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
2995 /* Note dwType == float3 or float4 == 2 or 3 */
2996 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
2997 sd->u.s.diffuse.dwStride,
2998 sd->u.s.diffuse.lpData));
3000 if(curVBO != sd->u.s.diffuse.VBO) {
3001 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3002 checkGLcall("glBindBufferARB");
3003 curVBO = sd->u.s.diffuse.VBO;
3005 glColorPointer(4, GL_UNSIGNED_BYTE,
3006 sd->u.s.diffuse.dwStride,
3007 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3008 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3009 glEnableClientState(GL_COLOR_ARRAY);
3010 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3012 } else {
3013 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3014 checkGLcall("glColor4f(1, 1, 1, 1)");
3017 /* Specular Colour ------------------------------------------*/
3018 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3019 TRACE("setting specular colour\n");
3020 /* Note dwType == float3 or float4 == 2 or 3 */
3021 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3022 sd->u.s.specular.dwStride,
3023 sd->u.s.specular.lpData));
3024 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3025 if(curVBO != sd->u.s.specular.VBO) {
3026 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3027 checkGLcall("glBindBufferARB");
3028 curVBO = sd->u.s.specular.VBO;
3030 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3031 sd->u.s.specular.dwStride,
3032 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3033 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3034 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3035 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3036 } else {
3038 /* Missing specular color is not critical, no warnings */
3039 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3042 } else {
3043 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3044 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3045 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3046 } else {
3048 /* Missing specular color is not critical, no warnings */
3049 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3053 /* Texture coords -------------------------------------------*/
3054 loadTexCoords(stateblock, sd, &curVBO);
3057 static inline void drawPrimitiveTraceDataLocations(
3058 WineDirect3DVertexStridedData *dataLocations) {
3060 /* Dump out what parts we have supplied */
3061 TRACE("Strided Data:\n");
3062 TRACE_STRIDED((dataLocations), position);
3063 TRACE_STRIDED((dataLocations), blendWeights);
3064 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3065 TRACE_STRIDED((dataLocations), normal);
3066 TRACE_STRIDED((dataLocations), pSize);
3067 TRACE_STRIDED((dataLocations), diffuse);
3068 TRACE_STRIDED((dataLocations), specular);
3069 TRACE_STRIDED((dataLocations), texCoords[0]);
3070 TRACE_STRIDED((dataLocations), texCoords[1]);
3071 TRACE_STRIDED((dataLocations), texCoords[2]);
3072 TRACE_STRIDED((dataLocations), texCoords[3]);
3073 TRACE_STRIDED((dataLocations), texCoords[4]);
3074 TRACE_STRIDED((dataLocations), texCoords[5]);
3075 TRACE_STRIDED((dataLocations), texCoords[6]);
3076 TRACE_STRIDED((dataLocations), texCoords[7]);
3077 TRACE_STRIDED((dataLocations), position2);
3078 TRACE_STRIDED((dataLocations), normal2);
3079 TRACE_STRIDED((dataLocations), tangent);
3080 TRACE_STRIDED((dataLocations), binormal);
3081 TRACE_STRIDED((dataLocations), tessFactor);
3082 TRACE_STRIDED((dataLocations), fog);
3083 TRACE_STRIDED((dataLocations), depth);
3084 TRACE_STRIDED((dataLocations), sample);
3086 return;
3089 /* Helper for vertexdeclaration() */
3090 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3091 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3092 BOOL fixup = FALSE;
3093 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3095 if(device->up_strided) {
3096 /* Note: this is a ddraw fixed-function code path */
3097 TRACE("================ Strided Input ===================\n");
3098 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3100 if(TRACE_ON(d3d)) {
3101 drawPrimitiveTraceDataLocations(dataLocations);
3103 } else {
3104 /* Note: This is a fixed function or shader codepath.
3105 * This means it must handle both types of strided data.
3106 * Shaders must go through here to zero the strided data, even if they
3107 * don't set any declaration at all
3109 TRACE("================ Vertex Declaration ===================\n");
3110 memset(dataLocations, 0, sizeof(*dataLocations));
3111 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3112 useVertexShaderFunction, dataLocations, &fixup);
3115 if (dataLocations->u.s.position_transformed) {
3116 useVertexShaderFunction = FALSE;
3119 /* Unload the old arrays before loading the new ones to get old junk out */
3120 if(context->numberedArraysLoaded) {
3121 unloadNumberedArrays(stateblock);
3122 context->numberedArraysLoaded = FALSE;
3124 if(context->namedArraysLoaded) {
3125 unloadVertexData(stateblock);
3126 context->namedArraysLoaded = FALSE;
3129 if(useVertexShaderFunction) {
3130 TRACE("Loading numbered arrays\n");
3131 loadNumberedArrays(stateblock, dataLocations);
3132 device->useDrawStridedSlow = FALSE;
3133 context->numberedArraysLoaded = TRUE;
3134 } else if (fixup ||
3135 (dataLocations->u.s.pSize.lpData == NULL &&
3136 dataLocations->u.s.diffuse.lpData == NULL &&
3137 dataLocations->u.s.specular.lpData == NULL)) {
3138 /* Load the vertex data using named arrays */
3139 TRACE("Loading vertex data\n");
3140 loadVertexData(stateblock, dataLocations);
3141 device->useDrawStridedSlow = FALSE;
3142 context->namedArraysLoaded = TRUE;
3143 } else {
3144 TRACE("Not loading vertex data\n");
3145 device->useDrawStridedSlow = TRUE;
3148 /* Generate some fixme's if unsupported functionality is being used */
3149 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3150 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3151 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3152 FIXME("Tweening is only valid with vertex shaders\n");
3154 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3155 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3157 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3158 FIXME("Extended attributes are only valid with vertex shaders\n");
3160 #undef BUFFER_OR_DATA
3163 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3164 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3165 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3166 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3167 BOOL transformed;
3168 /* Some stuff is in the device until we have per context tracking */
3169 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3170 BOOL wasrhw = context->last_was_rhw;
3172 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3173 * here simply check whether a shader was set, or the user disabled shaders
3175 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3176 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3177 useVertexShaderFunction = TRUE;
3179 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3180 updateFog = TRUE;
3182 } else if(context->last_was_foggy_shader) {
3183 updateFog = TRUE;
3186 handleStreams(stateblock, useVertexShaderFunction, context);
3188 transformed = device->strided_streams.u.s.position_transformed;
3189 if (transformed) useVertexShaderFunction = FALSE;
3191 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3192 updateFog = TRUE;
3195 /* Reapply lighting if it is not scheduled for reapplication already */
3196 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3197 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3200 if (transformed) {
3201 context->last_was_rhw = TRUE;
3202 } else {
3204 /* Untransformed, so relies on the view and projection matrices */
3205 context->last_was_rhw = FALSE;
3206 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3207 device->untransformed = TRUE;
3209 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3210 * Not needed as long as only hw shaders are supported
3213 /* This sets the shader output position correction constants.
3214 * TODO: Move to the viewport state
3216 if (useVertexShaderFunction) {
3217 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3221 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3222 * off this function will be called again anyway to make sure they're properly set
3224 if(!useVertexShaderFunction) {
3225 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3226 * or transformed / untransformed was switched
3228 if(wasrhw != context->last_was_rhw &&
3229 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3230 !isStateDirty(context, STATE_VIEWPORT)) {
3231 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3233 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3234 * mode.
3236 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3237 * this check will fail and the matrix not applied again. This is OK because a simple
3238 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3239 * needs of the vertex declaration.
3241 * World and view matrix go into the same gl matrix, so only apply them when neither is
3242 * dirty
3244 if(transformed != wasrhw &&
3245 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3246 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3247 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3250 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3251 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3254 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3255 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3257 } else {
3258 /* We compile the shader here because we need the vertex declaration
3259 * in order to determine if we need to do any swizzling for D3DCOLOR
3260 * registers. If the shader is already compiled this call will do nothing. */
3261 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3263 if(!context->last_was_vshader) {
3264 int i;
3265 static BOOL warned = FALSE;
3266 /* Disable all clip planes to get defined results on all drivers. See comment in the
3267 * state_clipping state handler
3269 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3270 glDisable(GL_CLIP_PLANE0 + i);
3271 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3274 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3275 FIXME("Clipping not supported with vertex shaders\n");
3276 warned = TRUE;
3281 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3282 * application
3284 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3285 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3287 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3288 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3292 context->last_was_vshader = useVertexShaderFunction;
3294 if(updateFog) {
3295 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3299 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3300 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3301 checkGLcall("glDepthRange");
3302 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3304 if(stateblock->wineD3DDevice->render_offscreen) {
3305 glViewport(stateblock->viewport.X,
3306 stateblock->viewport.Y,
3307 stateblock->viewport.Width, stateblock->viewport.Height);
3308 } else {
3309 glViewport(stateblock->viewport.X,
3310 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3311 stateblock->viewport.Width, stateblock->viewport.Height);
3314 checkGLcall("glViewport");
3316 stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
3317 stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
3318 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3319 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3324 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3325 UINT Index = state - STATE_ACTIVELIGHT(0);
3326 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3328 if(!lightInfo) {
3329 glDisable(GL_LIGHT0 + Index);
3330 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3331 } else {
3332 float quad_att;
3333 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3335 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3336 glMatrixMode(GL_MODELVIEW);
3337 glPushMatrix();
3338 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3340 /* Diffuse: */
3341 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3342 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3343 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3344 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3345 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3346 checkGLcall("glLightfv");
3348 /* Specular */
3349 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3350 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3351 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3352 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3353 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3354 checkGLcall("glLightfv");
3356 /* Ambient */
3357 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3358 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3359 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3360 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3361 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3362 checkGLcall("glLightfv");
3364 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3365 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3366 } else {
3367 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3370 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3371 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3372 * Attenuation0 to NaN and crashes in the gl lib
3375 switch (lightInfo->OriginalParms.Type) {
3376 case WINED3DLIGHT_POINT:
3377 /* Position */
3378 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3379 checkGLcall("glLightfv");
3380 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3381 checkGLcall("glLightf");
3382 /* Attenuation - Are these right? guessing... */
3383 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3384 checkGLcall("glLightf");
3385 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3386 checkGLcall("glLightf");
3387 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3388 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3389 checkGLcall("glLightf");
3390 /* FIXME: Range */
3391 break;
3393 case WINED3DLIGHT_SPOT:
3394 /* Position */
3395 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3396 checkGLcall("glLightfv");
3397 /* Direction */
3398 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3399 checkGLcall("glLightfv");
3400 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3401 checkGLcall("glLightf");
3402 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3403 checkGLcall("glLightf");
3404 /* Attenuation - Are these right? guessing... */
3405 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3406 checkGLcall("glLightf");
3407 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3408 checkGLcall("glLightf");
3409 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3410 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3411 checkGLcall("glLightf");
3412 /* FIXME: Range */
3413 break;
3415 case WINED3DLIGHT_DIRECTIONAL:
3416 /* Direction */
3417 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3418 checkGLcall("glLightfv");
3419 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3420 checkGLcall("glLightf");
3421 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3422 checkGLcall("glLightf");
3423 break;
3425 default:
3426 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3429 /* Restore the modelview matrix */
3430 glPopMatrix();
3432 glEnable(GL_LIGHT0 + Index);
3433 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3436 return;
3439 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3440 IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) stateblock->wineD3DDevice->swapchains[0];
3441 RECT *pRect = &stateblock->scissorRect;
3442 RECT windowRect;
3443 UINT winHeight;
3445 GetClientRect(swapchain->win_handle, &windowRect);
3446 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3447 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3449 winHeight = windowRect.bottom - windowRect.top;
3450 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3451 pRect->right - pRect->left, pRect->bottom - pRect->top);
3452 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3453 checkGLcall("glScissor");
3456 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3457 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3458 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3459 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3460 } else {
3461 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3462 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3467 const struct StateEntry StateTable[] =
3469 /* State name representative, apply function */
3470 { /* 0, Undefined */ 0, state_undefined },
3471 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3472 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3473 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3474 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3475 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3476 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3477 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3478 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3479 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3480 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3481 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3482 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3483 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3484 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3485 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3486 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3487 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3488 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3489 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3490 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3491 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3492 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3493 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3494 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3495 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3496 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3497 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3498 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3499 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3500 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3501 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3502 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3503 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3504 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3505 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3506 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3507 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3508 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3509 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3510 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3511 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3512 { /* 42, undefined */ 0, state_undefined },
3513 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3514 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3515 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3516 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3517 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3518 { /* 48, WINED3DRS_RANGEFOGENABLE */ 0, state_nogl },
3519 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3520 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3521 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3522 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3523 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3524 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3525 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3526 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3527 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3528 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3529 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3530 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3531 { /* 61, Undefined */ 0, state_undefined },
3532 { /* 62, Undefined */ 0, state_undefined },
3533 { /* 63, Undefined */ 0, state_undefined },
3534 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3535 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3536 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3537 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3538 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3539 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3540 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3541 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3542 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3543 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3544 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3545 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3546 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3547 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3548 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3549 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3550 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3551 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3552 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3553 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3554 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3555 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3556 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3557 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3558 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3559 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3560 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3561 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3562 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3563 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3564 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3565 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3566 { /* 96, Undefined */ 0, state_undefined },
3567 { /* 97, Undefined */ 0, state_undefined },
3568 { /* 98, Undefined */ 0, state_undefined },
3569 { /* 99, Undefined */ 0, state_undefined },
3570 { /*100, Undefined */ 0, state_undefined },
3571 { /*101, Undefined */ 0, state_undefined },
3572 { /*102, Undefined */ 0, state_undefined },
3573 { /*103, Undefined */ 0, state_undefined },
3574 { /*104, Undefined */ 0, state_undefined },
3575 { /*105, Undefined */ 0, state_undefined },
3576 { /*106, Undefined */ 0, state_undefined },
3577 { /*107, Undefined */ 0, state_undefined },
3578 { /*108, Undefined */ 0, state_undefined },
3579 { /*109, Undefined */ 0, state_undefined },
3580 { /*110, Undefined */ 0, state_undefined },
3581 { /*111, Undefined */ 0, state_undefined },
3582 { /*112, Undefined */ 0, state_undefined },
3583 { /*113, Undefined */ 0, state_undefined },
3584 { /*114, Undefined */ 0, state_undefined },
3585 { /*115, Undefined */ 0, state_undefined },
3586 { /*116, Undefined */ 0, state_undefined },
3587 { /*117, Undefined */ 0, state_undefined },
3588 { /*118, Undefined */ 0, state_undefined },
3589 { /*119, Undefined */ 0, state_undefined },
3590 { /*120, Undefined */ 0, state_undefined },
3591 { /*121, Undefined */ 0, state_undefined },
3592 { /*122, Undefined */ 0, state_undefined },
3593 { /*123, Undefined */ 0, state_undefined },
3594 { /*124, Undefined */ 0, state_undefined },
3595 { /*125, Undefined */ 0, state_undefined },
3596 { /*126, Undefined */ 0, state_undefined },
3597 { /*127, Undefined */ 0, state_undefined },
3598 /* Big hole ends */
3599 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3600 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3601 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3602 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3603 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3604 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3605 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3606 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3607 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3608 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3609 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3610 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3611 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3612 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3613 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3614 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3615 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3616 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3617 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3618 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3619 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3620 { /*149, Undefined */ 0, state_undefined },
3621 { /*150, Undefined */ 0, state_undefined },
3622 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3623 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3624 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3625 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
3626 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3627 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3628 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3629 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3630 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3631 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3632 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3633 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3634 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3635 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3636 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3637 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3638 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3639 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3640 { /*169, Undefined */ 0, state_undefined },
3641 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3642 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3643 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3644 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3645 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3646 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3647 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3648 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3649 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3650 { /*177, undefined */ 0, state_undefined },
3651 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3652 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3653 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3654 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3655 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3656 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3657 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3658 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3659 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3660 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3661 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3662 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3663 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3664 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3665 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3666 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3667 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite },
3668 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3669 { /*196, undefined */ 0, state_undefined },
3670 { /*197, undefined */ 0, state_undefined },
3671 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3672 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3673 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3674 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3675 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3676 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3677 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3678 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3679 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3680 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3681 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3682 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3683 /* Texture stage states */
3684 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3685 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3686 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3687 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3688 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3689 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3690 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3691 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3692 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3693 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3694 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3695 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3696 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3697 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3698 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3699 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3700 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3701 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3702 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3703 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3704 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3705 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3706 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3707 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3708 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3709 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3710 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3711 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3712 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3713 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3714 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3715 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3717 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3718 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3719 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3720 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3721 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3722 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3723 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3724 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3725 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3726 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3727 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3728 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3729 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3730 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3731 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3732 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3733 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3734 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3735 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3736 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3737 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3738 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3739 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3740 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3741 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3742 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3743 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3744 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3745 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3746 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3747 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3748 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3750 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3751 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3752 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3753 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3754 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3755 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3756 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3757 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3758 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3759 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3760 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3761 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3762 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3763 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3764 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3765 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3766 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3767 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3768 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3769 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3770 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3771 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3772 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3773 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3774 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3775 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3776 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3777 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
3778 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3779 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3780 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3781 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3783 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3784 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3785 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3786 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3787 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3788 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3789 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3790 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3791 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3792 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3793 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3794 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3795 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3796 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3797 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3798 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3799 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3800 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3801 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3802 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3803 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3804 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3805 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3806 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3807 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3808 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3809 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3810 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
3811 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3812 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3813 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3814 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3816 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3817 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3818 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3819 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3820 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3821 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3822 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3823 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3824 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3825 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3826 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3827 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3828 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3829 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3830 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3831 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3832 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3833 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3834 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3835 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3836 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3837 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3838 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3839 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3840 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3841 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3842 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3843 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
3844 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3845 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3846 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3847 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3849 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3850 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3851 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3852 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3853 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3854 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3855 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3856 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3857 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3858 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3859 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3860 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3861 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3862 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3863 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3864 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3865 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3866 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3867 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3868 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3869 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3870 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3871 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3872 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3873 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3874 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3875 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3876 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
3877 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3878 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3879 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3880 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3882 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3883 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3884 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3885 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3886 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3887 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3888 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3889 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3890 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3891 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3892 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3893 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3894 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3895 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3896 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3897 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3898 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3899 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3900 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3901 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3902 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3903 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3904 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3905 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3906 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3907 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3908 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3909 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
3910 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3911 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3912 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3913 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3915 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3916 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3917 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3918 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3919 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3920 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3921 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3922 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3923 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3924 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3925 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3926 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3927 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3928 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3929 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3930 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3931 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3932 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3933 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3934 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3935 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3936 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3937 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3938 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3939 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3940 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3941 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3942 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
3943 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3944 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3945 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3946 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3947 /* Sampler states */
3948 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
3949 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
3950 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
3951 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
3952 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
3953 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
3954 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
3955 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
3956 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
3957 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
3958 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
3959 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
3960 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
3961 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
3962 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
3963 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
3964 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
3965 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
3966 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
3967 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
3968 /* Pixel shader */
3969 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
3970 /* Transform states follow */
3971 { /* 1, undefined */ 0, state_undefined },
3972 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
3973 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
3974 { /* 4, undefined */ 0, state_undefined },
3975 { /* 5, undefined */ 0, state_undefined },
3976 { /* 6, undefined */ 0, state_undefined },
3977 { /* 7, undefined */ 0, state_undefined },
3978 { /* 8, undefined */ 0, state_undefined },
3979 { /* 9, undefined */ 0, state_undefined },
3980 { /* 10, undefined */ 0, state_undefined },
3981 { /* 11, undefined */ 0, state_undefined },
3982 { /* 12, undefined */ 0, state_undefined },
3983 { /* 13, undefined */ 0, state_undefined },
3984 { /* 14, undefined */ 0, state_undefined },
3985 { /* 15, undefined */ 0, state_undefined },
3986 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3987 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3988 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3989 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3990 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3991 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3992 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3993 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3994 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
3995 { /* 24, undefined */ 0, state_undefined },
3996 { /* 25, undefined */ 0, state_undefined },
3997 { /* 26, undefined */ 0, state_undefined },
3998 { /* 27, undefined */ 0, state_undefined },
3999 { /* 28, undefined */ 0, state_undefined },
4000 { /* 29, undefined */ 0, state_undefined },
4001 { /* 30, undefined */ 0, state_undefined },
4002 { /* 31, undefined */ 0, state_undefined },
4003 { /* 32, undefined */ 0, state_undefined },
4004 { /* 33, undefined */ 0, state_undefined },
4005 { /* 34, undefined */ 0, state_undefined },
4006 { /* 35, undefined */ 0, state_undefined },
4007 { /* 36, undefined */ 0, state_undefined },
4008 { /* 37, undefined */ 0, state_undefined },
4009 { /* 38, undefined */ 0, state_undefined },
4010 { /* 39, undefined */ 0, state_undefined },
4011 { /* 40, undefined */ 0, state_undefined },
4012 { /* 41, undefined */ 0, state_undefined },
4013 { /* 42, undefined */ 0, state_undefined },
4014 { /* 43, undefined */ 0, state_undefined },
4015 { /* 44, undefined */ 0, state_undefined },
4016 { /* 45, undefined */ 0, state_undefined },
4017 { /* 46, undefined */ 0, state_undefined },
4018 { /* 47, undefined */ 0, state_undefined },
4019 { /* 48, undefined */ 0, state_undefined },
4020 { /* 49, undefined */ 0, state_undefined },
4021 { /* 50, undefined */ 0, state_undefined },
4022 { /* 51, undefined */ 0, state_undefined },
4023 { /* 52, undefined */ 0, state_undefined },
4024 { /* 53, undefined */ 0, state_undefined },
4025 { /* 54, undefined */ 0, state_undefined },
4026 { /* 55, undefined */ 0, state_undefined },
4027 { /* 56, undefined */ 0, state_undefined },
4028 { /* 57, undefined */ 0, state_undefined },
4029 { /* 58, undefined */ 0, state_undefined },
4030 { /* 59, undefined */ 0, state_undefined },
4031 { /* 60, undefined */ 0, state_undefined },
4032 { /* 61, undefined */ 0, state_undefined },
4033 { /* 62, undefined */ 0, state_undefined },
4034 { /* 63, undefined */ 0, state_undefined },
4035 { /* 64, undefined */ 0, state_undefined },
4036 { /* 65, undefined */ 0, state_undefined },
4037 { /* 66, undefined */ 0, state_undefined },
4038 { /* 67, undefined */ 0, state_undefined },
4039 { /* 68, undefined */ 0, state_undefined },
4040 { /* 69, undefined */ 0, state_undefined },
4041 { /* 70, undefined */ 0, state_undefined },
4042 { /* 71, undefined */ 0, state_undefined },
4043 { /* 72, undefined */ 0, state_undefined },
4044 { /* 73, undefined */ 0, state_undefined },
4045 { /* 74, undefined */ 0, state_undefined },
4046 { /* 75, undefined */ 0, state_undefined },
4047 { /* 76, undefined */ 0, state_undefined },
4048 { /* 77, undefined */ 0, state_undefined },
4049 { /* 78, undefined */ 0, state_undefined },
4050 { /* 79, undefined */ 0, state_undefined },
4051 { /* 80, undefined */ 0, state_undefined },
4052 { /* 81, undefined */ 0, state_undefined },
4053 { /* 82, undefined */ 0, state_undefined },
4054 { /* 83, undefined */ 0, state_undefined },
4055 { /* 84, undefined */ 0, state_undefined },
4056 { /* 85, undefined */ 0, state_undefined },
4057 { /* 86, undefined */ 0, state_undefined },
4058 { /* 87, undefined */ 0, state_undefined },
4059 { /* 88, undefined */ 0, state_undefined },
4060 { /* 89, undefined */ 0, state_undefined },
4061 { /* 90, undefined */ 0, state_undefined },
4062 { /* 91, undefined */ 0, state_undefined },
4063 { /* 92, undefined */ 0, state_undefined },
4064 { /* 93, undefined */ 0, state_undefined },
4065 { /* 94, undefined */ 0, state_undefined },
4066 { /* 95, undefined */ 0, state_undefined },
4067 { /* 96, undefined */ 0, state_undefined },
4068 { /* 97, undefined */ 0, state_undefined },
4069 { /* 98, undefined */ 0, state_undefined },
4070 { /* 99, undefined */ 0, state_undefined },
4071 { /*100, undefined */ 0, state_undefined },
4072 { /*101, undefined */ 0, state_undefined },
4073 { /*102, undefined */ 0, state_undefined },
4074 { /*103, undefined */ 0, state_undefined },
4075 { /*104, undefined */ 0, state_undefined },
4076 { /*105, undefined */ 0, state_undefined },
4077 { /*106, undefined */ 0, state_undefined },
4078 { /*107, undefined */ 0, state_undefined },
4079 { /*108, undefined */ 0, state_undefined },
4080 { /*109, undefined */ 0, state_undefined },
4081 { /*110, undefined */ 0, state_undefined },
4082 { /*111, undefined */ 0, state_undefined },
4083 { /*112, undefined */ 0, state_undefined },
4084 { /*113, undefined */ 0, state_undefined },
4085 { /*114, undefined */ 0, state_undefined },
4086 { /*115, undefined */ 0, state_undefined },
4087 { /*116, undefined */ 0, state_undefined },
4088 { /*117, undefined */ 0, state_undefined },
4089 { /*118, undefined */ 0, state_undefined },
4090 { /*119, undefined */ 0, state_undefined },
4091 { /*120, undefined */ 0, state_undefined },
4092 { /*121, undefined */ 0, state_undefined },
4093 { /*122, undefined */ 0, state_undefined },
4094 { /*123, undefined */ 0, state_undefined },
4095 { /*124, undefined */ 0, state_undefined },
4096 { /*125, undefined */ 0, state_undefined },
4097 { /*126, undefined */ 0, state_undefined },
4098 { /*127, undefined */ 0, state_undefined },
4099 { /*128, undefined */ 0, state_undefined },
4100 { /*129, undefined */ 0, state_undefined },
4101 { /*130, undefined */ 0, state_undefined },
4102 { /*131, undefined */ 0, state_undefined },
4103 { /*132, undefined */ 0, state_undefined },
4104 { /*133, undefined */ 0, state_undefined },
4105 { /*134, undefined */ 0, state_undefined },
4106 { /*135, undefined */ 0, state_undefined },
4107 { /*136, undefined */ 0, state_undefined },
4108 { /*137, undefined */ 0, state_undefined },
4109 { /*138, undefined */ 0, state_undefined },
4110 { /*139, undefined */ 0, state_undefined },
4111 { /*140, undefined */ 0, state_undefined },
4112 { /*141, undefined */ 0, state_undefined },
4113 { /*142, undefined */ 0, state_undefined },
4114 { /*143, undefined */ 0, state_undefined },
4115 { /*144, undefined */ 0, state_undefined },
4116 { /*145, undefined */ 0, state_undefined },
4117 { /*146, undefined */ 0, state_undefined },
4118 { /*147, undefined */ 0, state_undefined },
4119 { /*148, undefined */ 0, state_undefined },
4120 { /*149, undefined */ 0, state_undefined },
4121 { /*150, undefined */ 0, state_undefined },
4122 { /*151, undefined */ 0, state_undefined },
4123 { /*152, undefined */ 0, state_undefined },
4124 { /*153, undefined */ 0, state_undefined },
4125 { /*154, undefined */ 0, state_undefined },
4126 { /*155, undefined */ 0, state_undefined },
4127 { /*156, undefined */ 0, state_undefined },
4128 { /*157, undefined */ 0, state_undefined },
4129 { /*158, undefined */ 0, state_undefined },
4130 { /*159, undefined */ 0, state_undefined },
4131 { /*160, undefined */ 0, state_undefined },
4132 { /*161, undefined */ 0, state_undefined },
4133 { /*162, undefined */ 0, state_undefined },
4134 { /*163, undefined */ 0, state_undefined },
4135 { /*164, undefined */ 0, state_undefined },
4136 { /*165, undefined */ 0, state_undefined },
4137 { /*166, undefined */ 0, state_undefined },
4138 { /*167, undefined */ 0, state_undefined },
4139 { /*168, undefined */ 0, state_undefined },
4140 { /*169, undefined */ 0, state_undefined },
4141 { /*170, undefined */ 0, state_undefined },
4142 { /*171, undefined */ 0, state_undefined },
4143 { /*172, undefined */ 0, state_undefined },
4144 { /*173, undefined */ 0, state_undefined },
4145 { /*174, undefined */ 0, state_undefined },
4146 { /*175, undefined */ 0, state_undefined },
4147 { /*176, undefined */ 0, state_undefined },
4148 { /*177, undefined */ 0, state_undefined },
4149 { /*178, undefined */ 0, state_undefined },
4150 { /*179, undefined */ 0, state_undefined },
4151 { /*180, undefined */ 0, state_undefined },
4152 { /*181, undefined */ 0, state_undefined },
4153 { /*182, undefined */ 0, state_undefined },
4154 { /*183, undefined */ 0, state_undefined },
4155 { /*184, undefined */ 0, state_undefined },
4156 { /*185, undefined */ 0, state_undefined },
4157 { /*186, undefined */ 0, state_undefined },
4158 { /*187, undefined */ 0, state_undefined },
4159 { /*188, undefined */ 0, state_undefined },
4160 { /*189, undefined */ 0, state_undefined },
4161 { /*190, undefined */ 0, state_undefined },
4162 { /*191, undefined */ 0, state_undefined },
4163 { /*192, undefined */ 0, state_undefined },
4164 { /*193, undefined */ 0, state_undefined },
4165 { /*194, undefined */ 0, state_undefined },
4166 { /*195, undefined */ 0, state_undefined },
4167 { /*196, undefined */ 0, state_undefined },
4168 { /*197, undefined */ 0, state_undefined },
4169 { /*198, undefined */ 0, state_undefined },
4170 { /*199, undefined */ 0, state_undefined },
4171 { /*200, undefined */ 0, state_undefined },
4172 { /*201, undefined */ 0, state_undefined },
4173 { /*202, undefined */ 0, state_undefined },
4174 { /*203, undefined */ 0, state_undefined },
4175 { /*204, undefined */ 0, state_undefined },
4176 { /*205, undefined */ 0, state_undefined },
4177 { /*206, undefined */ 0, state_undefined },
4178 { /*207, undefined */ 0, state_undefined },
4179 { /*208, undefined */ 0, state_undefined },
4180 { /*209, undefined */ 0, state_undefined },
4181 { /*210, undefined */ 0, state_undefined },
4182 { /*211, undefined */ 0, state_undefined },
4183 { /*212, undefined */ 0, state_undefined },
4184 { /*213, undefined */ 0, state_undefined },
4185 { /*214, undefined */ 0, state_undefined },
4186 { /*215, undefined */ 0, state_undefined },
4187 { /*216, undefined */ 0, state_undefined },
4188 { /*217, undefined */ 0, state_undefined },
4189 { /*218, undefined */ 0, state_undefined },
4190 { /*219, undefined */ 0, state_undefined },
4191 { /*220, undefined */ 0, state_undefined },
4192 { /*221, undefined */ 0, state_undefined },
4193 { /*222, undefined */ 0, state_undefined },
4194 { /*223, undefined */ 0, state_undefined },
4195 { /*224, undefined */ 0, state_undefined },
4196 { /*225, undefined */ 0, state_undefined },
4197 { /*226, undefined */ 0, state_undefined },
4198 { /*227, undefined */ 0, state_undefined },
4199 { /*228, undefined */ 0, state_undefined },
4200 { /*229, undefined */ 0, state_undefined },
4201 { /*230, undefined */ 0, state_undefined },
4202 { /*231, undefined */ 0, state_undefined },
4203 { /*232, undefined */ 0, state_undefined },
4204 { /*233, undefined */ 0, state_undefined },
4205 { /*234, undefined */ 0, state_undefined },
4206 { /*235, undefined */ 0, state_undefined },
4207 { /*236, undefined */ 0, state_undefined },
4208 { /*237, undefined */ 0, state_undefined },
4209 { /*238, undefined */ 0, state_undefined },
4210 { /*239, undefined */ 0, state_undefined },
4211 { /*240, undefined */ 0, state_undefined },
4212 { /*241, undefined */ 0, state_undefined },
4213 { /*242, undefined */ 0, state_undefined },
4214 { /*243, undefined */ 0, state_undefined },
4215 { /*244, undefined */ 0, state_undefined },
4216 { /*245, undefined */ 0, state_undefined },
4217 { /*246, undefined */ 0, state_undefined },
4218 { /*247, undefined */ 0, state_undefined },
4219 { /*248, undefined */ 0, state_undefined },
4220 { /*249, undefined */ 0, state_undefined },
4221 { /*250, undefined */ 0, state_undefined },
4222 { /*251, undefined */ 0, state_undefined },
4223 { /*252, undefined */ 0, state_undefined },
4224 { /*253, undefined */ 0, state_undefined },
4225 { /*254, undefined */ 0, state_undefined },
4226 { /*255, undefined */ 0, state_undefined },
4227 /* End huge gap */
4228 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4229 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4230 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4231 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4232 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4233 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4234 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4235 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4236 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4237 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4238 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4239 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4240 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4241 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4242 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4243 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4244 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4245 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4246 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4247 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4248 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4249 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4250 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4251 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4252 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4253 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4254 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4255 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4256 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4257 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4258 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4259 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4260 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4261 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4262 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4263 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4264 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4265 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4266 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4267 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4268 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4269 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4270 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4271 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4272 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4273 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4274 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4275 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4276 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4277 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4278 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4279 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4280 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4281 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4282 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4283 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4284 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4285 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4286 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4287 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4288 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4289 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4290 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4291 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4292 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4293 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4294 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4295 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4296 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4297 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4298 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4299 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4300 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4301 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4302 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4303 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4304 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4305 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4306 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4307 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4308 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4309 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4310 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4311 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4312 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4313 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4314 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4315 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4316 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4317 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4318 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4319 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4320 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4321 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4322 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4323 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4324 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4325 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4326 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4327 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4328 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4329 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4330 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4331 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4332 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4333 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4334 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4335 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4336 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4337 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4338 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4339 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4340 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4341 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4342 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4343 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4344 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4345 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4346 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4347 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4348 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4349 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4350 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4351 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4352 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4353 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4354 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4355 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4356 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4357 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4358 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4359 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4360 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4361 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4362 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4363 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4364 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4365 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4366 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4367 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4368 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4369 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4370 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4371 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4372 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4373 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4374 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4375 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4376 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4377 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4378 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4379 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4380 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4381 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4382 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4383 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4384 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4385 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4386 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4387 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4388 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4389 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4390 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4391 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4392 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4393 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4394 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4395 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4396 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4397 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4398 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4399 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4400 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4401 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4402 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4403 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4404 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4405 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4406 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4407 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4408 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4409 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4410 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4411 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4412 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4413 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4414 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4415 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4416 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4417 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4418 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4419 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4420 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4421 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4422 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4423 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4424 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4425 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4426 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4427 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4428 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4429 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4430 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4431 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4432 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4433 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4434 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4435 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4436 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4437 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4438 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4439 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4440 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4441 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4442 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4443 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4444 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4445 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4446 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4447 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4448 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4449 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4450 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4451 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4452 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4453 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4454 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4455 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4456 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4457 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4458 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4459 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4460 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4461 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4462 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4463 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4464 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4465 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4466 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4467 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4468 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4469 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4470 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4471 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4472 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4473 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4474 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4475 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4476 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4477 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4478 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4479 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4480 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4481 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4482 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4483 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4484 /* Various Vertex states follow */
4485 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4486 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4487 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4488 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4489 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4490 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4491 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4492 /* Lights */
4493 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4494 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4495 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4496 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4497 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4498 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4499 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4500 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4502 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4503 /* Clip planes */
4504 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4505 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4506 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4507 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4508 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4509 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4510 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4511 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4512 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4513 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4514 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4515 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4516 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4517 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4518 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4519 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4520 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4521 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4522 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4523 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4524 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4525 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4526 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4527 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4528 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4529 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4530 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4531 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4532 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4533 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4534 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4535 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4537 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},