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
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
39 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
45 if(STATE_IS_RENDER(state)) {
46 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
49 /* Shouldn't have an unknown type here */
50 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56 * list without causing confusing terminal output. Deliberately no special debug name here
57 * because its undefined.
59 WARN("undefined state %d\n", state);
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
66 case WINED3DFILL_POINT:
67 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
70 case WINED3DFILL_WIREFRAME:
71 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
74 case WINED3DFILL_SOLID:
75 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
96 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
97 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
98 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
100 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
101 glEnable(GL_LIGHTING);
102 checkGLcall("glEnable GL_LIGHTING");
104 glDisable(GL_LIGHTING);
105 checkGLcall("glDisable GL_LIGHTING");
109 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
110 /* No z test without depth stencil buffers */
111 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
112 TRACE("No Z buffer - disabling depth test\n");
113 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
114 checkGLcall("glDisable GL_DEPTH_TEST");
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
138 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
141 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
142 case WINED3DCULL_NONE:
143 glDisable(GL_CULL_FACE);
144 checkGLcall("glDisable GL_CULL_FACE");
147 glEnable(GL_CULL_FACE);
148 checkGLcall("glEnable GL_CULL_FACE");
149 glCullFace(GL_FRONT);
150 checkGLcall("glCullFace(GL_FRONT)");
152 case WINED3DCULL_CCW:
153 glEnable(GL_CULL_FACE);
154 checkGLcall("glEnable GL_CULL_FACE");
156 checkGLcall("glCullFace(GL_BACK)");
159 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
163 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
164 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
165 case WINED3DSHADE_FLAT:
166 glShadeModel(GL_FLAT);
167 checkGLcall("glShadeModel(GL_FLAT)");
169 case WINED3DSHADE_GOURAUD:
170 glShadeModel(GL_SMOOTH);
171 checkGLcall("glShadeModel(GL_SMOOTH)");
173 case WINED3DSHADE_PHONG:
174 FIXME("WINED3DSHADE_PHONG isn't supported\n");
177 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
181 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
182 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
184 checkGLcall("glEnable GL_DITHER");
186 glDisable(GL_DITHER);
187 checkGLcall("glDisable GL_DITHER");
191 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
192 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
193 * this has to be merged with ZENABLE and ZFUNC
195 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
197 checkGLcall("glDepthMask(1)");
200 checkGLcall("glDepthMask(0)");
204 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
205 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
208 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
209 static BOOL once = FALSE;
210 /* There are a few issues with this: First, our inability to
211 * select a proper Z depth, most of the time we're stuck with
212 * D24S8, even if the app selects D32 or D16. There seem to be
213 * some other precision problems which have to be debugged to
214 * make NOTEQUAL and EQUAL work properly
218 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
223 checkGLcall("glDepthFunc");
227 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
229 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
231 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
232 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
233 checkGLcall("glLightModel for MODEL_AMBIENT");
236 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
237 int srcBlend = GL_ZERO;
238 int dstBlend = GL_ZERO;
239 const StaticPixelFormatDesc *rtFormat;
240 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
242 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
243 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
244 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
245 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
247 checkGLcall("glEnable GL_BLEND");
250 checkGLcall("glDisable GL_BLEND");
251 /* Nothing more to do - get out */
255 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
256 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
257 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
258 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
259 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
260 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
261 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
262 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
263 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
265 /* To compensate the lack of format switching with backbuffer offscreen rendering,
266 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
267 * if the render target doesn't support alpha blending. A nonexistent alpha channel
268 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
270 case WINED3DBLEND_DESTALPHA :
271 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
272 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
274 case WINED3DBLEND_INVDESTALPHA :
275 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
276 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
279 case WINED3DBLEND_SRCALPHASAT :
280 dstBlend = GL_SRC_ALPHA_SATURATE;
281 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
284 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
285 * values which are still valid up to d3d9. They should not occur as dest blend values
287 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
288 srcBlend = GL_SRC_ALPHA;
289 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
292 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
293 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
294 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
297 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
298 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
300 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
303 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
304 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
305 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
306 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
307 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
308 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
309 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
310 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
311 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
312 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
314 case WINED3DBLEND_DESTALPHA :
315 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
316 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
318 case WINED3DBLEND_INVDESTALPHA :
319 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
320 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
323 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
324 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
327 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
328 dstBlend = GL_SRC_ALPHA;
331 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
332 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
334 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
337 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
338 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
339 glEnable(GL_LINE_SMOOTH);
340 checkGLcall("glEnable(GL_LINE_SMOOTH)");
341 if(srcBlend != GL_SRC_ALPHA) {
342 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
344 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
345 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
348 glDisable(GL_LINE_SMOOTH);
349 checkGLcall("glDisable(GL_LINE_SMOOTH)");
352 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
353 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
354 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
357 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
358 int srcBlendAlpha = GL_ZERO;
359 int dstBlendAlpha = GL_ZERO;
361 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
362 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
363 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
367 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
368 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
369 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
370 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
371 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
372 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
373 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
374 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
375 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
376 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
377 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
378 case WINED3DBLEND_SRCALPHASAT :
379 dstBlend = GL_SRC_ALPHA_SATURATE;
380 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
382 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
383 * values which are still valid up to d3d9. They should not occur as dest blend values
385 case WINED3DBLEND_BOTHSRCALPHA :
386 dstBlendAlpha = GL_SRC_ALPHA;
387 srcBlendAlpha = GL_SRC_ALPHA;
388 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
390 case WINED3DBLEND_BOTHINVSRCALPHA :
391 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
392 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
393 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
395 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
396 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
398 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
401 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
402 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
403 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
404 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
405 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
406 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
407 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
408 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
409 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
410 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
411 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
412 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
413 case WINED3DBLEND_BOTHSRCALPHA :
414 srcBlendAlpha = GL_SRC_ALPHA;
415 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
417 case WINED3DBLEND_BOTHINVSRCALPHA :
418 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
419 dstBlendAlpha = GL_SRC_ALPHA;
421 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
422 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
424 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
427 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
428 checkGLcall("glBlendFuncSeparateEXT");
430 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
431 glBlendFunc(srcBlend, dstBlend);
432 checkGLcall("glBlendFunc");
435 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
436 so it may need updating */
437 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
438 const struct StateEntry *StateTable = stateblock->wineD3DDevice->shader_backend->StateTable;
439 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
443 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
446 if(!GL_SUPPORT(EXT_BLEND_COLOR)) {
447 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
451 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
452 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
453 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
454 checkGLcall("glBlendColor");
457 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
460 BOOL enable_ckey = FALSE;
462 IWineD3DSurfaceImpl *surf;
464 /* Find out if the texture on the first stage has a ckey set
465 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
466 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
467 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
468 * in case it finds some texture+colorkeyenable combination which needs extra care.
470 if(stateblock->textures[0] && (
471 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
472 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
473 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
475 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
476 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
477 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
478 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
479 * surface has alpha bits
481 if(fmt->alphaMask == 0x00000000) {
487 if(enable_ckey || context->last_was_ckey) {
488 const struct StateEntry *StateTable = stateblock->wineD3DDevice->shader_backend->StateTable;
489 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
491 context->last_was_ckey = enable_ckey;
493 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
494 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
495 glEnable(GL_ALPHA_TEST);
496 checkGLcall("glEnable GL_ALPHA_TEST");
498 glDisable(GL_ALPHA_TEST);
499 checkGLcall("glDisable GL_ALPHA_TEST");
500 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
506 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
507 glParm = GL_NOTEQUAL;
510 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
511 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
514 glAlphaFunc(glParm, ref);
515 checkGLcall("glAlphaFunc");
519 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
520 DWORD enable = 0xFFFFFFFF;
521 DWORD disable = 0x00000000;
523 if (use_vs(stateblock->wineD3DDevice)) {
524 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
525 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
526 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
527 * of that - don't do anything here and keep them disabled
529 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
530 static BOOL warned = FALSE;
532 FIXME("Clipping not supported with vertex shaders\n");
539 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
540 * of already set values
543 /* If enabling / disabling all
544 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
546 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
547 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
548 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
549 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
550 glDisable(GL_DEPTH_CLAMP_NV);
551 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
554 disable = 0xffffffff;
556 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
557 glEnable(GL_DEPTH_CLAMP_NV);
558 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
562 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
563 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
564 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
565 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
566 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
567 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
569 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
570 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
571 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
572 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
573 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
574 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
576 /** update clipping status */
578 stateblock->clip_status.ClipUnion = 0;
579 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
581 stateblock->clip_status.ClipUnion = 0;
582 stateblock->clip_status.ClipIntersection = 0;
586 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
587 int blendEquation = GL_FUNC_ADD;
588 int blendEquationAlpha = GL_FUNC_ADD;
590 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
591 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
595 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
596 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
597 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
601 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
602 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
603 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
604 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
605 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
606 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
608 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
611 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
612 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
613 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
614 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
615 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
616 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
618 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
621 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
622 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
623 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
624 checkGLcall("glBlendEquationSeparateEXT");
626 TRACE("glBlendEquation(%x)\n", blendEquation);
627 GL_EXTCALL(glBlendEquationEXT(blendEquation));
628 checkGLcall("glBlendEquation");
633 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
634 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
635 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
636 * specular color. This is wrong:
637 * Separate specular color means the specular colour is maintained separately, whereas
638 * single color means it is merged in. However in both cases they are being used to
640 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
641 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
645 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
646 * Instead, we need to setup the FinalCombiner properly.
648 * The default setup for the FinalCombiner is:
650 * <variable> <input> <mapping> <usage>
651 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
652 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
653 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
654 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
655 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
656 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
657 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
659 * That's pretty much fine as it is, except for variable B, which needs to take
660 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
661 * whether WINED3DRS_SPECULARENABLE is enabled or not.
664 TRACE("Setting specular enable state and materials\n");
665 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
666 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
667 checkGLcall("glMaterialfv");
669 if(stateblock->material.Power > GL_LIMITS(shininess)) {
670 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
671 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
672 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
673 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
674 * them, it should be safe to do so without major visual dissortions.
676 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
677 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
679 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
681 checkGLcall("glMaterialf(GL_SHININESS)");
683 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
684 glEnable(GL_COLOR_SUM_EXT);
686 TRACE("Specular colors cannot be enabled in this version of opengl\n");
688 checkGLcall("glEnable(GL_COLOR_SUM)");
690 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
691 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
692 checkGLcall("glFinalCombinerInputNV()");
695 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
697 /* for the case of enabled lighting: */
698 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
699 checkGLcall("glMaterialfv");
701 /* for the case of disabled lighting: */
702 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
703 glDisable(GL_COLOR_SUM_EXT);
705 TRACE("Specular colors cannot be disabled in this version of opengl\n");
707 checkGLcall("glDisable(GL_COLOR_SUM)");
709 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
710 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
711 checkGLcall("glFinalCombinerInputNV()");
715 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
716 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
717 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
718 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
719 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
720 stateblock->material.Specular.b, stateblock->material.Specular.a);
721 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
722 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
724 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
725 checkGLcall("glMaterialfv(GL_AMBIENT)");
726 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
727 checkGLcall("glMaterialfv(GL_DIFFUSE)");
728 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
729 checkGLcall("glMaterialfv(GL_EMISSION)");
732 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
735 /* Note the texture color applies to all textures whereas
736 * GL_TEXTURE_ENV_COLOR applies to active only
739 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
741 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
742 /* And now the default texture color as well */
743 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
744 /* Note the WINED3DRS value applies to all textures, but GL has one
745 * per texture, so apply it now ready to be used!
747 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
748 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
749 checkGLcall("glActiveTextureARB");
751 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
754 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
755 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
758 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
763 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
764 #if 0 /* Don't use OpenGL 2.0 calls for now */
765 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
766 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
767 checkGLcall("glStencilFuncSeparate(...)");
768 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
769 checkGLcall("glStencilOpSeparate(...)");
773 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
774 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
775 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
776 GL_EXTCALL(glActiveStencilFaceEXT(face));
777 checkGLcall("glActiveStencilFaceEXT(...)");
778 glStencilFunc(func, ref, mask);
779 checkGLcall("glStencilFunc(...)");
780 glStencilOp(stencilFail, depthFail, stencilPass);
781 checkGLcall("glStencilOp(...)");
782 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
783 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
784 checkGLcall("glStencilFuncSeparateATI(...)");
785 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
786 checkGLcall("glStencilOpSeparateATI(...)");
788 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
793 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
794 DWORD onesided_enable = FALSE;
795 DWORD twosided_enable = FALSE;
796 GLint func = GL_ALWAYS;
797 GLint func_ccw = GL_ALWAYS;
800 GLint stencilFail = GL_KEEP;
801 GLint depthFail = GL_KEEP;
802 GLint stencilPass = GL_KEEP;
803 GLint stencilFail_ccw = GL_KEEP;
804 GLint depthFail_ccw = GL_KEEP;
805 GLint stencilPass_ccw = GL_KEEP;
807 /* No stencil test without a stencil buffer */
808 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
809 glDisable(GL_STENCIL_TEST);
810 checkGLcall("glDisable GL_STENCIL_TEST");
814 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
815 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
816 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
818 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
819 func_ccw = GL_ALWAYS;
820 ref = stateblock->renderState[WINED3DRS_STENCILREF];
821 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
822 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
823 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
824 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
825 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
826 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
827 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
829 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
830 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
831 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
832 onesided_enable, twosided_enable, ref, mask,
833 func, stencilFail, depthFail, stencilPass,
834 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
836 if (twosided_enable && onesided_enable) {
837 glEnable(GL_STENCIL_TEST);
838 checkGLcall("glEnable GL_STENCIL_TEST");
840 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
841 * which has an effect on the code below too. If we apply the front face
842 * afterwards, we are sure that the active stencil face is set to front,
843 * and other stencil functions which do not use two sided stencil do not have
846 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
847 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
848 } else if(onesided_enable) {
849 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
850 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
851 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
854 glEnable(GL_STENCIL_TEST);
855 checkGLcall("glEnable GL_STENCIL_TEST");
856 glStencilFunc(func, ref, mask);
857 checkGLcall("glStencilFunc(...)");
858 glStencilOp(stencilFail, depthFail, stencilPass);
859 checkGLcall("glStencilOp(...)");
861 glDisable(GL_STENCIL_TEST);
862 checkGLcall("glDisable GL_STENCIL_TEST");
866 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
869 if(stateblock->wineD3DDevice->stencilBufferTarget) {
870 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
875 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
876 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
877 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
879 checkGLcall("glStencilMask");
880 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
881 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
886 checkGLcall("glStencilMask");
889 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
890 /* TODO: Put this into the vertex type block once that is in the state table */
891 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
892 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
893 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
894 float fogstart, fogend;
902 /* No fog? Disable it, and we're done :-) */
904 checkGLcall("glDisable GL_FOG");
905 if( use_ps(stateblock->wineD3DDevice)
906 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
907 /* disable fog in the pixel shader
908 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
909 * -1/(e-s) and e/(e-s) respectively.
911 glFogf(GL_FOG_START, 0.0f);
912 checkGLcall("glFogf(GL_FOG_START, fogstart)");
913 glFogf(GL_FOG_END, 1.0f);
914 checkGLcall("glFogf(GL_FOG_END, fogend)");
919 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
920 fogstart = tmpvalue.f;
921 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
926 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
927 * It can use the Z value of the vertex, or the alpha component of the specular color.
928 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
929 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
930 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
932 * FOGTABLEMODE != NONE:
933 * The Z value is used, with the equation specified, no matter what vertex type.
935 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
936 * Per vertex fog is calculated using the specified fog equation and the parameters
938 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
939 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
940 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
943 * Rules for vertex fog with shaders:
945 * When mixing fixed function functionality with the programmable pipeline, D3D expects
946 * the fog computation to happen during transformation while openGL expects it to happen
947 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
948 * the pixel shader while openGL always expects the pixel shader to handle the blending.
949 * To solve this problem, WineD3D does:
950 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
952 * and 2) disables the fog computation (in either the fixed function or programmable
953 * rasterizer) if using a vertex program.
956 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
961 if( !use_vs(stateblock->wineD3DDevice)
962 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
963 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
967 if (use_vs(stateblock->wineD3DDevice)
968 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
969 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
970 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
974 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
975 glFogi(GL_FOG_MODE, GL_LINEAR);
976 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
981 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
982 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
983 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
984 context->fog_coord = FALSE;
986 context->last_was_foggy_shader = TRUE;
988 else if( use_ps(stateblock->wineD3DDevice) ) {
989 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
990 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
993 context->last_was_foggy_shader = FALSE;
995 /* If both fogmodes are set use the table fog mode */
996 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
997 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
999 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1002 case WINED3DFOG_EXP:
1003 case WINED3DFOG_EXP2:
1004 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1009 case WINED3DFOG_LINEAR:
1010 fogstart = -1.0f/(fogend-fogstart);
1011 fogend *= -fogstart;
1014 case WINED3DFOG_NONE:
1015 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1019 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1022 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1023 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1024 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1025 context->fog_coord = FALSE;
1028 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1029 * the system will apply only pixel(=table) fog effects."
1031 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1032 glHint(GL_FOG_HINT, GL_FASTEST);
1033 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1034 context->last_was_foggy_shader = FALSE;
1036 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1037 /* If processed vertices are used, fall through to the NONE case */
1038 case WINED3DFOG_EXP: {
1039 if(!context->last_was_rhw) {
1040 glFogi(GL_FOG_MODE, GL_EXP);
1041 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1042 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1043 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1044 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1045 context->fog_coord = FALSE;
1050 case WINED3DFOG_EXP2: {
1051 if(!context->last_was_rhw) {
1052 glFogi(GL_FOG_MODE, GL_EXP2);
1053 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1054 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1055 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1056 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1057 context->fog_coord = FALSE;
1062 case WINED3DFOG_LINEAR: {
1063 if(!context->last_was_rhw) {
1064 glFogi(GL_FOG_MODE, GL_LINEAR);
1065 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1066 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1067 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1068 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1069 context->fog_coord = FALSE;
1074 case WINED3DFOG_NONE: {
1075 /* Both are none? According to msdn the alpha channel of the specular
1076 * color contains a fog factor. Set it in drawStridedSlow.
1077 * Same happens with Vertexfog on transformed vertices
1079 if(GL_SUPPORT(EXT_FOG_COORD)) {
1080 if(context->fog_coord == FALSE) {
1081 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1082 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1083 context->fog_coord = TRUE;
1085 glFogi(GL_FOG_MODE, GL_LINEAR);
1086 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1090 /* Disable GL fog, handle this in software in drawStridedSlow */
1095 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1098 glHint(GL_FOG_HINT, GL_NICEST);
1099 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1100 context->last_was_foggy_shader = FALSE;
1102 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1103 case WINED3DFOG_EXP:
1104 glFogi(GL_FOG_MODE, GL_EXP);
1105 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1106 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1107 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1108 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1109 context->fog_coord = FALSE;
1113 case WINED3DFOG_EXP2:
1114 glFogi(GL_FOG_MODE, GL_EXP2);
1115 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1116 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1117 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1118 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1119 context->fog_coord = FALSE;
1123 case WINED3DFOG_LINEAR:
1124 glFogi(GL_FOG_MODE, GL_LINEAR);
1125 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1126 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1127 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1128 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1129 context->fog_coord = FALSE;
1133 case WINED3DFOG_NONE: /* Won't happen */
1135 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1141 checkGLcall("glEnable GL_FOG");
1143 if(fogstart != fogend)
1145 glFogfv(GL_FOG_START, &fogstart);
1146 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1147 TRACE("Fog Start == %f\n", fogstart);
1149 glFogfv(GL_FOG_END, &fogend);
1150 checkGLcall("glFogf(GL_FOG_END, fogend)");
1151 TRACE("Fog End == %f\n", fogend);
1155 glFogf(GL_FOG_START, -1.0 / 0.0);
1156 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1157 TRACE("Fog Start == %f\n", fogstart);
1159 glFogf(GL_FOG_END, 0.0);
1160 checkGLcall("glFogf(GL_FOG_END, fogend)");
1161 TRACE("Fog End == %f\n", fogend);
1165 checkGLcall("glDisable GL_FOG");
1166 if( use_ps(stateblock->wineD3DDevice) ) {
1167 /* disable fog in the pixel shader
1168 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1169 * -1/(e-s) and e/(e-s) respectively.
1171 glFogf(GL_FOG_START, 0.0f);
1172 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1173 glFogf(GL_FOG_END, 1.0f);
1174 checkGLcall("glFogf(GL_FOG_END, fogend)");
1179 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1180 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1181 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1182 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1183 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1185 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1188 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1189 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1190 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1195 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1197 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1198 glFogfv(GL_FOG_COLOR, &col[0]);
1199 checkGLcall("glFog GL_FOG_COLOR");
1202 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1207 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1208 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1209 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1212 /* TODO: Merge with primitive type + init_materials()!! */
1213 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1214 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1216 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1217 BOOL isDiffuseSupplied;
1219 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1220 * The vertex declaration will call this function if the fixed function pipeline is used.
1223 if(isStateDirty(context, STATE_VDECL)) {
1227 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1229 context->num_untracked_materials = 0;
1230 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1231 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1232 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1233 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1234 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1235 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1237 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1238 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1239 Parm = GL_AMBIENT_AND_DIFFUSE;
1243 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1244 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1245 context->num_untracked_materials++;
1247 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1248 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1249 context->num_untracked_materials++;
1251 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1253 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1254 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1255 context->num_untracked_materials++;
1257 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1258 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1259 context->num_untracked_materials++;
1261 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1263 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1264 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1265 context->num_untracked_materials++;
1267 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1272 /* Nothing changed, return. */
1273 if (Parm == context->tracking_parm) return;
1276 glDisable(GL_COLOR_MATERIAL);
1277 checkGLcall("glDisable GL_COLOR_MATERIAL");
1279 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1280 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1281 glEnable(GL_COLOR_MATERIAL);
1282 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1285 /* Apparently calls to glMaterialfv are ignored for properties we're
1286 * tracking with glColorMaterial, so apply those here. */
1287 switch (context->tracking_parm) {
1288 case GL_AMBIENT_AND_DIFFUSE:
1289 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1290 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1291 checkGLcall("glMaterialfv");
1295 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1296 checkGLcall("glMaterialfv");
1300 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1301 checkGLcall("glMaterialfv");
1305 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1306 checkGLcall("glMaterialfv");
1310 /* Only change material color if specular is enabled, otherwise it is set to black */
1311 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1312 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1313 checkGLcall("glMaterialfv");
1315 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1316 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1317 checkGLcall("glMaterialfv");
1322 context->tracking_parm = Parm;
1325 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1328 WINED3DLINEPATTERN lp;
1330 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1332 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1334 if (tmppattern.lp.wRepeatFactor) {
1335 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1336 checkGLcall("glLineStipple(repeat, linepattern)");
1337 glEnable(GL_LINE_STIPPLE);
1338 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1340 glDisable(GL_LINE_STIPPLE);
1341 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1345 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1351 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1352 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1353 TRACE("ZBias value %f\n", tmpvalue.f);
1354 glPolygonOffset(0, -tmpvalue.f);
1355 checkGLcall("glPolygonOffset(0, -Value)");
1356 glEnable(GL_POLYGON_OFFSET_FILL);
1357 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1358 glEnable(GL_POLYGON_OFFSET_LINE);
1359 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1360 glEnable(GL_POLYGON_OFFSET_POINT);
1361 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1363 glDisable(GL_POLYGON_OFFSET_FILL);
1364 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1365 glDisable(GL_POLYGON_OFFSET_LINE);
1366 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1367 glDisable(GL_POLYGON_OFFSET_POINT);
1368 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1373 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1374 if(isStateDirty(context, STATE_VDECL)) {
1377 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1378 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1379 * by zero and is not properly defined in opengl, so avoid it
1381 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1382 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1383 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1384 glEnable(GL_NORMALIZE);
1385 checkGLcall("glEnable(GL_NORMALIZE);");
1387 glDisable(GL_NORMALIZE);
1388 checkGLcall("glDisable(GL_NORMALIZE);");
1392 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1398 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1399 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1400 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1401 checkGLcall("glPointParameterfARB(...)");
1403 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1404 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1405 checkGLcall("glPointParameterfEXT(...)");
1406 } else if(tmpvalue.f != 1.0) {
1407 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1411 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1417 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1418 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1419 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1420 checkGLcall("glPointParameterfARB(...)");
1422 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1423 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1424 checkGLcall("glPointParameterfEXT(...)");
1425 } else if(tmpvalue.f != 64.0) {
1426 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1430 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1431 /* TODO: Group this with the viewport */
1433 * POINTSCALEENABLE controls how point size value is treated. If set to
1434 * true, the point size is scaled with respect to height of viewport.
1435 * When set to false point size is in pixels.
1438 /* Default values */
1439 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1443 } pointSize, A, B, C;
1445 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1446 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1447 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1448 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1450 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1451 GLfloat scaleFactor;
1452 float h = stateblock->viewport.Height;
1454 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1456 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1457 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1458 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1459 * are less than 1.0f. scale_factor = 1.0f / point_size.
1461 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1462 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1463 * is 1.0, but then accepts points below that and draws too small points
1465 pointSize.f = GL_LIMITS(pointsizemin);
1466 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1467 /* gl already scales the input to glPointSize,
1468 * d3d scales the result after the point size scale.
1469 * If the point size is bigger than the max size, use the
1470 * scaling to scale it bigger, and set the gl point size to max
1472 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1473 TRACE("scale: %f\n", scaleFactor);
1474 pointSize.f = GL_LIMITS(pointsize);
1478 scaleFactor = pow(h * scaleFactor, 2);
1480 att[0] = A.f / scaleFactor;
1481 att[1] = B.f / scaleFactor;
1482 att[2] = C.f / scaleFactor;
1485 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1486 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1487 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1489 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1490 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1491 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1492 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1493 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1496 glPointSize(pointSize.f);
1497 checkGLcall("glPointSize(...);");
1500 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1501 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1503 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1504 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1505 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1506 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1507 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1508 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1509 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1510 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1511 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1512 checkGLcall("glColorMask(...)");
1514 /* depends on WINED3DRS_COLORWRITEENABLE. */
1515 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1516 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1517 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1518 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1519 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1520 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1521 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1525 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1526 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1527 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1528 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1530 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1531 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1535 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1536 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1537 TRACE("Last Pixel Drawing Enabled\n");
1539 static BOOL first = TRUE;
1541 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1544 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1549 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1550 /* TODO: NV_POINT_SPRITE */
1551 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1552 TRACE("Point sprites not supported\n");
1556 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1557 glEnable(GL_POINT_SPRITE_ARB);
1558 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1560 glDisable(GL_POINT_SPRITE_ARB);
1561 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1565 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1567 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1568 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1569 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1570 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1572 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1575 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1576 stateblock->renderState[WINED3DRS_WRAP1] ||
1577 stateblock->renderState[WINED3DRS_WRAP2] ||
1578 stateblock->renderState[WINED3DRS_WRAP3] ||
1579 stateblock->renderState[WINED3DRS_WRAP4] ||
1580 stateblock->renderState[WINED3DRS_WRAP5] ||
1581 stateblock->renderState[WINED3DRS_WRAP6] ||
1582 stateblock->renderState[WINED3DRS_WRAP7] ||
1583 stateblock->renderState[WINED3DRS_WRAP8] ||
1584 stateblock->renderState[WINED3DRS_WRAP9] ||
1585 stateblock->renderState[WINED3DRS_WRAP10] ||
1586 stateblock->renderState[WINED3DRS_WRAP11] ||
1587 stateblock->renderState[WINED3DRS_WRAP12] ||
1588 stateblock->renderState[WINED3DRS_WRAP13] ||
1589 stateblock->renderState[WINED3DRS_WRAP14] ||
1590 stateblock->renderState[WINED3DRS_WRAP15] ) {
1591 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1595 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1596 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1597 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1598 glEnable(GL_MULTISAMPLE_ARB);
1599 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1601 glDisable(GL_MULTISAMPLE_ARB);
1602 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1605 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1606 WARN("Multisample antialiasing not supported by gl\n");
1611 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1612 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1613 glEnable(GL_SCISSOR_TEST);
1614 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1616 glDisable(GL_SCISSOR_TEST);
1617 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1621 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1627 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1628 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1629 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1630 glEnable(GL_POLYGON_OFFSET_FILL);
1631 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1632 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1633 checkGLcall("glPolygonOffset(...)");
1635 glDisable(GL_POLYGON_OFFSET_FILL);
1636 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1640 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1641 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1642 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1643 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1645 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1646 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1650 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1652 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1653 FIXME(" Stippled Alpha not supported yet.\n");
1656 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1658 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1659 FIXME(" Antialias not supported yet.\n");
1662 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1664 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1665 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1668 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1670 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1671 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1674 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1682 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1684 static BOOL displayed = FALSE;
1686 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1688 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1694 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1696 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1697 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1700 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1702 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1703 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1706 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1708 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1709 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1712 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1713 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1714 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1718 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1719 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1720 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1724 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1725 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1726 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1730 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1731 if(stateblock->renderState[WINED3DRS_ROP2]) {
1732 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1736 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1737 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1738 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1742 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1743 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1744 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1748 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1749 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1750 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1754 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1755 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1756 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1760 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1761 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1762 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1766 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1767 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1768 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1772 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1773 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1774 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1778 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1779 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1780 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1784 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1785 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1786 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1790 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1791 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1792 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1796 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1797 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1798 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1802 /* Activates the texture dimension according to the bound D3D texture.
1803 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1804 * Requires the caller to activate the correct unit before
1806 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1807 BOOL bumpmap = FALSE;
1809 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1810 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1812 context->texShaderBumpMap |= (1 << stage);
1814 context->texShaderBumpMap &= ~(1 << stage);
1817 if(stateblock->textures[stage]) {
1818 switch(stateblock->textureDimensions[stage]) {
1820 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1821 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1822 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1824 glDisable(GL_TEXTURE_3D);
1825 checkGLcall("glDisable(GL_TEXTURE_3D)");
1826 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1827 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1828 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1830 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1831 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1832 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1834 glEnable(GL_TEXTURE_2D);
1835 checkGLcall("glEnable(GL_TEXTURE_2D)");
1838 case GL_TEXTURE_RECTANGLE_ARB:
1839 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1840 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB);
1841 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
1843 glDisable(GL_TEXTURE_2D);
1844 checkGLcall("glDisable(GL_TEXTURE_2D)");
1845 glDisable(GL_TEXTURE_3D);
1846 checkGLcall("glDisable(GL_TEXTURE_3D)");
1847 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1848 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1849 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1851 glEnable(GL_TEXTURE_RECTANGLE_ARB);
1852 checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
1856 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1857 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1858 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)");
1860 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1861 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1862 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1864 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1865 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1866 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1868 glDisable(GL_TEXTURE_2D);
1869 checkGLcall("glDisable(GL_TEXTURE_2D)");
1870 glEnable(GL_TEXTURE_3D);
1871 checkGLcall("glEnable(GL_TEXTURE_3D)");
1874 case GL_TEXTURE_CUBE_MAP_ARB:
1875 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1876 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1877 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
1879 glDisable(GL_TEXTURE_2D);
1880 checkGLcall("glDisable(GL_TEXTURE_2D)");
1881 glDisable(GL_TEXTURE_3D);
1882 checkGLcall("glDisable(GL_TEXTURE_3D)");
1883 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1884 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1885 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1887 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1888 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1893 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1894 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1895 checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)");
1897 glEnable(GL_TEXTURE_2D);
1898 checkGLcall("glEnable(GL_TEXTURE_2D)");
1899 glDisable(GL_TEXTURE_3D);
1900 checkGLcall("glDisable(GL_TEXTURE_3D)");
1901 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1902 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1903 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1905 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1906 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1907 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1909 /* Binding textures is done by samplers. A dummy texture will be bound */
1914 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1915 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1916 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1917 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1919 TRACE("Setting color op for stage %d\n", stage);
1921 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1922 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1923 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1927 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1929 if (mapped_stage != -1) {
1930 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1931 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1932 FIXME("Attempt to enable unsupported stage!\n");
1935 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1936 checkGLcall("glActiveTextureARB");
1937 } else if (stage > 0) {
1938 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1943 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1944 if(stateblock->lowest_disabled_stage > 0) {
1945 glEnable(GL_REGISTER_COMBINERS_NV);
1946 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1948 glDisable(GL_REGISTER_COMBINERS_NV);
1951 if(stage >= stateblock->lowest_disabled_stage) {
1952 TRACE("Stage disabled\n");
1953 if (mapped_stage != -1) {
1954 /* Disable everything here */
1955 glDisable(GL_TEXTURE_2D);
1956 checkGLcall("glDisable(GL_TEXTURE_2D)");
1957 glDisable(GL_TEXTURE_3D);
1958 checkGLcall("glDisable(GL_TEXTURE_3D)");
1959 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1960 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1961 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1963 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1964 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1965 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1967 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1968 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1975 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1976 * if the sampler for this stage is dirty
1978 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1979 if (tex_used) activate_dimensions(stage, stateblock, context);
1982 /* Set the texture combiners */
1983 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1984 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1985 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1986 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1987 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1988 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1991 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1992 * thus the texture shader may have to be updated
1994 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1995 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1996 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1997 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1998 if(usesBump != usedBump) {
1999 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
2000 checkGLcall("glActiveTextureARB");
2001 activate_dimensions(stage + 1, stateblock, context);
2002 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2003 checkGLcall("glActiveTextureARB");
2007 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2008 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2009 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2010 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2011 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2015 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2016 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2017 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2018 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2019 DWORD op, arg1, arg2, arg0;
2021 TRACE("Setting alpha op for stage %d\n", stage);
2022 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2023 if (mapped_stage != -1) {
2024 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2025 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2026 FIXME("Attempt to enable unsupported stage!\n");
2029 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2030 checkGLcall("glActiveTextureARB");
2031 } else if (stage > 0) {
2032 /* We can't do anything here */
2033 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2038 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2039 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2040 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2041 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2043 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
2044 stateblock->textures[0] &&
2045 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
2046 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2048 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
2049 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
2051 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
2052 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
2053 * cannot remove the texture's alpha channel entirely.
2055 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
2056 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
2057 * draw things like translucent text and perform other blending effects.
2059 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
2060 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
2061 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
2062 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
2063 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
2064 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
2065 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
2066 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
2068 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
2070 if(op == WINED3DTOP_DISABLE) {
2071 arg1 = WINED3DTA_TEXTURE;
2072 op = WINED3DTOP_SELECTARG1;
2074 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
2075 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
2076 arg2 = WINED3DTA_TEXTURE;
2077 op = WINED3DTOP_MODULATE;
2079 else arg1 = WINED3DTA_TEXTURE;
2081 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
2082 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
2083 arg1 = WINED3DTA_TEXTURE;
2084 op = WINED3DTOP_MODULATE;
2086 else arg2 = WINED3DTA_TEXTURE;
2091 TRACE("Setting alpha op for stage %d\n", stage);
2092 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2093 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2094 op, arg1, arg2, arg0,
2097 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2098 op, arg1, arg2, arg0);
2102 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2103 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
2104 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2107 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2108 if(use_vs(stateblock->wineD3DDevice) ||
2109 isStateDirty(context, STATE_VDECL)) {
2110 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
2114 if (mapped_stage == -1) return;
2116 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2117 if(mapped_stage >= GL_LIMITS(textures)) {
2120 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2121 checkGLcall("glActiveTextureARB");
2122 } else if (mapped_stage > 0) {
2123 /* We can't do anything here */
2124 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2127 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
2129 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
2130 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
2132 context->last_was_rhw,
2133 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
2134 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
2135 WINED3DDECLTYPE_UNUSED);
2137 /* The sampler applying function calls us if this changes */
2138 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
2140 FIXME("Non-power2 texture being used with generated texture coords\n");
2142 TRACE("Non power two matrix multiply fixup\n");
2143 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
2147 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
2150 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
2151 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2152 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2156 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2157 UINT *offset = stateblock->streamOffset;
2158 unsigned int mapped_stage = 0;
2159 unsigned int textureNo = 0;
2161 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2162 /* Abort if we don't support the extension. */
2163 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2164 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2168 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2169 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2171 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2172 if (mapped_stage == -1) continue;
2174 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2175 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2176 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2178 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2179 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2180 checkGLcall("glBindBufferARB");
2181 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2184 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2185 checkGLcall("glClientActiveTextureARB");
2187 /* The coords to supply depend completely on the fvf / vertex shader */
2189 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2190 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2191 sd->u.s.texCoords[coordIdx].dwStride,
2192 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2193 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2195 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2198 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2199 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2200 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2201 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2206 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2207 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2208 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2210 if (mapped_stage == -1) {
2211 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2215 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2216 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2219 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2220 checkGLcall("glActiveTextureARB");
2221 } else if (stage > 0) {
2222 /* We can't do anything here */
2223 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2227 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2229 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2230 * one flag, you can still specify an index value, which the system uses to
2231 * determine the texture wrapping mode.
2232 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2233 * means use the vertex position (camera-space) as the input texture coordinates
2234 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2235 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2236 * to the TEXCOORDINDEX value
2240 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2242 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2243 case WINED3DTSS_TCI_PASSTHRU:
2244 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2245 glDisable(GL_TEXTURE_GEN_S);
2246 glDisable(GL_TEXTURE_GEN_T);
2247 glDisable(GL_TEXTURE_GEN_R);
2248 glDisable(GL_TEXTURE_GEN_Q);
2249 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2252 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2253 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2254 * as the input texture coordinates for this stage's texture transformation. This
2255 * equates roughly to EYE_LINEAR
2258 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2259 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2260 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2261 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2262 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2264 glMatrixMode(GL_MODELVIEW);
2267 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2268 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2269 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2270 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2273 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2274 glEnable(GL_TEXTURE_GEN_S);
2275 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2276 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2277 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2278 glEnable(GL_TEXTURE_GEN_T);
2279 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2280 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2281 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2282 glEnable(GL_TEXTURE_GEN_R);
2283 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2284 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2285 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2289 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2291 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2292 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2293 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2294 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2295 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2296 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2298 glMatrixMode(GL_MODELVIEW);
2301 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2302 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2303 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2304 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2307 glEnable(GL_TEXTURE_GEN_S);
2308 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2309 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2310 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2311 glEnable(GL_TEXTURE_GEN_T);
2312 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2313 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2314 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2315 glEnable(GL_TEXTURE_GEN_R);
2316 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2317 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2318 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2323 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2325 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2326 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2327 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2328 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2329 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2330 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2332 glMatrixMode(GL_MODELVIEW);
2335 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2336 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2337 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2338 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2341 glEnable(GL_TEXTURE_GEN_S);
2342 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2343 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2344 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2345 glEnable(GL_TEXTURE_GEN_T);
2346 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2347 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2348 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2349 glEnable(GL_TEXTURE_GEN_R);
2350 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2351 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2352 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2357 /* Unhandled types: */
2360 /* ? disable GL_TEXTURE_GEN_n ? */
2361 glDisable(GL_TEXTURE_GEN_S);
2362 glDisable(GL_TEXTURE_GEN_T);
2363 glDisable(GL_TEXTURE_GEN_R);
2364 glDisable(GL_TEXTURE_GEN_Q);
2365 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2369 /* Update the texture matrix */
2370 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2371 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2374 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2375 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2376 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2377 * and do all the things linked to it
2378 * TODO: Tidy that up to reload only the arrays of the changed unit
2380 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2382 unloadTexCoords(stateblock);
2383 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2387 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2388 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2390 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2391 * has an update pending
2393 if(isStateDirty(context, STATE_VDECL) ||
2394 isStateDirty(context, STATE_PIXELSHADER)) {
2398 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2401 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2402 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2408 if(stateblock->pixelShader && stage != 0 &&
2409 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2410 /* The pixel shader has to know the luminance scale. Do a constants update if it
2411 * isn't scheduled anyway
2413 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2414 !isStateDirty(context, STATE_PIXELSHADER)) {
2415 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2419 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2420 if(tmpvalue.f != 0.0) {
2421 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2425 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2426 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2432 if(stateblock->pixelShader && stage != 0 &&
2433 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2434 /* The pixel shader has to know the luminance offset. Do a constants update if it
2435 * isn't scheduled anyway
2437 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2438 !isStateDirty(context, STATE_PIXELSHADER)) {
2439 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2443 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2444 if(tmpvalue.f != 0.0) {
2445 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2449 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2450 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2452 if(stage >= GL_LIMITS(texture_stages)) {
2456 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2457 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2461 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2462 DWORD sampler = state - STATE_SAMPLER(0);
2463 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2469 TRACE("Sampler: %d\n", sampler);
2470 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2471 * only has to bind textures and set the per texture states
2474 if (mapped_stage == -1) {
2475 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2479 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2480 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2483 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2484 checkGLcall("glActiveTextureARB");
2485 } else if (sampler > 0) {
2486 /* We can't do anything here */
2487 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2491 if(stateblock->textures[sampler]) {
2492 BOOL texIsPow2 = FALSE;
2494 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2495 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2496 * scaling is reapplied or removed, the texture matrix has to be reapplied
2498 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2499 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2500 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2501 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0 ||
2502 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[5] != 1.0 ) {
2505 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2506 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0) {
2511 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2512 context->lastWasPow2Texture[sampler] = texIsPow2;
2513 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2517 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
2518 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2520 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2521 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2522 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2523 GL_TEXTURE_LOD_BIAS_EXT,
2525 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
2528 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2529 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2530 /* Using a pixel shader? Verify the sampler types */
2532 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2533 * dimensions because the shader knows from which texture type to sample from. For the sake of
2534 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2535 * dimensions. This should make wrong sampling sources visible :-)
2537 glEnable(stateblock->textureDimensions[sampler]);
2538 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2539 } else if(sampler < stateblock->lowest_disabled_stage) {
2540 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2541 activate_dimensions(sampler, stateblock, context);
2544 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2545 /* If color keying is enabled update the alpha test, it depends on the existence
2546 * of a color key in stage 0
2548 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2551 } else if(mapped_stage < GL_LIMITS(textures)) {
2552 if(sampler < stateblock->lowest_disabled_stage) {
2553 /* TODO: What should I do with pixel shaders here ??? */
2554 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2555 activate_dimensions(sampler, stateblock, context);
2558 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2559 /* If color keying is enabled update the alpha test, it depends on the existence
2560 * of a color key in stage 0
2562 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2564 } /* Otherwise tex_colorop disables the stage */
2565 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2566 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2570 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2571 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2572 BOOL use_pshader = use_ps(device);
2573 BOOL use_vshader = use_vs(device);
2574 BOOL update_fog = FALSE;
2578 if(!context->last_was_pshader) {
2579 /* Former draw without a pixel shader, some samplers
2580 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2581 * make sure to enable them
2583 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2584 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2585 sampler(STATE_SAMPLER(i), stateblock, context);
2590 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2591 * if a different texture was bound. I don't have to do anything.
2595 /* Compile and bind the shader */
2596 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2598 /* Disabled the pixel shader - color ops weren't applied
2599 * while it was enabled, so re-apply them.
2601 for(i=0; i < MAX_TEXTURES; i++) {
2602 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2603 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2606 if(context->last_was_pshader)
2610 if(!isStateDirty(context, FFPStateTable[STATE_VSHADER].representative)) {
2611 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2613 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2614 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2619 state_fog(state, stateblock, context);
2621 context->last_was_pshader = use_pshader;
2624 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2625 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2627 if(stateblock->pixelShader && stage != 0 &&
2628 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
2629 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2632 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2633 !isStateDirty(context, STATE_PIXELSHADER)) {
2634 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2638 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2639 if(stage >= GL_LIMITS(texture_stages)) {
2640 WARN("Bump env matrix of unsupported stage set\n");
2641 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2642 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2643 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2645 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2646 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2647 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2648 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2649 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, (float *) mat));
2650 checkGLcall("glTexBumpParameterfvATI");
2651 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2652 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2653 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2654 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2655 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2656 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2658 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2660 if(mapped_stage < GL_LIMITS(textures)) {
2661 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2662 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2664 /* We can't just pass a pointer to the stateblock to GL due to the different matrix
2665 * format(column major vs row major)
2667 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2668 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2669 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2670 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2671 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *) mat);
2672 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)");
2677 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2678 /* This function is called by transform_view below if the view matrix was changed too
2680 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2681 * does not always update the world matrix, only on a switch between transformed
2682 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
2683 * draw, but that should be rather rare and cheaper in total.
2685 glMatrixMode(GL_MODELVIEW);
2686 checkGLcall("glMatrixMode");
2688 if(context->last_was_rhw) {
2690 checkGLcall("glLoadIdentity()");
2692 /* In the general case, the view matrix is the identity matrix */
2693 if (stateblock->wineD3DDevice->view_ident) {
2694 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2695 checkGLcall("glLoadMatrixf");
2697 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2698 checkGLcall("glLoadMatrixf");
2699 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2700 checkGLcall("glMultMatrixf");
2705 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2706 UINT index = state - STATE_CLIPPLANE(0);
2708 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2712 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2713 glMatrixMode(GL_MODELVIEW);
2715 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2717 TRACE("Clipplane [%f,%f,%f,%f]\n",
2718 stateblock->clipplane[index][0],
2719 stateblock->clipplane[index][1],
2720 stateblock->clipplane[index][2],
2721 stateblock->clipplane[index][3]);
2722 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2723 checkGLcall("glClipPlane");
2728 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2729 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2731 TRACE("Setting world matrix %d\n", matrix);
2733 if(matrix >= GL_LIMITS(blends)) {
2734 WARN("Unsupported blend matrix set\n");
2736 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2740 /* GL_MODELVIEW0_ARB: 0x1700
2741 * GL_MODELVIEW1_ARB: 0x0x850a
2742 * GL_MODELVIEW2_ARB: 0x8722
2743 * GL_MODELVIEW3_ARB: 0x8723
2745 * GL_MODELVIEW31_ARB: 0x873F
2747 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2748 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2750 glMatrixMode(glMat);
2751 checkGLcall("glMatrixMode(glMat)");
2753 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2754 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2756 if(stateblock->wineD3DDevice->view_ident) {
2757 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2758 checkGLcall("glLoadMatrixf")
2760 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2761 checkGLcall("glLoadMatrixf")
2762 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2763 checkGLcall("glMultMatrixf")
2767 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2768 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2771 case WINED3DVBF_1WEIGHTS:
2772 case WINED3DVBF_2WEIGHTS:
2773 case WINED3DVBF_3WEIGHTS:
2774 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2775 glEnable(GL_VERTEX_BLEND_ARB);
2776 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2778 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2779 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2781 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2783 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2785 for(i = 1; i < GL_LIMITS(blends); i++) {
2786 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2787 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2790 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2793 static BOOL once = FALSE;
2796 /* TODO: Implement vertex blending in drawStridedSlow */
2797 FIXME("Vertex blending enabled, but not supported by hardware\n");
2802 case WINED3DVBF_DISABLE:
2803 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2804 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2805 glDisable(GL_VERTEX_BLEND_ARB);
2806 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2808 TRACE("Vertex blending disabled\n");
2812 case WINED3DVBF_TWEENING:
2813 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2814 * vertex weights in the vertices?
2815 * For now we don't report that as supported, so a warn should suffice
2817 WARN("Tweening not supported yet\n");
2822 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2825 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2826 * NOTE: We have to reset the positions even if the light/plane is not currently
2827 * enabled, since the call to enable it will not reset the position.
2828 * NOTE2: Apparently texture transforms do NOT need reapplying
2831 PLIGHTINFOEL *light = NULL;
2833 glMatrixMode(GL_MODELVIEW);
2834 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2835 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2836 checkGLcall("glLoadMatrixf(...)");
2838 /* Reset lights. TODO: Call light apply func */
2839 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2840 light = stateblock->activeLights[k];
2841 if(!light) continue;
2842 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2843 checkGLcall("glLightfv posn");
2844 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2845 checkGLcall("glLightfv dirn");
2848 /* Reset Clipping Planes */
2849 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2850 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2851 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2855 if(context->last_was_rhw) {
2857 checkGLcall("glLoadIdentity()");
2858 /* No need to update the world matrix, the identity is fine */
2862 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2863 * No need to do it here if the state is scheduled for update.
2865 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2866 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2869 /* Avoid looping over a number of matrices if the app never used the functionality */
2870 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2871 for(k = 1; k < GL_LIMITS(blends); k++) {
2872 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2873 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2879 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2880 glMatrixMode(GL_PROJECTION);
2881 checkGLcall("glMatrixMode(GL_PROJECTION)");
2883 checkGLcall("glLoadIdentity");
2885 if(context->last_was_rhw) {
2886 double X, Y, height, width, minZ, maxZ;
2888 X = stateblock->viewport.X;
2889 Y = stateblock->viewport.Y;
2890 height = stateblock->viewport.Height;
2891 width = stateblock->viewport.Width;
2892 minZ = stateblock->viewport.MinZ;
2893 maxZ = stateblock->viewport.MaxZ;
2895 if(!stateblock->wineD3DDevice->untransformed) {
2896 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2897 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2898 * suppress depth clipping. This can be done because it is an orthogonal projection and
2899 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2900 * Persia 3D need this.
2902 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2903 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2904 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2907 * Also note that this breaks z comparison against z values filled in with clear,
2908 * but no app depending on that and disabled clipping has been found yet. Comparing
2909 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2912 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2913 * but this would break Z buffer operation. Raising the range to something less than
2914 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2917 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2918 if(stateblock->wineD3DDevice->render_offscreen) {
2919 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2921 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2924 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2925 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2926 * unmodified to opengl.
2928 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2929 * replacement shader.
2931 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2932 if(stateblock->wineD3DDevice->render_offscreen) {
2933 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2935 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2938 checkGLcall("glOrtho");
2940 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2941 glTranslatef(0.5, 0.5, 0);
2942 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2943 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2944 * render everything upside down when rendering offscreen. */
2945 if (stateblock->wineD3DDevice->render_offscreen) {
2946 glScalef(1.0, -1.0, 1.0);
2947 checkGLcall("glScalef");
2950 /* The rule is that the window coordinate 0 does not correspond to the
2951 beginning of the first pixel, but the center of the first pixel.
2952 As a consequence if you want to correctly draw one line exactly from
2953 the left to the right end of the viewport (with all matrices set to
2954 be identity), the x coords of both ends of the line would be not
2955 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2958 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2959 divide by the Width/Height, so we need the half range(1.0) to translate by
2962 The other fun is that d3d's output z range after the transformation is [0;1],
2963 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2964 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2965 of Z buffer precision and the clear values do not match in the z test. Thus scale
2966 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2968 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2969 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2970 if (stateblock->wineD3DDevice->render_offscreen) {
2971 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2972 * render everything upside down when rendering offscreen. */
2973 glScalef(1.0, -1.0, 2.0);
2975 glScalef(1.0, 1.0, 2.0);
2977 checkGLcall("glScalef");
2979 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2980 checkGLcall("glLoadMatrixf");
2984 /* This should match any arrays loaded in loadVertexData.
2985 * stateblock impl is required for GL_SUPPORT
2986 * TODO: Only load / unload arrays if we have to.
2988 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2989 glDisableClientState(GL_VERTEX_ARRAY);
2990 glDisableClientState(GL_NORMAL_ARRAY);
2991 glDisableClientState(GL_COLOR_ARRAY);
2992 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2993 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2995 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2996 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2997 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2998 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3000 unloadTexCoords(stateblock);
3003 /* This should match any arrays loaded in loadNumberedArrays
3004 * TODO: Only load / unload arrays if we have to.
3006 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
3007 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3008 GLint maxAttribs = 16;
3011 /* Leave all the attribs disabled */
3012 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3013 /* MESA does not support it right not */
3014 if (glGetError() != GL_NO_ERROR)
3016 for (i = 0; i < maxAttribs; ++i) {
3017 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3018 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3022 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
3023 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3025 UINT *offset = stateblock->streamOffset;
3026 IWineD3DVertexBufferImpl *vb;
3027 DWORD_PTR shift_index;
3029 /* Default to no instancing */
3030 stateblock->wineD3DDevice->instancedDraw = FALSE;
3032 for (i = 0; i < MAX_ATTRIBS; i++) {
3034 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
3037 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3038 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3039 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3040 stateblock->wineD3DDevice->instancedDraw = TRUE;
3044 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3046 if(strided->u.input[i].dwStride) {
3047 if(curVBO != strided->u.input[i].VBO) {
3048 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3049 checkGLcall("glBindBufferARB");
3050 curVBO = strided->u.input[i].VBO;
3052 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3053 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3054 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3055 * vbo we won't be load converted attributes anyway
3057 if(curVBO && vb->conv_shift) {
3058 TRACE("Loading attribute from shifted buffer\n");
3059 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
3060 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3061 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3062 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3063 shift_index = shift_index % strided->u.input[i].dwStride;
3064 GL_EXTCALL(glVertexAttribPointerARB(i,
3065 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3066 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3067 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3070 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
3071 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3072 offset[strided->u.input[i].streamNo]));
3075 GL_EXTCALL(glVertexAttribPointerARB(i,
3076 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3077 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3078 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3079 strided->u.input[i].dwStride,
3081 strided->u.input[i].lpData +
3082 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3083 offset[strided->u.input[i].streamNo]) );
3085 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3087 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3088 * set up the attribute statically. But we have to figure out the system memory address.
3090 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3091 if(strided->u.input[i].VBO) {
3092 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3093 ptr += (long) vb->resource.allocatedMemory;
3095 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3097 switch(strided->u.input[i].dwType) {
3098 case WINED3DDECLTYPE_FLOAT1:
3099 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
3101 case WINED3DDECLTYPE_FLOAT2:
3102 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
3104 case WINED3DDECLTYPE_FLOAT3:
3105 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
3107 case WINED3DDECLTYPE_FLOAT4:
3108 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
3111 case WINED3DDECLTYPE_UBYTE4:
3112 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3114 case WINED3DDECLTYPE_UBYTE4N:
3115 case WINED3DDECLTYPE_D3DCOLOR:
3116 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3119 case WINED3DDECLTYPE_SHORT2:
3120 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3122 case WINED3DDECLTYPE_SHORT4:
3123 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3126 case WINED3DDECLTYPE_SHORT2N:
3128 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
3129 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3132 case WINED3DDECLTYPE_USHORT2N:
3134 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
3135 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3138 case WINED3DDECLTYPE_SHORT4N:
3139 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
3141 case WINED3DDECLTYPE_USHORT4N:
3142 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
3145 case WINED3DDECLTYPE_UDEC3:
3146 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3147 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
3149 case WINED3DDECLTYPE_DEC3N:
3150 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3151 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
3154 case WINED3DDECLTYPE_FLOAT16_2:
3155 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3156 * byte float according to the IEEE standard
3158 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3160 case WINED3DDECLTYPE_FLOAT16_4:
3161 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3164 case WINED3DDECLTYPE_UNUSED:
3166 ERR("Unexpected declaration in stride 0 attributes\n");
3172 checkGLcall("Loading numbered arrays");
3175 /* Used from 2 different functions, and too big to justify making it inlined */
3176 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3177 UINT *offset = stateblock->streamOffset;
3178 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3180 TRACE("Using fast vertex array code\n");
3182 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3183 stateblock->wineD3DDevice->instancedDraw = FALSE;
3185 /* Blend Data ---------------------------------------------- */
3186 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3187 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3189 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3190 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3191 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3193 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3194 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3196 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3198 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3199 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3200 sd->u.s.blendWeights.dwStride,
3201 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3203 if(curVBO != sd->u.s.blendWeights.VBO) {
3204 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3205 checkGLcall("glBindBufferARB");
3206 curVBO = sd->u.s.blendWeights.VBO;
3209 GL_EXTCALL(glWeightPointerARB)(
3210 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3211 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3212 sd->u.s.blendWeights.dwStride,
3213 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3215 checkGLcall("glWeightPointerARB");
3217 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3218 static BOOL showfixme = TRUE;
3220 FIXME("blendMatrixIndices support\n");
3224 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3225 /* FIXME("TODO\n");*/
3228 GL_EXTCALL(glVertexWeightPointerEXT)(
3229 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3230 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3231 sd->u.s.blendWeights.dwStride,
3232 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3233 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3234 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3235 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3239 /* TODO: support blends in drawStridedSlow
3240 * No need to write a FIXME here, this is done after the general vertex decl decoding
3242 WARN("unsupported blending in openGl\n");
3245 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3246 static const GLbyte one = 1;
3247 GL_EXTCALL(glWeightbvARB(1, &one));
3248 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3252 #if 0 /* FOG ----------------------------------------------*/
3253 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3255 if (GL_SUPPORT(EXT_FOG_COORD) {
3256 glEnableClientState(GL_FOG_COORDINATE_EXT);
3257 (GL_EXTCALL)(FogCoordPointerEXT)(
3258 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3259 sd->u.s.fog.dwStride,
3260 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3262 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3263 /* FIXME: fixme once */
3264 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3267 if (GL_SUPPRT(EXT_FOR_COORD) {
3268 /* make sure fog is disabled */
3269 glDisableClientState(GL_FOG_COORDINATE_EXT);
3274 #if 0 /* tangents ----------------------------------------------*/
3275 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3276 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3278 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3279 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3280 glEnable(GL_TANGENT_ARRAY_EXT);
3281 (GL_EXTCALL)(TangentPointerEXT)(
3282 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3283 sd->u.s.tangent.dwStride,
3284 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3286 glDisable(GL_TANGENT_ARRAY_EXT);
3288 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3289 glEnable(GL_BINORMAL_ARRAY_EXT);
3290 (GL_EXTCALL)(BinormalPointerEXT)(
3291 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3292 sd->u.s.binormal.dwStride,
3293 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3295 glDisable(GL_BINORMAL_ARRAY_EXT);
3299 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3300 /* FIXME: fixme once */
3301 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3304 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3305 /* make sure fog is disabled */
3306 glDisable(GL_TANGENT_ARRAY_EXT);
3307 glDisable(GL_BINORMAL_ARRAY_EXT);
3312 /* Point Size ----------------------------------------------*/
3313 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3315 /* no such functionality in the fixed function GL pipeline */
3316 TRACE("Cannot change ptSize here in openGl\n");
3317 /* TODO: Implement this function in using shaders if they are available */
3321 /* Vertex Pointers -----------------------------------------*/
3322 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3323 /* Note dwType == float3 or float4 == 2 or 3 */
3324 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3325 sd->u.s.position.dwStride,
3326 sd->u.s.position.dwType + 1,
3327 sd->u.s.position.lpData));
3329 if(curVBO != sd->u.s.position.VBO) {
3330 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3331 checkGLcall("glBindBufferARB");
3332 curVBO = sd->u.s.position.VBO;
3335 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3336 handling for rhw mode should not impact screen position whereas in GL it does.
3337 This may result in very slightly distorted textures in rhw mode.
3338 There's always the other option of fixing the view matrix to
3339 prevent w from having any effect.
3341 This only applies to user pointer sources, in VBOs the vertices are fixed up
3343 if(sd->u.s.position.VBO == 0) {
3344 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3345 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3346 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3349 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3350 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3351 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3353 checkGLcall("glVertexPointer(...)");
3354 glEnableClientState(GL_VERTEX_ARRAY);
3355 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3358 /* Normals -------------------------------------------------*/
3359 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3360 /* Note dwType == float3 or float4 == 2 or 3 */
3361 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3362 sd->u.s.normal.dwStride,
3363 sd->u.s.normal.lpData));
3364 if(curVBO != sd->u.s.normal.VBO) {
3365 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3366 checkGLcall("glBindBufferARB");
3367 curVBO = sd->u.s.normal.VBO;
3370 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3371 sd->u.s.normal.dwStride,
3372 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3373 checkGLcall("glNormalPointer(...)");
3374 glEnableClientState(GL_NORMAL_ARRAY);
3375 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3378 glNormal3f(0, 0, 0);
3379 checkGLcall("glNormal3f(0, 0, 0)");
3382 /* Diffuse Colour --------------------------------------------*/
3383 /* WARNING: Data here MUST be in RGBA format, so cannot */
3384 /* go directly into fast mode from app pgm, because */
3385 /* directx requires data in BGRA format. */
3386 /* currently fixupVertices swizzles the format, but this isn't*/
3387 /* very practical when using VBOS */
3388 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3389 /* , or the user doesn't care and wants the speed advantage */
3391 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3392 /* Note dwType == float3 or float4 == 2 or 3 */
3393 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3394 sd->u.s.diffuse.dwStride,
3395 sd->u.s.diffuse.lpData));
3397 if(curVBO != sd->u.s.diffuse.VBO) {
3398 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3399 checkGLcall("glBindBufferARB");
3400 curVBO = sd->u.s.diffuse.VBO;
3403 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3404 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3405 sd->u.s.diffuse.dwStride,
3406 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3407 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3408 glEnableClientState(GL_COLOR_ARRAY);
3409 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3412 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3413 checkGLcall("glColor4f(1, 1, 1, 1)");
3416 /* Specular Colour ------------------------------------------*/
3417 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3418 TRACE("setting specular colour\n");
3419 /* Note dwType == float3 or float4 == 2 or 3 */
3420 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3421 sd->u.s.specular.dwStride,
3422 sd->u.s.specular.lpData));
3423 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3424 if(curVBO != sd->u.s.specular.VBO) {
3425 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3426 checkGLcall("glBindBufferARB");
3427 curVBO = sd->u.s.specular.VBO;
3429 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3430 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3431 sd->u.s.specular.dwStride,
3432 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3433 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3434 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3435 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3438 /* Missing specular color is not critical, no warnings */
3439 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3443 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3444 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3445 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3448 /* Missing specular color is not critical, no warnings */
3449 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3453 /* Texture coords -------------------------------------------*/
3454 loadTexCoords(stateblock, sd, &curVBO);
3457 static inline void drawPrimitiveTraceDataLocations(
3458 WineDirect3DVertexStridedData *dataLocations) {
3460 /* Dump out what parts we have supplied */
3461 TRACE("Strided Data:\n");
3462 TRACE_STRIDED((dataLocations), position);
3463 TRACE_STRIDED((dataLocations), blendWeights);
3464 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3465 TRACE_STRIDED((dataLocations), normal);
3466 TRACE_STRIDED((dataLocations), pSize);
3467 TRACE_STRIDED((dataLocations), diffuse);
3468 TRACE_STRIDED((dataLocations), specular);
3469 TRACE_STRIDED((dataLocations), texCoords[0]);
3470 TRACE_STRIDED((dataLocations), texCoords[1]);
3471 TRACE_STRIDED((dataLocations), texCoords[2]);
3472 TRACE_STRIDED((dataLocations), texCoords[3]);
3473 TRACE_STRIDED((dataLocations), texCoords[4]);
3474 TRACE_STRIDED((dataLocations), texCoords[5]);
3475 TRACE_STRIDED((dataLocations), texCoords[6]);
3476 TRACE_STRIDED((dataLocations), texCoords[7]);
3477 TRACE_STRIDED((dataLocations), position2);
3478 TRACE_STRIDED((dataLocations), normal2);
3479 TRACE_STRIDED((dataLocations), tangent);
3480 TRACE_STRIDED((dataLocations), binormal);
3481 TRACE_STRIDED((dataLocations), tessFactor);
3482 TRACE_STRIDED((dataLocations), fog);
3483 TRACE_STRIDED((dataLocations), depth);
3484 TRACE_STRIDED((dataLocations), sample);
3489 /* Helper for vertexdeclaration() */
3490 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3491 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3493 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3495 if(device->up_strided) {
3496 /* Note: this is a ddraw fixed-function code path */
3497 TRACE("================ Strided Input ===================\n");
3498 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3501 drawPrimitiveTraceDataLocations(dataLocations);
3504 /* Note: This is a fixed function or shader codepath.
3505 * This means it must handle both types of strided data.
3506 * Shaders must go through here to zero the strided data, even if they
3507 * don't set any declaration at all
3509 TRACE("================ Vertex Declaration ===================\n");
3510 memset(dataLocations, 0, sizeof(*dataLocations));
3511 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3512 useVertexShaderFunction, dataLocations, &fixup);
3515 if (dataLocations->u.s.position_transformed) {
3516 useVertexShaderFunction = FALSE;
3519 /* Unload the old arrays before loading the new ones to get old junk out */
3520 if(context->numberedArraysLoaded) {
3521 unloadNumberedArrays(stateblock);
3522 context->numberedArraysLoaded = FALSE;
3524 if(context->namedArraysLoaded) {
3525 unloadVertexData(stateblock);
3526 context->namedArraysLoaded = FALSE;
3529 if(useVertexShaderFunction) {
3530 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3531 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3532 device->useDrawStridedSlow = TRUE;
3533 context->numberedArraysLoaded = FALSE;
3535 TRACE("Loading numbered arrays\n");
3536 loadNumberedArrays(stateblock, dataLocations);
3537 device->useDrawStridedSlow = FALSE;
3538 context->numberedArraysLoaded = TRUE;
3541 (dataLocations->u.s.pSize.lpData == NULL &&
3542 dataLocations->u.s.diffuse.lpData == NULL &&
3543 dataLocations->u.s.specular.lpData == NULL)) {
3544 /* Load the vertex data using named arrays */
3545 TRACE("Loading vertex data\n");
3546 loadVertexData(stateblock, dataLocations);
3547 device->useDrawStridedSlow = FALSE;
3548 context->namedArraysLoaded = TRUE;
3550 TRACE("Not loading vertex data\n");
3551 device->useDrawStridedSlow = TRUE;
3554 /* Generate some fixme's if unsupported functionality is being used */
3555 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3556 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3557 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3558 FIXME("Tweening is only valid with vertex shaders\n");
3560 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3561 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3563 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3564 FIXME("Extended attributes are only valid with vertex shaders\n");
3566 #undef BUFFER_OR_DATA
3569 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3570 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3571 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3572 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3574 /* Some stuff is in the device until we have per context tracking */
3575 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3576 BOOL wasrhw = context->last_was_rhw;
3578 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3579 * here simply check whether a shader was set, or the user disabled shaders
3581 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3582 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3583 useVertexShaderFunction = TRUE;
3585 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3588 } else if(context->last_was_foggy_shader) {
3592 handleStreams(stateblock, useVertexShaderFunction, context);
3594 transformed = device->strided_streams.u.s.position_transformed;
3595 if (transformed) useVertexShaderFunction = FALSE;
3597 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3601 /* Reapply lighting if it is not scheduled for reapplication already */
3602 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3603 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3607 context->last_was_rhw = TRUE;
3610 /* Untransformed, so relies on the view and projection matrices */
3611 context->last_was_rhw = FALSE;
3612 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3613 device->untransformed = TRUE;
3615 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3616 * Not needed as long as only hw shaders are supported
3619 /* This sets the shader output position correction constants.
3620 * TODO: Move to the viewport state
3622 if (useVertexShaderFunction) {
3623 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3624 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3628 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3629 * off this function will be called again anyway to make sure they're properly set
3631 if(!useVertexShaderFunction) {
3632 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3633 * or transformed / untransformed was switched
3635 if(wasrhw != context->last_was_rhw &&
3636 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3637 !isStateDirty(context, STATE_VIEWPORT)) {
3638 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3640 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3643 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3644 * this check will fail and the matrix not applied again. This is OK because a simple
3645 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3646 * needs of the vertex declaration.
3648 * World and view matrix go into the same gl matrix, so only apply them when neither is
3651 if(transformed != wasrhw &&
3652 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3653 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3654 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3657 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3658 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3661 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3662 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3664 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3665 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3668 /* We compile the shader here because we need the vertex declaration
3669 * in order to determine if we need to do any swizzling for D3DCOLOR
3670 * registers. If the shader is already compiled this call will do nothing. */
3671 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3673 if(!context->last_was_vshader) {
3675 static BOOL warned = FALSE;
3676 /* Disable all clip planes to get defined results on all drivers. See comment in the
3677 * state_clipping state handler
3679 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3680 glDisable(GL_CLIP_PLANE0 + i);
3681 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3684 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3685 FIXME("Clipping not supported with vertex shaders\n");
3689 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3690 * shaders themselves do not need it, but the matrices are not reapplied automatically when
3691 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3692 * fixed function vertex processing states back in a sane state before switching to shaders
3694 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3695 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3697 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3698 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3704 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3707 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3708 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3710 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3711 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3715 context->last_was_vshader = useVertexShaderFunction;
3718 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3720 if(!useVertexShaderFunction) {
3722 for(i = 0; i < MAX_TEXTURES; i++) {
3723 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3724 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3730 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3732 IWineD3DSurfaceImpl *target;
3734 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3735 checkGLcall("glDepthRange");
3736 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3738 if(stateblock->wineD3DDevice->render_offscreen) {
3739 glViewport(stateblock->viewport.X,
3740 stateblock->viewport.Y,
3741 stateblock->viewport.Width, stateblock->viewport.Height);
3743 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3744 target->get_drawable_size(target, &width, &height);
3746 glViewport(stateblock->viewport.X,
3747 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3748 stateblock->viewport.Width, stateblock->viewport.Height);
3751 checkGLcall("glViewport");
3753 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3754 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3755 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3756 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3758 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3759 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3763 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3764 UINT Index = state - STATE_ACTIVELIGHT(0);
3765 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3768 glDisable(GL_LIGHT0 + Index);
3769 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3772 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3774 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3775 glMatrixMode(GL_MODELVIEW);
3777 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3780 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3781 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3782 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3783 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3784 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3785 checkGLcall("glLightfv");
3788 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3789 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3790 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3791 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3792 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3793 checkGLcall("glLightfv");
3796 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3797 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3798 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3799 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3800 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3801 checkGLcall("glLightfv");
3803 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3804 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3806 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3809 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3810 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3811 * Attenuation0 to NaN and crashes in the gl lib
3814 switch (lightInfo->OriginalParms.Type) {
3815 case WINED3DLIGHT_POINT:
3817 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3818 checkGLcall("glLightfv");
3819 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3820 checkGLcall("glLightf");
3821 /* Attenuation - Are these right? guessing... */
3822 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3823 checkGLcall("glLightf");
3824 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3825 checkGLcall("glLightf");
3826 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3827 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3828 checkGLcall("glLightf");
3832 case WINED3DLIGHT_SPOT:
3834 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3835 checkGLcall("glLightfv");
3837 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3838 checkGLcall("glLightfv");
3839 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3840 checkGLcall("glLightf");
3841 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3842 checkGLcall("glLightf");
3843 /* Attenuation - Are these right? guessing... */
3844 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3845 checkGLcall("glLightf");
3846 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3847 checkGLcall("glLightf");
3848 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3849 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3850 checkGLcall("glLightf");
3854 case WINED3DLIGHT_DIRECTIONAL:
3856 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3857 checkGLcall("glLightfv");
3858 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3859 checkGLcall("glLightf");
3860 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3861 checkGLcall("glLightf");
3865 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3868 /* Restore the modelview matrix */
3871 glEnable(GL_LIGHT0 + Index);
3872 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3878 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3879 RECT *pRect = &stateblock->scissorRect;
3882 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3884 target->get_drawable_size(target, &width, &height);
3885 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3886 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3888 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3889 pRect->right - pRect->left, pRect->bottom - pRect->top);
3891 if (stateblock->wineD3DDevice->render_offscreen) {
3892 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3894 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3896 checkGLcall("glScissor");
3899 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3900 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3901 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3902 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3904 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3905 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3910 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3911 if(stateblock->wineD3DDevice->render_offscreen) {
3912 glFrontFace(GL_CCW);
3913 checkGLcall("glFrontFace(GL_CCW)");
3916 checkGLcall("glFrontFace(GL_CW)");
3920 const struct StateEntry FFPStateTable[] =
3922 /* State name representative, apply function */
3923 { /* 0, Undefined */ 0, state_undefined },
3924 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3925 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3926 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3927 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3928 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3929 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3930 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3931 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3932 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3933 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3934 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3935 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3936 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3937 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3938 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3939 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3940 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3941 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3942 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3943 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3944 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3945 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3946 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3947 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3948 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3949 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3950 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3951 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3952 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3953 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3954 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3955 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3956 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3957 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3958 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3959 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3960 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3961 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3962 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3963 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3964 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3965 { /* 42, undefined */ 0, state_undefined },
3966 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3967 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3968 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3969 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3970 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3971 { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog },
3972 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3973 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3974 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3975 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3976 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3977 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3978 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3979 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3980 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3981 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3982 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3983 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3984 { /* 61, Undefined */ 0, state_undefined },
3985 { /* 62, Undefined */ 0, state_undefined },
3986 { /* 63, Undefined */ 0, state_undefined },
3987 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3988 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3989 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3990 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3991 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3992 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3993 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3994 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3995 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3996 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3997 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3998 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3999 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4000 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4001 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4002 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4003 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4004 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4005 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4006 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4007 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4008 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4009 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4010 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4011 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4012 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4013 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4014 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4015 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4016 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4017 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4018 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
4019 { /* 96, Undefined */ 0, state_undefined },
4020 { /* 97, Undefined */ 0, state_undefined },
4021 { /* 98, Undefined */ 0, state_undefined },
4022 { /* 99, Undefined */ 0, state_undefined },
4023 { /*100, Undefined */ 0, state_undefined },
4024 { /*101, Undefined */ 0, state_undefined },
4025 { /*102, Undefined */ 0, state_undefined },
4026 { /*103, Undefined */ 0, state_undefined },
4027 { /*104, Undefined */ 0, state_undefined },
4028 { /*105, Undefined */ 0, state_undefined },
4029 { /*106, Undefined */ 0, state_undefined },
4030 { /*107, Undefined */ 0, state_undefined },
4031 { /*108, Undefined */ 0, state_undefined },
4032 { /*109, Undefined */ 0, state_undefined },
4033 { /*110, Undefined */ 0, state_undefined },
4034 { /*111, Undefined */ 0, state_undefined },
4035 { /*112, Undefined */ 0, state_undefined },
4036 { /*113, Undefined */ 0, state_undefined },
4037 { /*114, Undefined */ 0, state_undefined },
4038 { /*115, Undefined */ 0, state_undefined },
4039 { /*116, Undefined */ 0, state_undefined },
4040 { /*117, Undefined */ 0, state_undefined },
4041 { /*118, Undefined */ 0, state_undefined },
4042 { /*119, Undefined */ 0, state_undefined },
4043 { /*120, Undefined */ 0, state_undefined },
4044 { /*121, Undefined */ 0, state_undefined },
4045 { /*122, Undefined */ 0, state_undefined },
4046 { /*123, Undefined */ 0, state_undefined },
4047 { /*124, Undefined */ 0, state_undefined },
4048 { /*125, Undefined */ 0, state_undefined },
4049 { /*126, Undefined */ 0, state_undefined },
4050 { /*127, Undefined */ 0, state_undefined },
4052 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4053 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4054 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4055 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4056 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4057 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4058 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4059 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4060 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
4061 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
4062 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
4063 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
4064 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
4065 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4066 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
4067 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
4068 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
4069 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4070 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4071 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4072 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
4073 { /*149, Undefined */ 0, state_undefined },
4074 { /*150, Undefined */ 0, state_undefined },
4075 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
4076 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
4077 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
4078 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4079 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
4080 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
4081 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4082 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4083 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4084 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
4085 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
4086 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
4087 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
4088 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
4089 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
4090 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
4091 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
4092 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4093 { /*169, Undefined */ 0, state_undefined },
4094 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
4095 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
4096 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
4097 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
4098 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
4099 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
4100 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
4101 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
4102 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4103 { /*177, undefined */ 0, state_undefined },
4104 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4105 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4106 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4107 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4108 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4109 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4110 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
4111 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4112 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4113 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4114 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4115 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
4116 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4117 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4118 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
4119 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
4120 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_PIXELSHADER, pixelshader },
4121 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
4122 { /*196, undefined */ 0, state_undefined },
4123 { /*197, undefined */ 0, state_undefined },
4124 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4125 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4126 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4127 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4128 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4129 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4130 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4131 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
4132 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4133 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4134 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
4135 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blendop },
4136 /* Texture stage states */
4137 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4138 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4139 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4140 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4141 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4142 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4143 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4144 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4145 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4146 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4147 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4148 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4149 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4150 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4151 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4152 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4153 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4154 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4155 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4156 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4157 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4158 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4159 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4160 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4161 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4162 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
4163 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
4164 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
4165 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4166 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4167 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4168 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4170 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4171 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4172 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4173 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4174 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4175 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4176 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4177 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4178 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4179 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4180 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4181 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4182 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4183 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4184 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4185 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4186 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4187 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4188 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4189 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4190 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4191 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4192 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4193 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4194 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4195 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
4196 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
4197 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
4198 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4199 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4200 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4201 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4203 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4204 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4205 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4206 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4207 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4208 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4209 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4210 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4211 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4212 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4213 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4214 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4215 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4216 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4217 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4218 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4219 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4220 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4221 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4222 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4223 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4224 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4225 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4226 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4227 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4228 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
4229 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
4230 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
4231 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4232 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4233 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4234 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4236 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4237 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4238 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4239 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4240 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4241 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4242 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4243 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4244 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4245 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4246 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4247 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4248 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4249 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4250 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4251 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4252 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4253 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4254 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4255 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4256 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4257 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4258 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4259 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4260 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4261 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
4262 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
4263 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
4264 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4265 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4266 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4267 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4269 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4270 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4271 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4272 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4273 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4274 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4275 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4276 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4277 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4278 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4279 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4280 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4281 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4282 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4283 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4284 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4285 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4286 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4287 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4288 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4289 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4290 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4291 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4292 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4293 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4294 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
4295 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
4296 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
4297 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4298 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4299 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4300 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4302 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4303 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4304 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4305 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4306 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4307 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4308 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4309 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4310 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4311 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4312 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4313 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4314 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4315 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4316 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4317 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4318 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4319 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4320 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4321 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4322 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4323 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4324 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4325 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4326 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4327 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4328 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4329 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
4330 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4331 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4332 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4333 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4335 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4336 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4337 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4338 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4339 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4340 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4341 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4342 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4343 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4344 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4345 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4346 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4347 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4348 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4349 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4350 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4351 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4352 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4353 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4354 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4355 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4356 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4357 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4358 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4359 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4360 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4361 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4362 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
4363 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4364 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4365 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4366 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4368 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4369 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4370 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4371 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4372 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4373 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4374 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4375 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4376 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4377 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4378 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4379 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4380 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4381 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4382 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4383 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4384 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4385 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4386 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4387 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4388 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4389 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4390 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4391 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4392 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4393 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4394 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4395 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
4396 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4397 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4398 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4399 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4400 /* Sampler states */
4401 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
4402 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
4403 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
4404 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
4405 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
4406 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
4407 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
4408 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
4409 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
4410 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
4411 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
4412 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
4413 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
4414 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
4415 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
4416 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
4417 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
4418 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
4419 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
4420 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
4422 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
4423 /* Transform states follow */
4424 { /* 1, undefined */ 0, state_undefined },
4425 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
4426 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
4427 { /* 4, undefined */ 0, state_undefined },
4428 { /* 5, undefined */ 0, state_undefined },
4429 { /* 6, undefined */ 0, state_undefined },
4430 { /* 7, undefined */ 0, state_undefined },
4431 { /* 8, undefined */ 0, state_undefined },
4432 { /* 9, undefined */ 0, state_undefined },
4433 { /* 10, undefined */ 0, state_undefined },
4434 { /* 11, undefined */ 0, state_undefined },
4435 { /* 12, undefined */ 0, state_undefined },
4436 { /* 13, undefined */ 0, state_undefined },
4437 { /* 14, undefined */ 0, state_undefined },
4438 { /* 15, undefined */ 0, state_undefined },
4439 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4440 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4441 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4442 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4443 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4444 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4445 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4446 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4447 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
4448 { /* 24, undefined */ 0, state_undefined },
4449 { /* 25, undefined */ 0, state_undefined },
4450 { /* 26, undefined */ 0, state_undefined },
4451 { /* 27, undefined */ 0, state_undefined },
4452 { /* 28, undefined */ 0, state_undefined },
4453 { /* 29, undefined */ 0, state_undefined },
4454 { /* 30, undefined */ 0, state_undefined },
4455 { /* 31, undefined */ 0, state_undefined },
4456 { /* 32, undefined */ 0, state_undefined },
4457 { /* 33, undefined */ 0, state_undefined },
4458 { /* 34, undefined */ 0, state_undefined },
4459 { /* 35, undefined */ 0, state_undefined },
4460 { /* 36, undefined */ 0, state_undefined },
4461 { /* 37, undefined */ 0, state_undefined },
4462 { /* 38, undefined */ 0, state_undefined },
4463 { /* 39, undefined */ 0, state_undefined },
4464 { /* 40, undefined */ 0, state_undefined },
4465 { /* 41, undefined */ 0, state_undefined },
4466 { /* 42, undefined */ 0, state_undefined },
4467 { /* 43, undefined */ 0, state_undefined },
4468 { /* 44, undefined */ 0, state_undefined },
4469 { /* 45, undefined */ 0, state_undefined },
4470 { /* 46, undefined */ 0, state_undefined },
4471 { /* 47, undefined */ 0, state_undefined },
4472 { /* 48, undefined */ 0, state_undefined },
4473 { /* 49, undefined */ 0, state_undefined },
4474 { /* 50, undefined */ 0, state_undefined },
4475 { /* 51, undefined */ 0, state_undefined },
4476 { /* 52, undefined */ 0, state_undefined },
4477 { /* 53, undefined */ 0, state_undefined },
4478 { /* 54, undefined */ 0, state_undefined },
4479 { /* 55, undefined */ 0, state_undefined },
4480 { /* 56, undefined */ 0, state_undefined },
4481 { /* 57, undefined */ 0, state_undefined },
4482 { /* 58, undefined */ 0, state_undefined },
4483 { /* 59, undefined */ 0, state_undefined },
4484 { /* 60, undefined */ 0, state_undefined },
4485 { /* 61, undefined */ 0, state_undefined },
4486 { /* 62, undefined */ 0, state_undefined },
4487 { /* 63, undefined */ 0, state_undefined },
4488 { /* 64, undefined */ 0, state_undefined },
4489 { /* 65, undefined */ 0, state_undefined },
4490 { /* 66, undefined */ 0, state_undefined },
4491 { /* 67, undefined */ 0, state_undefined },
4492 { /* 68, undefined */ 0, state_undefined },
4493 { /* 69, undefined */ 0, state_undefined },
4494 { /* 70, undefined */ 0, state_undefined },
4495 { /* 71, undefined */ 0, state_undefined },
4496 { /* 72, undefined */ 0, state_undefined },
4497 { /* 73, undefined */ 0, state_undefined },
4498 { /* 74, undefined */ 0, state_undefined },
4499 { /* 75, undefined */ 0, state_undefined },
4500 { /* 76, undefined */ 0, state_undefined },
4501 { /* 77, undefined */ 0, state_undefined },
4502 { /* 78, undefined */ 0, state_undefined },
4503 { /* 79, undefined */ 0, state_undefined },
4504 { /* 80, undefined */ 0, state_undefined },
4505 { /* 81, undefined */ 0, state_undefined },
4506 { /* 82, undefined */ 0, state_undefined },
4507 { /* 83, undefined */ 0, state_undefined },
4508 { /* 84, undefined */ 0, state_undefined },
4509 { /* 85, undefined */ 0, state_undefined },
4510 { /* 86, undefined */ 0, state_undefined },
4511 { /* 87, undefined */ 0, state_undefined },
4512 { /* 88, undefined */ 0, state_undefined },
4513 { /* 89, undefined */ 0, state_undefined },
4514 { /* 90, undefined */ 0, state_undefined },
4515 { /* 91, undefined */ 0, state_undefined },
4516 { /* 92, undefined */ 0, state_undefined },
4517 { /* 93, undefined */ 0, state_undefined },
4518 { /* 94, undefined */ 0, state_undefined },
4519 { /* 95, undefined */ 0, state_undefined },
4520 { /* 96, undefined */ 0, state_undefined },
4521 { /* 97, undefined */ 0, state_undefined },
4522 { /* 98, undefined */ 0, state_undefined },
4523 { /* 99, undefined */ 0, state_undefined },
4524 { /*100, undefined */ 0, state_undefined },
4525 { /*101, undefined */ 0, state_undefined },
4526 { /*102, undefined */ 0, state_undefined },
4527 { /*103, undefined */ 0, state_undefined },
4528 { /*104, undefined */ 0, state_undefined },
4529 { /*105, undefined */ 0, state_undefined },
4530 { /*106, undefined */ 0, state_undefined },
4531 { /*107, undefined */ 0, state_undefined },
4532 { /*108, undefined */ 0, state_undefined },
4533 { /*109, undefined */ 0, state_undefined },
4534 { /*110, undefined */ 0, state_undefined },
4535 { /*111, undefined */ 0, state_undefined },
4536 { /*112, undefined */ 0, state_undefined },
4537 { /*113, undefined */ 0, state_undefined },
4538 { /*114, undefined */ 0, state_undefined },
4539 { /*115, undefined */ 0, state_undefined },
4540 { /*116, undefined */ 0, state_undefined },
4541 { /*117, undefined */ 0, state_undefined },
4542 { /*118, undefined */ 0, state_undefined },
4543 { /*119, undefined */ 0, state_undefined },
4544 { /*120, undefined */ 0, state_undefined },
4545 { /*121, undefined */ 0, state_undefined },
4546 { /*122, undefined */ 0, state_undefined },
4547 { /*123, undefined */ 0, state_undefined },
4548 { /*124, undefined */ 0, state_undefined },
4549 { /*125, undefined */ 0, state_undefined },
4550 { /*126, undefined */ 0, state_undefined },
4551 { /*127, undefined */ 0, state_undefined },
4552 { /*128, undefined */ 0, state_undefined },
4553 { /*129, undefined */ 0, state_undefined },
4554 { /*130, undefined */ 0, state_undefined },
4555 { /*131, undefined */ 0, state_undefined },
4556 { /*132, undefined */ 0, state_undefined },
4557 { /*133, undefined */ 0, state_undefined },
4558 { /*134, undefined */ 0, state_undefined },
4559 { /*135, undefined */ 0, state_undefined },
4560 { /*136, undefined */ 0, state_undefined },
4561 { /*137, undefined */ 0, state_undefined },
4562 { /*138, undefined */ 0, state_undefined },
4563 { /*139, undefined */ 0, state_undefined },
4564 { /*140, undefined */ 0, state_undefined },
4565 { /*141, undefined */ 0, state_undefined },
4566 { /*142, undefined */ 0, state_undefined },
4567 { /*143, undefined */ 0, state_undefined },
4568 { /*144, undefined */ 0, state_undefined },
4569 { /*145, undefined */ 0, state_undefined },
4570 { /*146, undefined */ 0, state_undefined },
4571 { /*147, undefined */ 0, state_undefined },
4572 { /*148, undefined */ 0, state_undefined },
4573 { /*149, undefined */ 0, state_undefined },
4574 { /*150, undefined */ 0, state_undefined },
4575 { /*151, undefined */ 0, state_undefined },
4576 { /*152, undefined */ 0, state_undefined },
4577 { /*153, undefined */ 0, state_undefined },
4578 { /*154, undefined */ 0, state_undefined },
4579 { /*155, undefined */ 0, state_undefined },
4580 { /*156, undefined */ 0, state_undefined },
4581 { /*157, undefined */ 0, state_undefined },
4582 { /*158, undefined */ 0, state_undefined },
4583 { /*159, undefined */ 0, state_undefined },
4584 { /*160, undefined */ 0, state_undefined },
4585 { /*161, undefined */ 0, state_undefined },
4586 { /*162, undefined */ 0, state_undefined },
4587 { /*163, undefined */ 0, state_undefined },
4588 { /*164, undefined */ 0, state_undefined },
4589 { /*165, undefined */ 0, state_undefined },
4590 { /*166, undefined */ 0, state_undefined },
4591 { /*167, undefined */ 0, state_undefined },
4592 { /*168, undefined */ 0, state_undefined },
4593 { /*169, undefined */ 0, state_undefined },
4594 { /*170, undefined */ 0, state_undefined },
4595 { /*171, undefined */ 0, state_undefined },
4596 { /*172, undefined */ 0, state_undefined },
4597 { /*173, undefined */ 0, state_undefined },
4598 { /*174, undefined */ 0, state_undefined },
4599 { /*175, undefined */ 0, state_undefined },
4600 { /*176, undefined */ 0, state_undefined },
4601 { /*177, undefined */ 0, state_undefined },
4602 { /*178, undefined */ 0, state_undefined },
4603 { /*179, undefined */ 0, state_undefined },
4604 { /*180, undefined */ 0, state_undefined },
4605 { /*181, undefined */ 0, state_undefined },
4606 { /*182, undefined */ 0, state_undefined },
4607 { /*183, undefined */ 0, state_undefined },
4608 { /*184, undefined */ 0, state_undefined },
4609 { /*185, undefined */ 0, state_undefined },
4610 { /*186, undefined */ 0, state_undefined },
4611 { /*187, undefined */ 0, state_undefined },
4612 { /*188, undefined */ 0, state_undefined },
4613 { /*189, undefined */ 0, state_undefined },
4614 { /*190, undefined */ 0, state_undefined },
4615 { /*191, undefined */ 0, state_undefined },
4616 { /*192, undefined */ 0, state_undefined },
4617 { /*193, undefined */ 0, state_undefined },
4618 { /*194, undefined */ 0, state_undefined },
4619 { /*195, undefined */ 0, state_undefined },
4620 { /*196, undefined */ 0, state_undefined },
4621 { /*197, undefined */ 0, state_undefined },
4622 { /*198, undefined */ 0, state_undefined },
4623 { /*199, undefined */ 0, state_undefined },
4624 { /*200, undefined */ 0, state_undefined },
4625 { /*201, undefined */ 0, state_undefined },
4626 { /*202, undefined */ 0, state_undefined },
4627 { /*203, undefined */ 0, state_undefined },
4628 { /*204, undefined */ 0, state_undefined },
4629 { /*205, undefined */ 0, state_undefined },
4630 { /*206, undefined */ 0, state_undefined },
4631 { /*207, undefined */ 0, state_undefined },
4632 { /*208, undefined */ 0, state_undefined },
4633 { /*209, undefined */ 0, state_undefined },
4634 { /*210, undefined */ 0, state_undefined },
4635 { /*211, undefined */ 0, state_undefined },
4636 { /*212, undefined */ 0, state_undefined },
4637 { /*213, undefined */ 0, state_undefined },
4638 { /*214, undefined */ 0, state_undefined },
4639 { /*215, undefined */ 0, state_undefined },
4640 { /*216, undefined */ 0, state_undefined },
4641 { /*217, undefined */ 0, state_undefined },
4642 { /*218, undefined */ 0, state_undefined },
4643 { /*219, undefined */ 0, state_undefined },
4644 { /*220, undefined */ 0, state_undefined },
4645 { /*221, undefined */ 0, state_undefined },
4646 { /*222, undefined */ 0, state_undefined },
4647 { /*223, undefined */ 0, state_undefined },
4648 { /*224, undefined */ 0, state_undefined },
4649 { /*225, undefined */ 0, state_undefined },
4650 { /*226, undefined */ 0, state_undefined },
4651 { /*227, undefined */ 0, state_undefined },
4652 { /*228, undefined */ 0, state_undefined },
4653 { /*229, undefined */ 0, state_undefined },
4654 { /*230, undefined */ 0, state_undefined },
4655 { /*231, undefined */ 0, state_undefined },
4656 { /*232, undefined */ 0, state_undefined },
4657 { /*233, undefined */ 0, state_undefined },
4658 { /*234, undefined */ 0, state_undefined },
4659 { /*235, undefined */ 0, state_undefined },
4660 { /*236, undefined */ 0, state_undefined },
4661 { /*237, undefined */ 0, state_undefined },
4662 { /*238, undefined */ 0, state_undefined },
4663 { /*239, undefined */ 0, state_undefined },
4664 { /*240, undefined */ 0, state_undefined },
4665 { /*241, undefined */ 0, state_undefined },
4666 { /*242, undefined */ 0, state_undefined },
4667 { /*243, undefined */ 0, state_undefined },
4668 { /*244, undefined */ 0, state_undefined },
4669 { /*245, undefined */ 0, state_undefined },
4670 { /*246, undefined */ 0, state_undefined },
4671 { /*247, undefined */ 0, state_undefined },
4672 { /*248, undefined */ 0, state_undefined },
4673 { /*249, undefined */ 0, state_undefined },
4674 { /*250, undefined */ 0, state_undefined },
4675 { /*251, undefined */ 0, state_undefined },
4676 { /*252, undefined */ 0, state_undefined },
4677 { /*253, undefined */ 0, state_undefined },
4678 { /*254, undefined */ 0, state_undefined },
4679 { /*255, undefined */ 0, state_undefined },
4681 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4682 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4683 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4684 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4685 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4686 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4687 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4688 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4689 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4690 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4691 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4692 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4693 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4694 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4695 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4696 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4697 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4698 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4699 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4700 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4701 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4702 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4703 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4704 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4705 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4706 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4707 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4708 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4709 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4710 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4711 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4712 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4713 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4714 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4715 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4716 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4717 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4718 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4719 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4720 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4721 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4722 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4723 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4724 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4725 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4726 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4727 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4728 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4729 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4730 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4731 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4732 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4733 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4734 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4735 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4736 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4737 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4738 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4739 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4740 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4741 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4742 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4743 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4744 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4745 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4746 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4747 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4748 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4749 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4750 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4751 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4752 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4753 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4754 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4755 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4756 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4757 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4758 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4759 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4760 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4761 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4762 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4763 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4764 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4765 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4766 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4767 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4768 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4769 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4770 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4771 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4772 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4773 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4774 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4775 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4776 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4777 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4778 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4779 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4780 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4781 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4782 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4783 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4784 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4785 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4786 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4787 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4788 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4789 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4790 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4791 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4792 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4793 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4794 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4795 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4796 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4797 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4798 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4799 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4800 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4801 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4802 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4803 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4804 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4805 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4806 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4807 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4808 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4809 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4810 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4811 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4812 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4813 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4814 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4815 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4816 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4817 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4818 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4819 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4820 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4821 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4822 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4823 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4824 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4825 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4826 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4827 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4828 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4829 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4830 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4831 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4832 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4833 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4834 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4835 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4836 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4837 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4838 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4839 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4840 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4841 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4842 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4843 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4844 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4845 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4846 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4847 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4848 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4849 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4850 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4851 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4852 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4853 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4854 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4855 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4856 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4857 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4858 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4859 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4860 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4861 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4862 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4863 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4864 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4865 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4866 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4867 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4868 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4869 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4870 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4871 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4872 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4873 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4874 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4875 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4876 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4877 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4878 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4879 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4880 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4881 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4882 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4883 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4884 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4885 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4886 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4887 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4888 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4889 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4890 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4891 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4892 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4893 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4894 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4895 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4896 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4897 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4898 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4899 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4900 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4901 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4902 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4903 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4904 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4905 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4906 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4907 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4908 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4909 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4910 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4911 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4912 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4913 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4914 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4915 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4916 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4917 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4918 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4919 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4920 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4921 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4922 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4923 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4924 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4925 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4926 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4927 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4928 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4929 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4930 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4931 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4932 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4933 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4934 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4935 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4936 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4937 /* Various Vertex states follow */
4938 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4939 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4940 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4941 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4942 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4943 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4944 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4946 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4947 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4948 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4949 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4950 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4951 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4952 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4953 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4955 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4957 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4958 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4959 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4960 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4961 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4962 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4963 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4964 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4965 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4966 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4967 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4968 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4969 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4970 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4971 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4972 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4973 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4974 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4975 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4976 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4977 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4978 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4979 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4980 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4981 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4982 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4983 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4984 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4985 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4986 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4987 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4988 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4990 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
4991 { /* STATE_FRONTFACE */ STATE_FRONTFACE, frontface },