push 599a9d3db769aad8dabfd10a59120f719b00f4ee
[wine/hacks.git] / dlls / wined3d / state.c
blob20a7fa56e3fb552d27937dfddd0b21c16fef2baf
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_DESTBLEND]) {
251 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
252 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
253 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
254 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
255 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
256 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
257 case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
258 case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
259 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
260 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
262 case WINED3DBLEND_SRCALPHASAT :
263 dstBlend = GL_SRC_ALPHA_SATURATE;
264 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
265 break;
267 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
268 * values which are still valid up to d3d9. They should not occur as dest blend values
270 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
271 srcBlend = GL_SRC_ALPHA;
272 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
273 break;
275 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
276 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
277 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
278 break;
280 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
281 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
282 default:
283 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
286 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
287 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
288 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
289 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
290 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
291 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
292 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
293 case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
294 case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
295 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
296 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
297 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
299 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
300 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
301 break;
303 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
304 dstBlend = GL_SRC_ALPHA;
305 break;
307 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
308 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
309 default:
310 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
314 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
315 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
316 glEnable(GL_LINE_SMOOTH);
317 checkGLcall("glEnable(GL_LINE_SMOOTH)");
318 if(srcBlend != GL_SRC_ALPHA) {
319 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
321 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
322 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
324 } else {
325 glDisable(GL_LINE_SMOOTH);
326 checkGLcall("glDisable(GL_LINE_SMOOTH)");
329 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
330 glBlendFunc(srcBlend, dstBlend);
331 checkGLcall("glBlendFunc");
334 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
335 float col[4];
337 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
338 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
339 GL_EXTCALL(glBlendColor (col[0],col[1],col[2],col[3]));
340 checkGLcall("glBlendColor");
343 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
344 int glParm = 0;
345 float ref;
346 BOOL enable_ckey = FALSE;
348 IWineD3DSurfaceImpl *surf;
350 /* Find out if the texture on the first stage has a ckey set
351 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
352 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
353 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
354 * in case it finds some texture+colorkeyenable combination which needs extra care.
356 if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
357 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
359 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
360 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
361 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
362 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
363 * surface has alpha bits
365 if(fmt->alphaMask == 0x00000000) {
366 enable_ckey = TRUE;
371 if(enable_ckey || context->last_was_ckey) {
372 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
374 context->last_was_ckey = enable_ckey;
376 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
377 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
378 glEnable(GL_ALPHA_TEST);
379 checkGLcall("glEnable GL_ALPHA_TEST");
380 } else {
381 glDisable(GL_ALPHA_TEST);
382 checkGLcall("glDisable GL_ALPHA_TEST");
383 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
384 * enable call
386 return;
389 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
390 glParm = GL_NOTEQUAL;
391 ref = 0.0;
392 } else {
393 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
394 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
396 if(glParm) {
397 glAlphaFunc(glParm, ref);
398 checkGLcall("glAlphaFunc");
402 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
403 DWORD enable = 0xFFFFFFFF;
404 DWORD disable = 0x00000000;
406 if (use_vs(stateblock->wineD3DDevice)) {
407 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
408 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
409 * contitions I got sick of tracking down. The shader state handler disables all clip planes because
410 * of that - don't do anything here and keep them disabled
412 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
413 static BOOL warned = FALSE;
414 if(!warned) {
415 FIXME("Clipping not supported with vertex shaders\n");
416 warned = TRUE;
419 return;
422 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
423 * of already set values
426 /* If enabling / disabling all
427 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
429 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
430 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
431 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
432 } else {
433 disable = 0xffffffff;
434 enable = 0x00;
437 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
438 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
439 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
440 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
441 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
442 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
444 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
445 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
446 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
447 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
448 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
449 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
451 /** update clipping status */
452 if (enable) {
453 stateblock->clip_status.ClipUnion = 0;
454 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
455 } else {
456 stateblock->clip_status.ClipUnion = 0;
457 stateblock->clip_status.ClipIntersection = 0;
461 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
462 int glParm = GL_FUNC_ADD;
464 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
465 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
466 return;
469 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
470 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
471 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
472 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
473 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
474 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
475 default:
476 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
479 TRACE("glBlendEquation(%x)\n", glParm);
480 GL_EXTCALL(glBlendEquation(glParm));
481 checkGLcall("glBlendEquation");
484 static void
485 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
486 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
487 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
488 * specular color. This is wrong:
489 * Separate specular color means the specular colour is maintained separately, whereas
490 * single color means it is merged in. However in both cases they are being used to
491 * some extent.
492 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
493 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
494 * running 1.4 yet!
497 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
498 * Instead, we need to setup the FinalCombiner properly.
500 * The default setup for the FinalCombiner is:
502 * <variable> <input> <mapping> <usage>
503 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
504 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
505 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
506 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
507 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
508 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
509 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
511 * That's pretty much fine as it is, except for variable B, which needs to take
512 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
513 * whether WINED3DRS_SPECULARENABLE is enabled or not.
516 TRACE("Setting specular enable state and materials\n");
517 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
518 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
519 checkGLcall("glMaterialfv");
521 if(stateblock->material.Power > 128.0) {
522 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
523 * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
524 * them, since 128 results in a hardly visible specular highlight, so it should be safe to
525 * to clamp to 128
527 WARN("Material power > 128\n");
528 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
529 } else {
530 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
532 checkGLcall("glMaterialf(GL_SHININESS");
534 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
535 glEnable(GL_COLOR_SUM_EXT);
536 } else {
537 TRACE("Specular colors cannot be enabled in this version of opengl\n");
539 checkGLcall("glEnable(GL_COLOR_SUM)");
541 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
542 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
543 checkGLcall("glFinalCombinerInputNV()");
545 } else {
546 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
548 /* for the case of enabled lighting: */
549 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
550 checkGLcall("glMaterialfv");
552 /* for the case of disabled lighting: */
553 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
554 glDisable(GL_COLOR_SUM_EXT);
555 } else {
556 TRACE("Specular colors cannot be disabled in this version of opengl\n");
558 checkGLcall("glDisable(GL_COLOR_SUM)");
560 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
561 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
562 checkGLcall("glFinalCombinerInputNV()");
566 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
567 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
568 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
569 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
570 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
571 stateblock->material.Specular.b, stateblock->material.Specular.a);
572 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
573 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
575 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
576 checkGLcall("glMaterialfv(GL_AMBIENT)");
577 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
578 checkGLcall("glMaterialfv(GL_DIFFUSE)");
579 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
580 checkGLcall("glMaterialfv(GL_EMISSION)");
583 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
584 unsigned int i;
586 /* Note the texture color applies to all textures whereas
587 * GL_TEXTURE_ENV_COLOR applies to active only
589 float col[4];
590 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
592 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
593 /* And now the default texture color as well */
594 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
595 /* Note the WINED3DRS value applies to all textures, but GL has one
596 * per texture, so apply it now ready to be used!
598 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
599 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
600 checkGLcall("glActiveTextureARB");
601 } else if (i>0) {
602 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
605 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
606 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
608 } else {
609 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
613 static void
614 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
615 #if 0 /* Don't use OpenGL 2.0 calls for now */
616 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
617 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
618 checkGLcall("glStencilFuncSeparate(...)");
619 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
620 checkGLcall("glStencilOpSeparate(...)");
622 else
623 #endif
624 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
625 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
626 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
627 GL_EXTCALL(glActiveStencilFaceEXT(face));
628 checkGLcall("glActiveStencilFaceEXT(...)");
629 glStencilFunc(func, ref, mask);
630 checkGLcall("glStencilFunc(...)");
631 glStencilOp(stencilFail, depthFail, stencilPass);
632 checkGLcall("glStencilOp(...)");
633 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
634 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
635 checkGLcall("glStencilFuncSeparateATI(...)");
636 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
637 checkGLcall("glStencilOpSeparateATI(...)");
638 } else {
639 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
643 static void
644 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
645 DWORD onesided_enable = FALSE;
646 DWORD twosided_enable = FALSE;
647 GLint func = GL_ALWAYS;
648 GLint func_ccw = GL_ALWAYS;
649 GLint ref = 0;
650 GLuint mask = 0;
651 GLint stencilFail = GL_KEEP;
652 GLint depthFail = GL_KEEP;
653 GLint stencilPass = GL_KEEP;
654 GLint stencilFail_ccw = GL_KEEP;
655 GLint depthFail_ccw = GL_KEEP;
656 GLint stencilPass_ccw = GL_KEEP;
658 /* No stencil test without a stencil buffer */
659 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
660 glDisable(GL_STENCIL_TEST);
661 checkGLcall("glDisable GL_STENCIL_TEST");
662 return;
665 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
666 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
667 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
668 func = GL_ALWAYS;
669 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
670 func = GL_ALWAYS;
671 ref = stateblock->renderState[WINED3DRS_STENCILREF];
672 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
673 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
674 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
675 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
676 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
677 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
678 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
680 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
681 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
682 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
683 onesided_enable, twosided_enable, ref, mask,
684 func, stencilFail, depthFail, stencilPass,
685 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
687 if (twosided_enable) {
688 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
689 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
690 } else {
691 if (onesided_enable) {
692 glEnable(GL_STENCIL_TEST);
693 checkGLcall("glEnable GL_STENCIL_TEST");
694 glStencilFunc(func, ref, mask);
695 checkGLcall("glStencilFunc(...)");
696 glStencilOp(stencilFail, depthFail, stencilPass);
697 checkGLcall("glStencilOp(...)");
698 } else {
699 glDisable(GL_STENCIL_TEST);
700 checkGLcall("glDisable GL_STENCIL_TEST");
705 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
706 if(stateblock->wineD3DDevice->stencilBufferTarget) {
707 glStencilMask(stateblock->renderState[WINED3DRS_STENCILWRITEMASK]);
708 } else {
709 glStencilMask(0);
711 checkGLcall("glStencilMask");
714 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
715 /* TODO: Put this into the vertex type block once that is in the state table */
716 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
717 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
718 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
719 float fogstart, fogend;
721 union {
722 DWORD d;
723 float f;
724 } tmpvalue;
726 if (!fogenable) {
727 /* No fog? Disable it, and we're done :-) */
728 glDisable(GL_FOG);
729 checkGLcall("glDisable GL_FOG");
730 if( use_ps(stateblock->wineD3DDevice)
731 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
732 /* disable fog in the pixel shader
733 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
734 * -1/(e-s) and e/(e-s) respectively.
736 glFogf(GL_FOG_START, 0.0f);
737 checkGLcall("glFogf(GL_FOG_START, fogstart");
738 glFogf(GL_FOG_END, 1.0f);
739 checkGLcall("glFogf(GL_FOG_END, fogend");
741 return;
744 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
745 fogstart = tmpvalue.f;
746 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
747 fogend = tmpvalue.f;
749 /* Fog Rules:
751 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
752 * It can use the Z value of the vertex, or the alpha component of the specular color.
753 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
754 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
755 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
757 * FOGTABLEMODE != NONE:
758 * The Z value is used, with the equation specified, no matter what vertex type.
760 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
761 * Per vertex fog is calculated using the specified fog equation and the parameters
763 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
764 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
765 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
768 * Rules for vertex fog with shaders:
770 * When mixing fixed function functionality with the programmable pipeline, D3D expects
771 * the fog computation to happen during transformation while openGL expects it to happen
772 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
773 * the pixel shader while openGL always expects the pixel shader to handle the blending.
774 * To solve this problem, WineD3D does:
775 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
776 * shader,
777 * and 2) disables the fog computation (in either the fixed function or programmable
778 * rasterizer) if using a vertex program.
781 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
782 * without shaders).
785 if( is_ps3 ) {
786 if( !use_vs(stateblock->wineD3DDevice)
787 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
788 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
792 if (use_vs(stateblock->wineD3DDevice)
793 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
794 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
795 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
796 /* Disable fog */
797 fogenable = FALSE;
798 } else {
799 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
800 glFogi(GL_FOG_MODE, GL_LINEAR);
801 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
802 fogstart = 1.0;
803 fogend = 0.0;
806 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
807 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
808 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
809 context->fog_coord = FALSE;
811 context->last_was_foggy_shader = TRUE;
813 else if( use_ps(stateblock->wineD3DDevice) ) {
814 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
815 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
817 WINED3DFOGMODE mode;
818 context->last_was_foggy_shader = FALSE;
820 /* If both fogmodes are set use the table fog mode */
821 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
822 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
823 else
824 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
826 switch (mode) {
827 case WINED3DFOG_EXP:
828 case WINED3DFOG_EXP2:
829 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
830 /* Disable fog */
831 fogenable = FALSE;
832 break;
834 case WINED3DFOG_LINEAR:
835 fogstart = -1.0f/(fogend-fogstart);
836 fogend *= -fogstart;
837 break;
839 case WINED3DFOG_NONE:
840 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
841 /* Disable fog */
842 fogenable = FALSE;
843 break;
844 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
847 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
848 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
849 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
850 context->fog_coord = FALSE;
853 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
854 * the system will apply only pixel(=table) fog effects."
856 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
857 glHint(GL_FOG_HINT, GL_FASTEST);
858 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
859 context->last_was_foggy_shader = FALSE;
861 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
862 /* If processed vertices are used, fall through to the NONE case */
863 case WINED3DFOG_EXP: {
864 if(!context->last_was_rhw) {
865 glFogi(GL_FOG_MODE, GL_EXP);
866 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
867 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
868 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
869 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
870 context->fog_coord = FALSE;
872 break;
875 case WINED3DFOG_EXP2: {
876 if(!context->last_was_rhw) {
877 glFogi(GL_FOG_MODE, GL_EXP2);
878 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
879 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
880 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
881 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
882 context->fog_coord = FALSE;
884 break;
887 case WINED3DFOG_LINEAR: {
888 if(!context->last_was_rhw) {
889 glFogi(GL_FOG_MODE, GL_LINEAR);
890 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
891 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
892 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
893 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
894 context->fog_coord = FALSE;
896 break;
899 case WINED3DFOG_NONE: {
900 /* Both are none? According to msdn the alpha channel of the specular
901 * color contains a fog factor. Set it in drawStridedSlow.
902 * Same happens with Vertexfog on transformed vertices
904 if(GL_SUPPORT(EXT_FOG_COORD)) {
905 if(context->fog_coord == FALSE) {
906 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
907 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
908 context->fog_coord = TRUE;
910 glFogi(GL_FOG_MODE, GL_LINEAR);
911 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
912 fogstart = 0xff;
913 fogend = 0x0;
914 } else {
915 /* Disable GL fog, handle this in software in drawStridedSlow */
916 fogenable = FALSE;
918 break;
920 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
922 } else {
923 glHint(GL_FOG_HINT, GL_NICEST);
924 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
925 context->last_was_foggy_shader = FALSE;
927 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
928 case WINED3DFOG_EXP:
929 glFogi(GL_FOG_MODE, GL_EXP);
930 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
931 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
932 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
933 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
934 context->fog_coord = FALSE;
936 break;
938 case WINED3DFOG_EXP2:
939 glFogi(GL_FOG_MODE, GL_EXP2);
940 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
941 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
942 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
943 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
944 context->fog_coord = FALSE;
946 break;
948 case WINED3DFOG_LINEAR:
949 glFogi(GL_FOG_MODE, GL_LINEAR);
950 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
951 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
952 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
953 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
954 context->fog_coord = FALSE;
956 break;
958 case WINED3DFOG_NONE: /* Won't happen */
959 default:
960 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
964 if(fogenable) {
965 glEnable(GL_FOG);
966 checkGLcall("glEnable GL_FOG");
968 if(fogstart != fogend)
970 glFogfv(GL_FOG_START, &fogstart);
971 checkGLcall("glFogf(GL_FOG_START, fogstart");
972 TRACE("Fog Start == %f\n", fogstart);
974 glFogfv(GL_FOG_END, &fogend);
975 checkGLcall("glFogf(GL_FOG_END, fogend");
976 TRACE("Fog End == %f\n", fogend);
978 else
980 glFogf(GL_FOG_START, -1.0 / 0.0);
981 checkGLcall("glFogf(GL_FOG_START, fogstart");
982 TRACE("Fog Start == %f\n", fogstart);
984 glFogf(GL_FOG_END, 0.0);
985 checkGLcall("glFogf(GL_FOG_END, fogend");
986 TRACE("Fog End == %f\n", fogend);
988 } else {
989 glDisable(GL_FOG);
990 checkGLcall("glDisable GL_FOG");
991 if( use_ps(stateblock->wineD3DDevice) ) {
992 /* disable fog in the pixel shader
993 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
994 * -1/(e-s) and e/(e-s) respectively.
996 glFogf(GL_FOG_START, 0.0f);
997 checkGLcall("glFogf(GL_FOG_START, fogstart");
998 glFogf(GL_FOG_END, 1.0f);
999 checkGLcall("glFogf(GL_FOG_END, fogend");
1004 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1005 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1006 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1007 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1008 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1009 } else {
1010 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1012 } else {
1013 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1014 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1015 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1020 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1021 float col[4];
1022 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1023 glFogfv(GL_FOG_COLOR, &col[0]);
1024 checkGLcall("glFog GL_FOG_COLOR");
1027 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1028 union {
1029 DWORD d;
1030 float f;
1031 } tmpvalue;
1032 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1033 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1034 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1037 /* TODO: Merge with primitive type + init_materials()!! */
1038 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1039 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice;
1040 GLenum Parm = 0;
1041 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1042 BOOL isDiffuseSupplied;
1044 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1045 * The vertex declaration will call this function if the fixed function pipeline is used.
1048 if(isStateDirty(context, STATE_VDECL)) {
1049 return;
1052 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1054 context->num_untracked_materials = 0;
1055 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1056 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1057 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1058 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1059 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1060 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1062 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1063 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1064 Parm = GL_AMBIENT_AND_DIFFUSE;
1065 } else {
1066 Parm = GL_DIFFUSE;
1068 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1069 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1070 context->num_untracked_materials++;
1072 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1073 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1074 context->num_untracked_materials++;
1076 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1077 Parm = GL_AMBIENT;
1078 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1079 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1080 context->num_untracked_materials++;
1082 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1083 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1084 context->num_untracked_materials++;
1086 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1087 Parm = GL_EMISSION;
1088 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1089 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1090 context->num_untracked_materials++;
1092 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1093 Parm = GL_SPECULAR;
1097 /* Nothing changed, return. */
1098 if (Parm == context->tracking_parm) return;
1100 if(!Parm) {
1101 glDisable(GL_COLOR_MATERIAL);
1102 checkGLcall("glDisable GL_COLOR_MATERIAL");
1103 } else {
1104 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1105 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1106 glEnable(GL_COLOR_MATERIAL);
1107 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1110 /* Apparently calls to glMaterialfv are ignored for properties we're
1111 * tracking with glColorMaterial, so apply those here. */
1112 switch (context->tracking_parm) {
1113 case GL_AMBIENT_AND_DIFFUSE:
1114 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1115 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1116 checkGLcall("glMaterialfv");
1117 break;
1119 case GL_DIFFUSE:
1120 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1121 checkGLcall("glMaterialfv");
1122 break;
1124 case GL_AMBIENT:
1125 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1126 checkGLcall("glMaterialfv");
1127 break;
1129 case GL_EMISSION:
1130 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1131 checkGLcall("glMaterialfv");
1132 break;
1134 case GL_SPECULAR:
1135 /* Only change material color if specular is enabled, otherwise it is set to black */
1136 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1137 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1138 checkGLcall("glMaterialfv");
1139 } else {
1140 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1141 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1142 checkGLcall("glMaterialfv");
1144 break;
1147 context->tracking_parm = Parm;
1150 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1151 union {
1152 DWORD d;
1153 WINED3DLINEPATTERN lp;
1154 } tmppattern;
1155 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1157 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1159 if (tmppattern.lp.wRepeatFactor) {
1160 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1161 checkGLcall("glLineStipple(repeat, linepattern)");
1162 glEnable(GL_LINE_STIPPLE);
1163 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1164 } else {
1165 glDisable(GL_LINE_STIPPLE);
1166 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1170 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1171 union {
1172 DWORD d;
1173 float f;
1174 } tmpvalue;
1176 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1177 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1178 TRACE("ZBias value %f\n", tmpvalue.f);
1179 glPolygonOffset(0, -tmpvalue.f);
1180 checkGLcall("glPolygonOffset(0, -Value)");
1181 glEnable(GL_POLYGON_OFFSET_FILL);
1182 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1183 glEnable(GL_POLYGON_OFFSET_LINE);
1184 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1185 glEnable(GL_POLYGON_OFFSET_POINT);
1186 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1187 } else {
1188 glDisable(GL_POLYGON_OFFSET_FILL);
1189 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1190 glDisable(GL_POLYGON_OFFSET_LINE);
1191 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1192 glDisable(GL_POLYGON_OFFSET_POINT);
1193 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1198 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1199 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]) {
1200 glEnable(GL_NORMALIZE);
1201 checkGLcall("glEnable(GL_NORMALIZE);");
1202 } else {
1203 glDisable(GL_NORMALIZE);
1204 checkGLcall("glDisable(GL_NORMALIZE);");
1208 static void state_psize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1209 union {
1210 DWORD d;
1211 float f;
1212 } tmpvalue;
1214 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
1215 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1216 TRACE("Set point size to %f\n", tmpvalue.f);
1217 glPointSize(tmpvalue.f);
1218 checkGLcall("glPointSize(...);");
1221 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1222 union {
1223 DWORD d;
1224 float f;
1225 } tmpvalue;
1227 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1228 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1229 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1230 checkGLcall("glPointParameterfARB(...");
1232 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1233 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1234 checkGLcall("glPointParameterfEXT(...);");
1235 } else if(tmpvalue.f != 1.0) {
1236 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1240 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1241 union {
1242 DWORD d;
1243 float f;
1244 } tmpvalue;
1246 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1247 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1248 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1249 checkGLcall("glPointParameterfARB(...");
1251 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1252 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1253 checkGLcall("glPointParameterfEXT(...);");
1254 } else if(tmpvalue.f != 64.0) {
1255 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1259 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1260 /* TODO: Group this with the viewport */
1262 * POINTSCALEENABLE controls how point size value is treated. If set to
1263 * true, the point size is scaled with respect to height of viewport.
1264 * When set to false point size is in pixels.
1266 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
1269 /* Default values */
1270 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1273 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
1274 * This means that OpenGL will clamp really small point sizes to 1.0f.
1275 * To correct for this we need to multiply by the scale factor when sizes
1276 * are less than 1.0f. scale_factor = 1.0f / point_size.
1278 GLfloat pointSize = *((float*)&stateblock->renderState[WINED3DRS_POINTSIZE]);
1279 if(pointSize > 0.0f) {
1280 GLfloat scaleFactor;
1282 if(pointSize < 1.0f) {
1283 scaleFactor = pointSize * pointSize;
1284 } else {
1285 scaleFactor = 1.0f;
1288 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1289 att[0] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_A]) /
1290 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1291 att[1] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_B]) /
1292 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1293 att[2] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_C]) /
1294 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1298 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1299 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1300 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
1302 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1303 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1304 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
1305 } else {
1306 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
1310 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1311 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1313 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1314 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1315 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1316 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1317 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1318 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1319 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1320 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1321 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1322 checkGLcall("glColorMask(...)");
1324 /* depends on WINED3DRS_COLORWRITEENABLE. */
1325 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1326 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1327 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1328 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1329 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1330 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1331 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1335 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1336 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1337 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1338 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1339 } else {
1340 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1341 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1345 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1346 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1347 TRACE("Last Pixel Drawing Enabled\n");
1348 } else {
1349 static BOOL first = TRUE;
1350 if(first) {
1351 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1352 first = FALSE;
1353 } else {
1354 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1359 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1360 /* TODO: NV_POINT_SPRITE */
1361 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1362 TRACE("Point sprites not supported\n");
1363 return;
1366 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1367 glEnable(GL_POINT_SPRITE_ARB);
1368 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n");
1369 } else {
1370 glDisable(GL_POINT_SPRITE_ARB);
1371 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n");
1375 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1377 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1378 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
1379 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1380 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
1381 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1383 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1385 TRACE("Stub\n");
1386 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1387 stateblock->renderState[WINED3DRS_WRAP1] ||
1388 stateblock->renderState[WINED3DRS_WRAP2] ||
1389 stateblock->renderState[WINED3DRS_WRAP3] ||
1390 stateblock->renderState[WINED3DRS_WRAP4] ||
1391 stateblock->renderState[WINED3DRS_WRAP5] ||
1392 stateblock->renderState[WINED3DRS_WRAP6] ||
1393 stateblock->renderState[WINED3DRS_WRAP7] ||
1394 stateblock->renderState[WINED3DRS_WRAP8] ||
1395 stateblock->renderState[WINED3DRS_WRAP9] ||
1396 stateblock->renderState[WINED3DRS_WRAP10] ||
1397 stateblock->renderState[WINED3DRS_WRAP11] ||
1398 stateblock->renderState[WINED3DRS_WRAP12] ||
1399 stateblock->renderState[WINED3DRS_WRAP13] ||
1400 stateblock->renderState[WINED3DRS_WRAP14] ||
1401 stateblock->renderState[WINED3DRS_WRAP15] ) {
1402 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1406 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1407 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1408 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1409 glEnable(GL_MULTISAMPLE_ARB);
1410 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1411 } else {
1412 glDisable(GL_MULTISAMPLE_ARB);
1413 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1415 } else {
1416 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1417 WARN("Multisample antialiasing not supported by gl\n");
1422 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1423 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1424 glEnable(GL_SCISSOR_TEST);
1425 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1426 } else {
1427 glDisable(GL_SCISSOR_TEST);
1428 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1432 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1433 union {
1434 DWORD d;
1435 float f;
1436 } tmpvalue;
1438 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1439 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1440 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1441 glEnable(GL_POLYGON_OFFSET_FILL);
1442 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1443 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1444 checkGLcall("glPolygonOffset(...)");
1445 } else {
1446 glDisable(GL_POLYGON_OFFSET_FILL);
1447 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1451 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1452 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1453 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1454 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1455 } else {
1456 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1457 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1461 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1462 TRACE("Stub\n");
1463 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1464 FIXME(" Stippled Alpha not supported yet.\n");
1467 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1468 TRACE("Stub\n");
1469 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1470 FIXME(" Antialias not supported yet.\n");
1473 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1474 TRACE("Stub\n");
1475 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1476 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1479 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1480 TRACE("Stub\n");
1481 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1482 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1485 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1486 union {
1487 DWORD d;
1488 float f;
1489 } tmpvalue;
1490 tmpvalue.f = 1.0f;
1492 TRACE("Stub\n");
1493 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1495 static BOOL displayed = FALSE;
1497 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1498 if(!displayed)
1499 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1501 displayed = TRUE;
1505 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1506 TRACE("Stub\n");
1507 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1508 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1511 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1512 TRACE("Stub\n");
1513 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1514 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1517 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1518 TRACE("Stub\n");
1519 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1520 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1524 static void state_srgbwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1525 if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE])
1526 FIXME("Render state WINED3DRS_SRGBWRITEENABLE not yet implemented\n");
1529 static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1530 TRACE("Stub\n");
1531 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
1532 FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
1535 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1536 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1537 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1541 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1542 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1543 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1547 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1548 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1549 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1553 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1554 if(stateblock->renderState[WINED3DRS_ROP2]) {
1555 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1559 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1560 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1561 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1565 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1566 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1567 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1571 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1572 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1573 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1577 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1578 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1579 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1583 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1584 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1585 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1589 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1590 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1591 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1595 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1596 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1597 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1601 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1602 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1603 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1607 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1608 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1609 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1613 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1614 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1615 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1619 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1620 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1621 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1625 /* Activates the texture dimension according to the bound D3D texture.
1626 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1627 * Requires the caller to activate the correct unit before
1629 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1630 BOOL bumpmap = FALSE;
1632 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1633 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1634 bumpmap = TRUE;
1635 context->texShaderBumpMap |= (1 << stage);
1636 } else {
1637 context->texShaderBumpMap &= ~(1 << stage);
1640 if(stateblock->textures[stage]) {
1641 switch(stateblock->textureDimensions[stage]) {
1642 case GL_TEXTURE_2D:
1643 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1644 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1645 } else {
1646 glDisable(GL_TEXTURE_3D);
1647 checkGLcall("glDisable(GL_TEXTURE_3D)");
1648 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1649 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1650 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1652 glEnable(GL_TEXTURE_2D);
1653 checkGLcall("glEnable(GL_TEXTURE_2D)");
1655 break;
1656 case GL_TEXTURE_3D:
1657 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1658 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1659 } else {
1660 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1661 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1662 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1664 glDisable(GL_TEXTURE_2D);
1665 checkGLcall("glDisable(GL_TEXTURE_2D)");
1666 glEnable(GL_TEXTURE_3D);
1667 checkGLcall("glEnable(GL_TEXTURE_3D)");
1669 break;
1670 case GL_TEXTURE_CUBE_MAP_ARB:
1671 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1672 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1673 } else {
1674 glDisable(GL_TEXTURE_2D);
1675 checkGLcall("glDisable(GL_TEXTURE_2D)");
1676 glDisable(GL_TEXTURE_3D);
1677 checkGLcall("glDisable(GL_TEXTURE_3D)");
1678 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1679 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1681 break;
1683 } else {
1684 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1685 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1686 } else {
1687 glEnable(GL_TEXTURE_2D);
1688 checkGLcall("glEnable(GL_TEXTURE_2D)");
1689 glDisable(GL_TEXTURE_3D);
1690 checkGLcall("glDisable(GL_TEXTURE_3D)");
1691 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1692 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1693 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1695 /* Binding textures is done by samplers. A dummy texture will be bound */
1700 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1701 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1702 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1703 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1705 TRACE("Setting color op for stage %d\n", stage);
1707 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1708 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1709 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1710 return;
1713 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1715 if (mapped_stage != -1) {
1716 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1717 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1718 FIXME("Attempt to enable unsupported stage!\n");
1719 return;
1721 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1722 checkGLcall("glActiveTextureARB");
1723 } else if (stage > 0) {
1724 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1725 return;
1729 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1730 if(stateblock->lowest_disabled_stage > 0) {
1731 glEnable(GL_REGISTER_COMBINERS_NV);
1732 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1733 } else {
1734 glDisable(GL_REGISTER_COMBINERS_NV);
1737 if(stage >= stateblock->lowest_disabled_stage) {
1738 TRACE("Stage disabled\n");
1739 if (mapped_stage != -1) {
1740 /* Disable everything here */
1741 glDisable(GL_TEXTURE_2D);
1742 checkGLcall("glDisable(GL_TEXTURE_2D)");
1743 glDisable(GL_TEXTURE_3D);
1744 checkGLcall("glDisable(GL_TEXTURE_3D)");
1745 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1746 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1747 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1749 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1750 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1753 /* All done */
1754 return;
1757 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1758 * if the sampler for this stage is dirty
1760 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1761 if (tex_used) activate_dimensions(stage, stateblock, context);
1764 /* Set the texture combiners */
1765 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1766 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1767 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1768 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1769 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1770 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1771 mapped_stage);
1773 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1774 * thus the texture shader may have to be updated
1776 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1777 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1778 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1779 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1780 if(usesBump != usedBump) {
1781 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1782 checkGLcall("glActiveTextureARB");
1783 activate_dimensions(stage + 1, stateblock, context);
1784 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1785 checkGLcall("glActiveTextureARB");
1788 } else {
1789 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1790 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1791 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1792 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1793 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1797 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1798 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1799 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1800 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1801 DWORD op, arg1, arg2, arg0;
1803 TRACE("Setting alpha op for stage %d\n", stage);
1804 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1805 if (mapped_stage != -1) {
1806 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1807 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1808 FIXME("Attempt to enable unsupported stage!\n");
1809 return;
1811 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1812 checkGLcall("glActiveTextureARB");
1813 } else if (stage > 0) {
1814 /* We can't do anything here */
1815 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1816 return;
1820 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1821 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1822 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1823 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1825 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1826 stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
1827 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1829 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1830 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1832 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1833 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1834 * cannot remove the texture's alpha channel entirely.
1836 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1837 * on color keyed surfaces.
1839 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1841 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1842 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1843 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1847 TRACE("Setting alpha op for stage %d\n", stage);
1848 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1849 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1850 op, arg1, arg2, arg0,
1851 mapped_stage);
1852 } else {
1853 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1854 op, arg1, arg2, arg0);
1858 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1859 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1860 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1862 if (mapped_stage < 0) return;
1864 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1865 if(mapped_stage >= GL_LIMITS(textures)) {
1866 return;
1868 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1869 checkGLcall("glActiveTextureARB");
1870 } else if (mapped_stage > 0) {
1871 /* We can't do anything here */
1872 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1873 return;
1876 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1877 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1878 (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
1882 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1883 int texture_idx;
1885 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1886 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1887 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1891 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
1892 UINT *offset = stateblock->streamOffset;
1893 unsigned int mapped_stage = 0;
1894 unsigned int textureNo = 0;
1896 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1897 /* Abort if we don't support the extension. */
1898 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1899 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1900 return;
1903 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1904 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1906 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
1907 if (mapped_stage == -1) continue;
1909 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
1910 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1911 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1913 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1914 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1915 checkGLcall("glBindBufferARB");
1916 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
1919 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1920 checkGLcall("glClientActiveTextureARB");
1922 /* The coords to supply depend completely on the fvf / vertex shader */
1923 glTexCoordPointer(
1924 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1925 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1926 sd->u.s.texCoords[coordIdx].dwStride,
1927 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
1928 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1929 } else {
1930 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
1933 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1934 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
1935 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
1936 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1941 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1942 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1943 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1945 if (mapped_stage == -1) {
1946 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
1947 return;
1950 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1951 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
1952 return;
1954 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1955 checkGLcall("glActiveTextureARB");
1956 } else if (stage > 0) {
1957 /* We can't do anything here */
1958 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1959 return;
1962 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
1964 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
1965 * one flag, you can still specify an index value, which the system uses to
1966 * determine the texture wrapping mode.
1967 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
1968 * means use the vertex position (camera-space) as the input texture coordinates
1969 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
1970 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
1971 * to the TEXCOORDINDEX value
1975 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
1977 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
1978 case WINED3DTSS_TCI_PASSTHRU:
1979 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
1980 glDisable(GL_TEXTURE_GEN_S);
1981 glDisable(GL_TEXTURE_GEN_T);
1982 glDisable(GL_TEXTURE_GEN_R);
1983 glDisable(GL_TEXTURE_GEN_Q);
1984 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
1985 break;
1987 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
1988 /* CameraSpacePosition means use the vertex position, transformed to camera space,
1989 * as the input texture coordinates for this stage's texture transformation. This
1990 * equates roughly to EYE_LINEAR
1993 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1994 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1995 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1996 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1997 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
1999 glMatrixMode(GL_MODELVIEW);
2000 glPushMatrix();
2001 glLoadIdentity();
2002 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2003 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2004 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2005 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2006 glPopMatrix();
2008 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2009 glEnable(GL_TEXTURE_GEN_S);
2010 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2011 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2012 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2013 glEnable(GL_TEXTURE_GEN_T);
2014 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2015 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2016 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2017 glEnable(GL_TEXTURE_GEN_R);
2018 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2019 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2020 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2022 break;
2024 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2026 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2027 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2028 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2029 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2030 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2031 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2033 glMatrixMode(GL_MODELVIEW);
2034 glPushMatrix();
2035 glLoadIdentity();
2036 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2037 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2038 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2039 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2040 glPopMatrix();
2042 glEnable(GL_TEXTURE_GEN_S);
2043 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2044 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2045 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2046 glEnable(GL_TEXTURE_GEN_T);
2047 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2048 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2049 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2050 glEnable(GL_TEXTURE_GEN_R);
2051 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2052 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2053 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2056 break;
2058 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2060 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2061 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2062 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2063 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2064 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2065 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2067 glMatrixMode(GL_MODELVIEW);
2068 glPushMatrix();
2069 glLoadIdentity();
2070 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2071 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2072 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2073 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2074 glPopMatrix();
2076 glEnable(GL_TEXTURE_GEN_S);
2077 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2078 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2079 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2080 glEnable(GL_TEXTURE_GEN_T);
2081 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2082 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2083 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2084 glEnable(GL_TEXTURE_GEN_R);
2085 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2086 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2087 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2090 break;
2092 /* Unhandled types: */
2093 default:
2094 /* Todo: */
2095 /* ? disable GL_TEXTURE_GEN_n ? */
2096 glDisable(GL_TEXTURE_GEN_S);
2097 glDisable(GL_TEXTURE_GEN_T);
2098 glDisable(GL_TEXTURE_GEN_R);
2099 glDisable(GL_TEXTURE_GEN_Q);
2100 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2101 break;
2104 /* Update the texture matrix */
2105 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2106 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2109 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2110 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2111 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2112 * and do all the things linked to it
2113 * TODO: Tidy that up to reload only the arrays of the changed unit
2115 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2117 unloadTexCoords(stateblock);
2118 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2122 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2123 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2124 union {
2125 DWORD d;
2126 float f;
2127 } tmpvalue;
2129 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2130 if(tmpvalue.f != 0.0) {
2131 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2135 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2136 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2137 union {
2138 DWORD d;
2139 float f;
2140 } tmpvalue;
2142 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2143 if(tmpvalue.f != 0.0) {
2144 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2148 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2149 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2151 if(stage >= GL_LIMITS(texture_stages)) {
2152 return;
2155 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2156 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2160 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2161 DWORD sampler = state - STATE_SAMPLER(0);
2162 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2163 union {
2164 float f;
2165 DWORD d;
2166 } tmpvalue;
2168 TRACE("Sampler: %d\n", sampler);
2169 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2170 * only has to bind textures and set the per texture states
2173 if (mapped_stage == -1) {
2174 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2175 return;
2178 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2179 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2180 return;
2182 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2183 checkGLcall("glActiveTextureARB");
2184 } else if (sampler > 0) {
2185 /* We can't do anything here */
2186 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2187 return;
2190 if(stateblock->textures[sampler]) {
2191 BOOL texIsPow2 = FALSE;
2193 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2194 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2195 * scaling is reapplied or removed, the texture matrix has to be reapplied
2197 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2198 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
2199 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
2200 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {
2201 texIsPow2 = TRUE;
2203 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2204 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->pow2scalingFactor != 1.0) {
2205 texIsPow2 = TRUE;
2209 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2210 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2211 context->lastWasPow2Texture[sampler] = texIsPow2;
2215 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2216 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2218 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2219 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2220 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2221 GL_TEXTURE_LOD_BIAS_EXT,
2222 tmpvalue.f);
2223 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2226 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2227 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2228 /* Using a pixel shader? Verify the sampler types */
2230 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2231 * dimensions because the shader knows from which texture type to sample from. For the sake of
2232 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2233 * dimensions. This should make wrong sampling sources visible :-)
2235 glEnable(stateblock->textureDimensions[sampler]);
2236 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2237 } else if(sampler < stateblock->lowest_disabled_stage) {
2238 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2239 activate_dimensions(sampler, stateblock, context);
2242 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2243 /* If color keying is enabled update the alpha test, it depends on the existence
2244 * of a color key in stage 0
2246 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2249 } else if(sampler < GL_LIMITS(texture_stages)) {
2250 if(sampler < stateblock->lowest_disabled_stage) {
2251 /* TODO: What should I do with pixel shaders here ??? */
2252 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2253 activate_dimensions(sampler, stateblock, context);
2255 } /* Otherwise tex_colorop disables the stage */
2256 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2257 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2261 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2262 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2264 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2265 * has an update pending
2267 if(isStateDirty(context, STATE_VDECL) ||
2268 isStateDirty(context, STATE_PIXELSHADER)) {
2269 return;
2272 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2275 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2276 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2277 BOOL use_pshader = use_ps(device);
2278 BOOL use_vshader = use_vs(device);
2279 BOOL update_fog = FALSE;
2280 int i;
2282 if (use_pshader) {
2283 if(!context->last_was_pshader) {
2284 /* Former draw without a pixel shader, some samplers
2285 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2286 * make sure to enable them
2288 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2289 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2290 sampler(STATE_SAMPLER(i), stateblock, context);
2293 update_fog = TRUE;
2294 } else {
2295 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2296 * if a different texture was bound. I don't have to do anything.
2300 /* Compile and bind the shader */
2301 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2302 } else {
2303 /* Disabled the pixel shader - color ops weren't applied
2304 * while it was enabled, so re-apply them.
2306 for(i=0; i < MAX_TEXTURES; i++) {
2307 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2308 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2311 if(context->last_was_pshader)
2312 update_fog = TRUE;
2315 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2316 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2318 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2319 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2323 if(update_fog)
2324 state_fog(state, stateblock, context);
2326 context->last_was_pshader = use_pshader;
2329 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2330 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2332 if(stateblock->pixelShader && stage != 0 &&
2333 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2334 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2335 * anyway
2337 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2338 !isStateDirty(context, STATE_PIXELSHADER)) {
2339 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2343 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2344 if(stage >= GL_LIMITS(texture_stages)) {
2345 WARN("Bump env matrix of unsupported stage set\n");
2346 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2347 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2348 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2350 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2351 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2352 checkGLcall("glTexBumpParameterfvATI");
2354 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2355 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2356 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2357 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2358 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2359 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2361 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2363 if(mapped_stage < GL_LIMITS(textures)) {
2364 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2365 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2367 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2368 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2369 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2374 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2375 /* This function is called by transform_view below if the view matrix was changed too
2377 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2378 * does not always update the world matrix, only on a switch between transformed
2379 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2380 * draw, but that should be rather rare and cheaper in total.
2382 glMatrixMode(GL_MODELVIEW);
2383 checkGLcall("glMatrixMode");
2385 if(context->last_was_rhw) {
2386 glLoadIdentity();
2387 checkGLcall("glLoadIdentity()");
2388 } else {
2389 /* In the general case, the view matrix is the identity matrix */
2390 if (stateblock->wineD3DDevice->view_ident) {
2391 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2392 checkGLcall("glLoadMatrixf");
2393 } else {
2394 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2395 checkGLcall("glLoadMatrixf");
2396 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2397 checkGLcall("glMultMatrixf");
2402 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2403 UINT index = state - STATE_CLIPPLANE(0);
2405 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2406 return;
2409 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2410 glMatrixMode(GL_MODELVIEW);
2411 glPushMatrix();
2412 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2414 TRACE("Clipplane [%f,%f,%f,%f]\n",
2415 stateblock->clipplane[index][0],
2416 stateblock->clipplane[index][1],
2417 stateblock->clipplane[index][2],
2418 stateblock->clipplane[index][3]);
2419 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2420 checkGLcall("glClipPlane");
2422 glPopMatrix();
2425 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2426 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2427 GLenum glMat;
2428 TRACE("Setting world matrix %d\n", matrix);
2430 if(matrix >= GL_LIMITS(blends)) {
2431 WARN("Unsupported blend matrix set\n");
2432 return;
2433 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2434 return;
2437 /* GL_MODELVIEW0_ARB: 0x1700
2438 * GL_MODELVIEW1_ARB: 0x0x850a
2439 * GL_MODELVIEW2_ARB: 0x8722
2440 * GL_MODELVIEW3_ARB: 0x8723
2441 * etc
2442 * GL_MODELVIEW31_ARB: 0x873F
2444 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2445 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2447 glMatrixMode(glMat);
2448 checkGLcall("glMatrixMode(glMat)");
2450 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2451 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2453 if(stateblock->wineD3DDevice->view_ident) {
2454 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2455 checkGLcall("glLoadMatrixf")
2456 } else {
2457 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2458 checkGLcall("glLoadMatrixf")
2459 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2460 checkGLcall("glMultMatrixf")
2464 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2465 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2467 switch(val) {
2468 case WINED3DVBF_1WEIGHTS:
2469 case WINED3DVBF_2WEIGHTS:
2470 case WINED3DVBF_3WEIGHTS:
2471 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2472 glEnable(GL_VERTEX_BLEND_ARB);
2473 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2475 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2476 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2478 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2480 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2481 int i;
2482 for(i = 1; i < GL_LIMITS(blends); i++) {
2483 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2484 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2487 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2489 } else {
2490 /* TODO: Implement vertex blending in drawStridedSlow */
2491 FIXME("Vertex blending enabled, but not supported by hardware\n");
2493 break;
2495 case WINED3DVBF_DISABLE:
2496 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2497 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2498 glDisable(GL_VERTEX_BLEND_ARB);
2499 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2500 } else {
2501 TRACE("Vertex blending disabled\n");
2503 break;
2505 case WINED3DVBF_TWEENING:
2506 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2507 * vertex weights in the vertices?
2508 * For now we don't report that as supported, so a warn should suffice
2510 WARN("Tweening not supported yet\n");
2511 break;
2515 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2516 unsigned int k;
2518 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2519 * NOTE: We have to reset the positions even if the light/plane is not currently
2520 * enabled, since the call to enable it will not reset the position.
2521 * NOTE2: Apparently texture transforms do NOT need reapplying
2524 PLIGHTINFOEL *light = NULL;
2526 glMatrixMode(GL_MODELVIEW);
2527 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2528 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2529 checkGLcall("glLoadMatrixf(...)");
2531 /* Reset lights. TODO: Call light apply func */
2532 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2533 light = stateblock->activeLights[k];
2534 if(!light) continue;
2535 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2536 checkGLcall("glLightfv posn");
2537 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2538 checkGLcall("glLightfv dirn");
2541 /* Reset Clipping Planes */
2542 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2543 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2544 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2548 if(context->last_was_rhw) {
2549 glLoadIdentity();
2550 checkGLcall("glLoadIdentity()");
2551 /* No need to update the world matrix, the identity is fine */
2552 return;
2555 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2556 * No need to do it here if the state is scheduled for update.
2558 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2559 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2562 /* Avoid looping over a number of matrices if the app never used the functionality */
2563 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2564 for(k = 1; k < GL_LIMITS(blends); k++) {
2565 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2566 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2572 static const GLfloat invymat[16] = {
2573 1.0f, 0.0f, 0.0f, 0.0f,
2574 0.0f, -1.0f, 0.0f, 0.0f,
2575 0.0f, 0.0f, 1.0f, 0.0f,
2576 0.0f, 0.0f, 0.0f, 1.0f};
2578 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2579 glMatrixMode(GL_PROJECTION);
2580 checkGLcall("glMatrixMode(GL_PROJECTION)");
2581 glLoadIdentity();
2582 checkGLcall("glLoadIdentity");
2584 if(context->last_was_rhw) {
2585 double X, Y, height, width, minZ, maxZ;
2587 X = stateblock->viewport.X;
2588 Y = stateblock->viewport.Y;
2589 height = stateblock->viewport.Height;
2590 width = stateblock->viewport.Width;
2591 minZ = stateblock->viewport.MinZ;
2592 maxZ = stateblock->viewport.MaxZ;
2594 if(!stateblock->wineD3DDevice->untransformed) {
2595 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2596 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2597 * suppress depth clipping. This can be done because it is an orthogonal projection and
2598 * the Z coordinate does not affect the size of the primitives
2600 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2601 if(stateblock->wineD3DDevice->render_offscreen) {
2602 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2603 } else {
2604 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2606 } else {
2607 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2608 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2609 * unmodified to opengl.
2611 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2612 * replacement shader.
2614 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2615 if(stateblock->wineD3DDevice->render_offscreen) {
2616 glOrtho(X, X + width, -Y, -Y - height, 1.0, -1.0);
2617 } else {
2618 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
2621 checkGLcall("glOrtho");
2623 /* Window Coord 0 is the middle of the first pixel, so translate by 3/8 pixels */
2624 glTranslatef(0.375, 0.375, 0);
2625 checkGLcall("glTranslatef(0.375, 0.375, 0)");
2626 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2627 * render everything upside down when rendering offscreen. */
2628 if (stateblock->wineD3DDevice->render_offscreen) {
2629 glMultMatrixf(invymat);
2630 checkGLcall("glMultMatrixf(invymat)");
2632 } else {
2633 /* The rule is that the window coordinate 0 does not correspond to the
2634 beginning of the first pixel, but the center of the first pixel.
2635 As a consequence if you want to correctly draw one line exactly from
2636 the left to the right end of the viewport (with all matrices set to
2637 be identity), the x coords of both ends of the line would be not
2638 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2639 instead. */
2640 glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
2641 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
2643 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2644 * render everything upside down when rendering offscreen. */
2645 if (stateblock->wineD3DDevice->render_offscreen) {
2646 glMultMatrixf(invymat);
2647 checkGLcall("glMultMatrixf(invymat)");
2649 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2650 checkGLcall("glLoadMatrixf");
2654 /* This should match any arrays loaded in loadVertexData.
2655 * stateblock impl is required for GL_SUPPORT
2656 * TODO: Only load / unload arrays if we have to.
2658 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2659 glDisableClientState(GL_VERTEX_ARRAY);
2660 glDisableClientState(GL_NORMAL_ARRAY);
2661 glDisableClientState(GL_COLOR_ARRAY);
2662 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2663 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2665 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2666 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2667 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2668 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2670 unloadTexCoords(stateblock);
2673 /* This should match any arrays loaded in loadNumberedArrays
2674 * TODO: Only load / unload arrays if we have to.
2676 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2677 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2678 GLint maxAttribs;
2679 int i;
2681 /* Leave all the attribs disabled */
2682 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2683 /* MESA does not support it right not */
2684 if (glGetError() != GL_NO_ERROR)
2685 maxAttribs = 16;
2686 for (i = 0; i < maxAttribs; ++i) {
2687 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2688 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2692 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2693 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2694 int i;
2695 UINT *offset = stateblock->streamOffset;
2697 /* Default to no instancing */
2698 stateblock->wineD3DDevice->instancedDraw = FALSE;
2700 for (i = 0; i < MAX_ATTRIBS; i++) {
2702 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2703 continue;
2705 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2706 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2707 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2708 stateblock->wineD3DDevice->instancedDraw = TRUE;
2709 continue;
2712 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2714 if(strided->u.input[i].dwStride) {
2715 if(curVBO != strided->u.input[i].VBO) {
2716 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2717 checkGLcall("glBindBufferARB");
2718 curVBO = strided->u.input[i].VBO;
2720 GL_EXTCALL(glVertexAttribPointerARB(i,
2721 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2722 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2723 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2724 strided->u.input[i].dwStride,
2725 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2726 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2727 } else {
2728 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2729 * set up the attribute statically. But we have to figure out the system memory address.
2731 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2732 if(strided->u.input[i].VBO) {
2733 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2734 ptr += (long) vb->resource.allocatedMemory;
2736 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2738 switch(strided->u.input[i].dwType) {
2739 case WINED3DDECLTYPE_FLOAT1:
2740 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2741 break;
2742 case WINED3DDECLTYPE_FLOAT2:
2743 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2744 break;
2745 case WINED3DDECLTYPE_FLOAT3:
2746 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2747 break;
2748 case WINED3DDECLTYPE_FLOAT4:
2749 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2750 break;
2752 case WINED3DDECLTYPE_UBYTE4:
2753 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2754 break;
2755 case WINED3DDECLTYPE_UBYTE4N:
2756 case WINED3DDECLTYPE_D3DCOLOR:
2757 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2758 break;
2760 case WINED3DDECLTYPE_SHORT2:
2761 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2762 break;
2763 case WINED3DDECLTYPE_SHORT4:
2764 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2765 break;
2767 case WINED3DDECLTYPE_SHORT2N:
2769 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2770 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2771 break;
2773 case WINED3DDECLTYPE_USHORT2N:
2775 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2776 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2777 break;
2779 case WINED3DDECLTYPE_SHORT4N:
2780 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2781 break;
2782 case WINED3DDECLTYPE_USHORT4N:
2783 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2784 break;
2786 case WINED3DDECLTYPE_UDEC3:
2787 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2788 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2789 break;
2790 case WINED3DDECLTYPE_DEC3N:
2791 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2792 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2793 break;
2795 case WINED3DDECLTYPE_FLOAT16_2:
2796 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2797 * byte float according to the IEEE standard
2799 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2800 break;
2801 case WINED3DDECLTYPE_FLOAT16_4:
2802 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2803 break;
2805 case WINED3DDECLTYPE_UNUSED:
2806 default:
2807 ERR("Unexpected declaration in stride 0 attributes\n");
2808 break;
2815 /* Used from 2 different functions, and too big to justify making it inlined */
2816 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2817 UINT *offset = stateblock->streamOffset;
2818 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2820 TRACE("Using fast vertex array code\n");
2822 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2823 stateblock->wineD3DDevice->instancedDraw = FALSE;
2825 /* Blend Data ---------------------------------------------- */
2826 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2827 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2829 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2830 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2831 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2833 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
2834 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
2836 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
2838 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
2839 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
2840 sd->u.s.blendWeights.dwStride,
2841 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
2843 if(curVBO != sd->u.s.blendWeights.VBO) {
2844 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
2845 checkGLcall("glBindBufferARB");
2846 curVBO = sd->u.s.blendWeights.VBO;
2849 GL_EXTCALL(glWeightPointerARB)(
2850 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2851 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2852 sd->u.s.blendWeights.dwStride,
2853 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2855 checkGLcall("glWeightPointerARB");
2857 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
2858 static BOOL showfixme = TRUE;
2859 if(showfixme){
2860 FIXME("blendMatrixIndices support\n");
2861 showfixme = FALSE;
2864 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2865 /* FIXME("TODO\n");*/
2866 #if 0
2868 GL_EXTCALL(glVertexWeightPointerEXT)(
2869 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2870 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2871 sd->u.s.blendWeights.dwStride,
2872 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
2873 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
2874 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2875 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
2876 #endif
2878 } else {
2879 /* TODO: support blends in drawStridedSlow
2880 * No need to write a FIXME here, this is done after the general vertex decl decoding
2882 WARN("unsupported blending in openGl\n");
2884 } else {
2885 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2886 static const GLbyte one = 1;
2887 GL_EXTCALL(glWeightbvARB(1, &one));
2888 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
2892 #if 0 /* FOG ----------------------------------------------*/
2893 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
2894 /* TODO: fog*/
2895 if (GL_SUPPORT(EXT_FOG_COORD) {
2896 glEnableClientState(GL_FOG_COORDINATE_EXT);
2897 (GL_EXTCALL)(FogCoordPointerEXT)(
2898 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
2899 sd->u.s.fog.dwStride,
2900 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
2901 } else {
2902 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
2903 /* FIXME: fixme once */
2904 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
2906 } else {
2907 if (GL_SUPPRT(EXT_FOR_COORD) {
2908 /* make sure fog is disabled */
2909 glDisableClientState(GL_FOG_COORDINATE_EXT);
2912 #endif
2914 #if 0 /* tangents ----------------------------------------------*/
2915 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
2916 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2917 /* TODO: tangents*/
2918 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2919 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
2920 glEnable(GL_TANGENT_ARRAY_EXT);
2921 (GL_EXTCALL)(TangentPointerEXT)(
2922 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
2923 sd->u.s.tangent.dwStride,
2924 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
2925 } else {
2926 glDisable(GL_TANGENT_ARRAY_EXT);
2928 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2929 glEnable(GL_BINORMAL_ARRAY_EXT);
2930 (GL_EXTCALL)(BinormalPointerEXT)(
2931 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
2932 sd->u.s.binormal.dwStride,
2933 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
2934 } else{
2935 glDisable(GL_BINORMAL_ARRAY_EXT);
2938 } else {
2939 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
2940 /* FIXME: fixme once */
2941 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
2943 } else {
2944 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2945 /* make sure fog is disabled */
2946 glDisable(GL_TANGENT_ARRAY_EXT);
2947 glDisable(GL_BINORMAL_ARRAY_EXT);
2950 #endif
2952 /* Point Size ----------------------------------------------*/
2953 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
2955 /* no such functionality in the fixed function GL pipeline */
2956 TRACE("Cannot change ptSize here in openGl\n");
2957 /* TODO: Implement this function in using shaders if they are available */
2961 /* Vertex Pointers -----------------------------------------*/
2962 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
2963 /* Note dwType == float3 or float4 == 2 or 3 */
2964 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
2965 sd->u.s.position.dwStride,
2966 sd->u.s.position.dwType + 1,
2967 sd->u.s.position.lpData));
2969 if(curVBO != sd->u.s.position.VBO) {
2970 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
2971 checkGLcall("glBindBufferARB");
2972 curVBO = sd->u.s.position.VBO;
2975 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
2976 handling for rhw mode should not impact screen position whereas in GL it does.
2977 This may result in very slightly distored textures in rhw mode, but
2978 a very minimal different. There's always the other option of
2979 fixing the view matrix to prevent w from having any effect
2981 This only applies to user pointer sources, in VBOs the vertices are fixed up
2983 if(sd->u.s.position.VBO == 0) {
2984 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
2985 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2986 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2987 } else {
2988 glVertexPointer(
2989 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
2990 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2991 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2993 checkGLcall("glVertexPointer(...)");
2994 glEnableClientState(GL_VERTEX_ARRAY);
2995 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
2998 /* Normals -------------------------------------------------*/
2999 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3000 /* Note dwType == float3 or float4 == 2 or 3 */
3001 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3002 sd->u.s.normal.dwStride,
3003 sd->u.s.normal.lpData));
3004 if(curVBO != sd->u.s.normal.VBO) {
3005 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3006 checkGLcall("glBindBufferARB");
3007 curVBO = sd->u.s.normal.VBO;
3009 glNormalPointer(
3010 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3011 sd->u.s.normal.dwStride,
3012 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3013 checkGLcall("glNormalPointer(...)");
3014 glEnableClientState(GL_NORMAL_ARRAY);
3015 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3017 } else {
3018 glNormal3f(0, 0, 1);
3019 checkGLcall("glNormal3f(0, 0, 1)");
3022 /* Diffuse Colour --------------------------------------------*/
3023 /* WARNING: Data here MUST be in RGBA format, so cannot */
3024 /* go directly into fast mode from app pgm, because */
3025 /* directx requires data in BGRA format. */
3026 /* currently fixupVertices swizels the format, but this isn't */
3027 /* very practical when using VBOS */
3028 /* NOTE: Unless we write a vertex shader to swizel the colour */
3029 /* , or the user doesn't care and wants the speed advantage */
3031 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3032 /* Note dwType == float3 or float4 == 2 or 3 */
3033 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3034 sd->u.s.diffuse.dwStride,
3035 sd->u.s.diffuse.lpData));
3037 if(curVBO != sd->u.s.diffuse.VBO) {
3038 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3039 checkGLcall("glBindBufferARB");
3040 curVBO = sd->u.s.diffuse.VBO;
3042 glColorPointer(4, GL_UNSIGNED_BYTE,
3043 sd->u.s.diffuse.dwStride,
3044 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3045 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3046 glEnableClientState(GL_COLOR_ARRAY);
3047 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3049 } else {
3050 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3051 checkGLcall("glColor4f(1, 1, 1, 1)");
3054 /* Specular Colour ------------------------------------------*/
3055 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3056 TRACE("setting specular colour\n");
3057 /* Note dwType == float3 or float4 == 2 or 3 */
3058 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3059 sd->u.s.specular.dwStride,
3060 sd->u.s.specular.lpData));
3061 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3062 if(curVBO != sd->u.s.specular.VBO) {
3063 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3064 checkGLcall("glBindBufferARB");
3065 curVBO = sd->u.s.specular.VBO;
3067 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3068 sd->u.s.specular.dwStride,
3069 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3070 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3071 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3072 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3073 } else {
3075 /* Missing specular color is not critical, no warnings */
3076 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3079 } else {
3080 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3081 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3082 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3083 } else {
3085 /* Missing specular color is not critical, no warnings */
3086 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3090 /* Texture coords -------------------------------------------*/
3091 loadTexCoords(stateblock, sd, &curVBO);
3094 static inline void drawPrimitiveTraceDataLocations(
3095 WineDirect3DVertexStridedData *dataLocations) {
3097 /* Dump out what parts we have supplied */
3098 TRACE("Strided Data:\n");
3099 TRACE_STRIDED((dataLocations), position);
3100 TRACE_STRIDED((dataLocations), blendWeights);
3101 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3102 TRACE_STRIDED((dataLocations), normal);
3103 TRACE_STRIDED((dataLocations), pSize);
3104 TRACE_STRIDED((dataLocations), diffuse);
3105 TRACE_STRIDED((dataLocations), specular);
3106 TRACE_STRIDED((dataLocations), texCoords[0]);
3107 TRACE_STRIDED((dataLocations), texCoords[1]);
3108 TRACE_STRIDED((dataLocations), texCoords[2]);
3109 TRACE_STRIDED((dataLocations), texCoords[3]);
3110 TRACE_STRIDED((dataLocations), texCoords[4]);
3111 TRACE_STRIDED((dataLocations), texCoords[5]);
3112 TRACE_STRIDED((dataLocations), texCoords[6]);
3113 TRACE_STRIDED((dataLocations), texCoords[7]);
3114 TRACE_STRIDED((dataLocations), position2);
3115 TRACE_STRIDED((dataLocations), normal2);
3116 TRACE_STRIDED((dataLocations), tangent);
3117 TRACE_STRIDED((dataLocations), binormal);
3118 TRACE_STRIDED((dataLocations), tessFactor);
3119 TRACE_STRIDED((dataLocations), fog);
3120 TRACE_STRIDED((dataLocations), depth);
3121 TRACE_STRIDED((dataLocations), sample);
3123 return;
3126 /* Helper for vertexdeclaration() */
3127 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3128 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3129 BOOL fixup = FALSE;
3130 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3132 if(device->up_strided) {
3133 /* Note: this is a ddraw fixed-function code path */
3134 TRACE("================ Strided Input ===================\n");
3135 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3137 if(TRACE_ON(d3d)) {
3138 drawPrimitiveTraceDataLocations(dataLocations);
3140 } else {
3141 /* Note: This is a fixed function or shader codepath.
3142 * This means it must handle both types of strided data.
3143 * Shaders must go through here to zero the strided data, even if they
3144 * don't set any declaration at all
3146 TRACE("================ Vertex Declaration ===================\n");
3147 memset(dataLocations, 0, sizeof(*dataLocations));
3148 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3149 useVertexShaderFunction, dataLocations, &fixup);
3152 if (dataLocations->u.s.position_transformed) {
3153 useVertexShaderFunction = FALSE;
3156 /* Unload the old arrays before loading the new ones to get old junk out */
3157 if(context->numberedArraysLoaded) {
3158 unloadNumberedArrays(stateblock);
3159 context->numberedArraysLoaded = FALSE;
3161 if(context->namedArraysLoaded) {
3162 unloadVertexData(stateblock);
3163 context->namedArraysLoaded = FALSE;
3166 if(useVertexShaderFunction) {
3167 TRACE("Loading numbered arrays\n");
3168 loadNumberedArrays(stateblock, dataLocations);
3169 device->useDrawStridedSlow = FALSE;
3170 context->numberedArraysLoaded = TRUE;
3171 } else if (fixup ||
3172 (dataLocations->u.s.pSize.lpData == NULL &&
3173 dataLocations->u.s.diffuse.lpData == NULL &&
3174 dataLocations->u.s.specular.lpData == NULL)) {
3175 /* Load the vertex data using named arrays */
3176 TRACE("Loading vertex data\n");
3177 loadVertexData(stateblock, dataLocations);
3178 device->useDrawStridedSlow = FALSE;
3179 context->namedArraysLoaded = TRUE;
3180 } else {
3181 TRACE("Not loading vertex data\n");
3182 device->useDrawStridedSlow = TRUE;
3185 /* Generate some fixme's if unsupported functionality is being used */
3186 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3187 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3188 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3189 FIXME("Tweening is only valid with vertex shaders\n");
3191 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3192 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3194 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3195 FIXME("Extended attributes are only valid with vertex shaders\n");
3197 #undef BUFFER_OR_DATA
3200 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3201 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3202 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3203 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3204 BOOL transformed;
3205 /* Some stuff is in the device until we have per context tracking */
3206 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3207 BOOL wasrhw = context->last_was_rhw;
3209 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3210 * here simply check whether a shader was set, or the user disabled shaders
3212 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3213 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3214 useVertexShaderFunction = TRUE;
3216 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3217 updateFog = TRUE;
3219 } else if(context->last_was_foggy_shader) {
3220 updateFog = TRUE;
3223 handleStreams(stateblock, useVertexShaderFunction, context);
3225 transformed = device->strided_streams.u.s.position_transformed;
3226 if (transformed) useVertexShaderFunction = FALSE;
3228 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3229 updateFog = TRUE;
3232 /* Reapply lighting if it is not scheduled for reapplication already */
3233 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3234 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3237 if (transformed) {
3238 context->last_was_rhw = TRUE;
3239 } else {
3241 /* Untransformed, so relies on the view and projection matrices */
3242 context->last_was_rhw = FALSE;
3243 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3244 device->untransformed = TRUE;
3246 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3247 * Not needed as long as only hw shaders are supported
3250 /* This sets the shader output position correction constants.
3251 * TODO: Move to the viewport state
3253 if (useVertexShaderFunction) {
3254 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3258 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3259 * off this function will be called again anyway to make sure they're properly set
3261 if(!useVertexShaderFunction) {
3262 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3263 * or transformed / untransformed was switched
3265 if(wasrhw != context->last_was_rhw &&
3266 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3267 !isStateDirty(context, STATE_VIEWPORT)) {
3268 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3270 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3271 * mode.
3273 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3274 * this check will fail and the matrix not applied again. This is OK because a simple
3275 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3276 * needs of the vertex declaration.
3278 * World and view matrix go into the same gl matrix, so only apply them when neither is
3279 * dirty
3281 if(transformed != wasrhw &&
3282 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3283 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3284 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3287 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3288 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3291 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3292 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3294 } else {
3295 /* We compile the shader here because we need the vertex declaration
3296 * in order to determine if we need to do any swizzling for D3DCOLOR
3297 * registers. If the shader is already compiled this call will do nothing. */
3298 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3300 if(!context->last_was_vshader) {
3301 int i;
3302 static BOOL warned = FALSE;
3303 /* Disable all clip planes to get defined results on all drivers. See comment in the
3304 * state_clipping state handler
3306 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3307 glDisable(GL_CLIP_PLANE0 + i);
3308 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3311 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3312 FIXME("Clipping not supported with vertex shaders\n");
3313 warned = TRUE;
3318 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3319 * application
3321 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3322 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3324 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3325 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3329 context->last_was_vshader = useVertexShaderFunction;
3331 if(updateFog) {
3332 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3336 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3337 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3338 checkGLcall("glDepthRange");
3339 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3341 if(stateblock->wineD3DDevice->render_offscreen) {
3342 glViewport(stateblock->viewport.X,
3343 stateblock->viewport.Y,
3344 stateblock->viewport.Width, stateblock->viewport.Height);
3345 } else {
3346 glViewport(stateblock->viewport.X,
3347 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3348 stateblock->viewport.Width, stateblock->viewport.Height);
3351 checkGLcall("glViewport");
3353 stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
3354 stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
3355 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3356 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3361 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3362 UINT Index = state - STATE_ACTIVELIGHT(0);
3363 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3365 if(!lightInfo) {
3366 glDisable(GL_LIGHT0 + Index);
3367 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3368 } else {
3369 float quad_att;
3370 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3372 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3373 glMatrixMode(GL_MODELVIEW);
3374 glPushMatrix();
3375 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3377 /* Diffuse: */
3378 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3379 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3380 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3381 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3382 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3383 checkGLcall("glLightfv");
3385 /* Specular */
3386 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3387 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3388 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3389 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3390 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3391 checkGLcall("glLightfv");
3393 /* Ambient */
3394 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3395 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3396 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3397 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3398 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3399 checkGLcall("glLightfv");
3401 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3402 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3403 } else {
3404 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3407 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3408 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3409 * Attenuation0 to NaN and crashes in the gl lib
3412 switch (lightInfo->OriginalParms.Type) {
3413 case WINED3DLIGHT_POINT:
3414 /* Position */
3415 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3416 checkGLcall("glLightfv");
3417 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3418 checkGLcall("glLightf");
3419 /* Attenuation - Are these right? guessing... */
3420 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3421 checkGLcall("glLightf");
3422 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3423 checkGLcall("glLightf");
3424 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3425 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3426 checkGLcall("glLightf");
3427 /* FIXME: Range */
3428 break;
3430 case WINED3DLIGHT_SPOT:
3431 /* Position */
3432 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3433 checkGLcall("glLightfv");
3434 /* Direction */
3435 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3436 checkGLcall("glLightfv");
3437 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3438 checkGLcall("glLightf");
3439 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3440 checkGLcall("glLightf");
3441 /* Attenuation - Are these right? guessing... */
3442 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3443 checkGLcall("glLightf");
3444 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3445 checkGLcall("glLightf");
3446 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3447 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3448 checkGLcall("glLightf");
3449 /* FIXME: Range */
3450 break;
3452 case WINED3DLIGHT_DIRECTIONAL:
3453 /* Direction */
3454 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3455 checkGLcall("glLightfv");
3456 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3457 checkGLcall("glLightf");
3458 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3459 checkGLcall("glLightf");
3460 break;
3462 default:
3463 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3466 /* Restore the modelview matrix */
3467 glPopMatrix();
3469 glEnable(GL_LIGHT0 + Index);
3470 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3473 return;
3476 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3477 IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) stateblock->wineD3DDevice->swapchains[0];
3478 RECT *pRect = &stateblock->scissorRect;
3479 RECT windowRect;
3480 UINT winHeight;
3482 GetClientRect(swapchain->win_handle, &windowRect);
3483 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3484 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3486 winHeight = windowRect.bottom - windowRect.top;
3487 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3488 pRect->right - pRect->left, pRect->bottom - pRect->top);
3490 if (stateblock->wineD3DDevice->render_offscreen) {
3491 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3492 } else {
3493 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3495 checkGLcall("glScissor");
3498 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3499 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3500 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3501 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3502 } else {
3503 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3504 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3509 const struct StateEntry StateTable[] =
3511 /* State name representative, apply function */
3512 { /* 0, Undefined */ 0, state_undefined },
3513 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3514 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3515 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3516 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3517 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3518 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3519 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3520 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3521 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3522 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3523 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3524 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3525 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3526 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3527 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3528 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3529 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3530 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3531 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3532 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3533 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3534 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3535 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3536 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3537 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3538 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3539 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3540 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3541 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3542 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3543 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3544 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3545 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3546 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3547 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3548 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3549 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3550 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3551 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3552 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3553 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3554 { /* 42, undefined */ 0, state_undefined },
3555 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3556 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3557 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3558 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3559 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3560 { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog },
3561 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3562 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3563 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3564 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3565 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3566 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3567 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3568 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3569 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3570 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3571 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3572 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3573 { /* 61, Undefined */ 0, state_undefined },
3574 { /* 62, Undefined */ 0, state_undefined },
3575 { /* 63, Undefined */ 0, state_undefined },
3576 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3577 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3578 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3579 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3580 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3581 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3582 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3583 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3584 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3585 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3586 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3587 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3588 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3589 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3590 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3591 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3592 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3593 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3594 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3595 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3596 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3597 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3598 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3599 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3600 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3601 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3602 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3603 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3604 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3605 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3606 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3607 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3608 { /* 96, Undefined */ 0, state_undefined },
3609 { /* 97, Undefined */ 0, state_undefined },
3610 { /* 98, Undefined */ 0, state_undefined },
3611 { /* 99, Undefined */ 0, state_undefined },
3612 { /*100, Undefined */ 0, state_undefined },
3613 { /*101, Undefined */ 0, state_undefined },
3614 { /*102, Undefined */ 0, state_undefined },
3615 { /*103, Undefined */ 0, state_undefined },
3616 { /*104, Undefined */ 0, state_undefined },
3617 { /*105, Undefined */ 0, state_undefined },
3618 { /*106, Undefined */ 0, state_undefined },
3619 { /*107, Undefined */ 0, state_undefined },
3620 { /*108, Undefined */ 0, state_undefined },
3621 { /*109, Undefined */ 0, state_undefined },
3622 { /*110, Undefined */ 0, state_undefined },
3623 { /*111, Undefined */ 0, state_undefined },
3624 { /*112, Undefined */ 0, state_undefined },
3625 { /*113, Undefined */ 0, state_undefined },
3626 { /*114, Undefined */ 0, state_undefined },
3627 { /*115, Undefined */ 0, state_undefined },
3628 { /*116, Undefined */ 0, state_undefined },
3629 { /*117, Undefined */ 0, state_undefined },
3630 { /*118, Undefined */ 0, state_undefined },
3631 { /*119, Undefined */ 0, state_undefined },
3632 { /*120, Undefined */ 0, state_undefined },
3633 { /*121, Undefined */ 0, state_undefined },
3634 { /*122, Undefined */ 0, state_undefined },
3635 { /*123, Undefined */ 0, state_undefined },
3636 { /*124, Undefined */ 0, state_undefined },
3637 { /*125, Undefined */ 0, state_undefined },
3638 { /*126, Undefined */ 0, state_undefined },
3639 { /*127, Undefined */ 0, state_undefined },
3640 /* Big hole ends */
3641 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3642 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3643 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3644 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3645 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3646 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3647 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3648 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3649 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3650 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3651 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3652 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3653 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3654 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3655 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3656 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3657 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3658 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3659 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3660 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3661 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3662 { /*149, Undefined */ 0, state_undefined },
3663 { /*150, Undefined */ 0, state_undefined },
3664 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3665 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3666 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3667 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
3668 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3669 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3670 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3671 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3672 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3673 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3674 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3675 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3676 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3677 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3678 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3679 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3680 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3681 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3682 { /*169, Undefined */ 0, state_undefined },
3683 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3684 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3685 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3686 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3687 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3688 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3689 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3690 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3691 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3692 { /*177, undefined */ 0, state_undefined },
3693 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3694 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3695 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3696 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3697 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3698 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3699 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3700 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3701 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3702 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3703 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3704 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3705 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3706 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3707 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3708 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3709 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite },
3710 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3711 { /*196, undefined */ 0, state_undefined },
3712 { /*197, undefined */ 0, state_undefined },
3713 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3714 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3715 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3716 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3717 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3718 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3719 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3720 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3721 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3722 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3723 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3724 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3725 /* Texture stage states */
3726 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3727 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3728 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3729 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3730 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3731 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3732 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3733 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3734 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3735 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3736 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3737 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3738 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3739 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3740 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3741 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3742 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3743 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3744 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3745 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3746 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3747 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3748 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3749 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3750 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3751 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3752 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3753 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3754 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3755 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3756 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3757 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3759 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3760 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3761 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3762 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3763 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3764 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3765 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3766 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3767 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3768 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3769 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3770 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3771 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3772 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3773 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3774 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3775 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3776 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3777 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3778 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3779 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3780 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3781 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3782 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3783 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3784 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3785 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3786 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3787 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3788 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3789 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3790 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3792 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3793 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3794 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3795 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3796 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3797 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3798 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3799 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3800 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3801 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3802 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3803 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3804 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3805 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3806 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3807 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3808 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3809 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3810 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3811 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3812 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3813 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3814 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3815 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3816 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3817 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3818 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3819 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
3820 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3821 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3822 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3823 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3825 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3826 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3827 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3828 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3829 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3830 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3831 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3832 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3833 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3834 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3835 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3836 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3837 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3838 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3839 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3840 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3841 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3842 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3843 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3844 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3845 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3846 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3847 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3848 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3849 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3850 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3851 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3852 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
3853 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3854 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3855 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3856 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3858 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3859 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3860 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3861 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3862 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3863 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3864 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3865 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3866 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3867 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3868 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3869 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3870 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3871 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3872 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3873 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3874 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3875 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3876 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3877 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3878 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3879 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3880 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3881 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3882 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3883 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3884 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3885 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
3886 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3887 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3888 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3889 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3891 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3892 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3893 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3894 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3895 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3896 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3897 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3898 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3899 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3900 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3901 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3902 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3903 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3904 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3905 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3906 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3907 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3908 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3909 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3910 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3911 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3912 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3913 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3914 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3915 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3916 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3917 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3918 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
3919 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3920 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3921 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3922 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3924 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3925 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3926 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3927 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3928 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3929 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3930 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3931 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3932 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3933 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3934 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3935 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3936 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3937 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3938 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3939 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3940 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3941 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3942 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3943 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3944 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3945 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3946 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3947 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3948 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3949 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3950 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3951 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
3952 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3953 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3954 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3955 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3957 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3958 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3959 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3960 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3961 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3962 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3963 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3964 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3965 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3966 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3967 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3968 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3969 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3970 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3971 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3972 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3973 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3974 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3975 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3976 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3977 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3978 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3979 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3980 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3981 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3982 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3983 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3984 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
3985 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3986 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3987 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3988 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3989 /* Sampler states */
3990 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
3991 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
3992 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
3993 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
3994 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
3995 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
3996 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
3997 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
3998 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
3999 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
4000 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
4001 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
4002 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
4003 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
4004 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
4005 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
4006 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
4007 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
4008 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
4009 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
4010 /* Pixel shader */
4011 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
4012 /* Transform states follow */
4013 { /* 1, undefined */ 0, state_undefined },
4014 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
4015 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
4016 { /* 4, undefined */ 0, state_undefined },
4017 { /* 5, undefined */ 0, state_undefined },
4018 { /* 6, undefined */ 0, state_undefined },
4019 { /* 7, undefined */ 0, state_undefined },
4020 { /* 8, undefined */ 0, state_undefined },
4021 { /* 9, undefined */ 0, state_undefined },
4022 { /* 10, undefined */ 0, state_undefined },
4023 { /* 11, undefined */ 0, state_undefined },
4024 { /* 12, undefined */ 0, state_undefined },
4025 { /* 13, undefined */ 0, state_undefined },
4026 { /* 14, undefined */ 0, state_undefined },
4027 { /* 15, undefined */ 0, state_undefined },
4028 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4029 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4030 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4031 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4032 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4033 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4034 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4035 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4036 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
4037 { /* 24, undefined */ 0, state_undefined },
4038 { /* 25, undefined */ 0, state_undefined },
4039 { /* 26, undefined */ 0, state_undefined },
4040 { /* 27, undefined */ 0, state_undefined },
4041 { /* 28, undefined */ 0, state_undefined },
4042 { /* 29, undefined */ 0, state_undefined },
4043 { /* 30, undefined */ 0, state_undefined },
4044 { /* 31, undefined */ 0, state_undefined },
4045 { /* 32, undefined */ 0, state_undefined },
4046 { /* 33, undefined */ 0, state_undefined },
4047 { /* 34, undefined */ 0, state_undefined },
4048 { /* 35, undefined */ 0, state_undefined },
4049 { /* 36, undefined */ 0, state_undefined },
4050 { /* 37, undefined */ 0, state_undefined },
4051 { /* 38, undefined */ 0, state_undefined },
4052 { /* 39, undefined */ 0, state_undefined },
4053 { /* 40, undefined */ 0, state_undefined },
4054 { /* 41, undefined */ 0, state_undefined },
4055 { /* 42, undefined */ 0, state_undefined },
4056 { /* 43, undefined */ 0, state_undefined },
4057 { /* 44, undefined */ 0, state_undefined },
4058 { /* 45, undefined */ 0, state_undefined },
4059 { /* 46, undefined */ 0, state_undefined },
4060 { /* 47, undefined */ 0, state_undefined },
4061 { /* 48, undefined */ 0, state_undefined },
4062 { /* 49, undefined */ 0, state_undefined },
4063 { /* 50, undefined */ 0, state_undefined },
4064 { /* 51, undefined */ 0, state_undefined },
4065 { /* 52, undefined */ 0, state_undefined },
4066 { /* 53, undefined */ 0, state_undefined },
4067 { /* 54, undefined */ 0, state_undefined },
4068 { /* 55, undefined */ 0, state_undefined },
4069 { /* 56, undefined */ 0, state_undefined },
4070 { /* 57, undefined */ 0, state_undefined },
4071 { /* 58, undefined */ 0, state_undefined },
4072 { /* 59, undefined */ 0, state_undefined },
4073 { /* 60, undefined */ 0, state_undefined },
4074 { /* 61, undefined */ 0, state_undefined },
4075 { /* 62, undefined */ 0, state_undefined },
4076 { /* 63, undefined */ 0, state_undefined },
4077 { /* 64, undefined */ 0, state_undefined },
4078 { /* 65, undefined */ 0, state_undefined },
4079 { /* 66, undefined */ 0, state_undefined },
4080 { /* 67, undefined */ 0, state_undefined },
4081 { /* 68, undefined */ 0, state_undefined },
4082 { /* 69, undefined */ 0, state_undefined },
4083 { /* 70, undefined */ 0, state_undefined },
4084 { /* 71, undefined */ 0, state_undefined },
4085 { /* 72, undefined */ 0, state_undefined },
4086 { /* 73, undefined */ 0, state_undefined },
4087 { /* 74, undefined */ 0, state_undefined },
4088 { /* 75, undefined */ 0, state_undefined },
4089 { /* 76, undefined */ 0, state_undefined },
4090 { /* 77, undefined */ 0, state_undefined },
4091 { /* 78, undefined */ 0, state_undefined },
4092 { /* 79, undefined */ 0, state_undefined },
4093 { /* 80, undefined */ 0, state_undefined },
4094 { /* 81, undefined */ 0, state_undefined },
4095 { /* 82, undefined */ 0, state_undefined },
4096 { /* 83, undefined */ 0, state_undefined },
4097 { /* 84, undefined */ 0, state_undefined },
4098 { /* 85, undefined */ 0, state_undefined },
4099 { /* 86, undefined */ 0, state_undefined },
4100 { /* 87, undefined */ 0, state_undefined },
4101 { /* 88, undefined */ 0, state_undefined },
4102 { /* 89, undefined */ 0, state_undefined },
4103 { /* 90, undefined */ 0, state_undefined },
4104 { /* 91, undefined */ 0, state_undefined },
4105 { /* 92, undefined */ 0, state_undefined },
4106 { /* 93, undefined */ 0, state_undefined },
4107 { /* 94, undefined */ 0, state_undefined },
4108 { /* 95, undefined */ 0, state_undefined },
4109 { /* 96, undefined */ 0, state_undefined },
4110 { /* 97, undefined */ 0, state_undefined },
4111 { /* 98, undefined */ 0, state_undefined },
4112 { /* 99, undefined */ 0, state_undefined },
4113 { /*100, undefined */ 0, state_undefined },
4114 { /*101, undefined */ 0, state_undefined },
4115 { /*102, undefined */ 0, state_undefined },
4116 { /*103, undefined */ 0, state_undefined },
4117 { /*104, undefined */ 0, state_undefined },
4118 { /*105, undefined */ 0, state_undefined },
4119 { /*106, undefined */ 0, state_undefined },
4120 { /*107, undefined */ 0, state_undefined },
4121 { /*108, undefined */ 0, state_undefined },
4122 { /*109, undefined */ 0, state_undefined },
4123 { /*110, undefined */ 0, state_undefined },
4124 { /*111, undefined */ 0, state_undefined },
4125 { /*112, undefined */ 0, state_undefined },
4126 { /*113, undefined */ 0, state_undefined },
4127 { /*114, undefined */ 0, state_undefined },
4128 { /*115, undefined */ 0, state_undefined },
4129 { /*116, undefined */ 0, state_undefined },
4130 { /*117, undefined */ 0, state_undefined },
4131 { /*118, undefined */ 0, state_undefined },
4132 { /*119, undefined */ 0, state_undefined },
4133 { /*120, undefined */ 0, state_undefined },
4134 { /*121, undefined */ 0, state_undefined },
4135 { /*122, undefined */ 0, state_undefined },
4136 { /*123, undefined */ 0, state_undefined },
4137 { /*124, undefined */ 0, state_undefined },
4138 { /*125, undefined */ 0, state_undefined },
4139 { /*126, undefined */ 0, state_undefined },
4140 { /*127, undefined */ 0, state_undefined },
4141 { /*128, undefined */ 0, state_undefined },
4142 { /*129, undefined */ 0, state_undefined },
4143 { /*130, undefined */ 0, state_undefined },
4144 { /*131, undefined */ 0, state_undefined },
4145 { /*132, undefined */ 0, state_undefined },
4146 { /*133, undefined */ 0, state_undefined },
4147 { /*134, undefined */ 0, state_undefined },
4148 { /*135, undefined */ 0, state_undefined },
4149 { /*136, undefined */ 0, state_undefined },
4150 { /*137, undefined */ 0, state_undefined },
4151 { /*138, undefined */ 0, state_undefined },
4152 { /*139, undefined */ 0, state_undefined },
4153 { /*140, undefined */ 0, state_undefined },
4154 { /*141, undefined */ 0, state_undefined },
4155 { /*142, undefined */ 0, state_undefined },
4156 { /*143, undefined */ 0, state_undefined },
4157 { /*144, undefined */ 0, state_undefined },
4158 { /*145, undefined */ 0, state_undefined },
4159 { /*146, undefined */ 0, state_undefined },
4160 { /*147, undefined */ 0, state_undefined },
4161 { /*148, undefined */ 0, state_undefined },
4162 { /*149, undefined */ 0, state_undefined },
4163 { /*150, undefined */ 0, state_undefined },
4164 { /*151, undefined */ 0, state_undefined },
4165 { /*152, undefined */ 0, state_undefined },
4166 { /*153, undefined */ 0, state_undefined },
4167 { /*154, undefined */ 0, state_undefined },
4168 { /*155, undefined */ 0, state_undefined },
4169 { /*156, undefined */ 0, state_undefined },
4170 { /*157, undefined */ 0, state_undefined },
4171 { /*158, undefined */ 0, state_undefined },
4172 { /*159, undefined */ 0, state_undefined },
4173 { /*160, undefined */ 0, state_undefined },
4174 { /*161, undefined */ 0, state_undefined },
4175 { /*162, undefined */ 0, state_undefined },
4176 { /*163, undefined */ 0, state_undefined },
4177 { /*164, undefined */ 0, state_undefined },
4178 { /*165, undefined */ 0, state_undefined },
4179 { /*166, undefined */ 0, state_undefined },
4180 { /*167, undefined */ 0, state_undefined },
4181 { /*168, undefined */ 0, state_undefined },
4182 { /*169, undefined */ 0, state_undefined },
4183 { /*170, undefined */ 0, state_undefined },
4184 { /*171, undefined */ 0, state_undefined },
4185 { /*172, undefined */ 0, state_undefined },
4186 { /*173, undefined */ 0, state_undefined },
4187 { /*174, undefined */ 0, state_undefined },
4188 { /*175, undefined */ 0, state_undefined },
4189 { /*176, undefined */ 0, state_undefined },
4190 { /*177, undefined */ 0, state_undefined },
4191 { /*178, undefined */ 0, state_undefined },
4192 { /*179, undefined */ 0, state_undefined },
4193 { /*180, undefined */ 0, state_undefined },
4194 { /*181, undefined */ 0, state_undefined },
4195 { /*182, undefined */ 0, state_undefined },
4196 { /*183, undefined */ 0, state_undefined },
4197 { /*184, undefined */ 0, state_undefined },
4198 { /*185, undefined */ 0, state_undefined },
4199 { /*186, undefined */ 0, state_undefined },
4200 { /*187, undefined */ 0, state_undefined },
4201 { /*188, undefined */ 0, state_undefined },
4202 { /*189, undefined */ 0, state_undefined },
4203 { /*190, undefined */ 0, state_undefined },
4204 { /*191, undefined */ 0, state_undefined },
4205 { /*192, undefined */ 0, state_undefined },
4206 { /*193, undefined */ 0, state_undefined },
4207 { /*194, undefined */ 0, state_undefined },
4208 { /*195, undefined */ 0, state_undefined },
4209 { /*196, undefined */ 0, state_undefined },
4210 { /*197, undefined */ 0, state_undefined },
4211 { /*198, undefined */ 0, state_undefined },
4212 { /*199, undefined */ 0, state_undefined },
4213 { /*200, undefined */ 0, state_undefined },
4214 { /*201, undefined */ 0, state_undefined },
4215 { /*202, undefined */ 0, state_undefined },
4216 { /*203, undefined */ 0, state_undefined },
4217 { /*204, undefined */ 0, state_undefined },
4218 { /*205, undefined */ 0, state_undefined },
4219 { /*206, undefined */ 0, state_undefined },
4220 { /*207, undefined */ 0, state_undefined },
4221 { /*208, undefined */ 0, state_undefined },
4222 { /*209, undefined */ 0, state_undefined },
4223 { /*210, undefined */ 0, state_undefined },
4224 { /*211, undefined */ 0, state_undefined },
4225 { /*212, undefined */ 0, state_undefined },
4226 { /*213, undefined */ 0, state_undefined },
4227 { /*214, undefined */ 0, state_undefined },
4228 { /*215, undefined */ 0, state_undefined },
4229 { /*216, undefined */ 0, state_undefined },
4230 { /*217, undefined */ 0, state_undefined },
4231 { /*218, undefined */ 0, state_undefined },
4232 { /*219, undefined */ 0, state_undefined },
4233 { /*220, undefined */ 0, state_undefined },
4234 { /*221, undefined */ 0, state_undefined },
4235 { /*222, undefined */ 0, state_undefined },
4236 { /*223, undefined */ 0, state_undefined },
4237 { /*224, undefined */ 0, state_undefined },
4238 { /*225, undefined */ 0, state_undefined },
4239 { /*226, undefined */ 0, state_undefined },
4240 { /*227, undefined */ 0, state_undefined },
4241 { /*228, undefined */ 0, state_undefined },
4242 { /*229, undefined */ 0, state_undefined },
4243 { /*230, undefined */ 0, state_undefined },
4244 { /*231, undefined */ 0, state_undefined },
4245 { /*232, undefined */ 0, state_undefined },
4246 { /*233, undefined */ 0, state_undefined },
4247 { /*234, undefined */ 0, state_undefined },
4248 { /*235, undefined */ 0, state_undefined },
4249 { /*236, undefined */ 0, state_undefined },
4250 { /*237, undefined */ 0, state_undefined },
4251 { /*238, undefined */ 0, state_undefined },
4252 { /*239, undefined */ 0, state_undefined },
4253 { /*240, undefined */ 0, state_undefined },
4254 { /*241, undefined */ 0, state_undefined },
4255 { /*242, undefined */ 0, state_undefined },
4256 { /*243, undefined */ 0, state_undefined },
4257 { /*244, undefined */ 0, state_undefined },
4258 { /*245, undefined */ 0, state_undefined },
4259 { /*246, undefined */ 0, state_undefined },
4260 { /*247, undefined */ 0, state_undefined },
4261 { /*248, undefined */ 0, state_undefined },
4262 { /*249, undefined */ 0, state_undefined },
4263 { /*250, undefined */ 0, state_undefined },
4264 { /*251, undefined */ 0, state_undefined },
4265 { /*252, undefined */ 0, state_undefined },
4266 { /*253, undefined */ 0, state_undefined },
4267 { /*254, undefined */ 0, state_undefined },
4268 { /*255, undefined */ 0, state_undefined },
4269 /* End huge gap */
4270 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4271 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4272 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4273 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4274 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4275 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4276 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4277 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4278 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4279 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4280 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4281 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4282 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4283 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4284 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4285 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4286 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4287 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4288 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4289 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4290 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4291 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4292 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4293 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4294 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4295 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4296 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4297 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4298 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4299 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4300 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4301 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4302 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4303 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4304 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4305 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4306 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4307 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4308 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4309 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4310 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4311 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4312 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4313 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4314 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4315 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4316 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4317 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4318 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4319 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4320 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4321 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4322 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4323 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4324 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4325 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4326 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4327 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4328 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4329 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4330 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4331 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4332 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4333 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4334 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4335 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4336 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4337 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4338 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4339 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4340 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4341 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4342 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4343 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4344 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4345 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4346 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4347 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4348 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4349 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4350 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4351 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4352 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4353 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4354 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4355 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4356 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4357 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4358 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4359 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4360 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4361 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4362 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4363 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4364 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4365 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4366 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4367 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4368 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4369 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4370 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4371 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4372 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4373 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4374 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4375 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4376 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4377 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4378 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4379 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4380 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4381 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4382 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4383 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4384 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4385 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4386 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4387 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4388 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4389 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4390 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4391 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4392 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4393 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4394 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4395 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4396 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4397 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4398 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4399 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4400 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4401 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4402 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4403 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4404 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4405 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4406 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4407 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4408 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4409 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4410 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4411 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4412 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4413 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4414 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4415 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4416 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4417 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4418 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4419 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4420 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4421 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4422 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4423 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4424 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4425 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4426 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4427 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4428 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4429 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4430 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4431 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4432 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4433 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4434 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4435 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4436 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4437 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4438 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4439 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4440 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4441 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4442 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4443 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4444 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4445 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4446 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4447 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4448 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4449 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4450 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4451 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4452 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4453 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4454 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4455 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4456 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4457 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4458 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4459 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4460 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4461 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4462 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4463 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4464 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4465 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4466 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4467 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4468 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4469 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4470 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4471 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4472 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4473 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4474 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4475 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4476 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4477 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4478 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4479 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4480 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4481 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4482 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4483 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4484 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4485 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4486 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4487 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4488 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4489 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4490 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4491 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4492 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4493 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4494 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4495 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4496 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4497 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4498 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4499 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4500 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4501 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4502 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4503 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4504 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4505 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4506 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4507 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4508 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4509 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4510 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4511 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4512 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4513 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4514 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4515 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4516 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4517 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4518 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4519 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4520 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4521 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4522 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4523 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4524 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4525 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4526 /* Various Vertex states follow */
4527 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4528 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4529 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4530 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4531 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4532 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4533 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4534 /* Lights */
4535 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4536 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4537 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4538 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4539 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4540 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4541 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4542 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4544 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4545 /* Clip planes */
4546 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4547 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4548 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4549 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4550 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4551 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4552 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4553 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4554 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4555 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4556 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4557 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4558 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4559 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4560 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4561 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4562 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4563 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4564 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4565 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4566 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4567 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4568 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4569 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4570 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4571 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4572 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4573 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4574 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4575 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4576 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4577 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4579 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},