push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / wined3d / state.c
blob787f3ead71be1498da998719e548f40014d2f4ab
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 TRACE("No Z buffer - disabling depth test\n");
111 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
112 checkGLcall("glDisable GL_DEPTH_TEST");
113 return;
116 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
117 case WINED3DZB_FALSE:
118 glDisable(GL_DEPTH_TEST);
119 checkGLcall("glDisable GL_DEPTH_TEST");
120 break;
121 case WINED3DZB_TRUE:
122 glEnable(GL_DEPTH_TEST);
123 checkGLcall("glEnable GL_DEPTH_TEST");
124 break;
125 case WINED3DZB_USEW:
126 glEnable(GL_DEPTH_TEST);
127 checkGLcall("glEnable GL_DEPTH_TEST");
128 FIXME("W buffer is not well handled\n");
129 break;
130 default:
131 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
135 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
136 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
137 * switch
139 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
140 case WINED3DCULL_NONE:
141 glDisable(GL_CULL_FACE);
142 checkGLcall("glDisable GL_CULL_FACE");
143 break;
144 case WINED3DCULL_CW:
145 glEnable(GL_CULL_FACE);
146 checkGLcall("glEnable GL_CULL_FACE");
147 glCullFace(GL_FRONT);
148 checkGLcall("glCullFace(GL_FRONT)");
149 break;
150 case WINED3DCULL_CCW:
151 glEnable(GL_CULL_FACE);
152 checkGLcall("glEnable GL_CULL_FACE");
153 glCullFace(GL_BACK);
154 checkGLcall("glCullFace(GL_BACK)");
155 break;
156 default:
157 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
161 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
162 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
163 case WINED3DSHADE_FLAT:
164 glShadeModel(GL_FLAT);
165 checkGLcall("glShadeModel(GL_FLAT)");
166 break;
167 case WINED3DSHADE_GOURAUD:
168 glShadeModel(GL_SMOOTH);
169 checkGLcall("glShadeModel(GL_SMOOTH)");
170 break;
171 case WINED3DSHADE_PHONG:
172 FIXME("WINED3DSHADE_PHONG isn't supported\n");
173 break;
174 default:
175 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
179 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
180 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
181 glEnable(GL_DITHER);
182 checkGLcall("glEnable GL_DITHER");
183 } else {
184 glDisable(GL_DITHER);
185 checkGLcall("glDisable GL_DITHER");
189 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
190 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
191 * this has to be merged with ZENABLE and ZFUNC
193 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
194 glDepthMask(1);
195 checkGLcall("glDepthMask(1)");
196 } else {
197 glDepthMask(0);
198 checkGLcall("glDepthMask(0)");
202 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
203 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
205 if(glParm) {
206 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
207 static BOOL once = FALSE;
208 /* There are a few issues with this: First, our inability to
209 * select a proper Z depth, most of the time we're stuck with
210 * D24S8, even if the app selects D32 or D16. There seem to be
211 * some other precision problems which have to be debugged to
212 * make NOTEQUAL and EQUAL work properly
214 if(!once) {
215 once = TRUE;
216 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
220 glDepthFunc(glParm);
221 checkGLcall("glDepthFunc");
225 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
226 float col[4];
227 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
229 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
230 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
231 checkGLcall("glLightModel for MODEL_AMBIENT");
234 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
235 int srcBlend = GL_ZERO;
236 int dstBlend = GL_ZERO;
238 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
239 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
240 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
241 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
242 glEnable(GL_BLEND);
243 checkGLcall("glEnable GL_BLEND");
244 } else {
245 glDisable(GL_BLEND);
246 checkGLcall("glDisable GL_BLEND");
247 /* Nothing more to do - get out */
248 return;
251 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
252 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
253 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
254 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
255 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
256 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
257 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
258 case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
259 case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
260 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
261 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
263 case WINED3DBLEND_SRCALPHASAT :
264 dstBlend = GL_SRC_ALPHA_SATURATE;
265 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
266 break;
268 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
269 * values which are still valid up to d3d9. They should not occur as dest blend values
271 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
272 srcBlend = GL_SRC_ALPHA;
273 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
274 break;
276 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
277 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
278 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
279 break;
281 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
282 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
283 default:
284 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
287 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
288 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
289 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
290 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
291 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
292 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
293 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
294 case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
295 case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
296 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
297 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
298 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
300 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
301 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
302 break;
304 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
305 dstBlend = GL_SRC_ALPHA;
306 break;
308 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
309 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
310 default:
311 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
315 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
316 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
317 glEnable(GL_LINE_SMOOTH);
318 checkGLcall("glEnable(GL_LINE_SMOOTH)");
319 if(srcBlend != GL_SRC_ALPHA) {
320 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
322 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
323 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
325 } else {
326 glDisable(GL_LINE_SMOOTH);
327 checkGLcall("glDisable(GL_LINE_SMOOTH)");
330 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
331 glBlendFunc(srcBlend, dstBlend);
332 checkGLcall("glBlendFunc");
335 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
336 float col[4];
338 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
339 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
340 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
341 checkGLcall("glBlendColor");
344 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
345 int glParm = 0;
346 float ref;
347 BOOL enable_ckey = FALSE;
349 IWineD3DSurfaceImpl *surf;
351 /* Find out if the texture on the first stage has a ckey set
352 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
353 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
354 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
355 * in case it finds some texture+colorkeyenable combination which needs extra care.
357 if(stateblock->textures[0] && (
358 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
359 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
360 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
362 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
363 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
364 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
365 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
366 * surface has alpha bits
368 if(fmt->alphaMask == 0x00000000) {
369 enable_ckey = TRUE;
374 if(enable_ckey || context->last_was_ckey) {
375 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
377 context->last_was_ckey = enable_ckey;
379 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
380 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
381 glEnable(GL_ALPHA_TEST);
382 checkGLcall("glEnable GL_ALPHA_TEST");
383 } else {
384 glDisable(GL_ALPHA_TEST);
385 checkGLcall("glDisable GL_ALPHA_TEST");
386 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
387 * enable call
389 return;
392 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
393 glParm = GL_NOTEQUAL;
394 ref = 0.0;
395 } else {
396 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
397 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
399 if(glParm) {
400 glAlphaFunc(glParm, ref);
401 checkGLcall("glAlphaFunc");
405 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
406 DWORD enable = 0xFFFFFFFF;
407 DWORD disable = 0x00000000;
409 if (use_vs(stateblock->wineD3DDevice)) {
410 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
411 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
412 * contitions I got sick of tracking down. The shader state handler disables all clip planes because
413 * of that - don't do anything here and keep them disabled
415 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
416 static BOOL warned = FALSE;
417 if(!warned) {
418 FIXME("Clipping not supported with vertex shaders\n");
419 warned = TRUE;
422 return;
425 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
426 * of already set values
429 /* If enabling / disabling all
430 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
432 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
433 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
434 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
435 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
436 glDisable(GL_DEPTH_CLAMP_NV);
437 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
439 } else {
440 disable = 0xffffffff;
441 enable = 0x00;
442 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
443 glEnable(GL_DEPTH_CLAMP_NV);
444 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
448 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
449 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
450 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
451 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
452 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
453 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
455 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
456 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
457 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
458 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
459 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
460 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
462 /** update clipping status */
463 if (enable) {
464 stateblock->clip_status.ClipUnion = 0;
465 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
466 } else {
467 stateblock->clip_status.ClipUnion = 0;
468 stateblock->clip_status.ClipIntersection = 0;
472 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
473 int glParm = GL_FUNC_ADD;
475 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
476 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
477 return;
480 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
481 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
482 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
483 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
484 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
485 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
486 default:
487 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
490 TRACE("glBlendEquation(%x)\n", glParm);
491 GL_EXTCALL(glBlendEquationEXT(glParm));
492 checkGLcall("glBlendEquation");
495 static void
496 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
497 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
498 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
499 * specular color. This is wrong:
500 * Separate specular color means the specular colour is maintained separately, whereas
501 * single color means it is merged in. However in both cases they are being used to
502 * some extent.
503 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
504 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
505 * running 1.4 yet!
508 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
509 * Instead, we need to setup the FinalCombiner properly.
511 * The default setup for the FinalCombiner is:
513 * <variable> <input> <mapping> <usage>
514 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
515 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
516 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
517 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
518 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
519 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
520 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
522 * That's pretty much fine as it is, except for variable B, which needs to take
523 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
524 * whether WINED3DRS_SPECULARENABLE is enabled or not.
527 TRACE("Setting specular enable state and materials\n");
528 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
529 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
530 checkGLcall("glMaterialfv");
532 if(stateblock->material.Power > 128.0) {
533 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
534 * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
535 * them, since 128 results in a hardly visible specular highlight, so it should be safe to
536 * to clamp to 128
538 WARN("Material power > 128\n");
539 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
540 } else {
541 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
543 checkGLcall("glMaterialf(GL_SHININESS");
545 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
546 glEnable(GL_COLOR_SUM_EXT);
547 } else {
548 TRACE("Specular colors cannot be enabled in this version of opengl\n");
550 checkGLcall("glEnable(GL_COLOR_SUM)");
552 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
553 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
554 checkGLcall("glFinalCombinerInputNV()");
556 } else {
557 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
559 /* for the case of enabled lighting: */
560 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
561 checkGLcall("glMaterialfv");
563 /* for the case of disabled lighting: */
564 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
565 glDisable(GL_COLOR_SUM_EXT);
566 } else {
567 TRACE("Specular colors cannot be disabled in this version of opengl\n");
569 checkGLcall("glDisable(GL_COLOR_SUM)");
571 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
572 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
573 checkGLcall("glFinalCombinerInputNV()");
577 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
578 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
579 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
580 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
581 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
582 stateblock->material.Specular.b, stateblock->material.Specular.a);
583 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
584 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
586 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
587 checkGLcall("glMaterialfv(GL_AMBIENT)");
588 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
589 checkGLcall("glMaterialfv(GL_DIFFUSE)");
590 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
591 checkGLcall("glMaterialfv(GL_EMISSION)");
594 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
595 unsigned int i;
597 /* Note the texture color applies to all textures whereas
598 * GL_TEXTURE_ENV_COLOR applies to active only
600 float col[4];
601 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
603 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
604 /* And now the default texture color as well */
605 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
606 /* Note the WINED3DRS value applies to all textures, but GL has one
607 * per texture, so apply it now ready to be used!
609 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
610 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
611 checkGLcall("glActiveTextureARB");
612 } else if (i>0) {
613 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
616 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
617 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
619 } else {
620 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
624 static void
625 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
626 #if 0 /* Don't use OpenGL 2.0 calls for now */
627 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
628 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
629 checkGLcall("glStencilFuncSeparate(...)");
630 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
631 checkGLcall("glStencilOpSeparate(...)");
633 else
634 #endif
635 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
636 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
637 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
638 GL_EXTCALL(glActiveStencilFaceEXT(face));
639 checkGLcall("glActiveStencilFaceEXT(...)");
640 glStencilFunc(func, ref, mask);
641 checkGLcall("glStencilFunc(...)");
642 glStencilOp(stencilFail, depthFail, stencilPass);
643 checkGLcall("glStencilOp(...)");
644 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
645 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
646 checkGLcall("glStencilFuncSeparateATI(...)");
647 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
648 checkGLcall("glStencilOpSeparateATI(...)");
649 } else {
650 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
654 static void
655 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
656 DWORD onesided_enable = FALSE;
657 DWORD twosided_enable = FALSE;
658 GLint func = GL_ALWAYS;
659 GLint func_ccw = GL_ALWAYS;
660 GLint ref = 0;
661 GLuint mask = 0;
662 GLint stencilFail = GL_KEEP;
663 GLint depthFail = GL_KEEP;
664 GLint stencilPass = GL_KEEP;
665 GLint stencilFail_ccw = GL_KEEP;
666 GLint depthFail_ccw = GL_KEEP;
667 GLint stencilPass_ccw = GL_KEEP;
669 /* No stencil test without a stencil buffer */
670 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
671 glDisable(GL_STENCIL_TEST);
672 checkGLcall("glDisable GL_STENCIL_TEST");
673 return;
676 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
677 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
678 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
679 func = GL_ALWAYS;
680 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
681 func_ccw = GL_ALWAYS;
682 ref = stateblock->renderState[WINED3DRS_STENCILREF];
683 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
684 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
685 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
686 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
687 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
688 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
689 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
691 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
692 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
693 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
694 onesided_enable, twosided_enable, ref, mask,
695 func, stencilFail, depthFail, stencilPass,
696 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
698 if (twosided_enable && onesided_enable) {
699 glEnable(GL_STENCIL_TEST);
700 checkGLcall("glEnable GL_STENCIL_TEST");
702 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
703 * which has an effect on the code below too. If we apply the front face
704 * afterwards, we are sure that the active stencil face is set to front,
705 * and other stencil functions which do not use two sided stencil do not have
706 * to set it back
708 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
709 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
710 } else if(onesided_enable) {
711 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
712 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
713 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
716 glEnable(GL_STENCIL_TEST);
717 checkGLcall("glEnable GL_STENCIL_TEST");
718 glStencilFunc(func, ref, mask);
719 checkGLcall("glStencilFunc(...)");
720 glStencilOp(stencilFail, depthFail, stencilPass);
721 checkGLcall("glStencilOp(...)");
722 } else {
723 glDisable(GL_STENCIL_TEST);
724 checkGLcall("glDisable GL_STENCIL_TEST");
728 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
729 DWORD mask;
731 if(stateblock->wineD3DDevice->stencilBufferTarget) {
732 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
733 } else {
734 mask = 0;
737 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
738 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
739 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
740 glStencilMask(mask);
741 checkGLcall("glStencilMask");
742 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
743 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
744 glStencilMask(mask);
745 } else {
746 glStencilMask(mask);
748 checkGLcall("glStencilMask");
751 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
752 /* TODO: Put this into the vertex type block once that is in the state table */
753 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
754 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
755 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
756 float fogstart, fogend;
758 union {
759 DWORD d;
760 float f;
761 } tmpvalue;
763 if (!fogenable) {
764 /* No fog? Disable it, and we're done :-) */
765 glDisable(GL_FOG);
766 checkGLcall("glDisable GL_FOG");
767 if( use_ps(stateblock->wineD3DDevice)
768 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
769 /* disable fog in the pixel shader
770 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
771 * -1/(e-s) and e/(e-s) respectively.
773 glFogf(GL_FOG_START, 0.0f);
774 checkGLcall("glFogf(GL_FOG_START, fogstart");
775 glFogf(GL_FOG_END, 1.0f);
776 checkGLcall("glFogf(GL_FOG_END, fogend");
778 return;
781 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
782 fogstart = tmpvalue.f;
783 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
784 fogend = tmpvalue.f;
786 /* Fog Rules:
788 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
789 * It can use the Z value of the vertex, or the alpha component of the specular color.
790 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
791 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
792 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
794 * FOGTABLEMODE != NONE:
795 * The Z value is used, with the equation specified, no matter what vertex type.
797 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
798 * Per vertex fog is calculated using the specified fog equation and the parameters
800 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
801 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
802 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
805 * Rules for vertex fog with shaders:
807 * When mixing fixed function functionality with the programmable pipeline, D3D expects
808 * the fog computation to happen during transformation while openGL expects it to happen
809 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
810 * the pixel shader while openGL always expects the pixel shader to handle the blending.
811 * To solve this problem, WineD3D does:
812 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
813 * shader,
814 * and 2) disables the fog computation (in either the fixed function or programmable
815 * rasterizer) if using a vertex program.
818 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
819 * without shaders).
822 if( is_ps3 ) {
823 if( !use_vs(stateblock->wineD3DDevice)
824 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
825 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
829 if (use_vs(stateblock->wineD3DDevice)
830 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
831 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
832 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
833 /* Disable fog */
834 fogenable = FALSE;
835 } else {
836 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
837 glFogi(GL_FOG_MODE, GL_LINEAR);
838 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
839 fogstart = 1.0;
840 fogend = 0.0;
843 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
844 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
845 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
846 context->fog_coord = FALSE;
848 context->last_was_foggy_shader = TRUE;
850 else if( use_ps(stateblock->wineD3DDevice) ) {
851 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
852 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
854 WINED3DFOGMODE mode;
855 context->last_was_foggy_shader = FALSE;
857 /* If both fogmodes are set use the table fog mode */
858 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
859 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
860 else
861 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
863 switch (mode) {
864 case WINED3DFOG_EXP:
865 case WINED3DFOG_EXP2:
866 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
867 /* Disable fog */
868 fogenable = FALSE;
869 break;
871 case WINED3DFOG_LINEAR:
872 fogstart = -1.0f/(fogend-fogstart);
873 fogend *= -fogstart;
874 break;
876 case WINED3DFOG_NONE:
877 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
878 /* Disable fog */
879 fogenable = FALSE;
880 break;
881 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
884 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
885 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
886 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
887 context->fog_coord = FALSE;
890 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
891 * the system will apply only pixel(=table) fog effects."
893 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
894 glHint(GL_FOG_HINT, GL_FASTEST);
895 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
896 context->last_was_foggy_shader = FALSE;
898 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
899 /* If processed vertices are used, fall through to the NONE case */
900 case WINED3DFOG_EXP: {
901 if(!context->last_was_rhw) {
902 glFogi(GL_FOG_MODE, GL_EXP);
903 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
904 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
905 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
906 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
907 context->fog_coord = FALSE;
909 break;
912 case WINED3DFOG_EXP2: {
913 if(!context->last_was_rhw) {
914 glFogi(GL_FOG_MODE, GL_EXP2);
915 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
916 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
917 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
918 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
919 context->fog_coord = FALSE;
921 break;
924 case WINED3DFOG_LINEAR: {
925 if(!context->last_was_rhw) {
926 glFogi(GL_FOG_MODE, GL_LINEAR);
927 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
928 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
929 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
930 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
931 context->fog_coord = FALSE;
933 break;
936 case WINED3DFOG_NONE: {
937 /* Both are none? According to msdn the alpha channel of the specular
938 * color contains a fog factor. Set it in drawStridedSlow.
939 * Same happens with Vertexfog on transformed vertices
941 if(GL_SUPPORT(EXT_FOG_COORD)) {
942 if(context->fog_coord == FALSE) {
943 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
944 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
945 context->fog_coord = TRUE;
947 glFogi(GL_FOG_MODE, GL_LINEAR);
948 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
949 fogstart = 0xff;
950 fogend = 0x0;
951 } else {
952 /* Disable GL fog, handle this in software in drawStridedSlow */
953 fogenable = FALSE;
955 break;
957 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
959 } else {
960 glHint(GL_FOG_HINT, GL_NICEST);
961 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
962 context->last_was_foggy_shader = FALSE;
964 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
965 case WINED3DFOG_EXP:
966 glFogi(GL_FOG_MODE, GL_EXP);
967 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
968 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
969 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
970 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
971 context->fog_coord = FALSE;
973 break;
975 case WINED3DFOG_EXP2:
976 glFogi(GL_FOG_MODE, GL_EXP2);
977 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
978 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
979 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
980 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
981 context->fog_coord = FALSE;
983 break;
985 case WINED3DFOG_LINEAR:
986 glFogi(GL_FOG_MODE, GL_LINEAR);
987 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
988 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
989 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
990 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
991 context->fog_coord = FALSE;
993 break;
995 case WINED3DFOG_NONE: /* Won't happen */
996 default:
997 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1001 if(fogenable) {
1002 glEnable(GL_FOG);
1003 checkGLcall("glEnable GL_FOG");
1005 if(fogstart != fogend)
1007 glFogfv(GL_FOG_START, &fogstart);
1008 checkGLcall("glFogf(GL_FOG_START, fogstart");
1009 TRACE("Fog Start == %f\n", fogstart);
1011 glFogfv(GL_FOG_END, &fogend);
1012 checkGLcall("glFogf(GL_FOG_END, fogend");
1013 TRACE("Fog End == %f\n", fogend);
1015 else
1017 glFogf(GL_FOG_START, -1.0 / 0.0);
1018 checkGLcall("glFogf(GL_FOG_START, fogstart");
1019 TRACE("Fog Start == %f\n", fogstart);
1021 glFogf(GL_FOG_END, 0.0);
1022 checkGLcall("glFogf(GL_FOG_END, fogend");
1023 TRACE("Fog End == %f\n", fogend);
1025 } else {
1026 glDisable(GL_FOG);
1027 checkGLcall("glDisable GL_FOG");
1028 if( use_ps(stateblock->wineD3DDevice) ) {
1029 /* disable fog in the pixel shader
1030 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1031 * -1/(e-s) and e/(e-s) respectively.
1033 glFogf(GL_FOG_START, 0.0f);
1034 checkGLcall("glFogf(GL_FOG_START, fogstart");
1035 glFogf(GL_FOG_END, 1.0f);
1036 checkGLcall("glFogf(GL_FOG_END, fogend");
1041 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1042 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1043 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1044 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1045 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1046 } else {
1047 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1049 } else {
1050 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1051 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1052 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1057 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1058 float col[4];
1059 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1060 glFogfv(GL_FOG_COLOR, &col[0]);
1061 checkGLcall("glFog GL_FOG_COLOR");
1064 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1065 union {
1066 DWORD d;
1067 float f;
1068 } tmpvalue;
1069 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1070 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1071 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1074 /* TODO: Merge with primitive type + init_materials()!! */
1075 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1076 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice;
1077 GLenum Parm = 0;
1078 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1079 BOOL isDiffuseSupplied;
1081 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1082 * The vertex declaration will call this function if the fixed function pipeline is used.
1085 if(isStateDirty(context, STATE_VDECL)) {
1086 return;
1089 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1091 context->num_untracked_materials = 0;
1092 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1093 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1094 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1095 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1096 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1097 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1099 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1100 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1101 Parm = GL_AMBIENT_AND_DIFFUSE;
1102 } else {
1103 Parm = GL_DIFFUSE;
1105 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1106 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1107 context->num_untracked_materials++;
1109 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1110 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1111 context->num_untracked_materials++;
1113 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1114 Parm = GL_AMBIENT;
1115 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1116 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1117 context->num_untracked_materials++;
1119 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1120 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1121 context->num_untracked_materials++;
1123 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1124 Parm = GL_EMISSION;
1125 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1126 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1127 context->num_untracked_materials++;
1129 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1130 Parm = GL_SPECULAR;
1134 /* Nothing changed, return. */
1135 if (Parm == context->tracking_parm) return;
1137 if(!Parm) {
1138 glDisable(GL_COLOR_MATERIAL);
1139 checkGLcall("glDisable GL_COLOR_MATERIAL");
1140 } else {
1141 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1142 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1143 glEnable(GL_COLOR_MATERIAL);
1144 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1147 /* Apparently calls to glMaterialfv are ignored for properties we're
1148 * tracking with glColorMaterial, so apply those here. */
1149 switch (context->tracking_parm) {
1150 case GL_AMBIENT_AND_DIFFUSE:
1151 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1152 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1153 checkGLcall("glMaterialfv");
1154 break;
1156 case GL_DIFFUSE:
1157 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1158 checkGLcall("glMaterialfv");
1159 break;
1161 case GL_AMBIENT:
1162 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1163 checkGLcall("glMaterialfv");
1164 break;
1166 case GL_EMISSION:
1167 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1168 checkGLcall("glMaterialfv");
1169 break;
1171 case GL_SPECULAR:
1172 /* Only change material color if specular is enabled, otherwise it is set to black */
1173 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1174 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1175 checkGLcall("glMaterialfv");
1176 } else {
1177 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1178 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1179 checkGLcall("glMaterialfv");
1181 break;
1184 context->tracking_parm = Parm;
1187 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1188 union {
1189 DWORD d;
1190 WINED3DLINEPATTERN lp;
1191 } tmppattern;
1192 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1194 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1196 if (tmppattern.lp.wRepeatFactor) {
1197 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1198 checkGLcall("glLineStipple(repeat, linepattern)");
1199 glEnable(GL_LINE_STIPPLE);
1200 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1201 } else {
1202 glDisable(GL_LINE_STIPPLE);
1203 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1207 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1208 union {
1209 DWORD d;
1210 float f;
1211 } tmpvalue;
1213 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1214 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1215 TRACE("ZBias value %f\n", tmpvalue.f);
1216 glPolygonOffset(0, -tmpvalue.f);
1217 checkGLcall("glPolygonOffset(0, -Value)");
1218 glEnable(GL_POLYGON_OFFSET_FILL);
1219 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1220 glEnable(GL_POLYGON_OFFSET_LINE);
1221 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1222 glEnable(GL_POLYGON_OFFSET_POINT);
1223 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1224 } else {
1225 glDisable(GL_POLYGON_OFFSET_FILL);
1226 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1227 glDisable(GL_POLYGON_OFFSET_LINE);
1228 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1229 glDisable(GL_POLYGON_OFFSET_POINT);
1230 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1235 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1236 if(isStateDirty(context, STATE_VDECL)) {
1237 return;
1239 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1240 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1241 * by zero and is not properly defined in opengl, so avoid it
1243 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1244 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1245 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1246 glEnable(GL_NORMALIZE);
1247 checkGLcall("glEnable(GL_NORMALIZE);");
1248 } else {
1249 glDisable(GL_NORMALIZE);
1250 checkGLcall("glDisable(GL_NORMALIZE);");
1254 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1255 union {
1256 DWORD d;
1257 float f;
1258 } tmpvalue;
1260 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1261 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1262 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1263 checkGLcall("glPointParameterfARB(...");
1265 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1266 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1267 checkGLcall("glPointParameterfEXT(...);");
1268 } else if(tmpvalue.f != 1.0) {
1269 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1273 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1274 union {
1275 DWORD d;
1276 float f;
1277 } tmpvalue;
1279 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1280 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1281 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1282 checkGLcall("glPointParameterfARB(...");
1284 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1285 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1286 checkGLcall("glPointParameterfEXT(...);");
1287 } else if(tmpvalue.f != 64.0) {
1288 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1292 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1293 /* TODO: Group this with the viewport */
1295 * POINTSCALEENABLE controls how point size value is treated. If set to
1296 * true, the point size is scaled with respect to height of viewport.
1297 * When set to false point size is in pixels.
1299 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
1302 /* Default values */
1303 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1304 union {
1305 DWORD d;
1306 float f;
1307 } pointSize, A, B, C;
1309 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1310 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1311 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1312 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1314 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1315 GLfloat scaleFactor;
1316 float h = stateblock->viewport.Height;
1318 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1320 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1321 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1322 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1323 * are less than 1.0f. scale_factor = 1.0f / point_size.
1325 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1326 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1327 * is 1.0, but then accepts points below that and draws too small points
1329 pointSize.f = GL_LIMITS(pointsizemin);
1330 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1331 /* gl already scales the input to glPointSize,
1332 * d3d scales the result after the point size scale.
1333 * If the point size is bigger than the max size, use the
1334 * scaling to scale it bigger, and set the gl point size to max
1336 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1337 TRACE("scale: %f\n", scaleFactor);
1338 pointSize.f = GL_LIMITS(pointsize);
1339 } else {
1340 scaleFactor = 1.0f;
1342 scaleFactor = pow(h * scaleFactor, 2);
1344 att[0] = A.f / scaleFactor;
1345 att[1] = B.f / scaleFactor;
1346 att[2] = C.f / scaleFactor;
1349 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1350 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1351 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
1353 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1354 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1355 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
1356 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1357 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1360 glPointSize(pointSize.f);
1361 checkGLcall("glPointSize(...);");
1364 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1365 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1367 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1368 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1369 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1370 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1371 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1372 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1373 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1374 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1375 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1376 checkGLcall("glColorMask(...)");
1378 /* depends on WINED3DRS_COLORWRITEENABLE. */
1379 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1380 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1381 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1382 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1383 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1384 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1385 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1389 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1390 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1391 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1392 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1393 } else {
1394 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1395 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1399 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1400 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1401 TRACE("Last Pixel Drawing Enabled\n");
1402 } else {
1403 static BOOL first = TRUE;
1404 if(first) {
1405 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1406 first = FALSE;
1407 } else {
1408 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1413 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1414 /* TODO: NV_POINT_SPRITE */
1415 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1416 TRACE("Point sprites not supported\n");
1417 return;
1420 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1421 glEnable(GL_POINT_SPRITE_ARB);
1422 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n");
1423 } else {
1424 glDisable(GL_POINT_SPRITE_ARB);
1425 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n");
1429 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1431 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1432 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
1433 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1434 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
1435 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1437 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1439 TRACE("Stub\n");
1440 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1441 stateblock->renderState[WINED3DRS_WRAP1] ||
1442 stateblock->renderState[WINED3DRS_WRAP2] ||
1443 stateblock->renderState[WINED3DRS_WRAP3] ||
1444 stateblock->renderState[WINED3DRS_WRAP4] ||
1445 stateblock->renderState[WINED3DRS_WRAP5] ||
1446 stateblock->renderState[WINED3DRS_WRAP6] ||
1447 stateblock->renderState[WINED3DRS_WRAP7] ||
1448 stateblock->renderState[WINED3DRS_WRAP8] ||
1449 stateblock->renderState[WINED3DRS_WRAP9] ||
1450 stateblock->renderState[WINED3DRS_WRAP10] ||
1451 stateblock->renderState[WINED3DRS_WRAP11] ||
1452 stateblock->renderState[WINED3DRS_WRAP12] ||
1453 stateblock->renderState[WINED3DRS_WRAP13] ||
1454 stateblock->renderState[WINED3DRS_WRAP14] ||
1455 stateblock->renderState[WINED3DRS_WRAP15] ) {
1456 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1460 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1461 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1462 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1463 glEnable(GL_MULTISAMPLE_ARB);
1464 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1465 } else {
1466 glDisable(GL_MULTISAMPLE_ARB);
1467 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1469 } else {
1470 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1471 WARN("Multisample antialiasing not supported by gl\n");
1476 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1477 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1478 glEnable(GL_SCISSOR_TEST);
1479 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1480 } else {
1481 glDisable(GL_SCISSOR_TEST);
1482 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1486 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1487 union {
1488 DWORD d;
1489 float f;
1490 } tmpvalue;
1492 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1493 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1494 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1495 glEnable(GL_POLYGON_OFFSET_FILL);
1496 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1497 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1498 checkGLcall("glPolygonOffset(...)");
1499 } else {
1500 glDisable(GL_POLYGON_OFFSET_FILL);
1501 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1505 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1506 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1507 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1508 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1509 } else {
1510 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1511 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1515 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1516 TRACE("Stub\n");
1517 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1518 FIXME(" Stippled Alpha not supported yet.\n");
1521 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1522 TRACE("Stub\n");
1523 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1524 FIXME(" Antialias not supported yet.\n");
1527 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1528 TRACE("Stub\n");
1529 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1530 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1533 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1534 TRACE("Stub\n");
1535 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1536 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1539 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1540 union {
1541 DWORD d;
1542 float f;
1543 } tmpvalue;
1544 tmpvalue.f = 1.0f;
1546 TRACE("Stub\n");
1547 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1549 static BOOL displayed = FALSE;
1551 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1552 if(!displayed)
1553 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1555 displayed = TRUE;
1559 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1560 TRACE("Stub\n");
1561 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1562 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1565 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1566 TRACE("Stub\n");
1567 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1568 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1571 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1572 TRACE("Stub\n");
1573 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1574 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1577 static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1578 TRACE("Stub\n");
1579 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
1580 FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
1583 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1584 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1585 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1589 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1590 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1591 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1595 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1596 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1597 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1601 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1602 if(stateblock->renderState[WINED3DRS_ROP2]) {
1603 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1607 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1608 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1609 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1613 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1614 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1615 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1619 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1620 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1621 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1625 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1626 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1627 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1631 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1632 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1633 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1637 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1638 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1639 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1643 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1644 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1645 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1649 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1650 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1651 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1655 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1656 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1657 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1661 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1662 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1663 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1667 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1668 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1669 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1673 /* Activates the texture dimension according to the bound D3D texture.
1674 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1675 * Requires the caller to activate the correct unit before
1677 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1678 BOOL bumpmap = FALSE;
1680 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1681 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1682 bumpmap = TRUE;
1683 context->texShaderBumpMap |= (1 << stage);
1684 } else {
1685 context->texShaderBumpMap &= ~(1 << stage);
1688 if(stateblock->textures[stage]) {
1689 switch(stateblock->textureDimensions[stage]) {
1690 case GL_TEXTURE_2D:
1691 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1692 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1693 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1694 } else {
1695 glDisable(GL_TEXTURE_3D);
1696 checkGLcall("glDisable(GL_TEXTURE_3D)");
1697 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1698 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1699 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1701 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1702 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1703 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1705 glEnable(GL_TEXTURE_2D);
1706 checkGLcall("glEnable(GL_TEXTURE_2D)");
1708 break;
1709 case GL_TEXTURE_RECTANGLE_ARB:
1710 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1711 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB);
1712 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1713 } else {
1714 glDisable(GL_TEXTURE_2D);
1715 checkGLcall("glDisable(GL_TEXTURE_2D)");
1716 glDisable(GL_TEXTURE_3D);
1717 checkGLcall("glDisable(GL_TEXTURE_3D)");
1718 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1719 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1720 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1722 glEnable(GL_TEXTURE_RECTANGLE_ARB);
1723 checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
1725 break;
1726 case GL_TEXTURE_3D:
1727 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1728 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1729 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)");
1730 } else {
1731 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1732 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1733 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1735 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1736 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1737 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1739 glDisable(GL_TEXTURE_2D);
1740 checkGLcall("glDisable(GL_TEXTURE_2D)");
1741 glEnable(GL_TEXTURE_3D);
1742 checkGLcall("glEnable(GL_TEXTURE_3D)");
1744 break;
1745 case GL_TEXTURE_CUBE_MAP_ARB:
1746 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1747 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1748 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
1749 } else {
1750 glDisable(GL_TEXTURE_2D);
1751 checkGLcall("glDisable(GL_TEXTURE_2D)");
1752 glDisable(GL_TEXTURE_3D);
1753 checkGLcall("glDisable(GL_TEXTURE_3D)");
1754 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1755 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1756 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1758 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1759 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1761 break;
1763 } else {
1764 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1765 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1766 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)");
1767 } else {
1768 glEnable(GL_TEXTURE_2D);
1769 checkGLcall("glEnable(GL_TEXTURE_2D)");
1770 glDisable(GL_TEXTURE_3D);
1771 checkGLcall("glDisable(GL_TEXTURE_3D)");
1772 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1773 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1774 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1776 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1777 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1778 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1780 /* Binding textures is done by samplers. A dummy texture will be bound */
1785 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1786 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1787 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1788 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1790 TRACE("Setting color op for stage %d\n", stage);
1792 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1793 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1794 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1795 return;
1798 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1800 if (mapped_stage != -1) {
1801 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1802 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1803 FIXME("Attempt to enable unsupported stage!\n");
1804 return;
1806 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1807 checkGLcall("glActiveTextureARB");
1808 } else if (stage > 0) {
1809 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1810 return;
1814 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1815 if(stateblock->lowest_disabled_stage > 0) {
1816 glEnable(GL_REGISTER_COMBINERS_NV);
1817 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1818 } else {
1819 glDisable(GL_REGISTER_COMBINERS_NV);
1822 if(stage >= stateblock->lowest_disabled_stage) {
1823 TRACE("Stage disabled\n");
1824 if (mapped_stage != -1) {
1825 /* Disable everything here */
1826 glDisable(GL_TEXTURE_2D);
1827 checkGLcall("glDisable(GL_TEXTURE_2D)");
1828 glDisable(GL_TEXTURE_3D);
1829 checkGLcall("glDisable(GL_TEXTURE_3D)");
1830 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1831 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1832 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1834 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1835 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1836 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1838 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1839 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1842 /* All done */
1843 return;
1846 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1847 * if the sampler for this stage is dirty
1849 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1850 if (tex_used) activate_dimensions(stage, stateblock, context);
1853 /* Set the texture combiners */
1854 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1855 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1856 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1857 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1858 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1859 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1860 mapped_stage);
1862 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1863 * thus the texture shader may have to be updated
1865 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1866 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1867 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1868 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1869 if(usesBump != usedBump) {
1870 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1871 checkGLcall("glActiveTextureARB");
1872 activate_dimensions(stage + 1, stateblock, context);
1873 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1874 checkGLcall("glActiveTextureARB");
1877 } else {
1878 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1879 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1880 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1881 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1882 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1886 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1887 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1888 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1889 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1890 DWORD op, arg1, arg2, arg0;
1892 TRACE("Setting alpha op for stage %d\n", stage);
1893 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1894 if (mapped_stage != -1) {
1895 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1896 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1897 FIXME("Attempt to enable unsupported stage!\n");
1898 return;
1900 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1901 checkGLcall("glActiveTextureARB");
1902 } else if (stage > 0) {
1903 /* We can't do anything here */
1904 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1905 return;
1909 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1910 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1911 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1912 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1914 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1915 stateblock->textures[0] &&
1916 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
1917 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1919 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1920 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1922 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1923 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1924 * cannot remove the texture's alpha channel entirely.
1926 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1927 * on color keyed surfaces.
1929 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1931 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1932 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1933 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1937 TRACE("Setting alpha op for stage %d\n", stage);
1938 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1939 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1940 op, arg1, arg2, arg0,
1941 mapped_stage);
1942 } else {
1943 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1944 op, arg1, arg2, arg0);
1948 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1949 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1950 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1951 BOOL generated;
1953 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
1954 if(use_vs(stateblock->wineD3DDevice) ||
1955 isStateDirty(context, STATE_VDECL)) {
1956 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
1957 return;
1960 if (mapped_stage < 0) return;
1962 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1963 if(mapped_stage >= GL_LIMITS(textures)) {
1964 return;
1966 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1967 checkGLcall("glActiveTextureARB");
1968 } else if (mapped_stage > 0) {
1969 /* We can't do anything here */
1970 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1971 return;
1973 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
1975 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1976 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1977 generated,
1978 context->last_was_rhw,
1979 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
1980 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
1981 WINED3DDECLTYPE_UNUSED);
1983 /* The sampler applying function calls us if this changes */
1984 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
1985 if(generated) {
1986 FIXME("Non-power2 texture being used with generated texture coords\n");
1988 TRACE("Non power two matrix multiply fixup\n");
1989 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
1993 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1994 int texture_idx;
1996 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1997 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1998 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2002 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2003 UINT *offset = stateblock->streamOffset;
2004 unsigned int mapped_stage = 0;
2005 unsigned int textureNo = 0;
2007 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2008 /* Abort if we don't support the extension. */
2009 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2010 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2011 return;
2014 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2015 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2017 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2018 if (mapped_stage == -1) continue;
2020 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2021 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2022 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2024 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2025 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2026 checkGLcall("glBindBufferARB");
2027 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2030 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2031 checkGLcall("glClientActiveTextureARB");
2033 /* The coords to supply depend completely on the fvf / vertex shader */
2034 glTexCoordPointer(
2035 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2036 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2037 sd->u.s.texCoords[coordIdx].dwStride,
2038 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2039 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2040 } else {
2041 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2044 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2045 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2046 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2047 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2052 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2053 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2054 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2056 if (mapped_stage == -1) {
2057 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2058 return;
2061 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2062 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2063 return;
2065 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2066 checkGLcall("glActiveTextureARB");
2067 } else if (stage > 0) {
2068 /* We can't do anything here */
2069 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2070 return;
2073 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2075 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2076 * one flag, you can still specify an index value, which the system uses to
2077 * determine the texture wrapping mode.
2078 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2079 * means use the vertex position (camera-space) as the input texture coordinates
2080 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2081 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2082 * to the TEXCOORDINDEX value
2086 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2088 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2089 case WINED3DTSS_TCI_PASSTHRU:
2090 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2091 glDisable(GL_TEXTURE_GEN_S);
2092 glDisable(GL_TEXTURE_GEN_T);
2093 glDisable(GL_TEXTURE_GEN_R);
2094 glDisable(GL_TEXTURE_GEN_Q);
2095 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2096 break;
2098 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2099 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2100 * as the input texture coordinates for this stage's texture transformation. This
2101 * equates roughly to EYE_LINEAR
2104 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2105 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2106 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2107 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2108 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2110 glMatrixMode(GL_MODELVIEW);
2111 glPushMatrix();
2112 glLoadIdentity();
2113 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2114 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2115 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2116 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2117 glPopMatrix();
2119 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2120 glEnable(GL_TEXTURE_GEN_S);
2121 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2122 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2123 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2124 glEnable(GL_TEXTURE_GEN_T);
2125 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2126 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2127 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2128 glEnable(GL_TEXTURE_GEN_R);
2129 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2130 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2131 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2133 break;
2135 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2137 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2138 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2139 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2140 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2141 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2142 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2144 glMatrixMode(GL_MODELVIEW);
2145 glPushMatrix();
2146 glLoadIdentity();
2147 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2148 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2149 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2150 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2151 glPopMatrix();
2153 glEnable(GL_TEXTURE_GEN_S);
2154 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2155 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2156 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2157 glEnable(GL_TEXTURE_GEN_T);
2158 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2159 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2160 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2161 glEnable(GL_TEXTURE_GEN_R);
2162 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2163 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2164 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2167 break;
2169 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2171 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2172 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2173 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2174 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2175 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2176 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2178 glMatrixMode(GL_MODELVIEW);
2179 glPushMatrix();
2180 glLoadIdentity();
2181 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2182 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2183 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2184 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2185 glPopMatrix();
2187 glEnable(GL_TEXTURE_GEN_S);
2188 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2189 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2190 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2191 glEnable(GL_TEXTURE_GEN_T);
2192 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2193 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2194 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2195 glEnable(GL_TEXTURE_GEN_R);
2196 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2197 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2198 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2201 break;
2203 /* Unhandled types: */
2204 default:
2205 /* Todo: */
2206 /* ? disable GL_TEXTURE_GEN_n ? */
2207 glDisable(GL_TEXTURE_GEN_S);
2208 glDisable(GL_TEXTURE_GEN_T);
2209 glDisable(GL_TEXTURE_GEN_R);
2210 glDisable(GL_TEXTURE_GEN_Q);
2211 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2212 break;
2215 /* Update the texture matrix */
2216 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2217 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2220 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2221 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2222 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2223 * and do all the things linked to it
2224 * TODO: Tidy that up to reload only the arrays of the changed unit
2226 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2228 unloadTexCoords(stateblock);
2229 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2233 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2234 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2236 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2237 * has an update pending
2239 if(isStateDirty(context, STATE_VDECL) ||
2240 isStateDirty(context, STATE_PIXELSHADER)) {
2241 return;
2244 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2247 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2248 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2249 union {
2250 DWORD d;
2251 float f;
2252 } tmpvalue;
2254 if(stateblock->pixelShader && stage != 0 &&
2255 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) {
2256 /* The pixel shader has to know the luminance scale. Do a constants update if it
2257 * isn't scheduled anyway
2259 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2260 !isStateDirty(context, STATE_PIXELSHADER)) {
2261 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2265 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2266 if(tmpvalue.f != 0.0) {
2267 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2271 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2272 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2273 union {
2274 DWORD d;
2275 float f;
2276 } tmpvalue;
2278 if(stateblock->pixelShader && stage != 0 &&
2279 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) {
2280 /* The pixel shader has to know the luminance offset. Do a constants update if it
2281 * isn't scheduled anyway
2283 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2284 !isStateDirty(context, STATE_PIXELSHADER)) {
2285 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2289 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2290 if(tmpvalue.f != 0.0) {
2291 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2295 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2296 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2298 if(stage >= GL_LIMITS(texture_stages)) {
2299 return;
2302 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2303 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2307 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2308 DWORD sampler = state - STATE_SAMPLER(0);
2309 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2310 union {
2311 float f;
2312 DWORD d;
2313 } tmpvalue;
2315 TRACE("Sampler: %d\n", sampler);
2316 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2317 * only has to bind textures and set the per texture states
2320 if (mapped_stage == -1) {
2321 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2322 return;
2325 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2326 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2327 return;
2329 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2330 checkGLcall("glActiveTextureARB");
2331 } else if (sampler > 0) {
2332 /* We can't do anything here */
2333 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2334 return;
2337 if(stateblock->textures[sampler]) {
2338 BOOL texIsPow2 = FALSE;
2340 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2341 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2342 * scaling is reapplied or removed, the texture matrix has to be reapplied
2344 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2345 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2346 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2347 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0 ||
2348 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[5] != 1.0 ) {
2349 texIsPow2 = TRUE;
2351 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2352 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0) {
2353 texIsPow2 = TRUE;
2357 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2358 context->lastWasPow2Texture[sampler] = texIsPow2;
2359 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2363 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2364 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2366 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2367 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2368 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2369 GL_TEXTURE_LOD_BIAS_EXT,
2370 tmpvalue.f);
2371 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2374 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2375 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2376 /* Using a pixel shader? Verify the sampler types */
2378 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2379 * dimensions because the shader knows from which texture type to sample from. For the sake of
2380 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2381 * dimensions. This should make wrong sampling sources visible :-)
2383 glEnable(stateblock->textureDimensions[sampler]);
2384 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2385 } else if(sampler < stateblock->lowest_disabled_stage) {
2386 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2387 activate_dimensions(sampler, stateblock, context);
2390 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2391 /* If color keying is enabled update the alpha test, it depends on the existence
2392 * of a color key in stage 0
2394 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2397 } else if(mapped_stage < GL_LIMITS(textures)) {
2398 if(sampler < stateblock->lowest_disabled_stage) {
2399 /* TODO: What should I do with pixel shaders here ??? */
2400 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2401 activate_dimensions(sampler, stateblock, context);
2403 } /* Otherwise tex_colorop disables the stage */
2404 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2405 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2409 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2410 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2411 BOOL use_pshader = use_ps(device);
2412 BOOL use_vshader = use_vs(device);
2413 BOOL update_fog = FALSE;
2414 int i;
2416 if (use_pshader) {
2417 if(!context->last_was_pshader) {
2418 /* Former draw without a pixel shader, some samplers
2419 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2420 * make sure to enable them
2422 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2423 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2424 sampler(STATE_SAMPLER(i), stateblock, context);
2427 update_fog = TRUE;
2428 } else {
2429 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2430 * if a different texture was bound. I don't have to do anything.
2434 /* Compile and bind the shader */
2435 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2436 } else {
2437 /* Disabled the pixel shader - color ops weren't applied
2438 * while it was enabled, so re-apply them.
2440 for(i=0; i < MAX_TEXTURES; i++) {
2441 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2442 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2445 if(context->last_was_pshader)
2446 update_fog = TRUE;
2449 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2450 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2452 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2453 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2457 if(update_fog)
2458 state_fog(state, stateblock, context);
2460 context->last_was_pshader = use_pshader;
2463 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2464 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2466 if(stateblock->pixelShader && stage != 0 &&
2467 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2468 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2469 * anyway
2471 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2472 !isStateDirty(context, STATE_PIXELSHADER)) {
2473 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2477 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2478 if(stage >= GL_LIMITS(texture_stages)) {
2479 WARN("Bump env matrix of unsupported stage set\n");
2480 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2481 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2482 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2484 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2485 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2486 checkGLcall("glTexBumpParameterfvATI");
2488 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2489 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2490 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2491 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2492 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2493 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2495 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2497 if(mapped_stage < GL_LIMITS(textures)) {
2498 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2499 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2501 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2502 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2503 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2508 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2509 /* This function is called by transform_view below if the view matrix was changed too
2511 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2512 * does not always update the world matrix, only on a switch between transformed
2513 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2514 * draw, but that should be rather rare and cheaper in total.
2516 glMatrixMode(GL_MODELVIEW);
2517 checkGLcall("glMatrixMode");
2519 if(context->last_was_rhw) {
2520 glLoadIdentity();
2521 checkGLcall("glLoadIdentity()");
2522 } else {
2523 /* In the general case, the view matrix is the identity matrix */
2524 if (stateblock->wineD3DDevice->view_ident) {
2525 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2526 checkGLcall("glLoadMatrixf");
2527 } else {
2528 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2529 checkGLcall("glLoadMatrixf");
2530 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2531 checkGLcall("glMultMatrixf");
2536 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2537 UINT index = state - STATE_CLIPPLANE(0);
2539 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2540 return;
2543 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2544 glMatrixMode(GL_MODELVIEW);
2545 glPushMatrix();
2546 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2548 TRACE("Clipplane [%f,%f,%f,%f]\n",
2549 stateblock->clipplane[index][0],
2550 stateblock->clipplane[index][1],
2551 stateblock->clipplane[index][2],
2552 stateblock->clipplane[index][3]);
2553 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2554 checkGLcall("glClipPlane");
2556 glPopMatrix();
2559 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2560 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2561 GLenum glMat;
2562 TRACE("Setting world matrix %d\n", matrix);
2564 if(matrix >= GL_LIMITS(blends)) {
2565 WARN("Unsupported blend matrix set\n");
2566 return;
2567 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2568 return;
2571 /* GL_MODELVIEW0_ARB: 0x1700
2572 * GL_MODELVIEW1_ARB: 0x0x850a
2573 * GL_MODELVIEW2_ARB: 0x8722
2574 * GL_MODELVIEW3_ARB: 0x8723
2575 * etc
2576 * GL_MODELVIEW31_ARB: 0x873F
2578 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2579 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2581 glMatrixMode(glMat);
2582 checkGLcall("glMatrixMode(glMat)");
2584 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2585 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2587 if(stateblock->wineD3DDevice->view_ident) {
2588 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2589 checkGLcall("glLoadMatrixf")
2590 } else {
2591 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2592 checkGLcall("glLoadMatrixf")
2593 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2594 checkGLcall("glMultMatrixf")
2598 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2599 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2601 switch(val) {
2602 case WINED3DVBF_1WEIGHTS:
2603 case WINED3DVBF_2WEIGHTS:
2604 case WINED3DVBF_3WEIGHTS:
2605 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2606 glEnable(GL_VERTEX_BLEND_ARB);
2607 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2609 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2610 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2612 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2614 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2615 int i;
2616 for(i = 1; i < GL_LIMITS(blends); i++) {
2617 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2618 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2621 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2623 } else {
2624 static BOOL once = FALSE;
2625 if(!once) {
2626 once = TRUE;
2627 /* TODO: Implement vertex blending in drawStridedSlow */
2628 FIXME("Vertex blending enabled, but not supported by hardware\n");
2631 break;
2633 case WINED3DVBF_DISABLE:
2634 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2635 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2636 glDisable(GL_VERTEX_BLEND_ARB);
2637 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2638 } else {
2639 TRACE("Vertex blending disabled\n");
2641 break;
2643 case WINED3DVBF_TWEENING:
2644 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2645 * vertex weights in the vertices?
2646 * For now we don't report that as supported, so a warn should suffice
2648 WARN("Tweening not supported yet\n");
2649 break;
2653 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2654 unsigned int k;
2656 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2657 * NOTE: We have to reset the positions even if the light/plane is not currently
2658 * enabled, since the call to enable it will not reset the position.
2659 * NOTE2: Apparently texture transforms do NOT need reapplying
2662 PLIGHTINFOEL *light = NULL;
2664 glMatrixMode(GL_MODELVIEW);
2665 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2666 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2667 checkGLcall("glLoadMatrixf(...)");
2669 /* Reset lights. TODO: Call light apply func */
2670 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2671 light = stateblock->activeLights[k];
2672 if(!light) continue;
2673 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2674 checkGLcall("glLightfv posn");
2675 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2676 checkGLcall("glLightfv dirn");
2679 /* Reset Clipping Planes */
2680 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2681 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2682 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2686 if(context->last_was_rhw) {
2687 glLoadIdentity();
2688 checkGLcall("glLoadIdentity()");
2689 /* No need to update the world matrix, the identity is fine */
2690 return;
2693 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2694 * No need to do it here if the state is scheduled for update.
2696 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2697 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2700 /* Avoid looping over a number of matrices if the app never used the functionality */
2701 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2702 for(k = 1; k < GL_LIMITS(blends); k++) {
2703 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2704 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2710 static const GLfloat invymat[16] = {
2711 1.0f, 0.0f, 0.0f, 0.0f,
2712 0.0f, -1.0f, 0.0f, 0.0f,
2713 0.0f, 0.0f, 1.0f, 0.0f,
2714 0.0f, 0.0f, 0.0f, 1.0f};
2716 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2717 glMatrixMode(GL_PROJECTION);
2718 checkGLcall("glMatrixMode(GL_PROJECTION)");
2719 glLoadIdentity();
2720 checkGLcall("glLoadIdentity");
2722 if(context->last_was_rhw) {
2723 double X, Y, height, width, minZ, maxZ;
2725 X = stateblock->viewport.X;
2726 Y = stateblock->viewport.Y;
2727 height = stateblock->viewport.Height;
2728 width = stateblock->viewport.Width;
2729 minZ = stateblock->viewport.MinZ;
2730 maxZ = stateblock->viewport.MaxZ;
2732 if(!stateblock->wineD3DDevice->untransformed) {
2733 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2734 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2735 * suppress depth clipping. This can be done because it is an orthogonal projection and
2736 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2737 * Persia 3D need this.
2739 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2740 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2741 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2742 * to the viewer.
2744 * Also note that this breaks z comparison against z values filled in with clear,
2745 * but no app depending on that and disabled clipping has been found yet. Comparing
2746 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2747 * surface removal.
2749 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2750 * but this would break Z buffer operation. Raising the range to something less than
2751 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2752 * problem either.
2754 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2755 if(stateblock->wineD3DDevice->render_offscreen) {
2756 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2757 } else {
2758 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2760 } else {
2761 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2762 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2763 * unmodified to opengl.
2765 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2766 * replacement shader.
2768 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2769 if(stateblock->wineD3DDevice->render_offscreen) {
2770 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2771 } else {
2772 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2775 checkGLcall("glOrtho");
2777 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2778 glTranslatef(0.5, 0.5, 0);
2779 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2780 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2781 * render everything upside down when rendering offscreen. */
2782 if (stateblock->wineD3DDevice->render_offscreen) {
2783 glMultMatrixf(invymat);
2784 checkGLcall("glMultMatrixf(invymat)");
2786 } else {
2787 /* The rule is that the window coordinate 0 does not correspond to the
2788 beginning of the first pixel, but the center of the first pixel.
2789 As a consequence if you want to correctly draw one line exactly from
2790 the left to the right end of the viewport (with all matrices set to
2791 be identity), the x coords of both ends of the line would be not
2792 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2793 instead.
2795 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2796 divide by the Width/Height, so we need the half range(1.0) to translate by
2797 half a pixel.
2799 The other fun is that d3d's output z range after the transformation is [0;1],
2800 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2801 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2802 of Z buffer precision and the clear values do not match in the z test. Thus scale
2803 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2805 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2806 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2807 glScalef(1.0, 1.0, 2.0);
2809 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2810 * render everything upside down when rendering offscreen. */
2811 if (stateblock->wineD3DDevice->render_offscreen) {
2812 glMultMatrixf(invymat);
2813 checkGLcall("glMultMatrixf(invymat)");
2815 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2816 checkGLcall("glLoadMatrixf");
2820 /* This should match any arrays loaded in loadVertexData.
2821 * stateblock impl is required for GL_SUPPORT
2822 * TODO: Only load / unload arrays if we have to.
2824 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2825 glDisableClientState(GL_VERTEX_ARRAY);
2826 glDisableClientState(GL_NORMAL_ARRAY);
2827 glDisableClientState(GL_COLOR_ARRAY);
2828 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2829 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2831 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2832 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2833 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2834 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2836 unloadTexCoords(stateblock);
2839 /* This should match any arrays loaded in loadNumberedArrays
2840 * TODO: Only load / unload arrays if we have to.
2842 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2843 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2844 GLint maxAttribs;
2845 int i;
2847 /* Leave all the attribs disabled */
2848 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2849 /* MESA does not support it right not */
2850 if (glGetError() != GL_NO_ERROR)
2851 maxAttribs = 16;
2852 for (i = 0; i < maxAttribs; ++i) {
2853 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2854 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2858 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2859 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2860 int i;
2861 UINT *offset = stateblock->streamOffset;
2863 /* Default to no instancing */
2864 stateblock->wineD3DDevice->instancedDraw = FALSE;
2866 for (i = 0; i < MAX_ATTRIBS; i++) {
2868 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2869 continue;
2871 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2872 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2873 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2874 stateblock->wineD3DDevice->instancedDraw = TRUE;
2875 continue;
2878 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2880 if(strided->u.input[i].dwStride) {
2881 if(curVBO != strided->u.input[i].VBO) {
2882 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2883 checkGLcall("glBindBufferARB");
2884 curVBO = strided->u.input[i].VBO;
2886 GL_EXTCALL(glVertexAttribPointerARB(i,
2887 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2888 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2889 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2890 strided->u.input[i].dwStride,
2891 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2892 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2893 } else {
2894 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2895 * set up the attribute statically. But we have to figure out the system memory address.
2897 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2898 if(strided->u.input[i].VBO) {
2899 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2900 ptr += (long) vb->resource.allocatedMemory;
2902 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2904 switch(strided->u.input[i].dwType) {
2905 case WINED3DDECLTYPE_FLOAT1:
2906 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2907 break;
2908 case WINED3DDECLTYPE_FLOAT2:
2909 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2910 break;
2911 case WINED3DDECLTYPE_FLOAT3:
2912 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2913 break;
2914 case WINED3DDECLTYPE_FLOAT4:
2915 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2916 break;
2918 case WINED3DDECLTYPE_UBYTE4:
2919 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2920 break;
2921 case WINED3DDECLTYPE_UBYTE4N:
2922 case WINED3DDECLTYPE_D3DCOLOR:
2923 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2924 break;
2926 case WINED3DDECLTYPE_SHORT2:
2927 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2928 break;
2929 case WINED3DDECLTYPE_SHORT4:
2930 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2931 break;
2933 case WINED3DDECLTYPE_SHORT2N:
2935 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2936 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2937 break;
2939 case WINED3DDECLTYPE_USHORT2N:
2941 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2942 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2943 break;
2945 case WINED3DDECLTYPE_SHORT4N:
2946 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2947 break;
2948 case WINED3DDECLTYPE_USHORT4N:
2949 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2950 break;
2952 case WINED3DDECLTYPE_UDEC3:
2953 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2954 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2955 break;
2956 case WINED3DDECLTYPE_DEC3N:
2957 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2958 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2959 break;
2961 case WINED3DDECLTYPE_FLOAT16_2:
2962 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2963 * byte float according to the IEEE standard
2965 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2966 break;
2967 case WINED3DDECLTYPE_FLOAT16_4:
2968 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2969 break;
2971 case WINED3DDECLTYPE_UNUSED:
2972 default:
2973 ERR("Unexpected declaration in stride 0 attributes\n");
2974 break;
2981 /* Used from 2 different functions, and too big to justify making it inlined */
2982 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2983 UINT *offset = stateblock->streamOffset;
2984 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2986 TRACE("Using fast vertex array code\n");
2988 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2989 stateblock->wineD3DDevice->instancedDraw = FALSE;
2991 /* Blend Data ---------------------------------------------- */
2992 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2993 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2995 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2996 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2997 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2999 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3000 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3002 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3004 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3005 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3006 sd->u.s.blendWeights.dwStride,
3007 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3009 if(curVBO != sd->u.s.blendWeights.VBO) {
3010 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3011 checkGLcall("glBindBufferARB");
3012 curVBO = sd->u.s.blendWeights.VBO;
3015 GL_EXTCALL(glWeightPointerARB)(
3016 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3017 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3018 sd->u.s.blendWeights.dwStride,
3019 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3021 checkGLcall("glWeightPointerARB");
3023 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3024 static BOOL showfixme = TRUE;
3025 if(showfixme){
3026 FIXME("blendMatrixIndices support\n");
3027 showfixme = FALSE;
3030 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3031 /* FIXME("TODO\n");*/
3032 #if 0
3034 GL_EXTCALL(glVertexWeightPointerEXT)(
3035 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3036 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3037 sd->u.s.blendWeights.dwStride,
3038 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3039 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3040 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3041 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3042 #endif
3044 } else {
3045 /* TODO: support blends in drawStridedSlow
3046 * No need to write a FIXME here, this is done after the general vertex decl decoding
3048 WARN("unsupported blending in openGl\n");
3050 } else {
3051 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3052 static const GLbyte one = 1;
3053 GL_EXTCALL(glWeightbvARB(1, &one));
3054 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3058 #if 0 /* FOG ----------------------------------------------*/
3059 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3060 /* TODO: fog*/
3061 if (GL_SUPPORT(EXT_FOG_COORD) {
3062 glEnableClientState(GL_FOG_COORDINATE_EXT);
3063 (GL_EXTCALL)(FogCoordPointerEXT)(
3064 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3065 sd->u.s.fog.dwStride,
3066 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3067 } else {
3068 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3069 /* FIXME: fixme once */
3070 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3072 } else {
3073 if (GL_SUPPRT(EXT_FOR_COORD) {
3074 /* make sure fog is disabled */
3075 glDisableClientState(GL_FOG_COORDINATE_EXT);
3078 #endif
3080 #if 0 /* tangents ----------------------------------------------*/
3081 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3082 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3083 /* TODO: tangents*/
3084 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3085 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3086 glEnable(GL_TANGENT_ARRAY_EXT);
3087 (GL_EXTCALL)(TangentPointerEXT)(
3088 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3089 sd->u.s.tangent.dwStride,
3090 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3091 } else {
3092 glDisable(GL_TANGENT_ARRAY_EXT);
3094 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3095 glEnable(GL_BINORMAL_ARRAY_EXT);
3096 (GL_EXTCALL)(BinormalPointerEXT)(
3097 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3098 sd->u.s.binormal.dwStride,
3099 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3100 } else{
3101 glDisable(GL_BINORMAL_ARRAY_EXT);
3104 } else {
3105 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3106 /* FIXME: fixme once */
3107 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3109 } else {
3110 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3111 /* make sure fog is disabled */
3112 glDisable(GL_TANGENT_ARRAY_EXT);
3113 glDisable(GL_BINORMAL_ARRAY_EXT);
3116 #endif
3118 /* Point Size ----------------------------------------------*/
3119 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3121 /* no such functionality in the fixed function GL pipeline */
3122 TRACE("Cannot change ptSize here in openGl\n");
3123 /* TODO: Implement this function in using shaders if they are available */
3127 /* Vertex Pointers -----------------------------------------*/
3128 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3129 /* Note dwType == float3 or float4 == 2 or 3 */
3130 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3131 sd->u.s.position.dwStride,
3132 sd->u.s.position.dwType + 1,
3133 sd->u.s.position.lpData));
3135 if(curVBO != sd->u.s.position.VBO) {
3136 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3137 checkGLcall("glBindBufferARB");
3138 curVBO = sd->u.s.position.VBO;
3141 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3142 handling for rhw mode should not impact screen position whereas in GL it does.
3143 This may result in very slightly distored textures in rhw mode, but
3144 a very minimal different. There's always the other option of
3145 fixing the view matrix to prevent w from having any effect
3147 This only applies to user pointer sources, in VBOs the vertices are fixed up
3149 if(sd->u.s.position.VBO == 0) {
3150 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3151 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3152 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3153 } else {
3154 glVertexPointer(
3155 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3156 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3157 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3159 checkGLcall("glVertexPointer(...)");
3160 glEnableClientState(GL_VERTEX_ARRAY);
3161 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3164 /* Normals -------------------------------------------------*/
3165 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3166 /* Note dwType == float3 or float4 == 2 or 3 */
3167 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3168 sd->u.s.normal.dwStride,
3169 sd->u.s.normal.lpData));
3170 if(curVBO != sd->u.s.normal.VBO) {
3171 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3172 checkGLcall("glBindBufferARB");
3173 curVBO = sd->u.s.normal.VBO;
3175 glNormalPointer(
3176 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3177 sd->u.s.normal.dwStride,
3178 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3179 checkGLcall("glNormalPointer(...)");
3180 glEnableClientState(GL_NORMAL_ARRAY);
3181 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3183 } else {
3184 glNormal3f(0, 0, 0);
3185 checkGLcall("glNormal3f(0, 0, 0)");
3188 /* Diffuse Colour --------------------------------------------*/
3189 /* WARNING: Data here MUST be in RGBA format, so cannot */
3190 /* go directly into fast mode from app pgm, because */
3191 /* directx requires data in BGRA format. */
3192 /* currently fixupVertices swizels the format, but this isn't */
3193 /* very practical when using VBOS */
3194 /* NOTE: Unless we write a vertex shader to swizel the colour */
3195 /* , or the user doesn't care and wants the speed advantage */
3197 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3198 /* Note dwType == float3 or float4 == 2 or 3 */
3199 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3200 sd->u.s.diffuse.dwStride,
3201 sd->u.s.diffuse.lpData));
3203 if(curVBO != sd->u.s.diffuse.VBO) {
3204 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3205 checkGLcall("glBindBufferARB");
3206 curVBO = sd->u.s.diffuse.VBO;
3208 glColorPointer(4, GL_UNSIGNED_BYTE,
3209 sd->u.s.diffuse.dwStride,
3210 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3211 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3212 glEnableClientState(GL_COLOR_ARRAY);
3213 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3215 } else {
3216 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3217 checkGLcall("glColor4f(1, 1, 1, 1)");
3220 /* Specular Colour ------------------------------------------*/
3221 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3222 TRACE("setting specular colour\n");
3223 /* Note dwType == float3 or float4 == 2 or 3 */
3224 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3225 sd->u.s.specular.dwStride,
3226 sd->u.s.specular.lpData));
3227 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3228 if(curVBO != sd->u.s.specular.VBO) {
3229 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3230 checkGLcall("glBindBufferARB");
3231 curVBO = sd->u.s.specular.VBO;
3233 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3234 sd->u.s.specular.dwStride,
3235 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3236 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3237 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3238 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3239 } else {
3241 /* Missing specular color is not critical, no warnings */
3242 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3245 } else {
3246 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3247 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3248 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3249 } else {
3251 /* Missing specular color is not critical, no warnings */
3252 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3256 /* Texture coords -------------------------------------------*/
3257 loadTexCoords(stateblock, sd, &curVBO);
3260 static inline void drawPrimitiveTraceDataLocations(
3261 WineDirect3DVertexStridedData *dataLocations) {
3263 /* Dump out what parts we have supplied */
3264 TRACE("Strided Data:\n");
3265 TRACE_STRIDED((dataLocations), position);
3266 TRACE_STRIDED((dataLocations), blendWeights);
3267 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3268 TRACE_STRIDED((dataLocations), normal);
3269 TRACE_STRIDED((dataLocations), pSize);
3270 TRACE_STRIDED((dataLocations), diffuse);
3271 TRACE_STRIDED((dataLocations), specular);
3272 TRACE_STRIDED((dataLocations), texCoords[0]);
3273 TRACE_STRIDED((dataLocations), texCoords[1]);
3274 TRACE_STRIDED((dataLocations), texCoords[2]);
3275 TRACE_STRIDED((dataLocations), texCoords[3]);
3276 TRACE_STRIDED((dataLocations), texCoords[4]);
3277 TRACE_STRIDED((dataLocations), texCoords[5]);
3278 TRACE_STRIDED((dataLocations), texCoords[6]);
3279 TRACE_STRIDED((dataLocations), texCoords[7]);
3280 TRACE_STRIDED((dataLocations), position2);
3281 TRACE_STRIDED((dataLocations), normal2);
3282 TRACE_STRIDED((dataLocations), tangent);
3283 TRACE_STRIDED((dataLocations), binormal);
3284 TRACE_STRIDED((dataLocations), tessFactor);
3285 TRACE_STRIDED((dataLocations), fog);
3286 TRACE_STRIDED((dataLocations), depth);
3287 TRACE_STRIDED((dataLocations), sample);
3289 return;
3292 /* Helper for vertexdeclaration() */
3293 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3294 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3295 BOOL fixup = FALSE;
3296 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3298 if(device->up_strided) {
3299 /* Note: this is a ddraw fixed-function code path */
3300 TRACE("================ Strided Input ===================\n");
3301 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3303 if(TRACE_ON(d3d)) {
3304 drawPrimitiveTraceDataLocations(dataLocations);
3306 } else {
3307 /* Note: This is a fixed function or shader codepath.
3308 * This means it must handle both types of strided data.
3309 * Shaders must go through here to zero the strided data, even if they
3310 * don't set any declaration at all
3312 TRACE("================ Vertex Declaration ===================\n");
3313 memset(dataLocations, 0, sizeof(*dataLocations));
3314 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3315 useVertexShaderFunction, dataLocations, &fixup);
3318 if (dataLocations->u.s.position_transformed) {
3319 useVertexShaderFunction = FALSE;
3322 /* Unload the old arrays before loading the new ones to get old junk out */
3323 if(context->numberedArraysLoaded) {
3324 unloadNumberedArrays(stateblock);
3325 context->numberedArraysLoaded = FALSE;
3327 if(context->namedArraysLoaded) {
3328 unloadVertexData(stateblock);
3329 context->namedArraysLoaded = FALSE;
3332 if(useVertexShaderFunction) {
3333 TRACE("Loading numbered arrays\n");
3334 loadNumberedArrays(stateblock, dataLocations);
3335 device->useDrawStridedSlow = FALSE;
3336 context->numberedArraysLoaded = TRUE;
3337 } else if (fixup ||
3338 (dataLocations->u.s.pSize.lpData == NULL &&
3339 dataLocations->u.s.diffuse.lpData == NULL &&
3340 dataLocations->u.s.specular.lpData == NULL)) {
3341 /* Load the vertex data using named arrays */
3342 TRACE("Loading vertex data\n");
3343 loadVertexData(stateblock, dataLocations);
3344 device->useDrawStridedSlow = FALSE;
3345 context->namedArraysLoaded = TRUE;
3346 } else {
3347 TRACE("Not loading vertex data\n");
3348 device->useDrawStridedSlow = TRUE;
3351 /* Generate some fixme's if unsupported functionality is being used */
3352 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3353 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3354 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3355 FIXME("Tweening is only valid with vertex shaders\n");
3357 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3358 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3360 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3361 FIXME("Extended attributes are only valid with vertex shaders\n");
3363 #undef BUFFER_OR_DATA
3366 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3367 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3368 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3369 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3370 BOOL transformed;
3371 /* Some stuff is in the device until we have per context tracking */
3372 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3373 BOOL wasrhw = context->last_was_rhw;
3375 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3376 * here simply check whether a shader was set, or the user disabled shaders
3378 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3379 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3380 useVertexShaderFunction = TRUE;
3382 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3383 updateFog = TRUE;
3385 } else if(context->last_was_foggy_shader) {
3386 updateFog = TRUE;
3389 handleStreams(stateblock, useVertexShaderFunction, context);
3391 transformed = device->strided_streams.u.s.position_transformed;
3392 if (transformed) useVertexShaderFunction = FALSE;
3394 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3395 updateFog = TRUE;
3398 /* Reapply lighting if it is not scheduled for reapplication already */
3399 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3400 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3403 if (transformed) {
3404 context->last_was_rhw = TRUE;
3405 } else {
3407 /* Untransformed, so relies on the view and projection matrices */
3408 context->last_was_rhw = FALSE;
3409 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3410 device->untransformed = TRUE;
3412 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3413 * Not needed as long as only hw shaders are supported
3416 /* This sets the shader output position correction constants.
3417 * TODO: Move to the viewport state
3419 if (useVertexShaderFunction) {
3420 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3421 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3425 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3426 * off this function will be called again anyway to make sure they're properly set
3428 if(!useVertexShaderFunction) {
3429 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3430 * or transformed / untransformed was switched
3432 if(wasrhw != context->last_was_rhw &&
3433 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3434 !isStateDirty(context, STATE_VIEWPORT)) {
3435 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3437 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3438 * mode.
3440 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3441 * this check will fail and the matrix not applied again. This is OK because a simple
3442 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3443 * needs of the vertex declaration.
3445 * World and view matrix go into the same gl matrix, so only apply them when neither is
3446 * dirty
3448 if(transformed != wasrhw &&
3449 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3450 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3451 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3454 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3455 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3458 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3459 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3461 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3462 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3464 } else {
3465 /* We compile the shader here because we need the vertex declaration
3466 * in order to determine if we need to do any swizzling for D3DCOLOR
3467 * registers. If the shader is already compiled this call will do nothing. */
3468 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3470 if(!context->last_was_vshader) {
3471 int i;
3472 static BOOL warned = FALSE;
3473 /* Disable all clip planes to get defined results on all drivers. See comment in the
3474 * state_clipping state handler
3476 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3477 glDisable(GL_CLIP_PLANE0 + i);
3478 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3481 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3482 FIXME("Clipping not supported with vertex shaders\n");
3483 warned = TRUE;
3485 if(wasrhw) {
3486 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3487 * shaders themselves do not need it it, but the matrices are not reapplied automatically when
3488 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3489 * fixed function vertex processing states back in a sane state before switching to shaders
3491 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3492 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3494 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3495 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3501 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3502 * application
3504 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3505 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3507 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3508 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3512 context->last_was_vshader = useVertexShaderFunction;
3514 if(updateFog) {
3515 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3517 if(!useVertexShaderFunction) {
3518 int i;
3519 for(i = 0; i < MAX_TEXTURES; i++) {
3520 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3521 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3527 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3528 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3529 checkGLcall("glDepthRange");
3530 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3532 if(stateblock->wineD3DDevice->render_offscreen) {
3533 glViewport(stateblock->viewport.X,
3534 stateblock->viewport.Y,
3535 stateblock->viewport.Width, stateblock->viewport.Height);
3536 } else {
3537 glViewport(stateblock->viewport.X,
3538 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3539 stateblock->viewport.Width, stateblock->viewport.Height);
3542 checkGLcall("glViewport");
3544 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3545 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3546 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3547 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3549 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3550 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3554 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3555 UINT Index = state - STATE_ACTIVELIGHT(0);
3556 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3558 if(!lightInfo) {
3559 glDisable(GL_LIGHT0 + Index);
3560 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3561 } else {
3562 float quad_att;
3563 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3565 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3566 glMatrixMode(GL_MODELVIEW);
3567 glPushMatrix();
3568 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3570 /* Diffuse: */
3571 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3572 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3573 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3574 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3575 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3576 checkGLcall("glLightfv");
3578 /* Specular */
3579 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3580 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3581 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3582 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3583 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3584 checkGLcall("glLightfv");
3586 /* Ambient */
3587 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3588 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3589 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3590 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3591 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3592 checkGLcall("glLightfv");
3594 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3595 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3596 } else {
3597 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3600 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3601 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3602 * Attenuation0 to NaN and crashes in the gl lib
3605 switch (lightInfo->OriginalParms.Type) {
3606 case WINED3DLIGHT_POINT:
3607 /* Position */
3608 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3609 checkGLcall("glLightfv");
3610 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3611 checkGLcall("glLightf");
3612 /* Attenuation - Are these right? guessing... */
3613 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3614 checkGLcall("glLightf");
3615 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3616 checkGLcall("glLightf");
3617 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3618 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3619 checkGLcall("glLightf");
3620 /* FIXME: Range */
3621 break;
3623 case WINED3DLIGHT_SPOT:
3624 /* Position */
3625 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3626 checkGLcall("glLightfv");
3627 /* Direction */
3628 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3629 checkGLcall("glLightfv");
3630 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3631 checkGLcall("glLightf");
3632 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3633 checkGLcall("glLightf");
3634 /* Attenuation - Are these right? guessing... */
3635 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3636 checkGLcall("glLightf");
3637 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3638 checkGLcall("glLightf");
3639 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3640 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3641 checkGLcall("glLightf");
3642 /* FIXME: Range */
3643 break;
3645 case WINED3DLIGHT_DIRECTIONAL:
3646 /* Direction */
3647 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3648 checkGLcall("glLightfv");
3649 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3650 checkGLcall("glLightf");
3651 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3652 checkGLcall("glLightf");
3653 break;
3655 default:
3656 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3659 /* Restore the modelview matrix */
3660 glPopMatrix();
3662 glEnable(GL_LIGHT0 + Index);
3663 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3666 return;
3669 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3670 RECT *pRect = &stateblock->scissorRect;
3671 RECT windowRect;
3672 UINT winHeight;
3674 windowRect.left = 0;
3675 windowRect.top = 0;
3676 windowRect.right = ((IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0])->currentDesc.Width;
3677 windowRect.bottom = ((IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height;
3679 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3680 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3682 winHeight = windowRect.bottom - windowRect.top;
3683 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3684 pRect->right - pRect->left, pRect->bottom - pRect->top);
3686 if (stateblock->wineD3DDevice->render_offscreen) {
3687 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3688 } else {
3689 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3691 checkGLcall("glScissor");
3694 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3695 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3696 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3697 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3698 } else {
3699 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3700 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3705 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3706 if(stateblock->wineD3DDevice->render_offscreen) {
3707 glFrontFace(GL_CCW);
3708 checkGLcall("glFrontFace(GL_CCW)");
3709 } else {
3710 glFrontFace(GL_CW);
3711 checkGLcall("glFrontFace(GL_CW)");
3715 const struct StateEntry StateTable[] =
3717 /* State name representative, apply function */
3718 { /* 0, Undefined */ 0, state_undefined },
3719 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3720 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3721 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3722 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3723 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3724 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3725 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3726 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3727 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3728 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3729 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3730 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3731 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3732 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3733 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3734 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3735 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3736 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3737 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3738 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3739 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3740 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3741 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3742 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3743 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3744 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3745 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3746 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3747 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3748 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3749 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3750 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3751 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3752 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3753 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3754 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3755 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3756 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3757 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3758 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3759 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3760 { /* 42, undefined */ 0, state_undefined },
3761 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3762 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3763 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3764 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3765 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3766 { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog },
3767 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3768 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3769 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3770 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3771 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3772 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3773 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3774 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3775 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3776 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3777 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3778 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3779 { /* 61, Undefined */ 0, state_undefined },
3780 { /* 62, Undefined */ 0, state_undefined },
3781 { /* 63, Undefined */ 0, state_undefined },
3782 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3783 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3784 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3785 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3786 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3787 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3788 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3789 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3790 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3791 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3792 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3793 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3794 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3795 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3796 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3797 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3798 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3799 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3800 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3801 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3802 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3803 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3804 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3805 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3806 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3807 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3808 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3809 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3810 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3811 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3812 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3813 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3814 { /* 96, Undefined */ 0, state_undefined },
3815 { /* 97, Undefined */ 0, state_undefined },
3816 { /* 98, Undefined */ 0, state_undefined },
3817 { /* 99, Undefined */ 0, state_undefined },
3818 { /*100, Undefined */ 0, state_undefined },
3819 { /*101, Undefined */ 0, state_undefined },
3820 { /*102, Undefined */ 0, state_undefined },
3821 { /*103, Undefined */ 0, state_undefined },
3822 { /*104, Undefined */ 0, state_undefined },
3823 { /*105, Undefined */ 0, state_undefined },
3824 { /*106, Undefined */ 0, state_undefined },
3825 { /*107, Undefined */ 0, state_undefined },
3826 { /*108, Undefined */ 0, state_undefined },
3827 { /*109, Undefined */ 0, state_undefined },
3828 { /*110, Undefined */ 0, state_undefined },
3829 { /*111, Undefined */ 0, state_undefined },
3830 { /*112, Undefined */ 0, state_undefined },
3831 { /*113, Undefined */ 0, state_undefined },
3832 { /*114, Undefined */ 0, state_undefined },
3833 { /*115, Undefined */ 0, state_undefined },
3834 { /*116, Undefined */ 0, state_undefined },
3835 { /*117, Undefined */ 0, state_undefined },
3836 { /*118, Undefined */ 0, state_undefined },
3837 { /*119, Undefined */ 0, state_undefined },
3838 { /*120, Undefined */ 0, state_undefined },
3839 { /*121, Undefined */ 0, state_undefined },
3840 { /*122, Undefined */ 0, state_undefined },
3841 { /*123, Undefined */ 0, state_undefined },
3842 { /*124, Undefined */ 0, state_undefined },
3843 { /*125, Undefined */ 0, state_undefined },
3844 { /*126, Undefined */ 0, state_undefined },
3845 { /*127, Undefined */ 0, state_undefined },
3846 /* Big hole ends */
3847 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3848 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3849 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3850 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3851 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3852 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3853 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3854 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3855 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3856 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3857 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3858 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3859 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3860 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3861 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3862 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3863 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3864 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3865 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3866 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3867 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3868 { /*149, Undefined */ 0, state_undefined },
3869 { /*150, Undefined */ 0, state_undefined },
3870 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3871 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3872 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3873 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3874 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3875 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3876 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3877 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3878 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3879 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3880 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3881 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3882 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3883 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3884 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3885 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3886 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3887 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3888 { /*169, Undefined */ 0, state_undefined },
3889 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3890 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3891 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3892 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3893 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3894 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3895 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3896 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3897 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3898 { /*177, undefined */ 0, state_undefined },
3899 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3900 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3901 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3902 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3903 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3904 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3905 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3906 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3907 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3908 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3909 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3910 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3911 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3912 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3913 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3914 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3915 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_PIXELSHADER, pixelshader },
3916 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3917 { /*196, undefined */ 0, state_undefined },
3918 { /*197, undefined */ 0, state_undefined },
3919 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3920 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3921 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3922 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3923 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3924 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3925 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3926 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3927 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3928 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3929 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3930 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3931 /* Texture stage states */
3932 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3933 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3934 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3935 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3936 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3937 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3938 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3939 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3940 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3941 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3942 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3943 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3944 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3945 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3946 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3947 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3948 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3949 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3950 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3951 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3952 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3953 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3954 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3955 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3956 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3957 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3958 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3959 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3960 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3961 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3962 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3963 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3965 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3966 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3967 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3968 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3969 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3970 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3971 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3972 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3973 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3974 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3975 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3976 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3977 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3978 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3979 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3980 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3981 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3982 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3983 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3984 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3985 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3986 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3987 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3988 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3989 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3990 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3991 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3992 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3993 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3994 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3995 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3996 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3998 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3999 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4000 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4001 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4002 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4003 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4004 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4005 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4006 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4007 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4008 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4009 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4010 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4011 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4012 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4013 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4014 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4015 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4016 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4017 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4018 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4019 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4020 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4021 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4022 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4023 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4024 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4025 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
4026 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4027 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4028 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4029 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4031 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4032 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4033 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4034 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4035 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4036 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4037 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4038 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4039 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4040 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4041 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4042 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4043 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4044 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4045 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4046 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4047 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4048 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4049 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4050 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4051 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4052 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4053 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4054 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4055 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4056 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4057 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4058 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
4059 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4060 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4061 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4062 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4064 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4065 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4066 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4067 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4068 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4069 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4070 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4071 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4072 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4073 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4074 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4075 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4076 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4077 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4078 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4079 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4080 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4081 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4082 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4083 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4084 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4085 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4086 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4087 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4088 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4089 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4090 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4091 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
4092 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4093 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4094 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4095 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4097 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4098 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4099 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4100 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4101 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4102 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4103 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4104 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4105 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4106 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4107 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4108 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4109 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4110 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4111 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4112 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4113 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4114 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4115 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4116 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4117 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4118 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4119 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4120 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4121 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4122 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4123 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4124 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
4125 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4126 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4127 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4128 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4130 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4131 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4132 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4133 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4134 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4135 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4136 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4137 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4138 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4139 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4140 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4141 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4142 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4143 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4144 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4145 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4146 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4147 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4148 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4149 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4150 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4151 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4152 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4153 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4154 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4155 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4156 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4157 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
4158 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4159 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4160 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4161 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4163 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4164 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4165 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4166 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4167 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4168 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4169 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4170 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4171 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4172 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4173 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4174 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4175 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4176 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4177 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4178 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4179 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4180 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4181 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4182 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4183 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4184 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4185 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4186 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4187 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4188 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4189 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4190 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
4191 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4192 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4193 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4194 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4195 /* Sampler states */
4196 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
4197 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
4198 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
4199 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
4200 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
4201 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
4202 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
4203 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
4204 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
4205 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
4206 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
4207 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
4208 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
4209 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
4210 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
4211 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
4212 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
4213 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
4214 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
4215 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
4216 /* Pixel shader */
4217 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
4218 /* Transform states follow */
4219 { /* 1, undefined */ 0, state_undefined },
4220 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
4221 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
4222 { /* 4, undefined */ 0, state_undefined },
4223 { /* 5, undefined */ 0, state_undefined },
4224 { /* 6, undefined */ 0, state_undefined },
4225 { /* 7, undefined */ 0, state_undefined },
4226 { /* 8, undefined */ 0, state_undefined },
4227 { /* 9, undefined */ 0, state_undefined },
4228 { /* 10, undefined */ 0, state_undefined },
4229 { /* 11, undefined */ 0, state_undefined },
4230 { /* 12, undefined */ 0, state_undefined },
4231 { /* 13, undefined */ 0, state_undefined },
4232 { /* 14, undefined */ 0, state_undefined },
4233 { /* 15, undefined */ 0, state_undefined },
4234 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4235 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4236 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4237 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4238 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4239 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4240 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4241 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4242 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
4243 { /* 24, undefined */ 0, state_undefined },
4244 { /* 25, undefined */ 0, state_undefined },
4245 { /* 26, undefined */ 0, state_undefined },
4246 { /* 27, undefined */ 0, state_undefined },
4247 { /* 28, undefined */ 0, state_undefined },
4248 { /* 29, undefined */ 0, state_undefined },
4249 { /* 30, undefined */ 0, state_undefined },
4250 { /* 31, undefined */ 0, state_undefined },
4251 { /* 32, undefined */ 0, state_undefined },
4252 { /* 33, undefined */ 0, state_undefined },
4253 { /* 34, undefined */ 0, state_undefined },
4254 { /* 35, undefined */ 0, state_undefined },
4255 { /* 36, undefined */ 0, state_undefined },
4256 { /* 37, undefined */ 0, state_undefined },
4257 { /* 38, undefined */ 0, state_undefined },
4258 { /* 39, undefined */ 0, state_undefined },
4259 { /* 40, undefined */ 0, state_undefined },
4260 { /* 41, undefined */ 0, state_undefined },
4261 { /* 42, undefined */ 0, state_undefined },
4262 { /* 43, undefined */ 0, state_undefined },
4263 { /* 44, undefined */ 0, state_undefined },
4264 { /* 45, undefined */ 0, state_undefined },
4265 { /* 46, undefined */ 0, state_undefined },
4266 { /* 47, undefined */ 0, state_undefined },
4267 { /* 48, undefined */ 0, state_undefined },
4268 { /* 49, undefined */ 0, state_undefined },
4269 { /* 50, undefined */ 0, state_undefined },
4270 { /* 51, undefined */ 0, state_undefined },
4271 { /* 52, undefined */ 0, state_undefined },
4272 { /* 53, undefined */ 0, state_undefined },
4273 { /* 54, undefined */ 0, state_undefined },
4274 { /* 55, undefined */ 0, state_undefined },
4275 { /* 56, undefined */ 0, state_undefined },
4276 { /* 57, undefined */ 0, state_undefined },
4277 { /* 58, undefined */ 0, state_undefined },
4278 { /* 59, undefined */ 0, state_undefined },
4279 { /* 60, undefined */ 0, state_undefined },
4280 { /* 61, undefined */ 0, state_undefined },
4281 { /* 62, undefined */ 0, state_undefined },
4282 { /* 63, undefined */ 0, state_undefined },
4283 { /* 64, undefined */ 0, state_undefined },
4284 { /* 65, undefined */ 0, state_undefined },
4285 { /* 66, undefined */ 0, state_undefined },
4286 { /* 67, undefined */ 0, state_undefined },
4287 { /* 68, undefined */ 0, state_undefined },
4288 { /* 69, undefined */ 0, state_undefined },
4289 { /* 70, undefined */ 0, state_undefined },
4290 { /* 71, undefined */ 0, state_undefined },
4291 { /* 72, undefined */ 0, state_undefined },
4292 { /* 73, undefined */ 0, state_undefined },
4293 { /* 74, undefined */ 0, state_undefined },
4294 { /* 75, undefined */ 0, state_undefined },
4295 { /* 76, undefined */ 0, state_undefined },
4296 { /* 77, undefined */ 0, state_undefined },
4297 { /* 78, undefined */ 0, state_undefined },
4298 { /* 79, undefined */ 0, state_undefined },
4299 { /* 80, undefined */ 0, state_undefined },
4300 { /* 81, undefined */ 0, state_undefined },
4301 { /* 82, undefined */ 0, state_undefined },
4302 { /* 83, undefined */ 0, state_undefined },
4303 { /* 84, undefined */ 0, state_undefined },
4304 { /* 85, undefined */ 0, state_undefined },
4305 { /* 86, undefined */ 0, state_undefined },
4306 { /* 87, undefined */ 0, state_undefined },
4307 { /* 88, undefined */ 0, state_undefined },
4308 { /* 89, undefined */ 0, state_undefined },
4309 { /* 90, undefined */ 0, state_undefined },
4310 { /* 91, undefined */ 0, state_undefined },
4311 { /* 92, undefined */ 0, state_undefined },
4312 { /* 93, undefined */ 0, state_undefined },
4313 { /* 94, undefined */ 0, state_undefined },
4314 { /* 95, undefined */ 0, state_undefined },
4315 { /* 96, undefined */ 0, state_undefined },
4316 { /* 97, undefined */ 0, state_undefined },
4317 { /* 98, undefined */ 0, state_undefined },
4318 { /* 99, undefined */ 0, state_undefined },
4319 { /*100, undefined */ 0, state_undefined },
4320 { /*101, undefined */ 0, state_undefined },
4321 { /*102, undefined */ 0, state_undefined },
4322 { /*103, undefined */ 0, state_undefined },
4323 { /*104, undefined */ 0, state_undefined },
4324 { /*105, undefined */ 0, state_undefined },
4325 { /*106, undefined */ 0, state_undefined },
4326 { /*107, undefined */ 0, state_undefined },
4327 { /*108, undefined */ 0, state_undefined },
4328 { /*109, undefined */ 0, state_undefined },
4329 { /*110, undefined */ 0, state_undefined },
4330 { /*111, undefined */ 0, state_undefined },
4331 { /*112, undefined */ 0, state_undefined },
4332 { /*113, undefined */ 0, state_undefined },
4333 { /*114, undefined */ 0, state_undefined },
4334 { /*115, undefined */ 0, state_undefined },
4335 { /*116, undefined */ 0, state_undefined },
4336 { /*117, undefined */ 0, state_undefined },
4337 { /*118, undefined */ 0, state_undefined },
4338 { /*119, undefined */ 0, state_undefined },
4339 { /*120, undefined */ 0, state_undefined },
4340 { /*121, undefined */ 0, state_undefined },
4341 { /*122, undefined */ 0, state_undefined },
4342 { /*123, undefined */ 0, state_undefined },
4343 { /*124, undefined */ 0, state_undefined },
4344 { /*125, undefined */ 0, state_undefined },
4345 { /*126, undefined */ 0, state_undefined },
4346 { /*127, undefined */ 0, state_undefined },
4347 { /*128, undefined */ 0, state_undefined },
4348 { /*129, undefined */ 0, state_undefined },
4349 { /*130, undefined */ 0, state_undefined },
4350 { /*131, undefined */ 0, state_undefined },
4351 { /*132, undefined */ 0, state_undefined },
4352 { /*133, undefined */ 0, state_undefined },
4353 { /*134, undefined */ 0, state_undefined },
4354 { /*135, undefined */ 0, state_undefined },
4355 { /*136, undefined */ 0, state_undefined },
4356 { /*137, undefined */ 0, state_undefined },
4357 { /*138, undefined */ 0, state_undefined },
4358 { /*139, undefined */ 0, state_undefined },
4359 { /*140, undefined */ 0, state_undefined },
4360 { /*141, undefined */ 0, state_undefined },
4361 { /*142, undefined */ 0, state_undefined },
4362 { /*143, undefined */ 0, state_undefined },
4363 { /*144, undefined */ 0, state_undefined },
4364 { /*145, undefined */ 0, state_undefined },
4365 { /*146, undefined */ 0, state_undefined },
4366 { /*147, undefined */ 0, state_undefined },
4367 { /*148, undefined */ 0, state_undefined },
4368 { /*149, undefined */ 0, state_undefined },
4369 { /*150, undefined */ 0, state_undefined },
4370 { /*151, undefined */ 0, state_undefined },
4371 { /*152, undefined */ 0, state_undefined },
4372 { /*153, undefined */ 0, state_undefined },
4373 { /*154, undefined */ 0, state_undefined },
4374 { /*155, undefined */ 0, state_undefined },
4375 { /*156, undefined */ 0, state_undefined },
4376 { /*157, undefined */ 0, state_undefined },
4377 { /*158, undefined */ 0, state_undefined },
4378 { /*159, undefined */ 0, state_undefined },
4379 { /*160, undefined */ 0, state_undefined },
4380 { /*161, undefined */ 0, state_undefined },
4381 { /*162, undefined */ 0, state_undefined },
4382 { /*163, undefined */ 0, state_undefined },
4383 { /*164, undefined */ 0, state_undefined },
4384 { /*165, undefined */ 0, state_undefined },
4385 { /*166, undefined */ 0, state_undefined },
4386 { /*167, undefined */ 0, state_undefined },
4387 { /*168, undefined */ 0, state_undefined },
4388 { /*169, undefined */ 0, state_undefined },
4389 { /*170, undefined */ 0, state_undefined },
4390 { /*171, undefined */ 0, state_undefined },
4391 { /*172, undefined */ 0, state_undefined },
4392 { /*173, undefined */ 0, state_undefined },
4393 { /*174, undefined */ 0, state_undefined },
4394 { /*175, undefined */ 0, state_undefined },
4395 { /*176, undefined */ 0, state_undefined },
4396 { /*177, undefined */ 0, state_undefined },
4397 { /*178, undefined */ 0, state_undefined },
4398 { /*179, undefined */ 0, state_undefined },
4399 { /*180, undefined */ 0, state_undefined },
4400 { /*181, undefined */ 0, state_undefined },
4401 { /*182, undefined */ 0, state_undefined },
4402 { /*183, undefined */ 0, state_undefined },
4403 { /*184, undefined */ 0, state_undefined },
4404 { /*185, undefined */ 0, state_undefined },
4405 { /*186, undefined */ 0, state_undefined },
4406 { /*187, undefined */ 0, state_undefined },
4407 { /*188, undefined */ 0, state_undefined },
4408 { /*189, undefined */ 0, state_undefined },
4409 { /*190, undefined */ 0, state_undefined },
4410 { /*191, undefined */ 0, state_undefined },
4411 { /*192, undefined */ 0, state_undefined },
4412 { /*193, undefined */ 0, state_undefined },
4413 { /*194, undefined */ 0, state_undefined },
4414 { /*195, undefined */ 0, state_undefined },
4415 { /*196, undefined */ 0, state_undefined },
4416 { /*197, undefined */ 0, state_undefined },
4417 { /*198, undefined */ 0, state_undefined },
4418 { /*199, undefined */ 0, state_undefined },
4419 { /*200, undefined */ 0, state_undefined },
4420 { /*201, undefined */ 0, state_undefined },
4421 { /*202, undefined */ 0, state_undefined },
4422 { /*203, undefined */ 0, state_undefined },
4423 { /*204, undefined */ 0, state_undefined },
4424 { /*205, undefined */ 0, state_undefined },
4425 { /*206, undefined */ 0, state_undefined },
4426 { /*207, undefined */ 0, state_undefined },
4427 { /*208, undefined */ 0, state_undefined },
4428 { /*209, undefined */ 0, state_undefined },
4429 { /*210, undefined */ 0, state_undefined },
4430 { /*211, undefined */ 0, state_undefined },
4431 { /*212, undefined */ 0, state_undefined },
4432 { /*213, undefined */ 0, state_undefined },
4433 { /*214, undefined */ 0, state_undefined },
4434 { /*215, undefined */ 0, state_undefined },
4435 { /*216, undefined */ 0, state_undefined },
4436 { /*217, undefined */ 0, state_undefined },
4437 { /*218, undefined */ 0, state_undefined },
4438 { /*219, undefined */ 0, state_undefined },
4439 { /*220, undefined */ 0, state_undefined },
4440 { /*221, undefined */ 0, state_undefined },
4441 { /*222, undefined */ 0, state_undefined },
4442 { /*223, undefined */ 0, state_undefined },
4443 { /*224, undefined */ 0, state_undefined },
4444 { /*225, undefined */ 0, state_undefined },
4445 { /*226, undefined */ 0, state_undefined },
4446 { /*227, undefined */ 0, state_undefined },
4447 { /*228, undefined */ 0, state_undefined },
4448 { /*229, undefined */ 0, state_undefined },
4449 { /*230, undefined */ 0, state_undefined },
4450 { /*231, undefined */ 0, state_undefined },
4451 { /*232, undefined */ 0, state_undefined },
4452 { /*233, undefined */ 0, state_undefined },
4453 { /*234, undefined */ 0, state_undefined },
4454 { /*235, undefined */ 0, state_undefined },
4455 { /*236, undefined */ 0, state_undefined },
4456 { /*237, undefined */ 0, state_undefined },
4457 { /*238, undefined */ 0, state_undefined },
4458 { /*239, undefined */ 0, state_undefined },
4459 { /*240, undefined */ 0, state_undefined },
4460 { /*241, undefined */ 0, state_undefined },
4461 { /*242, undefined */ 0, state_undefined },
4462 { /*243, undefined */ 0, state_undefined },
4463 { /*244, undefined */ 0, state_undefined },
4464 { /*245, undefined */ 0, state_undefined },
4465 { /*246, undefined */ 0, state_undefined },
4466 { /*247, undefined */ 0, state_undefined },
4467 { /*248, undefined */ 0, state_undefined },
4468 { /*249, undefined */ 0, state_undefined },
4469 { /*250, undefined */ 0, state_undefined },
4470 { /*251, undefined */ 0, state_undefined },
4471 { /*252, undefined */ 0, state_undefined },
4472 { /*253, undefined */ 0, state_undefined },
4473 { /*254, undefined */ 0, state_undefined },
4474 { /*255, undefined */ 0, state_undefined },
4475 /* End huge gap */
4476 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4477 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4478 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4479 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4480 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4481 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4482 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4483 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4484 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4485 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4486 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4487 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4488 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4489 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4490 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4491 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4492 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4493 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4494 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4495 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4496 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4497 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4498 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4499 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4500 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4501 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4502 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4503 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4504 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4505 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4506 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4507 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4508 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4509 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4510 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4511 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4512 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4513 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4514 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4515 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4516 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4517 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4518 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4519 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4520 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4521 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4522 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4523 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4524 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4525 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4526 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4527 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4528 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4529 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4530 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4531 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4532 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4533 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4534 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4535 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4536 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4537 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4538 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4539 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4540 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4541 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4542 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4543 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4544 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4545 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4546 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4547 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4548 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4549 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4550 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4551 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4552 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4553 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4554 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4555 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4556 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4557 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4558 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4559 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4560 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4561 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4562 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4563 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4564 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4565 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4566 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4567 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4568 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4569 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4570 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4571 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4572 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4573 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4574 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4575 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4576 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4577 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4578 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4579 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4580 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4581 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4582 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4583 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4584 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4585 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4586 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4587 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4588 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4589 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4590 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4591 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4592 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4593 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4594 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4595 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4596 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4597 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4598 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4599 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4600 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4601 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4602 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4603 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4604 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4605 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4606 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4607 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4608 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4609 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4610 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4611 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4612 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4613 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4614 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4615 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4616 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4617 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4618 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4619 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4620 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4621 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4622 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4623 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4624 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4625 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4626 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4627 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4628 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4629 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4630 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4631 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4632 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4633 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4634 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4635 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4636 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4637 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4638 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4639 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4640 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4641 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4642 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4643 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4644 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4645 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4646 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4647 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4648 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4649 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4650 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4651 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4652 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4653 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4654 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4655 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4656 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4657 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4658 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4659 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4660 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4661 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4662 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4663 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4664 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4665 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4666 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4667 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4668 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4669 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4670 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4671 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4672 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4673 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4674 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4675 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4676 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4677 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4678 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4679 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4680 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4681 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4682 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4683 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4684 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4685 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4686 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4687 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4688 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4689 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4690 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4691 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4692 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4693 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4694 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4695 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4696 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4697 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4698 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4699 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4700 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4701 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4702 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4703 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4704 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4705 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4706 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4707 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4708 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4709 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4710 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4711 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4712 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4713 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4714 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4715 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4716 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4717 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4718 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4719 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4720 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4721 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4722 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4723 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4724 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4725 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4726 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4727 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4728 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4729 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4730 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4731 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4732 /* Various Vertex states follow */
4733 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4734 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4735 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4736 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4737 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4738 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4739 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4740 /* Lights */
4741 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4742 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4743 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4744 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4745 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4746 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4747 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4748 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4750 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4751 /* Clip planes */
4752 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4753 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4754 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4755 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4756 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4757 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4758 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4759 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4760 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4761 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4762 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4763 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4764 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4765 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4766 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4767 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4768 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4769 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4770 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4771 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4772 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4773 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4774 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4775 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4776 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4777 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4778 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4779 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4780 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4781 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4782 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4783 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4785 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
4786 { /* STATE_FRONTFACE */ STATE_FRONTFACE, frontface },