d3d9: Test viewports that are bigger than the surface.
[wine/multimedia.git] / dlls / wined3d / state.c
blob637bec666c8e6cbf23988cd692679c1a4e704e66
1 /*
2 * Direct3D state management
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11 * Copyright 2009 Henri Verbeet for CodeWeavers
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "config.h"
29 #include <stdio.h>
30 #ifdef HAVE_FLOAT_H
31 # include <float.h>
32 #endif
33 #include "wined3d_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
36 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
38 #define GLINFO_LOCATION (*context->gl_info)
40 /* GL locking for state handlers is done by the caller. */
42 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context);
44 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
46 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
47 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
49 if(STATE_IS_RENDER(state)) {
50 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
51 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
52 } else {
53 /* Shouldn't have an unknown type here */
54 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
58 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
60 ERR("Undefined state.\n");
63 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
65 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
67 switch(Value) {
68 case WINED3DFILL_POINT:
69 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
70 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
71 break;
72 case WINED3DFILL_WIREFRAME:
73 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
74 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
75 break;
76 case WINED3DFILL_SOLID:
77 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
78 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 break;
80 default:
81 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
85 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
87 /* Lighting is not enabled if transformed vertices are drawn
88 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
89 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
90 * vertex declaration applying function calls this function for updating
93 if(isStateDirty(context, STATE_VDECL)) {
94 return;
97 if (stateblock->renderState[WINED3DRS_LIGHTING]
98 && !stateblock->wineD3DDevice->strided_streams.position_transformed)
100 glEnable(GL_LIGHTING);
101 checkGLcall("glEnable GL_LIGHTING");
102 } else {
103 glDisable(GL_LIGHTING);
104 checkGLcall("glDisable GL_LIGHTING");
108 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *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");
115 return;
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
122 break;
123 case WINED3DZB_TRUE:
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
126 break;
127 case WINED3DZB_USEW:
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
131 break;
132 default:
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
139 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
140 * switch
142 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
143 case WINED3DCULL_NONE:
144 glDisable(GL_CULL_FACE);
145 checkGLcall("glDisable GL_CULL_FACE");
146 break;
147 case WINED3DCULL_CW:
148 glEnable(GL_CULL_FACE);
149 checkGLcall("glEnable GL_CULL_FACE");
150 glCullFace(GL_FRONT);
151 checkGLcall("glCullFace(GL_FRONT)");
152 break;
153 case WINED3DCULL_CCW:
154 glEnable(GL_CULL_FACE);
155 checkGLcall("glEnable GL_CULL_FACE");
156 glCullFace(GL_BACK);
157 checkGLcall("glCullFace(GL_BACK)");
158 break;
159 default:
160 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
164 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
166 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
167 case WINED3DSHADE_FLAT:
168 glShadeModel(GL_FLAT);
169 checkGLcall("glShadeModel(GL_FLAT)");
170 break;
171 case WINED3DSHADE_GOURAUD:
172 glShadeModel(GL_SMOOTH);
173 checkGLcall("glShadeModel(GL_SMOOTH)");
174 break;
175 case WINED3DSHADE_PHONG:
176 FIXME("WINED3DSHADE_PHONG isn't supported\n");
177 break;
178 default:
179 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
183 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
185 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
186 glEnable(GL_DITHER);
187 checkGLcall("glEnable GL_DITHER");
188 } else {
189 glDisable(GL_DITHER);
190 checkGLcall("glDisable GL_DITHER");
194 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
196 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
197 * this has to be merged with ZENABLE and ZFUNC
199 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
200 glDepthMask(1);
201 checkGLcall("glDepthMask(1)");
202 } else {
203 glDepthMask(0);
204 checkGLcall("glDepthMask(0)");
208 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
210 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
212 if(glParm) {
213 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
214 static BOOL once = FALSE;
215 /* There are a few issues with this: First, our inability to
216 * select a proper Z depth, most of the time we're stuck with
217 * D24S8, even if the app selects D32 or D16. There seem to be
218 * some other precision problems which have to be debugged to
219 * make NOTEQUAL and EQUAL work properly
221 if(!once) {
222 once = TRUE;
223 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
227 glDepthFunc(glParm);
228 checkGLcall("glDepthFunc");
232 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
234 float col[4];
235 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
237 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
238 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
239 checkGLcall("glLightModel for MODEL_AMBIENT");
242 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
244 int srcBlend = GL_ZERO;
245 int dstBlend = GL_ZERO;
246 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
248 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
249 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
250 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
251 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
253 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
254 * The d3d9 visual test confirms the behavior. */
255 if (!(target->resource.format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
257 glDisable(GL_BLEND);
258 checkGLcall("glDisable GL_BLEND");
259 return;
260 } else {
261 glEnable(GL_BLEND);
262 checkGLcall("glEnable GL_BLEND");
264 } else {
265 glDisable(GL_BLEND);
266 checkGLcall("glDisable GL_BLEND");
267 /* Nothing more to do - get out */
268 return;
271 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
272 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
273 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
274 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
275 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
276 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
277 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
278 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
279 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
281 /* To compensate the lack of format switching with backbuffer offscreen rendering,
282 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
283 * if the render target doesn't support alpha blending. A nonexistent alpha channel
284 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
286 case WINED3DBLEND_DESTALPHA :
287 dstBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
288 break;
289 case WINED3DBLEND_INVDESTALPHA :
290 dstBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
291 break;
293 case WINED3DBLEND_SRCALPHASAT :
294 dstBlend = GL_SRC_ALPHA_SATURATE;
295 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
296 break;
298 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
299 * values which are still valid up to d3d9. They should not occur as dest blend values
301 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
302 srcBlend = GL_SRC_ALPHA;
303 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
304 break;
306 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
307 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
308 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
309 break;
311 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
312 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
313 default:
314 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
317 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
318 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
319 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
320 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
321 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
322 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
323 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
324 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
325 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
326 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
328 case WINED3DBLEND_DESTALPHA :
329 srcBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
330 break;
331 case WINED3DBLEND_INVDESTALPHA :
332 srcBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
333 break;
335 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
336 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
337 break;
339 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
340 dstBlend = GL_SRC_ALPHA;
341 break;
343 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
344 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
345 default:
346 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
349 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
350 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
351 glEnable(GL_LINE_SMOOTH);
352 checkGLcall("glEnable(GL_LINE_SMOOTH)");
353 if(srcBlend != GL_SRC_ALPHA) {
354 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
356 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
357 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
359 } else {
360 glDisable(GL_LINE_SMOOTH);
361 checkGLcall("glDisable(GL_LINE_SMOOTH)");
364 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
365 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
366 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
369 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
370 int srcBlendAlpha = GL_ZERO;
371 int dstBlendAlpha = GL_ZERO;
373 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
374 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
375 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
376 return;
379 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
380 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
381 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
382 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
383 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
384 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
385 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
386 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
387 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
388 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
389 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
390 case WINED3DBLEND_SRCALPHASAT :
391 dstBlend = GL_SRC_ALPHA_SATURATE;
392 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
393 break;
394 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
395 * values which are still valid up to d3d9. They should not occur as dest blend values
397 case WINED3DBLEND_BOTHSRCALPHA :
398 dstBlendAlpha = GL_SRC_ALPHA;
399 srcBlendAlpha = GL_SRC_ALPHA;
400 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
401 break;
402 case WINED3DBLEND_BOTHINVSRCALPHA :
403 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
404 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
405 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
406 break;
407 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
408 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
409 default:
410 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
413 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
414 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
415 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
416 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
417 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
418 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
419 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
420 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
421 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
422 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
423 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
424 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
425 case WINED3DBLEND_BOTHSRCALPHA :
426 srcBlendAlpha = GL_SRC_ALPHA;
427 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
428 break;
429 case WINED3DBLEND_BOTHINVSRCALPHA :
430 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
431 dstBlendAlpha = GL_SRC_ALPHA;
432 break;
433 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
434 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
435 default:
436 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
439 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
440 checkGLcall("glBlendFuncSeparateEXT");
441 } else {
442 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
443 glBlendFunc(srcBlend, dstBlend);
444 checkGLcall("glBlendFunc");
447 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
448 so it may need updating */
449 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
450 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
451 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
455 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
457 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
460 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
462 float col[4];
464 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
465 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
466 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
467 checkGLcall("glBlendColor");
470 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
472 int glParm = 0;
473 float ref;
474 BOOL enable_ckey = FALSE;
476 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
478 /* Find out if the texture on the first stage has a ckey set
479 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
480 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
481 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
482 * in case it finds some texture+colorkeyenable combination which needs extra care.
484 if (stateblock->textures[0])
486 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
488 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
490 IWineD3DSurfaceImpl *surf;
492 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
494 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
496 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
497 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
498 * surface has alpha bits */
499 if (!surf->resource.format_desc->alpha_mask) enable_ckey = TRUE;
504 if(enable_ckey || context->last_was_ckey) {
505 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
506 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
508 context->last_was_ckey = enable_ckey;
510 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
511 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
512 glEnable(GL_ALPHA_TEST);
513 checkGLcall("glEnable GL_ALPHA_TEST");
514 } else {
515 glDisable(GL_ALPHA_TEST);
516 checkGLcall("glDisable GL_ALPHA_TEST");
517 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
518 * enable call
520 return;
523 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
524 glParm = GL_NOTEQUAL;
525 ref = 0.0f;
526 } else {
527 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
528 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
530 if(glParm) {
531 glAlphaFunc(glParm, ref);
532 checkGLcall("glAlphaFunc");
536 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
538 DWORD enable = 0xFFFFFFFF;
539 DWORD disable = 0x00000000;
541 if (!stateblock->wineD3DDevice->vs_clipping && use_vs(stateblock))
543 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
544 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
545 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
546 * of that - don't do anything here and keep them disabled
548 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
549 static BOOL warned = FALSE;
550 if(!warned) {
551 FIXME("Clipping not supported with vertex shaders\n");
552 warned = TRUE;
555 return;
558 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
559 * of already set values
562 /* If enabling / disabling all
563 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
565 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
566 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
567 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
568 if (GL_SUPPORT(ARB_DEPTH_CLAMP))
570 glDisable(GL_DEPTH_CLAMP);
571 checkGLcall("glDisable(GL_DEPTH_CLAMP)");
573 } else {
574 disable = 0xffffffff;
575 enable = 0x00;
576 if (GL_SUPPORT(ARB_DEPTH_CLAMP))
578 glEnable(GL_DEPTH_CLAMP);
579 checkGLcall("glEnable(GL_DEPTH_CLAMP)");
583 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
584 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
585 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
586 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
587 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
588 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
590 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
591 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
592 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
593 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
594 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
595 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
597 /** update clipping status */
598 if (enable) {
599 stateblock->clip_status.ClipUnion = 0;
600 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
601 } else {
602 stateblock->clip_status.ClipUnion = 0;
603 stateblock->clip_status.ClipIntersection = 0;
607 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
609 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
612 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
614 int blendEquation = GL_FUNC_ADD;
615 int blendEquationAlpha = GL_FUNC_ADD;
617 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
618 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
619 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
620 return;
623 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
624 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
625 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
626 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
627 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
628 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
629 default:
630 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
633 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
634 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
635 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
636 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
637 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
638 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
639 default:
640 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
643 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
644 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
645 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
646 checkGLcall("glBlendEquationSeparateEXT");
647 } else {
648 TRACE("glBlendEquation(%x)\n", blendEquation);
649 GL_EXTCALL(glBlendEquationEXT(blendEquation));
650 checkGLcall("glBlendEquation");
654 static void state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
656 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
657 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
658 * specular color. This is wrong:
659 * Separate specular color means the specular colour is maintained separately, whereas
660 * single color means it is merged in. However in both cases they are being used to
661 * some extent.
662 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
663 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
664 * running 1.4 yet!
667 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
668 * Instead, we need to setup the FinalCombiner properly.
670 * The default setup for the FinalCombiner is:
672 * <variable> <input> <mapping> <usage>
673 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
674 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
675 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
676 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
677 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
678 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
679 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
681 * That's pretty much fine as it is, except for variable B, which needs to take
682 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
683 * whether WINED3DRS_SPECULARENABLE is enabled or not.
686 TRACE("Setting specular enable state and materials\n");
687 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
688 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
689 checkGLcall("glMaterialfv");
691 if(stateblock->material.Power > GL_LIMITS(shininess)) {
692 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
693 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
694 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
695 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
696 * them, it should be safe to do so without major visual distortions.
698 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
699 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
700 } else {
701 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
703 checkGLcall("glMaterialf(GL_SHININESS)");
705 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
706 glEnable(GL_COLOR_SUM_EXT);
707 } else {
708 TRACE("Specular colors cannot be enabled in this version of opengl\n");
710 checkGLcall("glEnable(GL_COLOR_SUM)");
712 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
713 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
714 checkGLcall("glFinalCombinerInputNV()");
716 } else {
717 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
719 /* for the case of enabled lighting: */
720 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
721 checkGLcall("glMaterialfv");
723 /* for the case of disabled lighting: */
724 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
725 glDisable(GL_COLOR_SUM_EXT);
726 } else {
727 TRACE("Specular colors cannot be disabled in this version of opengl\n");
729 checkGLcall("glDisable(GL_COLOR_SUM)");
731 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
732 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
733 checkGLcall("glFinalCombinerInputNV()");
737 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
738 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
739 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
740 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
741 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
742 stateblock->material.Specular.b, stateblock->material.Specular.a);
743 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
744 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
746 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
747 checkGLcall("glMaterialfv(GL_AMBIENT)");
748 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
749 checkGLcall("glMaterialfv(GL_DIFFUSE)");
750 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
751 checkGLcall("glMaterialfv(GL_EMISSION)");
754 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
756 unsigned int i;
758 /* Note the texture color applies to all textures whereas
759 * GL_TEXTURE_ENV_COLOR applies to active only
761 float col[4];
762 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
764 /* And now the default texture color as well */
765 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
766 /* Note the WINED3DRS value applies to all textures, but GL has one
767 * per texture, so apply it now ready to be used!
769 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
770 checkGLcall("glActiveTextureARB");
772 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
773 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
777 static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face,
778 GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
780 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
781 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
782 GL_EXTCALL(glActiveStencilFaceEXT(face));
783 checkGLcall("glActiveStencilFaceEXT(...)");
784 glStencilFunc(func, ref, mask);
785 checkGLcall("glStencilFunc(...)");
786 glStencilOp(stencilFail, depthFail, stencilPass);
787 checkGLcall("glStencilOp(...)");
790 static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
792 DWORD onesided_enable = FALSE;
793 DWORD twosided_enable = FALSE;
794 GLint func = GL_ALWAYS;
795 GLint func_ccw = GL_ALWAYS;
796 GLint ref = 0;
797 GLuint mask = 0;
798 GLint stencilFail = GL_KEEP;
799 GLint depthFail = GL_KEEP;
800 GLint stencilPass = GL_KEEP;
801 GLint stencilFail_ccw = GL_KEEP;
802 GLint depthFail_ccw = GL_KEEP;
803 GLint stencilPass_ccw = GL_KEEP;
805 /* No stencil test without a stencil buffer */
806 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
807 glDisable(GL_STENCIL_TEST);
808 checkGLcall("glDisable GL_STENCIL_TEST");
809 return;
812 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
813 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
814 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
815 func = GL_ALWAYS;
816 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
817 func_ccw = GL_ALWAYS;
818 ref = stateblock->renderState[WINED3DRS_STENCILREF];
819 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
820 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
821 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
822 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
823 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
824 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
825 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
827 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
828 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
829 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
830 onesided_enable, twosided_enable, ref, mask,
831 func, stencilFail, depthFail, stencilPass,
832 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
834 if (twosided_enable && onesided_enable) {
835 glEnable(GL_STENCIL_TEST);
836 checkGLcall("glEnable GL_STENCIL_TEST");
838 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
839 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
840 * which has an effect on the code below too. If we apply the front face
841 * afterwards, we are sure that the active stencil face is set to front,
842 * and other stencil functions which do not use two sided stencil do not have
843 * to set it back
845 renderstate_stencil_twosided(context, GL_BACK,
846 func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
847 renderstate_stencil_twosided(context, GL_FRONT,
848 func, ref, mask, stencilFail, depthFail, stencilPass);
849 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
850 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
851 checkGLcall("glStencilFuncSeparateATI(...)");
852 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
853 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
854 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
855 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
856 } else {
857 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
859 } else if(onesided_enable) {
860 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
861 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
862 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
865 /* This code disables the ATI extension as well, since the standard stencil functions are equal
866 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
868 glEnable(GL_STENCIL_TEST);
869 checkGLcall("glEnable GL_STENCIL_TEST");
870 glStencilFunc(func, ref, mask);
871 checkGLcall("glStencilFunc(...)");
872 glStencilOp(stencilFail, depthFail, stencilPass);
873 checkGLcall("glStencilOp(...)");
874 } else {
875 glDisable(GL_STENCIL_TEST);
876 checkGLcall("glDisable GL_STENCIL_TEST");
880 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
882 DWORD mask;
884 if(stateblock->wineD3DDevice->stencilBufferTarget) {
885 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
886 } else {
887 mask = 0;
890 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
891 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
892 glStencilMask(mask);
893 checkGLcall("glStencilMask");
894 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
895 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
896 glStencilMask(mask);
899 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
901 DWORD mask;
903 if(stateblock->wineD3DDevice->stencilBufferTarget) {
904 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
905 } else {
906 mask = 0;
909 glStencilMask(mask);
910 checkGLcall("glStencilMask");
913 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
916 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
918 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
920 /* Table fog on: Never use fog coords, and use per-fragment fog */
921 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
922 glHint(GL_FOG_HINT, GL_NICEST);
923 if(context->fog_coord) {
924 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
925 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
926 context->fog_coord = FALSE;
928 return;
931 /* Otherwise use per-vertex fog in any case */
932 glHint(GL_FOG_HINT, GL_FASTEST);
934 if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
935 /* No fog at all, or transformed vertices: Use fog coord */
936 if(!context->fog_coord) {
937 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
938 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
939 context->fog_coord = TRUE;
941 } else {
942 /* Otherwise, use the fragment depth */
943 if(context->fog_coord) {
944 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
945 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
946 context->fog_coord = FALSE;
951 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
953 float fogstart, fogend;
954 union {
955 DWORD d;
956 float f;
957 } tmpvalue;
959 switch(context->fog_source) {
960 case FOGSOURCE_VS:
961 fogstart = 1.0f;
962 fogend = 0.0f;
963 break;
965 case FOGSOURCE_COORD:
966 fogstart = 255.0f;
967 fogend = 0.0f;
968 break;
970 case FOGSOURCE_FFP:
971 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
972 fogstart = tmpvalue.f;
973 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
974 fogend = tmpvalue.f;
975 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
976 if(fogstart == fogend) {
977 fogstart = -1.0f / 0.0f;
978 fogend = 0.0f;
980 break;
982 default:
983 /* This should not happen.context->fog_source is set in wined3d, not the app.
984 * Still this is needed to make the compiler happy
986 ERR("Unexpected fog coordinate source\n");
987 fogstart = 0.0f;
988 fogend = 0.0f;
991 glFogf(GL_FOG_START, fogstart);
992 checkGLcall("glFogf(GL_FOG_START, fogstart)");
993 TRACE("Fog Start == %f\n", fogstart);
995 glFogf(GL_FOG_END, fogend);
996 checkGLcall("glFogf(GL_FOG_END, fogend)");
997 TRACE("Fog End == %f\n", fogend);
1000 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1002 enum fogsource new_source;
1004 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
1006 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
1007 /* No fog? Disable it, and we're done :-) */
1008 glDisableWINE(GL_FOG);
1009 checkGLcall("glDisable GL_FOG");
1010 return;
1013 /* Fog Rules:
1015 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
1016 * It can use the Z value of the vertex, or the alpha component of the specular color.
1017 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
1018 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
1019 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
1021 * FOGTABLEMODE != NONE:
1022 * The Z value is used, with the equation specified, no matter what vertex type.
1024 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1025 * Per vertex fog is calculated using the specified fog equation and the parameters
1027 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1028 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1029 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1032 * Rules for vertex fog with shaders:
1034 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1035 * the fog computation to happen during transformation while openGL expects it to happen
1036 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1037 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1038 * To solve this problem, WineD3D does:
1039 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1040 * shader,
1041 * and 2) disables the fog computation (in either the fixed function or programmable
1042 * rasterizer) if using a vertex program.
1044 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1045 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1046 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1047 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1048 * There are some GL differences between specular fog coords and vertex shaders though.
1050 * With table fog the vertex shader fog coordinate is ignored.
1052 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1053 * without shaders).
1056 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1057 * the system will apply only pixel(=table) fog effects."
1059 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1060 if(use_vs(stateblock)) {
1061 glFogi(GL_FOG_MODE, GL_LINEAR);
1062 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1063 new_source = FOGSOURCE_VS;
1064 } else {
1065 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1066 /* If processed vertices are used, fall through to the NONE case */
1067 case WINED3DFOG_EXP:
1068 if(!context->last_was_rhw) {
1069 glFogi(GL_FOG_MODE, GL_EXP);
1070 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1071 new_source = FOGSOURCE_FFP;
1072 break;
1074 /* drop through */
1076 case WINED3DFOG_EXP2:
1077 if(!context->last_was_rhw) {
1078 glFogi(GL_FOG_MODE, GL_EXP2);
1079 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1080 new_source = FOGSOURCE_FFP;
1081 break;
1083 /* drop through */
1085 case WINED3DFOG_LINEAR:
1086 if(!context->last_was_rhw) {
1087 glFogi(GL_FOG_MODE, GL_LINEAR);
1088 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1089 new_source = FOGSOURCE_FFP;
1090 break;
1092 /* drop through */
1094 case WINED3DFOG_NONE:
1095 /* Both are none? According to msdn the alpha channel of the specular
1096 * color contains a fog factor. Set it in drawStridedSlow.
1097 * Same happens with Vertexfog on transformed vertices
1099 new_source = FOGSOURCE_COORD;
1100 glFogi(GL_FOG_MODE, GL_LINEAR);
1101 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1102 break;
1104 default:
1105 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1106 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1109 } else {
1110 new_source = FOGSOURCE_FFP;
1112 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1113 case WINED3DFOG_EXP:
1114 glFogi(GL_FOG_MODE, GL_EXP);
1115 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1116 break;
1118 case WINED3DFOG_EXP2:
1119 glFogi(GL_FOG_MODE, GL_EXP2);
1120 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1121 break;
1123 case WINED3DFOG_LINEAR:
1124 glFogi(GL_FOG_MODE, GL_LINEAR);
1125 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1126 break;
1128 case WINED3DFOG_NONE: /* Won't happen */
1129 default:
1130 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1134 glEnableWINE(GL_FOG);
1135 checkGLcall("glEnable GL_FOG");
1136 if(new_source != context->fog_source) {
1137 context->fog_source = new_source;
1138 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1142 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1144 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1145 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1149 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1151 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1152 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1153 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1154 } else {
1155 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1156 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1160 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1162 float col[4];
1163 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1164 glFogfv(GL_FOG_COLOR, &col[0]);
1165 checkGLcall("glFog GL_FOG_COLOR");
1168 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1170 union {
1171 DWORD d;
1172 float f;
1173 } tmpvalue;
1174 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1175 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1176 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1179 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1181 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1182 GLenum Parm = 0;
1184 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1185 * The vertex declaration will call this function if the fixed function pipeline is used.
1188 if(isStateDirty(context, STATE_VDECL)) {
1189 return;
1192 context->num_untracked_materials = 0;
1193 if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE))
1194 && stateblock->renderState[WINED3DRS_COLORVERTEX])
1196 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1197 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1198 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1199 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1200 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1202 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1203 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1204 Parm = GL_AMBIENT_AND_DIFFUSE;
1205 } else {
1206 Parm = GL_DIFFUSE;
1208 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1209 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1210 context->num_untracked_materials++;
1212 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1213 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1214 context->num_untracked_materials++;
1216 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1217 Parm = GL_AMBIENT;
1218 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1219 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1220 context->num_untracked_materials++;
1222 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1223 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1224 context->num_untracked_materials++;
1226 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1227 Parm = GL_EMISSION;
1228 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1229 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1230 context->num_untracked_materials++;
1232 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1233 Parm = GL_SPECULAR;
1237 /* Nothing changed, return. */
1238 if (Parm == context->tracking_parm) return;
1240 if(!Parm) {
1241 glDisable(GL_COLOR_MATERIAL);
1242 checkGLcall("glDisable GL_COLOR_MATERIAL");
1243 } else {
1244 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1245 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1246 glEnable(GL_COLOR_MATERIAL);
1247 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1250 /* Apparently calls to glMaterialfv are ignored for properties we're
1251 * tracking with glColorMaterial, so apply those here. */
1252 switch (context->tracking_parm) {
1253 case GL_AMBIENT_AND_DIFFUSE:
1254 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1255 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1256 checkGLcall("glMaterialfv");
1257 break;
1259 case GL_DIFFUSE:
1260 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1261 checkGLcall("glMaterialfv");
1262 break;
1264 case GL_AMBIENT:
1265 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1266 checkGLcall("glMaterialfv");
1267 break;
1269 case GL_EMISSION:
1270 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1271 checkGLcall("glMaterialfv");
1272 break;
1274 case GL_SPECULAR:
1275 /* Only change material color if specular is enabled, otherwise it is set to black */
1276 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1277 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1278 checkGLcall("glMaterialfv");
1279 } else {
1280 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1281 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1282 checkGLcall("glMaterialfv");
1284 break;
1287 context->tracking_parm = Parm;
1290 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1292 union {
1293 DWORD d;
1294 WINED3DLINEPATTERN lp;
1295 } tmppattern;
1296 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1298 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1300 if (tmppattern.lp.wRepeatFactor) {
1301 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1302 checkGLcall("glLineStipple(repeat, linepattern)");
1303 glEnable(GL_LINE_STIPPLE);
1304 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1305 } else {
1306 glDisable(GL_LINE_STIPPLE);
1307 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1311 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1313 union {
1314 DWORD d;
1315 float f;
1316 } tmpvalue;
1318 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1319 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1320 TRACE("ZBias value %f\n", tmpvalue.f);
1321 glPolygonOffset(0, -tmpvalue.f);
1322 checkGLcall("glPolygonOffset(0, -Value)");
1323 glEnable(GL_POLYGON_OFFSET_FILL);
1324 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1325 glEnable(GL_POLYGON_OFFSET_LINE);
1326 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1327 glEnable(GL_POLYGON_OFFSET_POINT);
1328 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1329 } else {
1330 glDisable(GL_POLYGON_OFFSET_FILL);
1331 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1332 glDisable(GL_POLYGON_OFFSET_LINE);
1333 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1334 glDisable(GL_POLYGON_OFFSET_POINT);
1335 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1340 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1342 if(isStateDirty(context, STATE_VDECL)) {
1343 return;
1345 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1346 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1347 * by zero and is not properly defined in opengl, so avoid it
1349 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]
1350 && (stateblock->wineD3DDevice->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL)))
1352 glEnable(GL_NORMALIZE);
1353 checkGLcall("glEnable(GL_NORMALIZE);");
1354 } else {
1355 glDisable(GL_NORMALIZE);
1356 checkGLcall("glDisable(GL_NORMALIZE);");
1360 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1362 union {
1363 DWORD d;
1364 float f;
1365 } tmpvalue;
1367 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1368 if (tmpvalue.f != 1.0f)
1370 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1372 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1373 if (tmpvalue.f != 64.0f)
1375 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1380 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1382 union {
1383 DWORD d;
1384 float f;
1385 } min, max;
1387 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1388 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1390 /* Max point size trumps min point size */
1391 if(min.f > max.f) {
1392 min.f = max.f;
1395 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1396 checkGLcall("glPointParameterfEXT(...)");
1397 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1398 checkGLcall("glPointParameterfEXT(...)");
1401 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1403 union {
1404 DWORD d;
1405 float f;
1406 } min, max;
1408 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1409 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1411 /* Max point size trumps min point size */
1412 if(min.f > max.f) {
1413 min.f = max.f;
1416 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1417 checkGLcall("glPointParameterfARB(...)");
1418 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1419 checkGLcall("glPointParameterfARB(...)");
1422 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1424 /* TODO: Group this with the viewport */
1426 * POINTSCALEENABLE controls how point size value is treated. If set to
1427 * true, the point size is scaled with respect to height of viewport.
1428 * When set to false point size is in pixels.
1431 /* Default values */
1432 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1433 union {
1434 DWORD d;
1435 float f;
1436 } pointSize, A, B, C;
1438 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1439 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1440 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1441 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1443 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1444 GLfloat scaleFactor;
1445 float h = stateblock->viewport.Height;
1447 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1449 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1450 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1451 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1452 * are less than 1.0f. scale_factor = 1.0f / point_size.
1454 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1455 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1456 * is 1.0, but then accepts points below that and draws too small points
1458 pointSize.f = GL_LIMITS(pointsizemin);
1459 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1460 /* gl already scales the input to glPointSize,
1461 * d3d scales the result after the point size scale.
1462 * If the point size is bigger than the max size, use the
1463 * scaling to scale it bigger, and set the gl point size to max
1465 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1466 TRACE("scale: %f\n", scaleFactor);
1467 pointSize.f = GL_LIMITS(pointsize);
1468 } else {
1469 scaleFactor = 1.0f;
1471 scaleFactor = pow(h * scaleFactor, 2);
1473 att[0] = A.f / scaleFactor;
1474 att[1] = B.f / scaleFactor;
1475 att[2] = C.f / scaleFactor;
1478 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1479 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1480 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1482 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1483 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1484 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1485 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1486 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1489 glPointSize(pointSize.f);
1490 checkGLcall("glPointSize(...);");
1493 static void state_debug_monitor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1495 WARN("token: %#x\n", stateblock->renderState[WINED3DRS_DEBUGMONITORTOKEN]);
1498 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1500 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1502 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1503 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1504 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1505 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1506 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1507 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1508 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1509 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1510 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1511 checkGLcall("glColorMask(...)");
1513 /* depends on WINED3DRS_COLORWRITEENABLE. */
1514 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1515 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1516 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1517 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1518 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1519 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1520 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1524 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1526 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1527 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1528 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1529 } else {
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, struct wined3d_context *context)
1537 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1538 TRACE("Last Pixel Drawing Enabled\n");
1539 } else {
1540 static BOOL warned;
1541 if (!warned) {
1542 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1543 warned = TRUE;
1544 } else {
1545 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1550 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1552 BOOL warned = FALSE;
1553 /* TODO: NV_POINT_SPRITE */
1554 if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1555 /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1556 FIXME("Point sprites not supported\n");
1557 warned = TRUE;
1561 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1563 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1564 BOOL warned = FALSE;
1565 if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) {
1566 if(use_ps(stateblock) || stateblock->lowest_disabled_stage > GL_LIMITS(point_sprite_units)) {
1567 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1568 warned = TRUE;
1572 glEnable(GL_POINT_SPRITE_ARB);
1573 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1574 } else {
1575 glDisable(GL_POINT_SPRITE_ARB);
1576 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1580 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1583 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1584 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1585 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1586 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1588 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1590 TRACE("Stub\n");
1591 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1592 stateblock->renderState[WINED3DRS_WRAP1] ||
1593 stateblock->renderState[WINED3DRS_WRAP2] ||
1594 stateblock->renderState[WINED3DRS_WRAP3] ||
1595 stateblock->renderState[WINED3DRS_WRAP4] ||
1596 stateblock->renderState[WINED3DRS_WRAP5] ||
1597 stateblock->renderState[WINED3DRS_WRAP6] ||
1598 stateblock->renderState[WINED3DRS_WRAP7] ||
1599 stateblock->renderState[WINED3DRS_WRAP8] ||
1600 stateblock->renderState[WINED3DRS_WRAP9] ||
1601 stateblock->renderState[WINED3DRS_WRAP10] ||
1602 stateblock->renderState[WINED3DRS_WRAP11] ||
1603 stateblock->renderState[WINED3DRS_WRAP12] ||
1604 stateblock->renderState[WINED3DRS_WRAP13] ||
1605 stateblock->renderState[WINED3DRS_WRAP14] ||
1606 stateblock->renderState[WINED3DRS_WRAP15] ) {
1607 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1611 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1613 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1614 WARN("Multisample antialiasing not supported by gl\n");
1618 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1620 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1621 glEnable(GL_MULTISAMPLE_ARB);
1622 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1623 } else {
1624 glDisable(GL_MULTISAMPLE_ARB);
1625 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1629 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1631 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1632 glEnable(GL_SCISSOR_TEST);
1633 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1634 } else {
1635 glDisable(GL_SCISSOR_TEST);
1636 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1640 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1642 union {
1643 DWORD d;
1644 float f;
1645 } tmpvalue;
1647 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1648 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1649 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1650 glEnable(GL_POLYGON_OFFSET_FILL);
1651 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1652 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1653 checkGLcall("glPolygonOffset(...)");
1654 } else {
1655 glDisable(GL_POLYGON_OFFSET_FILL);
1656 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1660 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1662 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1663 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1664 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1665 } else {
1666 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1667 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1671 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1673 TRACE("Stub\n");
1674 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1675 FIXME(" Stippled Alpha not supported yet.\n");
1678 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1680 TRACE("Stub\n");
1681 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1682 FIXME(" Antialias not supported yet.\n");
1685 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1687 TRACE("Stub\n");
1688 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1689 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1692 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1694 TRACE("Stub\n");
1695 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1696 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1699 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1701 union {
1702 DWORD d;
1703 float f;
1704 } tmpvalue;
1705 tmpvalue.f = 1.0f;
1707 TRACE("Stub\n");
1708 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1710 static BOOL displayed = FALSE;
1712 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1713 if(!displayed)
1714 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1716 displayed = TRUE;
1720 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1722 TRACE("Stub\n");
1723 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1724 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1727 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1729 TRACE("Stub\n");
1730 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1731 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1734 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1736 TRACE("Stub\n");
1737 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1738 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1741 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1743 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1744 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1748 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1750 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1751 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1755 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1757 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1758 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1762 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1764 if(stateblock->renderState[WINED3DRS_ROP2]) {
1765 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1769 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1771 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1772 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1776 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1778 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1779 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1783 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1785 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1786 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1790 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1792 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1793 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1797 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1799 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1800 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1804 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1806 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1807 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1811 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1813 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1814 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1818 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1820 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1821 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1825 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1827 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1828 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1832 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1834 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1835 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1839 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1841 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1842 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1846 static void state_swvp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1848 if (stateblock->renderState[WINED3DRS_SOFTWAREVERTEXPROCESSING])
1850 FIXME("Software vertex processing not implemented.\n");
1854 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1855 #if defined (GL_VERSION_1_3)
1856 # define useext(A) A
1857 #elif defined (GL_EXT_texture_env_combine)
1858 # define useext(A) A##_EXT
1859 #elif defined (GL_ARB_texture_env_combine)
1860 # define useext(A) A##_ARB
1861 #endif
1863 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1864 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1865 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1866 * flag specifies the complement of the input should be used. */
1867 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1868 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1870 /* Calculate the operand */
1871 if (complement) {
1872 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1873 else *operand = GL_ONE_MINUS_SRC_COLOR;
1874 } else {
1875 if (from_alpha) *operand = GL_SRC_ALPHA;
1876 else *operand = GL_SRC_COLOR;
1879 /* Calculate the source */
1880 switch (arg & WINED3DTA_SELECTMASK) {
1881 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1882 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1883 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1884 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1885 case WINED3DTA_SPECULAR:
1887 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1888 * 'Secondary color' and isn't supported until base GL supports it
1889 * There is no concept of temp registers as far as I can tell
1891 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1892 *source = GL_TEXTURE;
1893 break;
1894 default:
1895 FIXME("Unrecognized texture arg %#x\n", arg);
1896 *source = GL_TEXTURE;
1897 break;
1901 /* Setup the texture operations texture stage states */
1902 static void set_tex_op(const struct wined3d_context *context, IWineD3DDevice *iface,
1903 BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1905 GLenum src1, src2, src3;
1906 GLenum opr1, opr2, opr3;
1907 GLenum comb_target;
1908 GLenum src0_target, src1_target, src2_target;
1909 GLenum opr0_target, opr1_target, opr2_target;
1910 GLenum scal_target;
1911 GLenum opr=0, invopr, src3_target, opr3_target;
1912 BOOL Handled = FALSE;
1913 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1915 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1917 /* This is called by a state handler which has the gl lock held and a context for the thread */
1919 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1920 the form (a1 <operation> a2). However, some of the more complex operations
1921 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1922 in a third parameter called a0. Therefore these are operations of the form
1923 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1925 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1926 functions below, expect their syntax to differ slightly to those listed in the
1927 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1928 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1930 if (isAlpha) {
1931 comb_target = useext(GL_COMBINE_ALPHA);
1932 src0_target = useext(GL_SOURCE0_ALPHA);
1933 src1_target = useext(GL_SOURCE1_ALPHA);
1934 src2_target = useext(GL_SOURCE2_ALPHA);
1935 opr0_target = useext(GL_OPERAND0_ALPHA);
1936 opr1_target = useext(GL_OPERAND1_ALPHA);
1937 opr2_target = useext(GL_OPERAND2_ALPHA);
1938 scal_target = GL_ALPHA_SCALE;
1940 else {
1941 comb_target = useext(GL_COMBINE_RGB);
1942 src0_target = useext(GL_SOURCE0_RGB);
1943 src1_target = useext(GL_SOURCE1_RGB);
1944 src2_target = useext(GL_SOURCE2_RGB);
1945 opr0_target = useext(GL_OPERAND0_RGB);
1946 opr1_target = useext(GL_OPERAND1_RGB);
1947 opr2_target = useext(GL_OPERAND2_RGB);
1948 scal_target = useext(GL_RGB_SCALE);
1951 /* If a texture stage references an invalid texture unit the stage just
1952 * passes through the result from the previous stage */
1953 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1954 arg1 = WINED3DTA_CURRENT;
1955 op = WINED3DTOP_SELECTARG1;
1958 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1959 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1960 } else {
1961 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1963 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1964 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1966 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1968 Handled = TRUE; /* Assume will be handled */
1970 /* Other texture operations require special extensions: */
1971 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1972 if (isAlpha) {
1973 opr = GL_SRC_ALPHA;
1974 invopr = GL_ONE_MINUS_SRC_ALPHA;
1975 src3_target = GL_SOURCE3_ALPHA_NV;
1976 opr3_target = GL_OPERAND3_ALPHA_NV;
1977 } else {
1978 opr = GL_SRC_COLOR;
1979 invopr = GL_ONE_MINUS_SRC_COLOR;
1980 src3_target = GL_SOURCE3_RGB_NV;
1981 opr3_target = GL_OPERAND3_RGB_NV;
1983 switch (op) {
1984 case WINED3DTOP_DISABLE: /* Only for alpha */
1985 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1986 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1987 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1988 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1989 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1990 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1991 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1992 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1993 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1994 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1995 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1996 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1997 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1998 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1999 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2000 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2001 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2002 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2003 break;
2004 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
2005 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
2006 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2007 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2008 if (op == WINED3DTOP_SELECTARG1) {
2009 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2010 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2011 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2012 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2013 } else {
2014 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2015 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2016 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2017 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2019 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2020 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2021 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2022 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2023 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2024 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2025 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2026 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2027 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2028 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2029 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2030 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2031 break;
2033 case WINED3DTOP_MODULATE:
2034 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2035 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2036 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2037 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2038 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2039 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2040 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2041 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2042 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2043 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2044 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2045 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2046 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2047 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2048 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2049 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2050 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2051 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2052 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2053 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2054 break;
2055 case WINED3DTOP_MODULATE2X:
2056 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2057 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2058 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2059 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2060 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2061 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2062 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2063 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2064 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2065 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2066 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2067 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2068 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2069 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2070 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2071 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2072 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2073 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2074 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2075 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2076 break;
2077 case WINED3DTOP_MODULATE4X:
2078 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2079 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2080 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2081 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2082 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2083 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2084 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2085 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2086 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2087 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2088 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2089 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2090 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2091 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2092 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2093 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2094 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2095 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2096 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2097 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2098 break;
2100 case WINED3DTOP_ADD:
2101 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2102 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2103 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2104 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2105 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2106 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2107 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2108 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2109 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2110 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2111 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2112 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2113 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2114 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2115 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2116 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2117 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2118 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2119 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2120 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2121 break;
2123 case WINED3DTOP_ADDSIGNED:
2124 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2125 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2126 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2127 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2128 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2129 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2130 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2131 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2132 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2133 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2134 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2135 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2136 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2137 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2138 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2139 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2140 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2141 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2142 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2143 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2144 break;
2146 case WINED3DTOP_ADDSIGNED2X:
2147 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2148 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2149 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2150 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2151 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2152 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2153 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2154 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2155 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2156 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2157 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2158 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2159 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2160 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2161 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2162 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2163 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2164 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2165 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2166 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2167 break;
2169 case WINED3DTOP_ADDSMOOTH:
2170 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2171 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2172 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2173 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2174 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2175 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2176 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2177 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2178 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2179 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2180 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2181 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2182 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2183 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2184 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2185 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2186 switch (opr1) {
2187 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2188 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2189 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2190 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2192 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2193 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2194 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2195 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2196 break;
2198 case WINED3DTOP_BLENDDIFFUSEALPHA:
2199 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2200 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2201 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2202 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2203 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2204 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2205 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2206 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2207 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2208 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2209 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2210 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2211 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2212 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2213 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2214 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2215 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2216 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2217 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2218 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2219 break;
2220 case WINED3DTOP_BLENDTEXTUREALPHA:
2221 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2222 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2223 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2224 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2225 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2226 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2227 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2228 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2229 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2230 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2231 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2232 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2233 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2234 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2235 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2236 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2237 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2238 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2239 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2240 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2241 break;
2242 case WINED3DTOP_BLENDFACTORALPHA:
2243 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2244 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2245 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2246 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2247 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2248 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2249 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2250 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2251 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2252 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2253 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2254 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2255 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2256 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2257 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2258 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2259 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2260 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2261 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2262 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2263 break;
2264 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2265 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2266 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2267 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2268 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2269 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2270 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2271 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2272 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2273 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2274 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2275 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2276 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2277 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2278 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2279 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2280 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2281 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2282 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2283 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2284 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2285 break;
2286 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2287 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2288 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2289 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2290 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2291 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2292 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2293 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2294 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2295 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2296 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2297 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2298 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2299 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2300 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2301 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2302 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2303 switch (opr) {
2304 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2305 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2307 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2308 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2309 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2310 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2311 break;
2312 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2313 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2314 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2315 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2316 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2317 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2318 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2319 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2320 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2321 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2322 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2323 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2324 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2325 switch (opr1) {
2326 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2327 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2329 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2330 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2331 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2332 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2333 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2334 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2335 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2336 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2337 break;
2338 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2339 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2340 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2341 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2342 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2343 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2344 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2345 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2346 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2347 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2348 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2349 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2350 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2351 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2352 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2353 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2354 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2355 switch (opr1) {
2356 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2357 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2358 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2359 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2361 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2362 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2363 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2364 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2365 break;
2366 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2367 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2368 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2369 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2370 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2371 switch (opr1) {
2372 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2373 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2374 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2375 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2377 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2378 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2379 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2380 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2381 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2382 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2383 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2384 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2385 switch (opr1) {
2386 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2387 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2389 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2390 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2391 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2392 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2393 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2394 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2395 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2396 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2397 break;
2398 case WINED3DTOP_MULTIPLYADD:
2399 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2400 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2401 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2402 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2403 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2404 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2405 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2406 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2407 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2408 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2409 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2410 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2411 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2412 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2413 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2414 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2415 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2416 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2417 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2418 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2419 break;
2421 case WINED3DTOP_BUMPENVMAP:
2425 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2426 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2428 default:
2429 Handled = FALSE;
2431 if (Handled) {
2432 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2433 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2435 return;
2437 } /* GL_NV_texture_env_combine4 */
2439 Handled = TRUE; /* Again, assume handled */
2440 switch (op) {
2441 case WINED3DTOP_DISABLE: /* Only for alpha */
2442 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2443 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2444 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2445 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2446 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2447 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2448 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2449 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2450 break;
2451 case WINED3DTOP_SELECTARG1:
2452 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2453 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2454 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2455 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2456 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2457 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2458 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2459 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2460 break;
2461 case WINED3DTOP_SELECTARG2:
2462 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2463 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2464 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2465 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2466 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2467 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2468 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2469 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2470 break;
2471 case WINED3DTOP_MODULATE:
2472 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2473 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2474 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2475 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2476 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2477 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2478 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2479 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2480 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2481 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2482 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2483 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2484 break;
2485 case WINED3DTOP_MODULATE2X:
2486 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2487 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2488 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2489 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2490 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2491 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2492 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2493 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2494 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2495 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2496 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2497 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2498 break;
2499 case WINED3DTOP_MODULATE4X:
2500 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2501 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2502 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2503 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2504 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2505 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2506 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2507 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2508 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2509 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2510 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2511 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2512 break;
2513 case WINED3DTOP_ADD:
2514 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2515 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2516 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2517 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2518 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2519 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2520 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2521 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2522 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2523 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2524 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2525 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2526 break;
2527 case WINED3DTOP_ADDSIGNED:
2528 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2529 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2530 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2531 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2532 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2533 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2534 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2535 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2536 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2537 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2538 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2539 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2540 break;
2541 case WINED3DTOP_ADDSIGNED2X:
2542 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2543 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2544 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2545 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2546 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2547 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2548 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2549 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2550 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2551 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2552 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2553 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2554 break;
2555 case WINED3DTOP_SUBTRACT:
2556 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2557 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2558 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2559 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2560 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2561 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2562 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2563 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2564 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2565 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2566 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2567 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2568 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2569 } else {
2570 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2572 break;
2574 case WINED3DTOP_BLENDDIFFUSEALPHA:
2575 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2576 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2577 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2578 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2579 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2580 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2581 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2582 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2583 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2584 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2585 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2586 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2587 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2588 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2589 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2590 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2591 break;
2592 case WINED3DTOP_BLENDTEXTUREALPHA:
2593 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2594 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2595 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2596 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2597 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2598 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2599 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2600 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2601 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2602 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2603 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2604 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2605 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2606 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2607 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2608 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2609 break;
2610 case WINED3DTOP_BLENDFACTORALPHA:
2611 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2612 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2613 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2614 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2615 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2616 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2617 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2618 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2619 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2620 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2621 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2622 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2623 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2624 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2625 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2626 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2627 break;
2628 case WINED3DTOP_BLENDCURRENTALPHA:
2629 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2630 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2631 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2632 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2633 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2634 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2635 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2636 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2637 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2638 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2639 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2640 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2641 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2642 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2643 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2644 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2645 break;
2646 case WINED3DTOP_DOTPRODUCT3:
2647 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2648 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2649 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2650 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2651 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2652 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2653 } else {
2654 FIXME("This version of opengl does not support GL_DOT3\n");
2656 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2657 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2658 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2659 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2660 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2661 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2662 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2663 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2664 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2665 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2666 break;
2667 case WINED3DTOP_LERP:
2668 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2669 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2670 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2671 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2672 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2673 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2674 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2675 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2676 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2677 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2678 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2679 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2680 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2681 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2682 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2683 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2684 break;
2685 case WINED3DTOP_ADDSMOOTH:
2686 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2687 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2688 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2689 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2690 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2691 switch (opr1) {
2692 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2693 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2694 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2695 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2697 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2698 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2699 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2700 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2701 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2702 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2703 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2704 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2705 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2706 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2707 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2708 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2709 } else
2710 Handled = FALSE;
2711 break;
2712 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2713 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2714 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2715 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2716 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2717 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2718 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2719 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2720 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2721 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2722 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2723 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2724 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2725 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2726 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2727 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2728 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2729 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2730 } else
2731 Handled = FALSE;
2732 break;
2733 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2734 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2735 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2736 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2737 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2738 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2739 switch (opr1) {
2740 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2741 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2742 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2743 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2745 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2746 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2747 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2748 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2749 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2750 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2751 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2752 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2753 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2754 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2755 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2756 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2757 } else
2758 Handled = FALSE;
2759 break;
2760 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2761 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2762 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2763 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2764 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2765 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2766 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2767 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2768 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2769 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2770 switch (opr1) {
2771 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2772 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2773 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2774 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2776 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2777 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2778 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2779 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2780 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2781 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2782 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2783 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2784 } else
2785 Handled = FALSE;
2786 break;
2787 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2788 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2789 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2790 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2791 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2792 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2793 switch (opr1) {
2794 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2795 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2796 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2797 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2799 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2800 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2801 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2802 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2803 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2804 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2805 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2806 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2807 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2808 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2809 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2810 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2811 } else
2812 Handled = FALSE;
2813 break;
2814 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2815 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2816 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2817 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2818 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2819 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2820 switch (opr1) {
2821 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2822 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2823 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2824 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2826 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2827 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2828 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2829 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2830 switch (opr1) {
2831 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2832 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2833 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2834 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2836 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2837 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2838 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2839 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2840 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2841 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2842 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2843 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2844 } else
2845 Handled = FALSE;
2846 break;
2847 case WINED3DTOP_MULTIPLYADD:
2848 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2849 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2850 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2851 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2852 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2853 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2854 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2855 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2856 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2857 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2858 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2859 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2860 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2861 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2862 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2863 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2864 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2865 } else
2866 Handled = FALSE;
2867 break;
2868 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2869 case WINED3DTOP_BUMPENVMAP:
2870 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2871 /* Technically texture shader support without register combiners is possible, but not expected to occur
2872 * on real world cards, so for now a fixme should be enough
2874 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2876 default:
2877 Handled = FALSE;
2880 if (Handled) {
2881 BOOL combineOK = TRUE;
2882 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2883 DWORD op2;
2885 if (isAlpha) {
2886 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2887 } else {
2888 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2891 /* Note: If COMBINE4 in effect can't go back to combine! */
2892 switch (op2) {
2893 case WINED3DTOP_ADDSMOOTH:
2894 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2895 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2896 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2897 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2898 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2899 case WINED3DTOP_MULTIPLYADD:
2900 /* Ignore those implemented in both cases */
2901 switch (op) {
2902 case WINED3DTOP_SELECTARG1:
2903 case WINED3DTOP_SELECTARG2:
2904 combineOK = FALSE;
2905 Handled = FALSE;
2906 break;
2907 default:
2908 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2909 return;
2914 if (combineOK) {
2915 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2916 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2918 return;
2922 /* After all the extensions, if still unhandled, report fixme */
2923 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2927 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
2929 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2930 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2931 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2933 TRACE("Setting color op for stage %d\n", stage);
2935 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2936 if (use_ps(stateblock)) return;
2938 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2940 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2942 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2943 FIXME("Attempt to enable unsupported stage!\n");
2944 return;
2946 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2947 checkGLcall("glActiveTextureARB");
2950 if(stage >= stateblock->lowest_disabled_stage) {
2951 TRACE("Stage disabled\n");
2952 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2954 /* Disable everything here */
2955 glDisable(GL_TEXTURE_2D);
2956 checkGLcall("glDisable(GL_TEXTURE_2D)");
2957 glDisable(GL_TEXTURE_3D);
2958 checkGLcall("glDisable(GL_TEXTURE_3D)");
2959 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2960 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2961 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2963 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2964 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2965 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2968 /* All done */
2969 return;
2972 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2973 * if the sampler for this stage is dirty
2975 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2976 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2979 set_tex_op(context, (IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2980 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2981 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2982 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2983 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2986 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
2988 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2989 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2990 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2991 DWORD op, arg1, arg2, arg0;
2993 TRACE("Setting alpha op for stage %d\n", stage);
2994 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2995 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2997 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2998 FIXME("Attempt to enable unsupported stage!\n");
2999 return;
3001 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3002 checkGLcall("glActiveTextureARB");
3005 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
3006 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
3007 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
3008 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
3010 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
3012 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
3014 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3016 IWineD3DSurfaceImpl *surf;
3018 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
3020 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
3022 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
3023 * properly. On the other hand applications can still use texture combiners apparently. This code
3024 * takes care that apps cannot remove the texture's alpha channel entirely.
3026 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
3027 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
3028 * and alpha component of diffuse color to draw things like translucent text and perform other
3029 * blending effects.
3031 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
3032 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
3033 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
3034 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
3035 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
3036 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
3037 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
3038 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
3039 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
3040 * alpha.
3042 * What to do with multitexturing? So far no app has been found that uses color keying with
3043 * multitexturing */
3044 if (op == WINED3DTOP_DISABLE)
3046 arg1 = WINED3DTA_TEXTURE;
3047 op = WINED3DTOP_SELECTARG1;
3049 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
3051 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3053 arg2 = WINED3DTA_TEXTURE;
3054 op = WINED3DTOP_MODULATE;
3056 else arg1 = WINED3DTA_TEXTURE;
3058 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
3060 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3062 arg1 = WINED3DTA_TEXTURE;
3063 op = WINED3DTOP_MODULATE;
3065 else arg2 = WINED3DTA_TEXTURE;
3071 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3072 * this if block here, and the other code(color keying, texture unit selection) are the same
3074 TRACE("Setting alpha op for stage %d\n", stage);
3075 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3076 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3077 op, arg1, arg2, arg0,
3078 mapped_stage,
3079 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
3080 } else {
3081 set_tex_op(context, (IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3082 op, arg1, arg2, arg0);
3086 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3088 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3089 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3090 BOOL generated;
3091 int coordIdx;
3093 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3094 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3096 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3097 return;
3100 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3102 if(mapped_stage >= GL_LIMITS(textures)) {
3103 return;
3105 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3106 checkGLcall("glActiveTextureARB");
3107 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3108 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3110 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3111 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3112 stateblock->wineD3DDevice->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
3113 ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format
3114 : WINED3DFMT_UNKNOWN,
3115 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3117 /* The sampler applying function calls us if this changes */
3118 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3120 if(generated) {
3121 FIXME("Non-power2 texture being used with generated texture coords\n");
3123 /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
3124 fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3125 if (!use_ps(stateblock)) {
3126 TRACE("Non power two matrix multiply fixup\n");
3127 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3132 static void unloadTexCoords(const struct wined3d_context *context)
3134 unsigned int texture_idx;
3136 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3137 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3138 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3142 static void loadTexCoords(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
3143 const struct wined3d_stream_info *si, GLuint *curVBO)
3145 const UINT *offset = stateblock->streamOffset;
3146 unsigned int mapped_stage = 0;
3147 unsigned int textureNo = 0;
3149 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3150 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3152 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3153 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3155 if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
3157 const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3159 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3160 textureNo, mapped_stage, coordIdx, e->data);
3162 if (*curVBO != e->buffer_object)
3164 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3165 checkGLcall("glBindBufferARB");
3166 *curVBO = e->buffer_object;
3169 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3170 checkGLcall("glClientActiveTextureARB");
3172 /* The coords to supply depend completely on the fvf / vertex shader */
3173 glTexCoordPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
3174 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3175 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3176 } else {
3177 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3180 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3181 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3182 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3183 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3187 checkGLcall("loadTexCoords");
3190 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3192 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3193 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3194 static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3195 static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3196 static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3197 static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3199 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3201 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3202 return;
3205 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3206 WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3207 return;
3209 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3210 checkGLcall("glActiveTextureARB");
3212 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3214 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3215 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3216 * means use the vertex position (camera-space) as the input texture coordinates
3217 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3218 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3219 * to the TEXCOORDINDEX value
3221 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3223 case WINED3DTSS_TCI_PASSTHRU:
3224 /* Use the specified texture coordinates contained within the
3225 * vertex format. This value resolves to zero. */
3226 glDisable(GL_TEXTURE_GEN_S);
3227 glDisable(GL_TEXTURE_GEN_T);
3228 glDisable(GL_TEXTURE_GEN_R);
3229 glDisable(GL_TEXTURE_GEN_Q);
3230 checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3231 break;
3233 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3234 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3235 * as the input texture coordinates for this stage's texture transformation. This
3236 * equates roughly to EYE_LINEAR */
3238 glMatrixMode(GL_MODELVIEW);
3239 glPushMatrix();
3240 glLoadIdentity();
3241 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3242 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3243 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3244 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3245 glPopMatrix();
3246 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3248 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3249 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3250 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3251 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3253 glEnable(GL_TEXTURE_GEN_S);
3254 glEnable(GL_TEXTURE_GEN_T);
3255 glEnable(GL_TEXTURE_GEN_R);
3256 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3258 break;
3260 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3261 /* Note that NV_TEXGEN_REFLECTION support is implied when
3262 * ARB_TEXTURE_CUBE_MAP is supported */
3263 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3265 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3266 break;
3269 glMatrixMode(GL_MODELVIEW);
3270 glPushMatrix();
3271 glLoadIdentity();
3272 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3273 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3274 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3275 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3276 glPopMatrix();
3277 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3279 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3280 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3281 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3282 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3284 glEnable(GL_TEXTURE_GEN_S);
3285 glEnable(GL_TEXTURE_GEN_T);
3286 glEnable(GL_TEXTURE_GEN_R);
3287 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3289 break;
3291 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3292 /* Note that NV_TEXGEN_REFLECTION support is implied when
3293 * ARB_TEXTURE_CUBE_MAP is supported */
3294 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3296 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3297 break;
3300 glMatrixMode(GL_MODELVIEW);
3301 glPushMatrix();
3302 glLoadIdentity();
3303 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3304 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3305 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3306 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3307 glPopMatrix();
3308 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3310 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3311 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3312 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3313 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3315 glEnable(GL_TEXTURE_GEN_S);
3316 glEnable(GL_TEXTURE_GEN_T);
3317 glEnable(GL_TEXTURE_GEN_R);
3318 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3320 break;
3322 case WINED3DTSS_TCI_SPHEREMAP:
3323 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3324 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3325 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3327 glEnable(GL_TEXTURE_GEN_S);
3328 glEnable(GL_TEXTURE_GEN_T);
3329 glDisable(GL_TEXTURE_GEN_R);
3330 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3332 break;
3334 default:
3335 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3336 stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3337 glDisable(GL_TEXTURE_GEN_S);
3338 glDisable(GL_TEXTURE_GEN_T);
3339 glDisable(GL_TEXTURE_GEN_R);
3340 glDisable(GL_TEXTURE_GEN_Q);
3341 checkGLcall("Disable texgen.");
3343 break;
3346 /* Update the texture matrix */
3347 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3348 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3351 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3352 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3353 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3354 * and do all the things linked to it
3355 * TODO: Tidy that up to reload only the arrays of the changed unit
3357 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3359 unloadTexCoords(context);
3360 loadTexCoords(context, stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3364 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3366 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3368 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3369 * has an update pending
3371 if(isStateDirty(context, STATE_VDECL) ||
3372 isStateDirty(context, STATE_PIXELSHADER)) {
3373 return;
3376 device->shader_backend->shader_load_constants(context, use_ps(stateblock), use_vs(stateblock));
3379 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3381 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3383 if (stateblock->pixelShader && stage != 0
3384 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage)))
3386 /* The pixel shader has to know the luminance scale. Do a constants update if it
3387 * isn't scheduled anyway
3389 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3390 !isStateDirty(context, STATE_PIXELSHADER)) {
3391 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3396 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3398 const DWORD sampler = state - STATE_SAMPLER(0);
3399 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3401 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3403 if(!texture) return;
3404 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3405 * basetexture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3406 * scaling is reapplied or removed, the texture matrix has to be reapplied
3408 * The mapped stage is already active because the sampler() function below, which is part of the
3409 * misc pipeline
3411 if(sampler < MAX_TEXTURES) {
3412 const BOOL texIsPow2 = !((IWineD3DBaseTextureImpl *)texture)->baseTexture.pow2Matrix_identity;
3414 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3416 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3417 else context->lastWasPow2Texture &= ~(1 << sampler);
3418 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3423 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3425 DWORD sampler = state - STATE_SAMPLER(0);
3426 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3427 union {
3428 float f;
3429 DWORD d;
3430 } tmpvalue;
3432 TRACE("Sampler: %d\n", sampler);
3433 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3434 * only has to bind textures and set the per texture states
3437 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3439 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3440 return;
3443 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3444 return;
3446 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3447 checkGLcall("glActiveTextureARB");
3449 if(stateblock->textures[sampler]) {
3450 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3451 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3452 tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3453 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3454 basetexture_apply_state_changes(stateblock->textures[sampler],
3455 stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3457 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3458 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3459 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3460 GL_TEXTURE_LOD_BIAS_EXT,
3461 tmpvalue.f);
3462 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3465 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3467 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3468 /* If color keying is enabled update the alpha test, it depends on the existence
3469 * of a color key in stage 0
3471 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3475 /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3476 if (!tex_impl->baseTexture.pow2Matrix_identity) {
3477 IWineD3DDeviceImpl* d3ddevice = stateblock->wineD3DDevice;
3478 d3ddevice->shader_backend->shader_load_np2fixup_constants(
3479 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3481 } else if(mapped_stage < GL_LIMITS(textures)) {
3482 if(sampler < stateblock->lowest_disabled_stage) {
3483 /* TODO: What should I do with pixel shaders here ??? */
3484 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3485 /* If color keying is enabled update the alpha test, it depends on the existence
3486 * of a color key in stage 0
3488 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3490 } /* Otherwise tex_colorop disables the stage */
3491 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3492 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3496 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3498 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3499 BOOL use_pshader = use_ps(stateblock);
3500 BOOL use_vshader = use_vs(stateblock);
3501 int i;
3503 if (use_pshader) {
3504 if(!context->last_was_pshader) {
3505 /* Former draw without a pixel shader, some samplers
3506 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3507 * make sure to enable them
3509 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3510 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3511 sampler(STATE_SAMPLER(i), stateblock, context);
3514 context->last_was_pshader = TRUE;
3515 } else {
3516 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3517 * if a different texture was bound. I don't have to do anything.
3520 } else {
3521 /* Disabled the pixel shader - color ops weren't applied
3522 * while it was enabled, so re-apply them.
3524 for(i=0; i < MAX_TEXTURES; i++) {
3525 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3526 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3527 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3530 context->last_was_pshader = FALSE;
3533 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3534 device->shader_backend->shader_select(context, use_pshader, use_vshader);
3536 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3537 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3542 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3544 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3545 if (stateblock->pixelShader && stage != 0
3546 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage)))
3548 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3549 * anyway
3551 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3552 !isStateDirty(context, STATE_PIXELSHADER)) {
3553 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3558 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3560 /* This function is called by transform_view below if the view matrix was changed too
3562 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3563 * does not always update the world matrix, only on a switch between transformed
3564 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3565 * draw, but that should be rather rare and cheaper in total.
3567 glMatrixMode(GL_MODELVIEW);
3568 checkGLcall("glMatrixMode");
3570 if(context->last_was_rhw) {
3571 glLoadIdentity();
3572 checkGLcall("glLoadIdentity()");
3573 } else {
3574 /* In the general case, the view matrix is the identity matrix */
3575 if (stateblock->wineD3DDevice->view_ident) {
3576 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3577 checkGLcall("glLoadMatrixf");
3578 } else {
3579 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3580 checkGLcall("glLoadMatrixf");
3581 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3582 checkGLcall("glMultMatrixf");
3587 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3589 UINT index = state - STATE_CLIPPLANE(0);
3591 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3592 return;
3595 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3596 if(!use_vs(stateblock)) {
3597 glMatrixMode(GL_MODELVIEW);
3598 glPushMatrix();
3599 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3600 } else {
3601 /* with vertex shaders, clip planes are not transformed in direct3d,
3602 * in OpenGL they are still transformed by the model view.
3603 * Use this to swap the y coordinate if necessary
3605 glMatrixMode(GL_MODELVIEW);
3606 glPushMatrix();
3607 glLoadIdentity();
3608 if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f);
3611 TRACE("Clipplane [%f,%f,%f,%f]\n",
3612 stateblock->clipplane[index][0],
3613 stateblock->clipplane[index][1],
3614 stateblock->clipplane[index][2],
3615 stateblock->clipplane[index][3]);
3616 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3617 checkGLcall("glClipPlane");
3619 glPopMatrix();
3622 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3624 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3625 GLenum glMat;
3626 TRACE("Setting world matrix %d\n", matrix);
3628 if(matrix >= GL_LIMITS(blends)) {
3629 WARN("Unsupported blend matrix set\n");
3630 return;
3631 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3632 return;
3635 /* GL_MODELVIEW0_ARB: 0x1700
3636 * GL_MODELVIEW1_ARB: 0x850a
3637 * GL_MODELVIEW2_ARB: 0x8722
3638 * GL_MODELVIEW3_ARB: 0x8723
3639 * etc
3640 * GL_MODELVIEW31_ARB: 0x873F
3642 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3643 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3645 glMatrixMode(glMat);
3646 checkGLcall("glMatrixMode(glMat)");
3648 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3649 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3651 if(stateblock->wineD3DDevice->view_ident) {
3652 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3653 checkGLcall("glLoadMatrixf");
3654 } else {
3655 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3656 checkGLcall("glLoadMatrixf");
3657 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3658 checkGLcall("glMultMatrixf");
3662 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3664 static BOOL once = FALSE;
3666 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3667 case WINED3DVBF_1WEIGHTS:
3668 case WINED3DVBF_2WEIGHTS:
3669 case WINED3DVBF_3WEIGHTS:
3670 if(!once) {
3671 once = TRUE;
3672 /* TODO: Implement vertex blending in drawStridedSlow */
3673 FIXME("Vertex blending enabled, but not supported by hardware\n");
3675 break;
3677 case WINED3DVBF_TWEENING:
3678 WARN("Tweening not supported yet\n");
3682 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3684 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3686 switch(val) {
3687 case WINED3DVBF_1WEIGHTS:
3688 case WINED3DVBF_2WEIGHTS:
3689 case WINED3DVBF_3WEIGHTS:
3690 glEnable(GL_VERTEX_BLEND_ARB);
3691 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3693 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3694 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3696 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3698 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3699 unsigned int i;
3700 for(i = 1; i < GL_LIMITS(blends); i++) {
3701 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3702 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3705 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3707 break;
3709 case WINED3DVBF_DISABLE:
3710 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3711 glDisable(GL_VERTEX_BLEND_ARB);
3712 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3713 break;
3715 case WINED3DVBF_TWEENING:
3716 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3717 * vertex weights in the vertices?
3718 * For now we don't report that as supported, so a warn should suffice
3720 WARN("Tweening not supported yet\n");
3721 break;
3725 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3727 unsigned int k;
3729 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3730 * NOTE: We have to reset the positions even if the light/plane is not currently
3731 * enabled, since the call to enable it will not reset the position.
3732 * NOTE2: Apparently texture transforms do NOT need reapplying
3735 const PLIGHTINFOEL *light = NULL;
3737 glMatrixMode(GL_MODELVIEW);
3738 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3739 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3740 checkGLcall("glLoadMatrixf(...)");
3742 /* Reset lights. TODO: Call light apply func */
3743 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3744 light = stateblock->activeLights[k];
3745 if(!light) continue;
3746 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3747 checkGLcall("glLightfv posn");
3748 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3749 checkGLcall("glLightfv dirn");
3752 /* Reset Clipping Planes */
3753 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3754 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3755 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3759 if(context->last_was_rhw) {
3760 glLoadIdentity();
3761 checkGLcall("glLoadIdentity()");
3762 /* No need to update the world matrix, the identity is fine */
3763 return;
3766 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3767 * No need to do it here if the state is scheduled for update.
3769 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3770 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3773 /* Avoid looping over a number of matrices if the app never used the functionality */
3774 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3775 for(k = 1; k < GL_LIMITS(blends); k++) {
3776 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3777 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3783 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3785 glMatrixMode(GL_PROJECTION);
3786 checkGLcall("glMatrixMode(GL_PROJECTION)");
3787 glLoadIdentity();
3788 checkGLcall("glLoadIdentity");
3790 if(context->last_was_rhw) {
3791 double X, Y, height, width, minZ, maxZ;
3793 X = stateblock->viewport.X;
3794 Y = stateblock->viewport.Y;
3795 height = stateblock->viewport.Height;
3796 width = stateblock->viewport.Width;
3797 minZ = stateblock->viewport.MinZ;
3798 maxZ = stateblock->viewport.MaxZ;
3800 if(!stateblock->wineD3DDevice->untransformed) {
3801 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3802 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3803 * suppress depth clipping. This can be done because it is an orthogonal projection and
3804 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3805 * Persia 3D need this.
3807 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3808 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3809 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3810 * to the viewer.
3812 * Also note that this breaks z comparison against z values filled in with clear,
3813 * but no app depending on that and disabled clipping has been found yet. Comparing
3814 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3815 * surface removal.
3817 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3818 * but this would break Z buffer operation. Raising the range to something less than
3819 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3820 * problem either.
3822 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3823 if (context->render_offscreen)
3825 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3826 } else {
3827 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3829 } else {
3830 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3831 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3832 * unmodified to opengl.
3834 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3835 * replacement shader.
3837 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3838 if (context->render_offscreen)
3840 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3841 } else {
3842 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3845 checkGLcall("glOrtho");
3847 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3848 glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f);
3849 checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)");
3851 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3852 * render everything upside down when rendering offscreen. */
3853 if (context->render_offscreen)
3855 glScalef(1.0f, -1.0f, 1.0f);
3856 checkGLcall("glScalef");
3858 } else {
3859 /* The rule is that the window coordinate 0 does not correspond to the
3860 beginning of the first pixel, but the center of the first pixel.
3861 As a consequence if you want to correctly draw one line exactly from
3862 the left to the right end of the viewport (with all matrices set to
3863 be identity), the x coords of both ends of the line would be not
3864 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3865 instead.
3867 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3868 divide by the Width/Height, so we need the half range(1.0) to translate by
3869 half a pixel.
3871 The other fun is that d3d's output z range after the transformation is [0;1],
3872 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3873 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3874 of Z buffer precision and the clear values do not match in the z test. Thus scale
3875 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3879 * Careful with the order of operations here, we're essentially working backwards:
3880 * x = x + 1/w;
3881 * y = (y - 1/h) * flip;
3882 * z = z * 2 - 1;
3884 * Becomes:
3885 * glTranslatef(0.0, 0.0, -1.0);
3886 * glScalef(1.0, 1.0, 2.0);
3888 * glScalef(1.0, flip, 1.0);
3889 * glTranslatef(1/w, -1/h, 0.0);
3891 * This is equivalent to:
3892 * glTranslatef(1/w, -flip/h, -1.0)
3893 * glScalef(1.0, flip, 2.0);
3896 /* Translate by slightly less than a half pixel to force a top-left
3897 * filling convention. We want the difference to be large enough that
3898 * it doesn't get lost due to rounding inside the driver, but small
3899 * enough to prevent it from interfering with any anti-aliasing. */
3900 GLfloat xoffset = (63.0f / 64.0f) / stateblock->viewport.Width;
3901 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
3903 if (context->render_offscreen)
3905 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3906 * render everything upside down when rendering offscreen. */
3907 glTranslatef(xoffset, -yoffset, -1.0f);
3908 checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)");
3909 glScalef(1.0f, -1.0f, 2.0f);
3910 } else {
3911 glTranslatef(xoffset, yoffset, -1.0f);
3912 checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)");
3913 glScalef(1.0f, 1.0f, 2.0f);
3915 checkGLcall("glScalef");
3917 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3918 checkGLcall("glLoadMatrixf");
3922 /* This should match any arrays loaded in loadVertexData.
3923 * stateblock impl is required for GL_SUPPORT
3924 * TODO: Only load / unload arrays if we have to.
3926 static inline void unloadVertexData(const struct wined3d_context *context)
3928 glDisableClientState(GL_VERTEX_ARRAY);
3929 glDisableClientState(GL_NORMAL_ARRAY);
3930 glDisableClientState(GL_COLOR_ARRAY);
3931 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3932 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3934 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3935 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3937 unloadTexCoords(context);
3940 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context, int i)
3942 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3943 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3945 context->numbered_array_mask &= ~(1 << i);
3948 /* This should match any arrays loaded in loadNumberedArrays
3949 * TODO: Only load / unload arrays if we have to.
3951 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3953 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3954 GLint maxAttribs = 16;
3955 int i;
3957 /* Leave all the attribs disabled */
3958 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3959 /* MESA does not support it right not */
3960 if (glGetError() != GL_NO_ERROR)
3961 maxAttribs = 16;
3962 for (i = 0; i < maxAttribs; ++i) {
3963 unload_numbered_array(stateblock, context, i);
3967 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3968 const struct wined3d_stream_info *stream_info, struct wined3d_context *context)
3970 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3971 int i;
3972 const UINT *offset = stateblock->streamOffset;
3973 struct wined3d_buffer *vb;
3974 DWORD_PTR shift_index;
3976 /* Default to no instancing */
3977 stateblock->wineD3DDevice->instancedDraw = FALSE;
3979 for (i = 0; i < MAX_ATTRIBS; i++) {
3980 if (!(stream_info->use_map & (1 << i)))
3982 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3983 continue;
3986 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3987 if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
3989 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3990 stateblock->wineD3DDevice->instancedDraw = TRUE;
3991 continue;
3994 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
3996 if (stream_info->elements[i].stride)
3998 if (curVBO != stream_info->elements[i].buffer_object)
4000 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
4001 checkGLcall("glBindBufferARB");
4002 curVBO = stream_info->elements[i].buffer_object;
4004 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4005 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
4006 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
4007 * vbo we won't be load converted attributes anyway
4009 if (curVBO && vb->conversion_shift)
4011 TRACE("Loading attribute from shifted buffer\n");
4012 TRACE("Attrib %d has original stride %d, new stride %d\n",
4013 i, stream_info->elements[i].stride, vb->conversion_stride);
4014 TRACE("Original offset %p, additional offset 0x%08x\n",
4015 stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
4016 TRACE("Opengl type %#x\n", stream_info->elements[i].format_desc->gl_vtx_type);
4017 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
4018 shift_index = shift_index % stream_info->elements[i].stride;
4019 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4020 stream_info->elements[i].format_desc->gl_vtx_type,
4021 stream_info->elements[i].format_desc->gl_normalized,
4022 vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
4023 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4024 + offset[stream_info->elements[i].stream_idx]));
4026 } else {
4027 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4028 stream_info->elements[i].format_desc->gl_vtx_type,
4029 stream_info->elements[i].format_desc->gl_normalized,
4030 stream_info->elements[i].stride, stream_info->elements[i].data
4031 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4032 + offset[stream_info->elements[i].stream_idx]));
4035 if (!(context->numbered_array_mask & (1 << i)))
4037 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
4038 context->numbered_array_mask |= (1 << i);
4040 } else {
4041 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
4042 * set up the attribute statically. But we have to figure out the system memory address.
4044 const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
4045 if (stream_info->elements[i].buffer_object)
4047 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4048 ptr += (long) buffer_get_sysmem(vb);
4051 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
4053 switch (stream_info->elements[i].format_desc->format)
4055 case WINED3DFMT_R32_FLOAT:
4056 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
4057 break;
4058 case WINED3DFMT_R32G32_FLOAT:
4059 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
4060 break;
4061 case WINED3DFMT_R32G32B32_FLOAT:
4062 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
4063 break;
4064 case WINED3DFMT_R32G32B32A32_FLOAT:
4065 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
4066 break;
4068 case WINED3DFMT_R8G8B8A8_UINT:
4069 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4070 break;
4071 case WINED3DFMT_B8G8R8A8_UNORM:
4072 if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
4074 const DWORD *src = (const DWORD *)ptr;
4075 DWORD c = *src & 0xff00ff00;
4076 c |= (*src & 0xff0000) >> 16;
4077 c |= (*src & 0xff) << 16;
4078 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
4079 break;
4081 /* else fallthrough */
4082 case WINED3DFMT_R8G8B8A8_UNORM:
4083 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4084 break;
4086 case WINED3DFMT_R16G16_SINT:
4087 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4088 break;
4089 case WINED3DFMT_R16G16B16A16_SINT:
4090 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4091 break;
4093 case WINED3DFMT_R16G16_SNORM:
4095 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4096 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4097 break;
4099 case WINED3DFMT_R16G16_UNORM:
4101 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4102 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4103 break;
4105 case WINED3DFMT_R16G16B16A16_SNORM:
4106 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4107 break;
4108 case WINED3DFMT_R16G16B16A16_UNORM:
4109 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4110 break;
4112 case WINED3DFMT_R10G10B10A2_UINT:
4113 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4114 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4115 break;
4116 case WINED3DFMT_R10G10B10A2_SNORM:
4117 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4118 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4119 break;
4121 case WINED3DFMT_R16G16_FLOAT:
4122 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4123 * byte float according to the IEEE standard
4125 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4126 break;
4127 case WINED3DFMT_R16G16B16A16_FLOAT:
4128 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4129 break;
4131 default:
4132 ERR("Unexpected declaration in stride 0 attributes\n");
4133 break;
4138 checkGLcall("Loading numbered arrays");
4141 /* Used from 2 different functions, and too big to justify making it inlined */
4142 static void loadVertexData(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
4143 const struct wined3d_stream_info *si)
4145 const UINT *offset = stateblock->streamOffset;
4146 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4147 const struct wined3d_stream_info_element *e;
4149 TRACE("Using fast vertex array code\n");
4151 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4152 stateblock->wineD3DDevice->instancedDraw = FALSE;
4154 /* Blend Data ---------------------------------------------- */
4155 if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
4156 || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4158 e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4160 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4161 TRACE("Blend %d %p %d\n", e->format_desc->component_count,
4162 e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4164 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4165 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4167 GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1));
4169 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4170 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4171 sd->u.s.blendWeights.dwStride,
4172 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4174 if (curVBO != e->buffer_object)
4176 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4177 checkGLcall("glBindBufferARB");
4178 curVBO = e->buffer_object;
4181 GL_EXTCALL(glWeightPointerARB)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4182 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4184 checkGLcall("glWeightPointerARB");
4186 if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4188 static BOOL warned;
4189 if (!warned)
4191 FIXME("blendMatrixIndices support\n");
4192 warned = TRUE;
4195 } else {
4196 /* TODO: support blends in drawStridedSlow
4197 * No need to write a FIXME here, this is done after the general vertex decl decoding
4199 WARN("unsupported blending in openGl\n");
4201 } else {
4202 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4203 static const GLbyte one = 1;
4204 GL_EXTCALL(glWeightbvARB(1, &one));
4205 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4209 /* Point Size ----------------------------------------------*/
4210 if (si->use_map & (1 << WINED3D_FFP_PSIZE))
4212 /* no such functionality in the fixed function GL pipeline */
4213 TRACE("Cannot change ptSize here in openGl\n");
4214 /* TODO: Implement this function in using shaders if they are available */
4217 /* Vertex Pointers -----------------------------------------*/
4218 if (si->use_map & (1 << WINED3D_FFP_POSITION))
4220 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data));
4222 e = &si->elements[WINED3D_FFP_POSITION];
4223 if (curVBO != e->buffer_object)
4225 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4226 checkGLcall("glBindBufferARB");
4227 curVBO = e->buffer_object;
4230 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4231 handling for rhw mode should not impact screen position whereas in GL it does.
4232 This may result in very slightly distorted textures in rhw mode.
4233 There's always the other option of fixing the view matrix to
4234 prevent w from having any effect.
4236 This only applies to user pointer sources, in VBOs the vertices are fixed up
4238 if (!e->buffer_object)
4240 glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride,
4241 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4242 } else {
4243 glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4244 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4246 checkGLcall("glVertexPointer(...)");
4247 glEnableClientState(GL_VERTEX_ARRAY);
4248 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4251 /* Normals -------------------------------------------------*/
4252 if (si->use_map & (1 << WINED3D_FFP_NORMAL))
4254 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data));
4256 e = &si->elements[WINED3D_FFP_NORMAL];
4257 if (curVBO != e->buffer_object)
4259 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4260 checkGLcall("glBindBufferARB");
4261 curVBO = e->buffer_object;
4263 glNormalPointer(e->format_desc->gl_vtx_type, e->stride,
4264 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4265 checkGLcall("glNormalPointer(...)");
4266 glEnableClientState(GL_NORMAL_ARRAY);
4267 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4269 } else {
4270 glNormal3f(0, 0, 0);
4271 checkGLcall("glNormal3f(0, 0, 0)");
4274 /* Diffuse Colour --------------------------------------------*/
4275 /* WARNING: Data here MUST be in RGBA format, so cannot */
4276 /* go directly into fast mode from app pgm, because */
4277 /* directx requires data in BGRA format. */
4278 /* currently fixupVertices swizzles the format, but this isn't*/
4279 /* very practical when using VBOs */
4280 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4281 /* , or the user doesn't care and wants the speed advantage */
4283 if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
4285 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4287 e = &si->elements[WINED3D_FFP_DIFFUSE];
4288 if (curVBO != e->buffer_object)
4290 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4291 checkGLcall("glBindBufferARB");
4292 curVBO = e->buffer_object;
4295 glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4296 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4297 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4298 glEnableClientState(GL_COLOR_ARRAY);
4299 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4301 } else {
4302 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4303 checkGLcall("glColor4f(1, 1, 1, 1)");
4306 /* Specular Colour ------------------------------------------*/
4307 if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
4309 TRACE("setting specular colour\n");
4310 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4312 e = &si->elements[WINED3D_FFP_SPECULAR];
4313 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4314 GLenum type = e->format_desc->gl_vtx_type;
4315 GLint format = e->format_desc->gl_vtx_format;
4317 if (curVBO != e->buffer_object)
4319 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4320 checkGLcall("glBindBufferARB");
4321 curVBO = e->buffer_object;
4324 if(format != 4 || (GLINFO_LOCATION.quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
4326 /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
4327 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
4328 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
4329 * 4 component secondary colors use it
4331 GL_EXTCALL(glSecondaryColorPointerEXT)(format, type,
4332 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4333 checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
4335 else
4337 switch(type)
4339 case GL_UNSIGNED_BYTE:
4340 GL_EXTCALL(glSecondaryColorPointerEXT)(3, GL_UNSIGNED_BYTE,
4341 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4342 checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
4343 break;
4345 default:
4346 FIXME("Add 4 component specular color pointers for type %x\n", type);
4347 /* Make sure that the right color component is dropped */
4348 GL_EXTCALL(glSecondaryColorPointerEXT)(3, type,
4349 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4350 checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
4353 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4354 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4355 } else {
4357 /* Missing specular color is not critical, no warnings */
4358 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4361 } else {
4362 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4363 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4364 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4365 } else {
4367 /* Missing specular color is not critical, no warnings */
4368 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4372 /* Texture coords -------------------------------------------*/
4373 loadTexCoords(context, stateblock, si, &curVBO);
4376 static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations)
4378 /* Dump out what parts we have supplied */
4379 TRACE("Strided Data:\n");
4380 TRACE_STRIDED((dataLocations), WINED3D_FFP_POSITION);
4381 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDWEIGHT);
4382 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDINDICES);
4383 TRACE_STRIDED((dataLocations), WINED3D_FFP_NORMAL);
4384 TRACE_STRIDED((dataLocations), WINED3D_FFP_PSIZE);
4385 TRACE_STRIDED((dataLocations), WINED3D_FFP_DIFFUSE);
4386 TRACE_STRIDED((dataLocations), WINED3D_FFP_SPECULAR);
4387 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD0);
4388 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD1);
4389 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD2);
4390 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD3);
4391 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD4);
4392 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD5);
4393 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD6);
4394 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD7);
4396 return;
4399 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4401 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4402 BOOL fixup = FALSE;
4403 struct wined3d_stream_info *dataLocations = &device->strided_streams;
4404 BOOL useVertexShaderFunction;
4405 BOOL load_numbered = FALSE;
4406 BOOL load_named = FALSE;
4408 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4410 if(device->up_strided) {
4411 /* Note: this is a ddraw fixed-function code path */
4412 TRACE("================ Strided Input ===================\n");
4413 device_stream_info_from_strided(device, device->up_strided, dataLocations);
4415 if(TRACE_ON(d3d)) {
4416 drawPrimitiveTraceDataLocations(dataLocations);
4418 } else {
4419 /* Note: This is a fixed function or shader codepath.
4420 * This means it must handle both types of strided data.
4421 * Shaders must go through here to zero the strided data, even if they
4422 * don't set any declaration at all
4424 TRACE("================ Vertex Declaration ===================\n");
4425 device_stream_info_from_declaration(device, useVertexShaderFunction, dataLocations, &fixup);
4428 if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4430 if(useVertexShaderFunction) {
4431 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4432 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4433 device->useDrawStridedSlow = TRUE;
4434 } else {
4435 load_numbered = TRUE;
4436 device->useDrawStridedSlow = FALSE;
4439 else
4441 WORD slow_mask = (1 << WINED3D_FFP_PSIZE);
4442 slow_mask |= -!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
4444 if (fixup || (!dataLocations->position_transformed
4445 && !(dataLocations->use_map & slow_mask)))
4447 /* Load the vertex data using named arrays */
4448 load_named = TRUE;
4449 device->useDrawStridedSlow = FALSE;
4451 else
4453 TRACE("Not loading vertex data\n");
4454 device->useDrawStridedSlow = TRUE;
4458 if (context->numberedArraysLoaded && !load_numbered)
4460 unloadNumberedArrays(stateblock, context);
4461 context->numberedArraysLoaded = FALSE;
4462 context->numbered_array_mask = 0;
4464 else if (context->namedArraysLoaded)
4466 unloadVertexData(context);
4467 context->namedArraysLoaded = FALSE;
4470 if (load_numbered)
4472 TRACE("Loading numbered arrays\n");
4473 loadNumberedArrays(stateblock, dataLocations, context);
4474 context->numberedArraysLoaded = TRUE;
4476 else if (load_named)
4478 TRACE("Loading vertex data\n");
4479 loadVertexData(context, stateblock, dataLocations);
4480 context->namedArraysLoaded = TRUE;
4484 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4486 BOOL updateFog = FALSE;
4487 BOOL useVertexShaderFunction = use_vs(stateblock);
4488 BOOL usePixelShaderFunction = use_ps(stateblock);
4489 BOOL transformed;
4490 /* Some stuff is in the device until we have per context tracking */
4491 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4492 BOOL wasrhw = context->last_was_rhw;
4493 unsigned int i;
4495 transformed = device->strided_streams.position_transformed;
4496 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4497 updateFog = TRUE;
4500 /* Reapply lighting if it is not scheduled for reapplication already */
4501 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4502 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4505 if (transformed) {
4506 context->last_was_rhw = TRUE;
4507 } else {
4509 /* Untransformed, so relies on the view and projection matrices */
4510 context->last_was_rhw = FALSE;
4511 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4512 device->untransformed = TRUE;
4514 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4515 * Not needed as long as only hw shaders are supported
4518 /* This sets the shader output position correction constants.
4519 * TODO: Move to the viewport state
4521 if (useVertexShaderFunction)
4523 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4524 device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f;
4525 device->posFixup[3] = device->posFixup[1] * yoffset;
4529 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4530 * off this function will be called again anyway to make sure they're properly set
4532 if(!useVertexShaderFunction) {
4533 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4534 * or transformed / untransformed was switched
4536 if(wasrhw != context->last_was_rhw &&
4537 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4538 !isStateDirty(context, STATE_VIEWPORT)) {
4539 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4541 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4542 * mode.
4544 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4545 * this check will fail and the matrix not applied again. This is OK because a simple
4546 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4547 * needs of the vertex declaration.
4549 * World and view matrix go into the same gl matrix, so only apply them when neither is
4550 * dirty
4552 if(transformed != wasrhw &&
4553 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4554 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4555 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4558 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4559 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4562 if(context->last_was_vshader) {
4563 updateFog = TRUE;
4564 if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4565 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4567 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4568 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4571 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4572 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4574 } else {
4575 if(!context->last_was_vshader) {
4576 static BOOL warned = FALSE;
4577 if(!device->vs_clipping) {
4578 /* Disable all clip planes to get defined results on all drivers. See comment in the
4579 * state_clipping state handler
4581 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4582 glDisable(GL_CLIP_PLANE0 + i);
4583 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4586 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4587 FIXME("Clipping not supported with vertex shaders\n");
4588 warned = TRUE;
4591 if(wasrhw) {
4592 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4593 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4594 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4595 * fixed function vertex processing states back in a sane state before switching to shaders
4597 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4598 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4600 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4601 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4604 updateFog = TRUE;
4606 /* Vertex shader clipping ignores the view matrix. Update all clipplanes
4607 * (Note: ARB shaders can read the clip planes for clipping emulation even if
4608 * device->vs_clipping is false.
4610 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4611 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4616 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4617 * application
4619 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4620 device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction);
4622 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4623 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4627 context->last_was_vshader = useVertexShaderFunction;
4629 if(updateFog) {
4630 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4632 if(!useVertexShaderFunction) {
4633 int i;
4634 for(i = 0; i < MAX_TEXTURES; i++) {
4635 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4636 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4642 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4644 UINT width, height;
4645 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4646 WINED3DVIEWPORT vp = stateblock->viewport;
4648 if(vp.Width > target->currentDesc.Width) vp.Width = target->currentDesc.Width;
4649 if(vp.Height > target->currentDesc.Height) vp.Height = target->currentDesc.Height;
4651 glDepthRange(vp.MinZ, vp.MaxZ);
4652 checkGLcall("glDepthRange");
4653 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4655 if (context->render_offscreen)
4657 glViewport(vp.X, vp.Y, vp.Width, vp.Height);
4658 } else {
4659 target->get_drawable_size(context, &width, &height);
4661 glViewport(vp.X,
4662 (height - (vp.Y + vp.Height)),
4663 vp.Width, vp.Height);
4666 checkGLcall("glViewport");
4669 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4671 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4673 stateblock->wineD3DDevice->posFixup[2] = (63.0f / 64.0f) / stateblock->viewport.Width;
4674 stateblock->wineD3DDevice->posFixup[3] = stateblock->wineD3DDevice->posFixup[1] * yoffset;
4676 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4677 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4679 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4680 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4684 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4686 UINT Index = state - STATE_ACTIVELIGHT(0);
4687 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4689 if(!lightInfo) {
4690 glDisable(GL_LIGHT0 + Index);
4691 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4692 } else {
4693 float quad_att;
4694 float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
4696 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4697 glMatrixMode(GL_MODELVIEW);
4698 glPushMatrix();
4699 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4701 /* Diffuse: */
4702 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4703 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4704 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4705 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4706 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4707 checkGLcall("glLightfv");
4709 /* Specular */
4710 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4711 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4712 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4713 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4714 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4715 checkGLcall("glLightfv");
4717 /* Ambient */
4718 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4719 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4720 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4721 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4722 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4723 checkGLcall("glLightfv");
4725 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4726 quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4727 } else {
4728 quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */
4731 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4732 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4733 * Attenuation0 to NaN and crashes in the gl lib
4736 switch (lightInfo->OriginalParms.Type) {
4737 case WINED3DLIGHT_POINT:
4738 /* Position */
4739 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4740 checkGLcall("glLightfv");
4741 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4742 checkGLcall("glLightf");
4743 /* Attenuation - Are these right? guessing... */
4744 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4745 checkGLcall("glLightf");
4746 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4747 checkGLcall("glLightf");
4748 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4749 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4750 checkGLcall("glLightf");
4751 /* FIXME: Range */
4752 break;
4754 case WINED3DLIGHT_SPOT:
4755 /* Position */
4756 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4757 checkGLcall("glLightfv");
4758 /* Direction */
4759 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4760 checkGLcall("glLightfv");
4761 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4762 checkGLcall("glLightf");
4763 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4764 checkGLcall("glLightf");
4765 /* Attenuation - Are these right? guessing... */
4766 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4767 checkGLcall("glLightf");
4768 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4769 checkGLcall("glLightf");
4770 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4771 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4772 checkGLcall("glLightf");
4773 /* FIXME: Range */
4774 break;
4776 case WINED3DLIGHT_DIRECTIONAL:
4777 /* Direction */
4778 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4779 checkGLcall("glLightfv");
4780 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4781 checkGLcall("glLightf");
4782 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4783 checkGLcall("glLightf");
4784 break;
4786 default:
4787 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4790 /* Restore the modelview matrix */
4791 glPopMatrix();
4793 glEnable(GL_LIGHT0 + Index);
4794 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4797 return;
4800 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4802 RECT *pRect = &stateblock->scissorRect;
4803 UINT height;
4804 UINT width;
4805 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4807 target->get_drawable_size(context, &width, &height);
4808 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4809 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4811 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4812 pRect->right - pRect->left, pRect->bottom - pRect->top);
4814 if (context->render_offscreen)
4816 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4817 } else {
4818 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4820 checkGLcall("glScissor");
4823 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4825 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4826 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4827 } else {
4828 struct wined3d_buffer *ib = (struct wined3d_buffer *) stateblock->pIndexData;
4829 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4833 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4835 if (context->render_offscreen)
4837 glFrontFace(GL_CCW);
4838 checkGLcall("glFrontFace(GL_CCW)");
4839 } else {
4840 glFrontFace(GL_CW);
4841 checkGLcall("glFrontFace(GL_CW)");
4845 const struct StateEntryTemplate misc_state_template[] = {
4846 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4847 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4848 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4849 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4850 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4851 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4852 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4853 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4854 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4855 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4856 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4857 { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4858 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
4859 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
4860 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4861 * vshader loadings are untied from each other
4863 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4864 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4865 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4866 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4867 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4868 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4869 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4870 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4871 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4872 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4873 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4874 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4875 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4876 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4877 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4878 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4879 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4880 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4881 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4882 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4883 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4884 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4885 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4886 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4887 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4888 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4889 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4890 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4891 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4892 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4893 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4894 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4895 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4896 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4897 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4898 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4899 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4900 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4901 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4902 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4903 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4904 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4905 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4906 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4907 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4908 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4909 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4910 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4911 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4912 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4914 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
4915 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4916 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE },
4917 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE },
4918 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE },
4919 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE },
4920 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE },
4921 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE },
4922 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
4923 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE },
4924 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE },
4925 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE },
4926 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE },
4927 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE },
4928 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4929 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4930 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4931 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4932 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE },
4933 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE },
4934 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE },
4935 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE },
4936 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE },
4937 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE },
4938 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE },
4939 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE },
4940 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE },
4941 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE },
4942 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE },
4943 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE },
4944 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE },
4945 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4946 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4947 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4948 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4949 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4950 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4951 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4952 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4953 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE },
4954 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4955 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4956 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4957 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4958 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4959 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4960 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4961 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4962 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4963 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4964 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4965 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4966 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4967 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4968 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4969 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4970 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4971 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4972 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4973 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4974 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4975 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE },
4976 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE },
4977 { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE },
4978 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE },
4979 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE },
4980 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE },
4981 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE },
4982 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4983 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4984 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4985 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4986 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4987 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4988 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4989 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4990 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE },
4991 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE },
4992 { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE },
4993 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4994 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4995 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE },
4996 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE },
4997 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
4998 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4999 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5000 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5001 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
5002 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE },
5003 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
5004 /* Samplers */
5005 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE },
5006 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE },
5007 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE },
5008 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE },
5009 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE },
5010 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE },
5011 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE },
5012 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE },
5013 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE },
5014 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE },
5015 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE },
5016 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE },
5017 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE },
5018 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE },
5019 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE },
5020 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE },
5021 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE },
5022 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE },
5023 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE },
5024 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
5025 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5028 const struct StateEntryTemplate ffp_vertexstate_template[] = {
5029 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5030 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5031 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5032 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5033 /* Clip planes */
5034 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
5035 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
5036 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
5037 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
5038 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
5039 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
5040 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
5041 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
5042 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE },
5043 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE },
5044 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE },
5045 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE },
5046 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE },
5047 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE },
5048 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE },
5049 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE },
5050 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE },
5051 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE },
5052 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE },
5053 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE },
5054 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE },
5055 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE },
5056 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE },
5057 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE },
5058 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE },
5059 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE },
5060 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE },
5061 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE },
5062 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE },
5063 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE },
5064 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE },
5065 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE },
5066 /* Lights */
5067 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE },
5068 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE },
5069 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE },
5070 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE },
5071 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE },
5072 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE },
5073 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE },
5074 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE },
5075 /* Viewport */
5076 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE },
5077 /* Transform states follow */
5078 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE },
5079 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE },
5080 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5081 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5082 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5083 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5084 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5085 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5086 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5087 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE },
5208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE },
5209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE },
5210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE },
5211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE },
5212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE },
5213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE },
5214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE },
5215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE },
5216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE },
5217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE },
5218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE },
5219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE },
5220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE },
5221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE },
5222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE },
5223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE },
5224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE },
5225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE },
5226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE },
5227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE },
5228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE },
5229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE },
5230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE },
5231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE },
5232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE },
5233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE },
5234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE },
5235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE },
5236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE },
5237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE },
5238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE },
5239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE },
5240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE },
5241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE },
5242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE },
5243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE },
5244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE },
5245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE },
5246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE },
5247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE },
5248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE },
5249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE },
5250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE },
5251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE },
5252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE },
5253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE },
5254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE },
5255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE },
5256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE },
5257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE },
5258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE },
5259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE },
5260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE },
5261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE },
5262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE },
5263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE },
5264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE },
5265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE },
5266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE },
5267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE },
5268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE },
5269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE },
5270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE },
5271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE },
5272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE },
5273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE },
5274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE },
5275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE },
5276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE },
5277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE },
5278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE },
5279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE },
5280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE },
5281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE },
5282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE },
5283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE },
5284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE },
5285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE },
5286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE },
5287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE },
5288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE },
5289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE },
5290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE },
5291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE },
5292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE },
5293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE },
5294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE },
5295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE },
5296 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE },
5297 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE },
5298 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE },
5299 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE },
5300 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE },
5301 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE },
5302 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE },
5303 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE },
5304 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE },
5305 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE },
5306 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE },
5307 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE },
5308 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE },
5309 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE },
5310 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE },
5311 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE },
5312 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE },
5313 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE },
5314 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE },
5315 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE },
5316 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE },
5317 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE },
5318 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE },
5319 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE },
5320 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE },
5321 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE },
5322 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE },
5323 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE },
5324 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE },
5325 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE },
5326 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE },
5327 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE },
5328 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE },
5329 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE },
5330 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE },
5331 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE },
5332 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE },
5333 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE },
5334 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE },
5335 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE },
5336 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE },
5337 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE },
5338 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE },
5339 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE },
5340 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE },
5341 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE },
5342 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE },
5343 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE },
5344 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5345 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5346 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5347 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5348 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5349 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5350 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5351 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5352 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5353 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5354 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5355 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5356 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5357 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5358 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5359 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5360 /* Fog */
5361 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5362 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5363 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5364 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5365 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE },
5366 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5367 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5368 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE },
5369 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE },
5370 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5371 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE },
5372 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE },
5373 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5374 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5375 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5376 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5377 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5378 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE },
5379 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5380 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5381 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5382 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5383 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5384 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE },
5385 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5386 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5387 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5388 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5389 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5390 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5391 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5392 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5393 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5394 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5396 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5397 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5398 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5399 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5400 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5401 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5402 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5403 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5404 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5405 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5406 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5407 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5408 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5409 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5410 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5411 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5412 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5413 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5414 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5415 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5416 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5417 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5418 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5419 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5420 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5423 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5424 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5425 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5426 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5427 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5428 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5429 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5430 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5431 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5432 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5433 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5434 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5435 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5436 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5437 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5438 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5439 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5440 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5441 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5442 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5443 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5444 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5445 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5446 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5447 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5448 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5449 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5450 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5451 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5452 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5453 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5454 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5455 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5456 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5457 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5458 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5459 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5460 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5461 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5462 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5463 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5464 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5465 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5466 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5467 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5468 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5469 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5470 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5471 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5472 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5473 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5474 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5475 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5476 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5477 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5478 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5479 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5480 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5481 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5482 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5483 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5484 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5485 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5486 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5487 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5488 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5489 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5490 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5491 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5492 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5493 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5494 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5495 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5496 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5497 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5498 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5499 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5500 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5501 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5502 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5503 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5504 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5505 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5506 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE },
5507 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE },
5508 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE },
5509 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE },
5510 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5511 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5512 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5513 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5514 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5515 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE },
5516 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE },
5517 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE },
5518 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE },
5519 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE },
5520 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE },
5521 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE },
5522 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE },
5523 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5525 #undef GLINFO_LOCATION
5527 #define GLINFO_LOCATION (*gl_info)
5528 /* Context activation is done by the caller. */
5529 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5531 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype,
5532 const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps)
5534 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5535 WINED3DTEXOPCAPS_ADDSIGNED |
5536 WINED3DTEXOPCAPS_ADDSIGNED2X |
5537 WINED3DTEXOPCAPS_MODULATE |
5538 WINED3DTEXOPCAPS_MODULATE2X |
5539 WINED3DTEXOPCAPS_MODULATE4X |
5540 WINED3DTEXOPCAPS_SELECTARG1 |
5541 WINED3DTEXOPCAPS_SELECTARG2 |
5542 WINED3DTEXOPCAPS_DISABLE;
5544 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5545 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5546 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5547 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5548 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5549 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5550 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5551 WINED3DTEXOPCAPS_LERP |
5552 WINED3DTEXOPCAPS_SUBTRACT;
5554 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5555 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5556 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5557 WINED3DTEXOPCAPS_MULTIPLYADD |
5558 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5559 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5560 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5562 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5563 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5565 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5566 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5569 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5570 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5571 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5573 if (TRACE_ON(d3d))
5575 TRACE("Checking support for fixup:\n");
5576 dump_color_fixup_desc(fixup);
5579 /* We only support identity conversions. */
5580 if (is_identity_fixup(fixup))
5582 TRACE("[OK]\n");
5583 return TRUE;
5586 TRACE("[FAILED]\n");
5587 return FALSE;
5590 const struct fragment_pipeline ffp_fragment_pipeline = {
5591 ffp_enable,
5592 ffp_fragment_get_caps,
5593 ffp_fragment_alloc,
5594 ffp_fragment_free,
5595 ffp_color_fixup_supported,
5596 ffp_fragmentstate_template,
5597 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5600 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5602 unsigned int i;
5603 for(i = 0; funcs[i]; i++);
5604 return i;
5607 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5609 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5610 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5613 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5615 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5616 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5617 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5620 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5621 const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
5622 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5624 unsigned int i, type, handlers;
5625 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5626 const struct StateEntryTemplate *cur;
5627 BOOL set[STATE_HIGHEST + 1];
5629 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5631 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5632 StateTable[i].representative = 0;
5633 StateTable[i].apply = state_undefined;
5636 for(type = 0; type < 3; type++) {
5637 /* This switch decides the order in which the states are applied */
5638 switch(type) {
5639 case 0: cur = misc; break;
5640 case 1: cur = fragment->states; break;
5641 case 2: cur = vertex; break;
5642 default: cur = NULL; /* Stupid compiler */
5644 if(!cur) continue;
5646 /* GL extension filtering should not prevent multiple handlers being applied from different
5647 * pipeline parts
5649 memset(set, 0, sizeof(set));
5651 for(i = 0; cur[i].state; i++) {
5652 APPLYSTATEFUNC *funcs_array;
5654 /* Only use the first matching state with the available extension from one template.
5655 * e.g.
5656 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5657 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5659 * if GL_XYZ_fancy is supported, ignore the 2nd line
5661 if(set[cur[i].state]) continue;
5662 /* Skip state lines depending on unsupported extensions */
5663 if (!GL_SUPPORT(cur[i].extension)) continue;
5664 set[cur[i].state] = TRUE;
5665 /* In some cases having an extension means that nothing has to be
5666 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5667 * supported, the texture coordinate fixup can be ignored. If the
5668 * apply function is used, mark the state set(done above) to prevent
5669 * applying later lines, but do not record anything in the state
5670 * table
5672 if(!cur[i].content.apply) continue;
5674 handlers = num_handlers(multistate_funcs[cur[i].state]);
5675 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5676 switch(handlers) {
5677 case 0:
5678 StateTable[cur[i].state].apply = cur[i].content.apply;
5679 break;
5680 case 1:
5681 StateTable[cur[i].state].apply = multistate_apply_2;
5682 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5684 sizeof(**dev_multistate_funcs) * 2);
5685 if (!dev_multistate_funcs[cur[i].state]) {
5686 goto out_of_mem;
5689 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5690 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5691 break;
5692 case 2:
5693 StateTable[cur[i].state].apply = multistate_apply_3;
5694 funcs_array = HeapReAlloc(GetProcessHeap(),
5696 dev_multistate_funcs[cur[i].state],
5697 sizeof(**dev_multistate_funcs) * 3);
5698 if (!funcs_array) {
5699 goto out_of_mem;
5702 dev_multistate_funcs[cur[i].state] = funcs_array;
5703 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5704 break;
5705 default:
5706 ERR("Unexpected amount of state handlers for state %u: %u\n",
5707 cur[i].state, handlers + 1);
5710 if(StateTable[cur[i].state].representative &&
5711 StateTable[cur[i].state].representative != cur[i].content.representative) {
5712 FIXME("State %u has different representatives in different pipeline parts\n",
5713 cur[i].state);
5715 StateTable[cur[i].state].representative = cur[i].content.representative;
5719 return WINED3D_OK;
5721 out_of_mem:
5722 for (i = 0; i <= STATE_HIGHEST; ++i) {
5723 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5726 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5728 return E_OUTOFMEMORY;
5730 #undef GLINFO_LOCATION