push 8b07bf1f08b23b9893a622b47d2be359556765b1
[wine/hacks.git] / dlls / wined3d / state.c
blob194cb9e9c6449c073731346543d693a6421f315d
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 static BOOL warned;
1554 /* TODO: NV_POINT_SPRITE */
1555 if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1556 /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1557 FIXME("Point sprites not supported\n");
1558 warned = TRUE;
1562 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1564 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1565 static BOOL warned;
1567 if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) {
1568 if(use_ps(stateblock) || stateblock->lowest_disabled_stage > GL_LIMITS(point_sprite_units)) {
1569 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1570 warned = TRUE;
1574 glEnable(GL_POINT_SPRITE_ARB);
1575 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1576 } else {
1577 glDisable(GL_POINT_SPRITE_ARB);
1578 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1582 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1585 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1586 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1587 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1588 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1590 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1592 TRACE("Stub\n");
1593 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1594 stateblock->renderState[WINED3DRS_WRAP1] ||
1595 stateblock->renderState[WINED3DRS_WRAP2] ||
1596 stateblock->renderState[WINED3DRS_WRAP3] ||
1597 stateblock->renderState[WINED3DRS_WRAP4] ||
1598 stateblock->renderState[WINED3DRS_WRAP5] ||
1599 stateblock->renderState[WINED3DRS_WRAP6] ||
1600 stateblock->renderState[WINED3DRS_WRAP7] ||
1601 stateblock->renderState[WINED3DRS_WRAP8] ||
1602 stateblock->renderState[WINED3DRS_WRAP9] ||
1603 stateblock->renderState[WINED3DRS_WRAP10] ||
1604 stateblock->renderState[WINED3DRS_WRAP11] ||
1605 stateblock->renderState[WINED3DRS_WRAP12] ||
1606 stateblock->renderState[WINED3DRS_WRAP13] ||
1607 stateblock->renderState[WINED3DRS_WRAP14] ||
1608 stateblock->renderState[WINED3DRS_WRAP15] ) {
1609 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1613 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1615 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1616 WARN("Multisample antialiasing not supported by gl\n");
1620 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1622 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1623 glEnable(GL_MULTISAMPLE_ARB);
1624 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1625 } else {
1626 glDisable(GL_MULTISAMPLE_ARB);
1627 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1631 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1633 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1634 glEnable(GL_SCISSOR_TEST);
1635 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1636 } else {
1637 glDisable(GL_SCISSOR_TEST);
1638 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1642 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1644 union {
1645 DWORD d;
1646 float f;
1647 } tmpvalue;
1649 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1650 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1651 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1652 glEnable(GL_POLYGON_OFFSET_FILL);
1653 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1654 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1655 checkGLcall("glPolygonOffset(...)");
1656 } else {
1657 glDisable(GL_POLYGON_OFFSET_FILL);
1658 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1662 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1664 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1665 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1666 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1667 } else {
1668 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1669 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1673 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1675 TRACE("Stub\n");
1676 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1677 FIXME(" Stippled Alpha not supported yet.\n");
1680 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1682 TRACE("Stub\n");
1683 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1684 FIXME(" Antialias not supported yet.\n");
1687 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1689 TRACE("Stub\n");
1690 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1691 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1694 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1696 TRACE("Stub\n");
1697 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1698 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1701 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1703 union {
1704 DWORD d;
1705 float f;
1706 } tmpvalue;
1707 tmpvalue.f = 1.0f;
1709 TRACE("Stub\n");
1710 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1712 static BOOL displayed = FALSE;
1714 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1715 if(!displayed)
1716 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1718 displayed = TRUE;
1722 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1724 TRACE("Stub\n");
1725 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1726 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1729 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1731 TRACE("Stub\n");
1732 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1733 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1736 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1738 TRACE("Stub\n");
1739 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1740 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1743 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1745 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1746 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1750 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1752 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1753 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1757 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1759 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1760 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1764 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1766 if(stateblock->renderState[WINED3DRS_ROP2]) {
1767 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1771 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1773 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1774 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1778 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1780 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1781 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1785 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1787 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1788 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1792 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1794 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1795 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1799 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1801 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1802 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1806 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1808 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1809 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1813 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1815 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1816 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1820 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1822 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1823 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1827 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1829 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1830 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1834 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1836 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1837 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1841 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1843 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1844 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1848 static void state_swvp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1850 if (stateblock->renderState[WINED3DRS_SOFTWAREVERTEXPROCESSING])
1852 FIXME("Software vertex processing not implemented.\n");
1856 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1857 #if defined (GL_VERSION_1_3)
1858 # define useext(A) A
1859 #elif defined (GL_EXT_texture_env_combine)
1860 # define useext(A) A##_EXT
1861 #elif defined (GL_ARB_texture_env_combine)
1862 # define useext(A) A##_ARB
1863 #endif
1865 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1866 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1867 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1868 * flag specifies the complement of the input should be used. */
1869 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1870 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1872 /* Calculate the operand */
1873 if (complement) {
1874 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1875 else *operand = GL_ONE_MINUS_SRC_COLOR;
1876 } else {
1877 if (from_alpha) *operand = GL_SRC_ALPHA;
1878 else *operand = GL_SRC_COLOR;
1881 /* Calculate the source */
1882 switch (arg & WINED3DTA_SELECTMASK) {
1883 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1884 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1885 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1886 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1887 case WINED3DTA_SPECULAR:
1889 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1890 * 'Secondary color' and isn't supported until base GL supports it
1891 * There is no concept of temp registers as far as I can tell
1893 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1894 *source = GL_TEXTURE;
1895 break;
1896 default:
1897 FIXME("Unrecognized texture arg %#x\n", arg);
1898 *source = GL_TEXTURE;
1899 break;
1903 /* Setup the texture operations texture stage states */
1904 static void set_tex_op(const struct wined3d_context *context, IWineD3DDevice *iface,
1905 BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1907 GLenum src1, src2, src3;
1908 GLenum opr1, opr2, opr3;
1909 GLenum comb_target;
1910 GLenum src0_target, src1_target, src2_target;
1911 GLenum opr0_target, opr1_target, opr2_target;
1912 GLenum scal_target;
1913 GLenum opr=0, invopr, src3_target, opr3_target;
1914 BOOL Handled = FALSE;
1915 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1917 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1919 /* This is called by a state handler which has the gl lock held and a context for the thread */
1921 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1922 the form (a1 <operation> a2). However, some of the more complex operations
1923 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1924 in a third parameter called a0. Therefore these are operations of the form
1925 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1927 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1928 functions below, expect their syntax to differ slightly to those listed in the
1929 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1930 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1932 if (isAlpha) {
1933 comb_target = useext(GL_COMBINE_ALPHA);
1934 src0_target = useext(GL_SOURCE0_ALPHA);
1935 src1_target = useext(GL_SOURCE1_ALPHA);
1936 src2_target = useext(GL_SOURCE2_ALPHA);
1937 opr0_target = useext(GL_OPERAND0_ALPHA);
1938 opr1_target = useext(GL_OPERAND1_ALPHA);
1939 opr2_target = useext(GL_OPERAND2_ALPHA);
1940 scal_target = GL_ALPHA_SCALE;
1942 else {
1943 comb_target = useext(GL_COMBINE_RGB);
1944 src0_target = useext(GL_SOURCE0_RGB);
1945 src1_target = useext(GL_SOURCE1_RGB);
1946 src2_target = useext(GL_SOURCE2_RGB);
1947 opr0_target = useext(GL_OPERAND0_RGB);
1948 opr1_target = useext(GL_OPERAND1_RGB);
1949 opr2_target = useext(GL_OPERAND2_RGB);
1950 scal_target = useext(GL_RGB_SCALE);
1953 /* If a texture stage references an invalid texture unit the stage just
1954 * passes through the result from the previous stage */
1955 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1956 arg1 = WINED3DTA_CURRENT;
1957 op = WINED3DTOP_SELECTARG1;
1960 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1961 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1962 } else {
1963 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1965 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1966 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1968 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1970 Handled = TRUE; /* Assume will be handled */
1972 /* Other texture operations require special extensions: */
1973 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1974 if (isAlpha) {
1975 opr = GL_SRC_ALPHA;
1976 invopr = GL_ONE_MINUS_SRC_ALPHA;
1977 src3_target = GL_SOURCE3_ALPHA_NV;
1978 opr3_target = GL_OPERAND3_ALPHA_NV;
1979 } else {
1980 opr = GL_SRC_COLOR;
1981 invopr = GL_ONE_MINUS_SRC_COLOR;
1982 src3_target = GL_SOURCE3_RGB_NV;
1983 opr3_target = GL_OPERAND3_RGB_NV;
1985 switch (op) {
1986 case WINED3DTOP_DISABLE: /* Only for alpha */
1987 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1988 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1989 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1990 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1991 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1992 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1993 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1994 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1995 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1996 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1997 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1998 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1999 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2000 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2001 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2002 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2003 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2004 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2005 break;
2006 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
2007 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
2008 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2009 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2010 if (op == WINED3DTOP_SELECTARG1) {
2011 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2012 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2013 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2014 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2015 } else {
2016 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2017 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2018 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2019 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2021 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2022 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2023 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2024 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2025 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2026 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2027 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2028 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2029 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2030 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2031 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2032 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2033 break;
2035 case WINED3DTOP_MODULATE:
2036 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2037 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2038 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2039 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2040 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2041 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2042 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2043 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2044 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2045 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2046 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2047 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2048 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2049 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2050 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2051 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2052 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2053 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2054 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2055 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2056 break;
2057 case WINED3DTOP_MODULATE2X:
2058 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2059 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2060 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2061 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2062 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2063 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2064 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2065 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2066 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2067 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2068 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2069 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2070 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2071 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2072 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2073 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2074 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2075 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2076 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2077 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2078 break;
2079 case WINED3DTOP_MODULATE4X:
2080 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2081 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2082 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2083 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2084 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2085 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2086 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2087 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2088 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2089 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2090 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2091 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2092 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2093 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2094 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2095 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2096 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2097 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2098 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2099 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2100 break;
2102 case WINED3DTOP_ADD:
2103 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2104 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2105 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2106 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2107 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2108 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2109 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2110 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2111 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2112 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2113 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2114 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2115 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2116 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2117 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2118 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2119 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2120 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2121 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2122 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2123 break;
2125 case WINED3DTOP_ADDSIGNED:
2126 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2127 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2128 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2129 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2130 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2131 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2132 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2133 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2134 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2135 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2136 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2137 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2138 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2139 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2140 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2141 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2142 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2143 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2144 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2145 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2146 break;
2148 case WINED3DTOP_ADDSIGNED2X:
2149 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2150 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2151 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2152 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2153 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2154 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2155 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2156 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2157 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2158 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2159 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2160 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2161 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2162 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2163 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2164 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2165 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2166 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2167 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2168 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2169 break;
2171 case WINED3DTOP_ADDSMOOTH:
2172 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2173 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2174 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2175 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2176 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2177 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2178 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2179 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2180 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2181 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2182 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2183 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2184 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2185 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2186 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2187 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2188 switch (opr1) {
2189 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2190 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2191 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2192 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2194 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2195 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2196 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2197 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2198 break;
2200 case WINED3DTOP_BLENDDIFFUSEALPHA:
2201 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2202 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2203 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2204 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2205 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2206 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2207 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2208 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2209 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2210 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2211 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2212 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2213 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2214 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2215 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2216 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2217 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2218 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2219 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2220 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2221 break;
2222 case WINED3DTOP_BLENDTEXTUREALPHA:
2223 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2224 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2225 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2226 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2227 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2228 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2229 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2230 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2231 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2232 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2233 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2234 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2235 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2236 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2237 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2238 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2239 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2240 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2241 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2242 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2243 break;
2244 case WINED3DTOP_BLENDFACTORALPHA:
2245 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2246 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2247 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2248 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2249 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2250 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2251 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2252 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2253 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2254 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2255 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2256 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2257 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2258 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2259 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2260 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2261 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2262 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2263 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2264 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2265 break;
2266 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2267 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2268 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2269 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2270 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2271 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2272 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2273 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2274 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2275 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2276 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2277 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2278 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2279 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2280 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2281 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2282 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2283 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2284 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2285 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2286 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2287 break;
2288 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2289 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2290 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2291 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2292 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2293 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2294 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2295 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2296 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2297 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2298 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2299 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2300 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2301 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2302 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2303 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2304 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2305 switch (opr) {
2306 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2307 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2309 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2310 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2311 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2312 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2313 break;
2314 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2315 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2316 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2317 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2318 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2319 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2320 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2321 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2322 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2323 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2324 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2325 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2326 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2327 switch (opr1) {
2328 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2329 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2331 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2332 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2333 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2334 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2335 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2336 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2337 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2338 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2339 break;
2340 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2341 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2342 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2343 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2344 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2345 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2346 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2347 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2348 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2349 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2350 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2351 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2352 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2353 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2354 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2355 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2356 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2357 switch (opr1) {
2358 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2359 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2360 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2361 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2363 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2364 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2365 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2366 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2367 break;
2368 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2369 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2370 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2371 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2372 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2373 switch (opr1) {
2374 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2375 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2376 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2377 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2379 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2380 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2381 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2382 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2383 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2384 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2385 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2386 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2387 switch (opr1) {
2388 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2389 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2391 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2392 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2393 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2394 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2395 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2396 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2397 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2398 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2399 break;
2400 case WINED3DTOP_MULTIPLYADD:
2401 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2402 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2403 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2404 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2405 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2406 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2407 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2408 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2409 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2410 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2411 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2412 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2413 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2414 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2415 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2416 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2417 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2418 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2419 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2420 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2421 break;
2423 case WINED3DTOP_BUMPENVMAP:
2427 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2428 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2430 default:
2431 Handled = FALSE;
2433 if (Handled) {
2434 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2435 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2437 return;
2439 } /* GL_NV_texture_env_combine4 */
2441 Handled = TRUE; /* Again, assume handled */
2442 switch (op) {
2443 case WINED3DTOP_DISABLE: /* Only for alpha */
2444 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2445 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2446 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2447 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2448 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2449 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2450 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2451 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2452 break;
2453 case WINED3DTOP_SELECTARG1:
2454 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2455 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2456 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2457 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2458 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2459 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2460 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2461 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2462 break;
2463 case WINED3DTOP_SELECTARG2:
2464 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2465 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2466 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2467 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2468 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2469 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2470 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2471 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2472 break;
2473 case WINED3DTOP_MODULATE:
2474 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2475 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2476 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2477 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2478 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2479 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2480 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2481 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2482 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2483 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2484 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2485 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2486 break;
2487 case WINED3DTOP_MODULATE2X:
2488 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2489 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2490 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2491 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2492 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2493 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2494 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2495 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2496 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2497 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2498 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2499 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2500 break;
2501 case WINED3DTOP_MODULATE4X:
2502 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2503 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2504 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2505 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2506 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2507 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2508 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2509 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2510 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2511 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2512 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2513 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2514 break;
2515 case WINED3DTOP_ADD:
2516 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2517 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2518 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2519 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2520 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2521 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2522 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2523 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2524 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2525 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2526 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2527 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2528 break;
2529 case WINED3DTOP_ADDSIGNED:
2530 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2531 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2532 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2533 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2534 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2535 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2536 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2537 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2538 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2539 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2540 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2541 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2542 break;
2543 case WINED3DTOP_ADDSIGNED2X:
2544 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2545 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2546 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2547 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2548 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2549 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2550 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2551 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2552 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2553 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2554 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2555 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2556 break;
2557 case WINED3DTOP_SUBTRACT:
2558 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2559 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2560 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2561 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2562 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2563 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2564 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2565 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2566 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2567 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2568 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2569 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2570 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2571 } else {
2572 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2574 break;
2576 case WINED3DTOP_BLENDDIFFUSEALPHA:
2577 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2578 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2579 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2580 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2581 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2582 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2583 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2584 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2585 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2586 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2587 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2588 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2589 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2590 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2591 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2592 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2593 break;
2594 case WINED3DTOP_BLENDTEXTUREALPHA:
2595 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2596 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2597 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2598 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2599 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2600 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2601 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2602 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2603 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2604 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2605 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2606 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2607 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2608 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2609 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2610 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2611 break;
2612 case WINED3DTOP_BLENDFACTORALPHA:
2613 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2614 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2615 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2616 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2617 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2618 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2619 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2620 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2621 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2622 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2623 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2624 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2625 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2626 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2627 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2628 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2629 break;
2630 case WINED3DTOP_BLENDCURRENTALPHA:
2631 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2632 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2633 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2634 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2635 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2636 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2637 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2638 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2639 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2640 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2641 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2642 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2643 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2644 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2645 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2646 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2647 break;
2648 case WINED3DTOP_DOTPRODUCT3:
2649 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2650 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2651 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2652 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2653 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2654 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2655 } else {
2656 FIXME("This version of opengl does not support GL_DOT3\n");
2658 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2659 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2660 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2661 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2662 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2663 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2664 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2665 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2666 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2667 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2668 break;
2669 case WINED3DTOP_LERP:
2670 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2671 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2672 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2673 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2674 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2675 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2676 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2677 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2678 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2679 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2680 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2681 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2682 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2683 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2684 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2685 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2686 break;
2687 case WINED3DTOP_ADDSMOOTH:
2688 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2689 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2690 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2691 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2692 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2693 switch (opr1) {
2694 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2695 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2696 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2697 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2699 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2700 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2701 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2702 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2703 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2704 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2705 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2706 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2707 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2708 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2709 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2710 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2711 } else
2712 Handled = FALSE;
2713 break;
2714 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2715 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2716 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2717 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2718 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2719 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2720 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2721 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2722 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2723 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2724 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2725 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2726 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2727 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2728 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2729 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2730 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2731 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2732 } else
2733 Handled = FALSE;
2734 break;
2735 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2736 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2737 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2738 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2739 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2740 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2741 switch (opr1) {
2742 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2743 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2744 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2745 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2747 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2748 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2749 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2750 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2751 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2752 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2753 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2754 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2755 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2756 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2757 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2758 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2759 } else
2760 Handled = FALSE;
2761 break;
2762 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2763 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2764 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2765 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2766 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2767 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2768 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2769 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2770 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2771 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2772 switch (opr1) {
2773 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2774 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2775 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2776 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2778 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2779 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2780 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2781 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2782 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2783 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2784 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2785 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2786 } else
2787 Handled = FALSE;
2788 break;
2789 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2790 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2791 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2792 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2793 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2794 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2795 switch (opr1) {
2796 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2797 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2798 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2799 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2801 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2802 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2803 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2804 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2805 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2806 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2807 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2808 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2809 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2810 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2811 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2812 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2813 } else
2814 Handled = FALSE;
2815 break;
2816 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2817 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2818 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2819 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2820 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2821 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2822 switch (opr1) {
2823 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2824 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2825 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2826 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2828 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2829 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2830 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2831 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2832 switch (opr1) {
2833 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2834 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2835 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2836 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2838 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2839 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2840 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2841 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2842 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2843 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2844 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2845 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2846 } else
2847 Handled = FALSE;
2848 break;
2849 case WINED3DTOP_MULTIPLYADD:
2850 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2851 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2852 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2853 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2854 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2855 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2856 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2857 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2858 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2859 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2860 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2861 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2862 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2863 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2864 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2865 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2866 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2867 } else
2868 Handled = FALSE;
2869 break;
2870 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2871 case WINED3DTOP_BUMPENVMAP:
2872 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2873 /* Technically texture shader support without register combiners is possible, but not expected to occur
2874 * on real world cards, so for now a fixme should be enough
2876 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2878 default:
2879 Handled = FALSE;
2882 if (Handled) {
2883 BOOL combineOK = TRUE;
2884 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2885 DWORD op2;
2887 if (isAlpha) {
2888 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2889 } else {
2890 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2893 /* Note: If COMBINE4 in effect can't go back to combine! */
2894 switch (op2) {
2895 case WINED3DTOP_ADDSMOOTH:
2896 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2897 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2898 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2899 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2900 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2901 case WINED3DTOP_MULTIPLYADD:
2902 /* Ignore those implemented in both cases */
2903 switch (op) {
2904 case WINED3DTOP_SELECTARG1:
2905 case WINED3DTOP_SELECTARG2:
2906 combineOK = FALSE;
2907 Handled = FALSE;
2908 break;
2909 default:
2910 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2911 return;
2916 if (combineOK) {
2917 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2918 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2920 return;
2924 /* After all the extensions, if still unhandled, report fixme */
2925 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2929 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
2931 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2932 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2933 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2935 TRACE("Setting color op for stage %d\n", stage);
2937 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2938 if (use_ps(stateblock)) return;
2940 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2942 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2944 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2945 FIXME("Attempt to enable unsupported stage!\n");
2946 return;
2948 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2949 checkGLcall("glActiveTextureARB");
2952 if(stage >= stateblock->lowest_disabled_stage) {
2953 TRACE("Stage disabled\n");
2954 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2956 /* Disable everything here */
2957 glDisable(GL_TEXTURE_2D);
2958 checkGLcall("glDisable(GL_TEXTURE_2D)");
2959 glDisable(GL_TEXTURE_3D);
2960 checkGLcall("glDisable(GL_TEXTURE_3D)");
2961 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2962 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2963 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2965 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2966 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2967 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2970 /* All done */
2971 return;
2974 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2975 * if the sampler for this stage is dirty
2977 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2978 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2981 set_tex_op(context, (IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2982 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2983 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2984 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2985 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2988 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
2990 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2991 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2992 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2993 DWORD op, arg1, arg2, arg0;
2995 TRACE("Setting alpha op for stage %d\n", stage);
2996 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2997 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2999 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
3000 FIXME("Attempt to enable unsupported stage!\n");
3001 return;
3003 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3004 checkGLcall("glActiveTextureARB");
3007 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
3008 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
3009 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
3010 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
3012 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
3014 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
3016 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3018 IWineD3DSurfaceImpl *surf;
3020 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
3022 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
3024 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
3025 * properly. On the other hand applications can still use texture combiners apparently. This code
3026 * takes care that apps cannot remove the texture's alpha channel entirely.
3028 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
3029 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
3030 * and alpha component of diffuse color to draw things like translucent text and perform other
3031 * blending effects.
3033 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
3034 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
3035 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
3036 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
3037 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
3038 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
3039 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
3040 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
3041 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
3042 * alpha.
3044 * What to do with multitexturing? So far no app has been found that uses color keying with
3045 * multitexturing */
3046 if (op == WINED3DTOP_DISABLE)
3048 arg1 = WINED3DTA_TEXTURE;
3049 op = WINED3DTOP_SELECTARG1;
3051 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
3053 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3055 arg2 = WINED3DTA_TEXTURE;
3056 op = WINED3DTOP_MODULATE;
3058 else arg1 = WINED3DTA_TEXTURE;
3060 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
3062 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3064 arg1 = WINED3DTA_TEXTURE;
3065 op = WINED3DTOP_MODULATE;
3067 else arg2 = WINED3DTA_TEXTURE;
3073 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3074 * this if block here, and the other code(color keying, texture unit selection) are the same
3076 TRACE("Setting alpha op for stage %d\n", stage);
3077 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3078 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3079 op, arg1, arg2, arg0,
3080 mapped_stage,
3081 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
3082 } else {
3083 set_tex_op(context, (IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3084 op, arg1, arg2, arg0);
3088 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3090 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3091 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3092 BOOL generated;
3093 int coordIdx;
3095 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3096 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3098 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3099 return;
3102 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3104 if(mapped_stage >= GL_LIMITS(textures)) {
3105 return;
3107 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3108 checkGLcall("glActiveTextureARB");
3109 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3110 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3112 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3113 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3114 stateblock->wineD3DDevice->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
3115 ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format
3116 : WINED3DFMT_UNKNOWN,
3117 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3119 /* The sampler applying function calls us if this changes */
3120 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3122 if(generated) {
3123 FIXME("Non-power2 texture being used with generated texture coords\n");
3125 /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
3126 fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3127 if (!use_ps(stateblock)) {
3128 TRACE("Non power two matrix multiply fixup\n");
3129 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3134 static void unloadTexCoords(const struct wined3d_context *context)
3136 unsigned int texture_idx;
3138 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3139 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3140 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3144 static void loadTexCoords(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
3145 const struct wined3d_stream_info *si, GLuint *curVBO)
3147 const UINT *offset = stateblock->streamOffset;
3148 unsigned int mapped_stage = 0;
3149 unsigned int textureNo = 0;
3151 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3152 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3154 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3155 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3157 if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
3159 const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3161 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3162 textureNo, mapped_stage, coordIdx, e->data);
3164 if (*curVBO != e->buffer_object)
3166 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3167 checkGLcall("glBindBufferARB");
3168 *curVBO = e->buffer_object;
3171 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3172 checkGLcall("glClientActiveTextureARB");
3174 /* The coords to supply depend completely on the fvf / vertex shader */
3175 glTexCoordPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
3176 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3177 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3178 } else {
3179 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3182 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3183 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3184 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3185 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3189 checkGLcall("loadTexCoords");
3192 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3194 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3195 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3196 static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3197 static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3198 static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3199 static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3201 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3203 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3204 return;
3207 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3208 WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3209 return;
3211 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3212 checkGLcall("glActiveTextureARB");
3214 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3216 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3217 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3218 * means use the vertex position (camera-space) as the input texture coordinates
3219 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3220 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3221 * to the TEXCOORDINDEX value
3223 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3225 case WINED3DTSS_TCI_PASSTHRU:
3226 /* Use the specified texture coordinates contained within the
3227 * vertex format. This value resolves to zero. */
3228 glDisable(GL_TEXTURE_GEN_S);
3229 glDisable(GL_TEXTURE_GEN_T);
3230 glDisable(GL_TEXTURE_GEN_R);
3231 glDisable(GL_TEXTURE_GEN_Q);
3232 checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3233 break;
3235 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3236 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3237 * as the input texture coordinates for this stage's texture transformation. This
3238 * equates roughly to EYE_LINEAR */
3240 glMatrixMode(GL_MODELVIEW);
3241 glPushMatrix();
3242 glLoadIdentity();
3243 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3244 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3245 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3246 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3247 glPopMatrix();
3248 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3250 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3251 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3252 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3253 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3255 glEnable(GL_TEXTURE_GEN_S);
3256 glEnable(GL_TEXTURE_GEN_T);
3257 glEnable(GL_TEXTURE_GEN_R);
3258 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3260 break;
3262 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3263 /* Note that NV_TEXGEN_REFLECTION support is implied when
3264 * ARB_TEXTURE_CUBE_MAP is supported */
3265 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3267 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3268 break;
3271 glMatrixMode(GL_MODELVIEW);
3272 glPushMatrix();
3273 glLoadIdentity();
3274 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3275 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3276 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3277 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3278 glPopMatrix();
3279 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3281 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3282 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3283 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3284 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3286 glEnable(GL_TEXTURE_GEN_S);
3287 glEnable(GL_TEXTURE_GEN_T);
3288 glEnable(GL_TEXTURE_GEN_R);
3289 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3291 break;
3293 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3294 /* Note that NV_TEXGEN_REFLECTION support is implied when
3295 * ARB_TEXTURE_CUBE_MAP is supported */
3296 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3298 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3299 break;
3302 glMatrixMode(GL_MODELVIEW);
3303 glPushMatrix();
3304 glLoadIdentity();
3305 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3306 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3307 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3308 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3309 glPopMatrix();
3310 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3312 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3313 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3314 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3315 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3317 glEnable(GL_TEXTURE_GEN_S);
3318 glEnable(GL_TEXTURE_GEN_T);
3319 glEnable(GL_TEXTURE_GEN_R);
3320 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3322 break;
3324 case WINED3DTSS_TCI_SPHEREMAP:
3325 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3326 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3327 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3329 glEnable(GL_TEXTURE_GEN_S);
3330 glEnable(GL_TEXTURE_GEN_T);
3331 glDisable(GL_TEXTURE_GEN_R);
3332 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3334 break;
3336 default:
3337 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3338 stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3339 glDisable(GL_TEXTURE_GEN_S);
3340 glDisable(GL_TEXTURE_GEN_T);
3341 glDisable(GL_TEXTURE_GEN_R);
3342 glDisable(GL_TEXTURE_GEN_Q);
3343 checkGLcall("Disable texgen.");
3345 break;
3348 /* Update the texture matrix */
3349 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3350 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3353 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3354 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3355 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3356 * and do all the things linked to it
3357 * TODO: Tidy that up to reload only the arrays of the changed unit
3359 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3361 unloadTexCoords(context);
3362 loadTexCoords(context, stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3366 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3368 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3370 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3371 * has an update pending
3373 if(isStateDirty(context, STATE_VDECL) ||
3374 isStateDirty(context, STATE_PIXELSHADER)) {
3375 return;
3378 device->shader_backend->shader_load_constants(context, use_ps(stateblock), use_vs(stateblock));
3381 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3383 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3385 if (stateblock->pixelShader && stage != 0
3386 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage)))
3388 /* The pixel shader has to know the luminance scale. Do a constants update if it
3389 * isn't scheduled anyway
3391 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3392 !isStateDirty(context, STATE_PIXELSHADER)) {
3393 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3398 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3400 const DWORD sampler = state - STATE_SAMPLER(0);
3401 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3403 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3405 if(!texture) return;
3406 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3407 * basetexture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3408 * scaling is reapplied or removed, the texture matrix has to be reapplied
3410 * The mapped stage is already active because the sampler() function below, which is part of the
3411 * misc pipeline
3413 if(sampler < MAX_TEXTURES) {
3414 const BOOL texIsPow2 = !((IWineD3DBaseTextureImpl *)texture)->baseTexture.pow2Matrix_identity;
3416 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3418 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3419 else context->lastWasPow2Texture &= ~(1 << sampler);
3420 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3425 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3427 DWORD sampler = state - STATE_SAMPLER(0);
3428 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3429 union {
3430 float f;
3431 DWORD d;
3432 } tmpvalue;
3434 TRACE("Sampler: %d\n", sampler);
3435 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3436 * only has to bind textures and set the per texture states
3439 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3441 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3442 return;
3445 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3446 return;
3448 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3449 checkGLcall("glActiveTextureARB");
3451 if(stateblock->textures[sampler]) {
3452 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3453 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3454 tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3455 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3456 basetexture_apply_state_changes(stateblock->textures[sampler],
3457 stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3459 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3460 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3461 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3462 GL_TEXTURE_LOD_BIAS_EXT,
3463 tmpvalue.f);
3464 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3467 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3469 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3470 /* If color keying is enabled update the alpha test, it depends on the existence
3471 * of a color key in stage 0
3473 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3477 /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3478 if (!tex_impl->baseTexture.pow2Matrix_identity) {
3479 IWineD3DDeviceImpl* d3ddevice = stateblock->wineD3DDevice;
3480 d3ddevice->shader_backend->shader_load_np2fixup_constants(
3481 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3483 } else if(mapped_stage < GL_LIMITS(textures)) {
3484 if(sampler < stateblock->lowest_disabled_stage) {
3485 /* TODO: What should I do with pixel shaders here ??? */
3486 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3487 /* If color keying is enabled update the alpha test, it depends on the existence
3488 * of a color key in stage 0
3490 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3492 } /* Otherwise tex_colorop disables the stage */
3493 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3494 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3498 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3500 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3501 BOOL use_pshader = use_ps(stateblock);
3502 BOOL use_vshader = use_vs(stateblock);
3503 int i;
3505 if (use_pshader) {
3506 if(!context->last_was_pshader) {
3507 /* Former draw without a pixel shader, some samplers
3508 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3509 * make sure to enable them
3511 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3512 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3513 sampler(STATE_SAMPLER(i), stateblock, context);
3516 context->last_was_pshader = TRUE;
3517 } else {
3518 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3519 * if a different texture was bound. I don't have to do anything.
3522 } else {
3523 /* Disabled the pixel shader - color ops weren't applied
3524 * while it was enabled, so re-apply them.
3526 for(i=0; i < MAX_TEXTURES; i++) {
3527 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3528 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3529 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3532 context->last_was_pshader = FALSE;
3535 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3536 device->shader_backend->shader_select(context, use_pshader, use_vshader);
3538 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3539 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3544 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3546 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3547 if (stateblock->pixelShader && stage != 0
3548 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage)))
3550 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3551 * anyway
3553 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3554 !isStateDirty(context, STATE_PIXELSHADER)) {
3555 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3560 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3562 /* This function is called by transform_view below if the view matrix was changed too
3564 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3565 * does not always update the world matrix, only on a switch between transformed
3566 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3567 * draw, but that should be rather rare and cheaper in total.
3569 glMatrixMode(GL_MODELVIEW);
3570 checkGLcall("glMatrixMode");
3572 if(context->last_was_rhw) {
3573 glLoadIdentity();
3574 checkGLcall("glLoadIdentity()");
3575 } else {
3576 /* In the general case, the view matrix is the identity matrix */
3577 if (stateblock->wineD3DDevice->view_ident) {
3578 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3579 checkGLcall("glLoadMatrixf");
3580 } else {
3581 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3582 checkGLcall("glLoadMatrixf");
3583 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3584 checkGLcall("glMultMatrixf");
3589 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3591 UINT index = state - STATE_CLIPPLANE(0);
3593 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3594 return;
3597 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3598 if(!use_vs(stateblock)) {
3599 glMatrixMode(GL_MODELVIEW);
3600 glPushMatrix();
3601 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3602 } else {
3603 /* with vertex shaders, clip planes are not transformed in direct3d,
3604 * in OpenGL they are still transformed by the model view.
3605 * Use this to swap the y coordinate if necessary
3607 glMatrixMode(GL_MODELVIEW);
3608 glPushMatrix();
3609 glLoadIdentity();
3610 if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f);
3613 TRACE("Clipplane [%f,%f,%f,%f]\n",
3614 stateblock->clipplane[index][0],
3615 stateblock->clipplane[index][1],
3616 stateblock->clipplane[index][2],
3617 stateblock->clipplane[index][3]);
3618 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3619 checkGLcall("glClipPlane");
3621 glPopMatrix();
3624 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3626 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3627 GLenum glMat;
3628 TRACE("Setting world matrix %d\n", matrix);
3630 if(matrix >= GL_LIMITS(blends)) {
3631 WARN("Unsupported blend matrix set\n");
3632 return;
3633 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3634 return;
3637 /* GL_MODELVIEW0_ARB: 0x1700
3638 * GL_MODELVIEW1_ARB: 0x850a
3639 * GL_MODELVIEW2_ARB: 0x8722
3640 * GL_MODELVIEW3_ARB: 0x8723
3641 * etc
3642 * GL_MODELVIEW31_ARB: 0x873F
3644 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3645 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3647 glMatrixMode(glMat);
3648 checkGLcall("glMatrixMode(glMat)");
3650 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3651 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3653 if(stateblock->wineD3DDevice->view_ident) {
3654 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3655 checkGLcall("glLoadMatrixf");
3656 } else {
3657 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3658 checkGLcall("glLoadMatrixf");
3659 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3660 checkGLcall("glMultMatrixf");
3664 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3666 static BOOL once = FALSE;
3668 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3669 case WINED3DVBF_1WEIGHTS:
3670 case WINED3DVBF_2WEIGHTS:
3671 case WINED3DVBF_3WEIGHTS:
3672 if(!once) {
3673 once = TRUE;
3674 /* TODO: Implement vertex blending in drawStridedSlow */
3675 FIXME("Vertex blending enabled, but not supported by hardware\n");
3677 break;
3679 case WINED3DVBF_TWEENING:
3680 WARN("Tweening not supported yet\n");
3684 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3686 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3688 switch(val) {
3689 case WINED3DVBF_1WEIGHTS:
3690 case WINED3DVBF_2WEIGHTS:
3691 case WINED3DVBF_3WEIGHTS:
3692 glEnable(GL_VERTEX_BLEND_ARB);
3693 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3695 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3696 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3698 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3700 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3701 unsigned int i;
3702 for(i = 1; i < GL_LIMITS(blends); i++) {
3703 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3704 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3707 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3709 break;
3711 case WINED3DVBF_DISABLE:
3712 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3713 glDisable(GL_VERTEX_BLEND_ARB);
3714 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3715 break;
3717 case WINED3DVBF_TWEENING:
3718 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3719 * vertex weights in the vertices?
3720 * For now we don't report that as supported, so a warn should suffice
3722 WARN("Tweening not supported yet\n");
3723 break;
3727 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3729 const struct wined3d_light_info *light = NULL;
3730 unsigned int k;
3732 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3733 * NOTE: We have to reset the positions even if the light/plane is not currently
3734 * enabled, since the call to enable it will not reset the position.
3735 * NOTE2: Apparently texture transforms do NOT need reapplying
3738 glMatrixMode(GL_MODELVIEW);
3739 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3740 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3741 checkGLcall("glLoadMatrixf(...)");
3743 /* Reset lights. TODO: Call light apply func */
3744 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3745 light = stateblock->activeLights[k];
3746 if(!light) continue;
3747 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3748 checkGLcall("glLightfv posn");
3749 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3750 checkGLcall("glLightfv dirn");
3753 /* Reset Clipping Planes */
3754 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3755 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3756 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3760 if(context->last_was_rhw) {
3761 glLoadIdentity();
3762 checkGLcall("glLoadIdentity()");
3763 /* No need to update the world matrix, the identity is fine */
3764 return;
3767 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3768 * No need to do it here if the state is scheduled for update.
3770 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3771 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3774 /* Avoid looping over a number of matrices if the app never used the functionality */
3775 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3776 for(k = 1; k < GL_LIMITS(blends); k++) {
3777 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3778 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3784 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3786 glMatrixMode(GL_PROJECTION);
3787 checkGLcall("glMatrixMode(GL_PROJECTION)");
3788 glLoadIdentity();
3789 checkGLcall("glLoadIdentity");
3791 if(context->last_was_rhw) {
3792 double X, Y, height, width, minZ, maxZ;
3794 X = stateblock->viewport.X;
3795 Y = stateblock->viewport.Y;
3796 height = stateblock->viewport.Height;
3797 width = stateblock->viewport.Width;
3798 minZ = stateblock->viewport.MinZ;
3799 maxZ = stateblock->viewport.MaxZ;
3801 if(!stateblock->wineD3DDevice->untransformed) {
3802 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3803 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3804 * suppress depth clipping. This can be done because it is an orthogonal projection and
3805 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3806 * Persia 3D need this.
3808 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3809 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3810 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3811 * to the viewer.
3813 * Also note that this breaks z comparison against z values filled in with clear,
3814 * but no app depending on that and disabled clipping has been found yet. Comparing
3815 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3816 * surface removal.
3818 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3819 * but this would break Z buffer operation. Raising the range to something less than
3820 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3821 * problem either.
3823 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3824 if (context->render_offscreen)
3826 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3827 } else {
3828 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3830 } else {
3831 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3832 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3833 * unmodified to opengl.
3835 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3836 * replacement shader.
3838 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3839 if (context->render_offscreen)
3841 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3842 } else {
3843 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3846 checkGLcall("glOrtho");
3848 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3849 glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f);
3850 checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)");
3852 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3853 * render everything upside down when rendering offscreen. */
3854 if (context->render_offscreen)
3856 glScalef(1.0f, -1.0f, 1.0f);
3857 checkGLcall("glScalef");
3859 } else {
3860 /* The rule is that the window coordinate 0 does not correspond to the
3861 beginning of the first pixel, but the center of the first pixel.
3862 As a consequence if you want to correctly draw one line exactly from
3863 the left to the right end of the viewport (with all matrices set to
3864 be identity), the x coords of both ends of the line would be not
3865 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3866 instead.
3868 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3869 divide by the Width/Height, so we need the half range(1.0) to translate by
3870 half a pixel.
3872 The other fun is that d3d's output z range after the transformation is [0;1],
3873 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3874 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3875 of Z buffer precision and the clear values do not match in the z test. Thus scale
3876 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3880 * Careful with the order of operations here, we're essentially working backwards:
3881 * x = x + 1/w;
3882 * y = (y - 1/h) * flip;
3883 * z = z * 2 - 1;
3885 * Becomes:
3886 * glTranslatef(0.0, 0.0, -1.0);
3887 * glScalef(1.0, 1.0, 2.0);
3889 * glScalef(1.0, flip, 1.0);
3890 * glTranslatef(1/w, -1/h, 0.0);
3892 * This is equivalent to:
3893 * glTranslatef(1/w, -flip/h, -1.0)
3894 * glScalef(1.0, flip, 2.0);
3897 /* Translate by slightly less than a half pixel to force a top-left
3898 * filling convention. We want the difference to be large enough that
3899 * it doesn't get lost due to rounding inside the driver, but small
3900 * enough to prevent it from interfering with any anti-aliasing. */
3901 GLfloat xoffset = (63.0f / 64.0f) / stateblock->viewport.Width;
3902 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
3904 if (context->render_offscreen)
3906 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3907 * render everything upside down when rendering offscreen. */
3908 glTranslatef(xoffset, -yoffset, -1.0f);
3909 checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)");
3910 glScalef(1.0f, -1.0f, 2.0f);
3911 } else {
3912 glTranslatef(xoffset, yoffset, -1.0f);
3913 checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)");
3914 glScalef(1.0f, 1.0f, 2.0f);
3916 checkGLcall("glScalef");
3918 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3919 checkGLcall("glLoadMatrixf");
3923 /* This should match any arrays loaded in loadVertexData.
3924 * stateblock impl is required for GL_SUPPORT
3925 * TODO: Only load / unload arrays if we have to.
3927 static inline void unloadVertexData(const struct wined3d_context *context)
3929 glDisableClientState(GL_VERTEX_ARRAY);
3930 glDisableClientState(GL_NORMAL_ARRAY);
3931 glDisableClientState(GL_COLOR_ARRAY);
3932 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3933 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3935 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3936 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3938 unloadTexCoords(context);
3941 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context, int i)
3943 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3944 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3946 context->numbered_array_mask &= ~(1 << i);
3949 /* This should match any arrays loaded in loadNumberedArrays
3950 * TODO: Only load / unload arrays if we have to.
3952 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3954 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3955 GLint maxAttribs = 16;
3956 int i;
3958 /* Leave all the attribs disabled */
3959 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3960 /* MESA does not support it right not */
3961 if (glGetError() != GL_NO_ERROR)
3962 maxAttribs = 16;
3963 for (i = 0; i < maxAttribs; ++i) {
3964 unload_numbered_array(stateblock, context, i);
3968 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3969 const struct wined3d_stream_info *stream_info, struct wined3d_context *context)
3971 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3972 int i;
3973 const UINT *offset = stateblock->streamOffset;
3974 struct wined3d_buffer *vb;
3975 DWORD_PTR shift_index;
3977 /* Default to no instancing */
3978 stateblock->wineD3DDevice->instancedDraw = FALSE;
3980 for (i = 0; i < MAX_ATTRIBS; i++) {
3981 if (!(stream_info->use_map & (1 << i)))
3983 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3984 continue;
3987 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3988 if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
3990 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3991 stateblock->wineD3DDevice->instancedDraw = TRUE;
3992 continue;
3995 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
3997 if (stream_info->elements[i].stride)
3999 if (curVBO != stream_info->elements[i].buffer_object)
4001 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
4002 checkGLcall("glBindBufferARB");
4003 curVBO = stream_info->elements[i].buffer_object;
4005 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4006 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
4007 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
4008 * vbo we won't be load converted attributes anyway
4010 if (curVBO && vb->conversion_shift)
4012 TRACE("Loading attribute from shifted buffer\n");
4013 TRACE("Attrib %d has original stride %d, new stride %d\n",
4014 i, stream_info->elements[i].stride, vb->conversion_stride);
4015 TRACE("Original offset %p, additional offset 0x%08x\n",
4016 stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
4017 TRACE("Opengl type %#x\n", stream_info->elements[i].format_desc->gl_vtx_type);
4018 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
4019 shift_index = shift_index % stream_info->elements[i].stride;
4020 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4021 stream_info->elements[i].format_desc->gl_vtx_type,
4022 stream_info->elements[i].format_desc->gl_normalized,
4023 vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
4024 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4025 + offset[stream_info->elements[i].stream_idx]));
4027 } else {
4028 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4029 stream_info->elements[i].format_desc->gl_vtx_type,
4030 stream_info->elements[i].format_desc->gl_normalized,
4031 stream_info->elements[i].stride, stream_info->elements[i].data
4032 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4033 + offset[stream_info->elements[i].stream_idx]));
4036 if (!(context->numbered_array_mask & (1 << i)))
4038 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
4039 context->numbered_array_mask |= (1 << i);
4041 } else {
4042 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
4043 * set up the attribute statically. But we have to figure out the system memory address.
4045 const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
4046 if (stream_info->elements[i].buffer_object)
4048 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4049 ptr += (long) buffer_get_sysmem(vb);
4052 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
4054 switch (stream_info->elements[i].format_desc->format)
4056 case WINED3DFMT_R32_FLOAT:
4057 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
4058 break;
4059 case WINED3DFMT_R32G32_FLOAT:
4060 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
4061 break;
4062 case WINED3DFMT_R32G32B32_FLOAT:
4063 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
4064 break;
4065 case WINED3DFMT_R32G32B32A32_FLOAT:
4066 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
4067 break;
4069 case WINED3DFMT_R8G8B8A8_UINT:
4070 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4071 break;
4072 case WINED3DFMT_B8G8R8A8_UNORM:
4073 if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
4075 const DWORD *src = (const DWORD *)ptr;
4076 DWORD c = *src & 0xff00ff00;
4077 c |= (*src & 0xff0000) >> 16;
4078 c |= (*src & 0xff) << 16;
4079 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
4080 break;
4082 /* else fallthrough */
4083 case WINED3DFMT_R8G8B8A8_UNORM:
4084 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4085 break;
4087 case WINED3DFMT_R16G16_SINT:
4088 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4089 break;
4090 case WINED3DFMT_R16G16B16A16_SINT:
4091 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4092 break;
4094 case WINED3DFMT_R16G16_SNORM:
4096 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4097 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4098 break;
4100 case WINED3DFMT_R16G16_UNORM:
4102 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4103 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4104 break;
4106 case WINED3DFMT_R16G16B16A16_SNORM:
4107 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4108 break;
4109 case WINED3DFMT_R16G16B16A16_UNORM:
4110 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4111 break;
4113 case WINED3DFMT_R10G10B10A2_UINT:
4114 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4115 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4116 break;
4117 case WINED3DFMT_R10G10B10A2_SNORM:
4118 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4119 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4120 break;
4122 case WINED3DFMT_R16G16_FLOAT:
4123 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4124 * byte float according to the IEEE standard
4126 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4127 break;
4128 case WINED3DFMT_R16G16B16A16_FLOAT:
4129 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4130 break;
4132 default:
4133 ERR("Unexpected declaration in stride 0 attributes\n");
4134 break;
4139 checkGLcall("Loading numbered arrays");
4142 /* Used from 2 different functions, and too big to justify making it inlined */
4143 static void loadVertexData(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
4144 const struct wined3d_stream_info *si)
4146 const UINT *offset = stateblock->streamOffset;
4147 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4148 const struct wined3d_stream_info_element *e;
4150 TRACE("Using fast vertex array code\n");
4152 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4153 stateblock->wineD3DDevice->instancedDraw = FALSE;
4155 /* Blend Data ---------------------------------------------- */
4156 if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
4157 || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4159 e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4161 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4162 TRACE("Blend %d %p %d\n", e->format_desc->component_count,
4163 e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4165 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4166 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4168 GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1));
4170 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4171 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4172 sd->u.s.blendWeights.dwStride,
4173 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4175 if (curVBO != e->buffer_object)
4177 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4178 checkGLcall("glBindBufferARB");
4179 curVBO = e->buffer_object;
4182 GL_EXTCALL(glWeightPointerARB)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4183 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4185 checkGLcall("glWeightPointerARB");
4187 if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4189 static BOOL warned;
4190 if (!warned)
4192 FIXME("blendMatrixIndices support\n");
4193 warned = TRUE;
4196 } else {
4197 /* TODO: support blends in drawStridedSlow
4198 * No need to write a FIXME here, this is done after the general vertex decl decoding
4200 WARN("unsupported blending in openGl\n");
4202 } else {
4203 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4204 static const GLbyte one = 1;
4205 GL_EXTCALL(glWeightbvARB(1, &one));
4206 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4210 /* Point Size ----------------------------------------------*/
4211 if (si->use_map & (1 << WINED3D_FFP_PSIZE))
4213 /* no such functionality in the fixed function GL pipeline */
4214 TRACE("Cannot change ptSize here in openGl\n");
4215 /* TODO: Implement this function in using shaders if they are available */
4218 /* Vertex Pointers -----------------------------------------*/
4219 if (si->use_map & (1 << WINED3D_FFP_POSITION))
4221 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data));
4223 e = &si->elements[WINED3D_FFP_POSITION];
4224 if (curVBO != e->buffer_object)
4226 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4227 checkGLcall("glBindBufferARB");
4228 curVBO = e->buffer_object;
4231 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4232 handling for rhw mode should not impact screen position whereas in GL it does.
4233 This may result in very slightly distorted textures in rhw mode.
4234 There's always the other option of fixing the view matrix to
4235 prevent w from having any effect.
4237 This only applies to user pointer sources, in VBOs the vertices are fixed up
4239 if (!e->buffer_object)
4241 glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride,
4242 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4243 } else {
4244 glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4245 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4247 checkGLcall("glVertexPointer(...)");
4248 glEnableClientState(GL_VERTEX_ARRAY);
4249 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4252 /* Normals -------------------------------------------------*/
4253 if (si->use_map & (1 << WINED3D_FFP_NORMAL))
4255 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data));
4257 e = &si->elements[WINED3D_FFP_NORMAL];
4258 if (curVBO != e->buffer_object)
4260 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4261 checkGLcall("glBindBufferARB");
4262 curVBO = e->buffer_object;
4264 glNormalPointer(e->format_desc->gl_vtx_type, e->stride,
4265 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4266 checkGLcall("glNormalPointer(...)");
4267 glEnableClientState(GL_NORMAL_ARRAY);
4268 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4270 } else {
4271 glNormal3f(0, 0, 0);
4272 checkGLcall("glNormal3f(0, 0, 0)");
4275 /* Diffuse Colour --------------------------------------------*/
4276 /* WARNING: Data here MUST be in RGBA format, so cannot */
4277 /* go directly into fast mode from app pgm, because */
4278 /* directx requires data in BGRA format. */
4279 /* currently fixupVertices swizzles the format, but this isn't*/
4280 /* very practical when using VBOs */
4281 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4282 /* , or the user doesn't care and wants the speed advantage */
4284 if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
4286 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4288 e = &si->elements[WINED3D_FFP_DIFFUSE];
4289 if (curVBO != e->buffer_object)
4291 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4292 checkGLcall("glBindBufferARB");
4293 curVBO = e->buffer_object;
4296 glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4297 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4298 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4299 glEnableClientState(GL_COLOR_ARRAY);
4300 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4302 } else {
4303 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4304 checkGLcall("glColor4f(1, 1, 1, 1)");
4307 /* Specular Colour ------------------------------------------*/
4308 if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
4310 TRACE("setting specular colour\n");
4311 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4313 e = &si->elements[WINED3D_FFP_SPECULAR];
4314 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4315 GLenum type = e->format_desc->gl_vtx_type;
4316 GLint format = e->format_desc->gl_vtx_format;
4318 if (curVBO != e->buffer_object)
4320 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4321 checkGLcall("glBindBufferARB");
4322 curVBO = e->buffer_object;
4325 if(format != 4 || (GLINFO_LOCATION.quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
4327 /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
4328 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
4329 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
4330 * 4 component secondary colors use it
4332 GL_EXTCALL(glSecondaryColorPointerEXT)(format, type,
4333 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4334 checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
4336 else
4338 switch(type)
4340 case GL_UNSIGNED_BYTE:
4341 GL_EXTCALL(glSecondaryColorPointerEXT)(3, GL_UNSIGNED_BYTE,
4342 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4343 checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
4344 break;
4346 default:
4347 FIXME("Add 4 component specular color pointers for type %x\n", type);
4348 /* Make sure that the right color component is dropped */
4349 GL_EXTCALL(glSecondaryColorPointerEXT)(3, type,
4350 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4351 checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
4354 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4355 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4356 } else {
4358 /* Missing specular color is not critical, no warnings */
4359 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4362 } else {
4363 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4364 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4365 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4366 } else {
4368 /* Missing specular color is not critical, no warnings */
4369 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4373 /* Texture coords -------------------------------------------*/
4374 loadTexCoords(context, stateblock, si, &curVBO);
4377 static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations)
4379 /* Dump out what parts we have supplied */
4380 TRACE("Strided Data:\n");
4381 TRACE_STRIDED((dataLocations), WINED3D_FFP_POSITION);
4382 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDWEIGHT);
4383 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDINDICES);
4384 TRACE_STRIDED((dataLocations), WINED3D_FFP_NORMAL);
4385 TRACE_STRIDED((dataLocations), WINED3D_FFP_PSIZE);
4386 TRACE_STRIDED((dataLocations), WINED3D_FFP_DIFFUSE);
4387 TRACE_STRIDED((dataLocations), WINED3D_FFP_SPECULAR);
4388 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD0);
4389 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD1);
4390 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD2);
4391 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD3);
4392 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD4);
4393 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD5);
4394 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD6);
4395 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD7);
4397 return;
4400 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4402 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4403 BOOL fixup = FALSE;
4404 struct wined3d_stream_info *dataLocations = &device->strided_streams;
4405 BOOL useVertexShaderFunction;
4406 BOOL load_numbered = FALSE;
4407 BOOL load_named = FALSE;
4409 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4411 if(device->up_strided) {
4412 /* Note: this is a ddraw fixed-function code path */
4413 TRACE("================ Strided Input ===================\n");
4414 device_stream_info_from_strided(device, device->up_strided, dataLocations);
4416 if(TRACE_ON(d3d)) {
4417 drawPrimitiveTraceDataLocations(dataLocations);
4419 } else {
4420 /* Note: This is a fixed function or shader codepath.
4421 * This means it must handle both types of strided data.
4422 * Shaders must go through here to zero the strided data, even if they
4423 * don't set any declaration at all
4425 TRACE("================ Vertex Declaration ===================\n");
4426 device_stream_info_from_declaration(device, useVertexShaderFunction, dataLocations, &fixup);
4429 if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4431 if(useVertexShaderFunction) {
4432 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4433 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4434 device->useDrawStridedSlow = TRUE;
4435 } else {
4436 load_numbered = TRUE;
4437 device->useDrawStridedSlow = FALSE;
4440 else
4442 WORD slow_mask = (1 << WINED3D_FFP_PSIZE);
4443 slow_mask |= -!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
4445 if (fixup || (!dataLocations->position_transformed
4446 && !(dataLocations->use_map & slow_mask)))
4448 /* Load the vertex data using named arrays */
4449 load_named = TRUE;
4450 device->useDrawStridedSlow = FALSE;
4452 else
4454 TRACE("Not loading vertex data\n");
4455 device->useDrawStridedSlow = TRUE;
4459 if (context->numberedArraysLoaded && !load_numbered)
4461 unloadNumberedArrays(stateblock, context);
4462 context->numberedArraysLoaded = FALSE;
4463 context->numbered_array_mask = 0;
4465 else if (context->namedArraysLoaded)
4467 unloadVertexData(context);
4468 context->namedArraysLoaded = FALSE;
4471 if (load_numbered)
4473 TRACE("Loading numbered arrays\n");
4474 loadNumberedArrays(stateblock, dataLocations, context);
4475 context->numberedArraysLoaded = TRUE;
4477 else if (load_named)
4479 TRACE("Loading vertex data\n");
4480 loadVertexData(context, stateblock, dataLocations);
4481 context->namedArraysLoaded = TRUE;
4485 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4487 BOOL updateFog = FALSE;
4488 BOOL useVertexShaderFunction = use_vs(stateblock);
4489 BOOL usePixelShaderFunction = use_ps(stateblock);
4490 BOOL transformed;
4491 /* Some stuff is in the device until we have per context tracking */
4492 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4493 BOOL wasrhw = context->last_was_rhw;
4494 unsigned int i;
4496 transformed = device->strided_streams.position_transformed;
4497 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4498 updateFog = TRUE;
4501 /* Reapply lighting if it is not scheduled for reapplication already */
4502 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4503 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4506 if (transformed) {
4507 context->last_was_rhw = TRUE;
4508 } else {
4510 /* Untransformed, so relies on the view and projection matrices */
4511 context->last_was_rhw = FALSE;
4512 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4513 device->untransformed = TRUE;
4515 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4516 * Not needed as long as only hw shaders are supported
4519 /* This sets the shader output position correction constants.
4520 * TODO: Move to the viewport state
4522 if (useVertexShaderFunction)
4524 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4525 device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f;
4526 device->posFixup[3] = device->posFixup[1] * yoffset;
4530 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4531 * off this function will be called again anyway to make sure they're properly set
4533 if(!useVertexShaderFunction) {
4534 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4535 * or transformed / untransformed was switched
4537 if(wasrhw != context->last_was_rhw &&
4538 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4539 !isStateDirty(context, STATE_VIEWPORT)) {
4540 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4542 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4543 * mode.
4545 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4546 * this check will fail and the matrix not applied again. This is OK because a simple
4547 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4548 * needs of the vertex declaration.
4550 * World and view matrix go into the same gl matrix, so only apply them when neither is
4551 * dirty
4553 if(transformed != wasrhw &&
4554 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4555 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4556 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4559 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4560 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4563 if(context->last_was_vshader) {
4564 updateFog = TRUE;
4565 if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4566 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4568 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4569 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4572 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4573 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4575 } else {
4576 if(!context->last_was_vshader) {
4577 static BOOL warned = FALSE;
4578 if(!device->vs_clipping) {
4579 /* Disable all clip planes to get defined results on all drivers. See comment in the
4580 * state_clipping state handler
4582 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4583 glDisable(GL_CLIP_PLANE0 + i);
4584 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4587 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4588 FIXME("Clipping not supported with vertex shaders\n");
4589 warned = TRUE;
4592 if(wasrhw) {
4593 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4594 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4595 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4596 * fixed function vertex processing states back in a sane state before switching to shaders
4598 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4599 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4601 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4602 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4605 updateFog = TRUE;
4607 /* Vertex shader clipping ignores the view matrix. Update all clipplanes
4608 * (Note: ARB shaders can read the clip planes for clipping emulation even if
4609 * device->vs_clipping is false.
4611 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4612 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4617 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4618 * application
4620 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4621 device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction);
4623 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4624 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4628 context->last_was_vshader = useVertexShaderFunction;
4630 if(updateFog) {
4631 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4633 if(!useVertexShaderFunction) {
4634 int i;
4635 for(i = 0; i < MAX_TEXTURES; i++) {
4636 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4637 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4643 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4645 UINT width, height;
4646 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4647 WINED3DVIEWPORT vp = stateblock->viewport;
4649 if(vp.Width > target->currentDesc.Width) vp.Width = target->currentDesc.Width;
4650 if(vp.Height > target->currentDesc.Height) vp.Height = target->currentDesc.Height;
4652 glDepthRange(vp.MinZ, vp.MaxZ);
4653 checkGLcall("glDepthRange");
4654 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4656 if (context->render_offscreen)
4658 glViewport(vp.X, vp.Y, vp.Width, vp.Height);
4659 } else {
4660 target->get_drawable_size(context, &width, &height);
4662 glViewport(vp.X,
4663 (height - (vp.Y + vp.Height)),
4664 vp.Width, vp.Height);
4667 checkGLcall("glViewport");
4670 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4672 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4674 stateblock->wineD3DDevice->posFixup[2] = (63.0f / 64.0f) / stateblock->viewport.Width;
4675 stateblock->wineD3DDevice->posFixup[3] = stateblock->wineD3DDevice->posFixup[1] * yoffset;
4677 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4678 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4680 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4681 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4685 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4687 UINT Index = state - STATE_ACTIVELIGHT(0);
4688 const struct wined3d_light_info *lightInfo = stateblock->activeLights[Index];
4690 if(!lightInfo) {
4691 glDisable(GL_LIGHT0 + Index);
4692 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4693 } else {
4694 float quad_att;
4695 float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
4697 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4698 glMatrixMode(GL_MODELVIEW);
4699 glPushMatrix();
4700 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4702 /* Diffuse: */
4703 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4704 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4705 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4706 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4707 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4708 checkGLcall("glLightfv");
4710 /* Specular */
4711 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4712 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4713 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4714 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4715 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4716 checkGLcall("glLightfv");
4718 /* Ambient */
4719 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4720 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4721 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4722 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4723 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4724 checkGLcall("glLightfv");
4726 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4727 quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4728 } else {
4729 quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */
4732 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4733 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4734 * Attenuation0 to NaN and crashes in the gl lib
4737 switch (lightInfo->OriginalParms.Type) {
4738 case WINED3DLIGHT_POINT:
4739 /* Position */
4740 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4741 checkGLcall("glLightfv");
4742 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4743 checkGLcall("glLightf");
4744 /* Attenuation - Are these right? guessing... */
4745 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4746 checkGLcall("glLightf");
4747 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4748 checkGLcall("glLightf");
4749 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4750 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4751 checkGLcall("glLightf");
4752 /* FIXME: Range */
4753 break;
4755 case WINED3DLIGHT_SPOT:
4756 /* Position */
4757 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4758 checkGLcall("glLightfv");
4759 /* Direction */
4760 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4761 checkGLcall("glLightfv");
4762 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4763 checkGLcall("glLightf");
4764 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4765 checkGLcall("glLightf");
4766 /* Attenuation - Are these right? guessing... */
4767 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4768 checkGLcall("glLightf");
4769 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4770 checkGLcall("glLightf");
4771 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4772 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4773 checkGLcall("glLightf");
4774 /* FIXME: Range */
4775 break;
4777 case WINED3DLIGHT_DIRECTIONAL:
4778 /* Direction */
4779 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4780 checkGLcall("glLightfv");
4781 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4782 checkGLcall("glLightf");
4783 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4784 checkGLcall("glLightf");
4785 break;
4787 default:
4788 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4791 /* Restore the modelview matrix */
4792 glPopMatrix();
4794 glEnable(GL_LIGHT0 + Index);
4795 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4798 return;
4801 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4803 RECT *pRect = &stateblock->scissorRect;
4804 UINT height;
4805 UINT width;
4806 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4808 target->get_drawable_size(context, &width, &height);
4809 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4810 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4812 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4813 pRect->right - pRect->left, pRect->bottom - pRect->top);
4815 if (context->render_offscreen)
4817 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4818 } else {
4819 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4821 checkGLcall("glScissor");
4824 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4826 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4827 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4828 } else {
4829 struct wined3d_buffer *ib = (struct wined3d_buffer *) stateblock->pIndexData;
4830 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4834 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4836 if (context->render_offscreen)
4838 glFrontFace(GL_CCW);
4839 checkGLcall("glFrontFace(GL_CCW)");
4840 } else {
4841 glFrontFace(GL_CW);
4842 checkGLcall("glFrontFace(GL_CW)");
4846 const struct StateEntryTemplate misc_state_template[] = {
4847 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4848 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4849 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4850 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4851 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4852 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4853 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { 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_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4856 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4857 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4858 { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4859 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
4860 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
4861 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4862 * vshader loadings are untied from each other
4864 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4865 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4866 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4867 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4868 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4869 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4870 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4871 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4872 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4873 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4874 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4875 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4876 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4877 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4878 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4879 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4880 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4881 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4882 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4883 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4884 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4885 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4886 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4887 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4888 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4889 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4890 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4891 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4892 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4893 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4894 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4895 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4896 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4897 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4898 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4899 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4900 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4901 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4902 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4903 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4904 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4905 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4906 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4907 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4908 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4909 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4910 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4911 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4912 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4913 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4915 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
4916 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4917 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE },
4918 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE },
4919 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE },
4920 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE },
4921 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE },
4922 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE },
4923 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
4924 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE },
4925 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE },
4926 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE },
4927 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE },
4928 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE },
4929 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4930 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4931 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4932 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4933 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE },
4934 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE },
4935 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE },
4936 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE },
4937 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE },
4938 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE },
4939 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE },
4940 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE },
4941 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE },
4942 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE },
4943 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE },
4944 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE },
4945 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE },
4946 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4947 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4948 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4949 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4950 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4951 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4952 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4953 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4954 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE },
4955 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4956 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4957 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4958 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4959 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4960 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4961 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4962 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4963 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4964 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4965 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4966 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4967 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4968 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4969 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4970 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4971 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4972 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4973 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4974 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4975 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4976 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE },
4977 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE },
4978 { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE },
4979 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE },
4980 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE },
4981 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE },
4982 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE },
4983 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4984 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4985 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4986 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4987 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4988 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4989 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4990 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4991 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE },
4992 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE },
4993 { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE },
4994 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4995 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4996 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE },
4997 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE },
4998 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
4999 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5000 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5001 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5002 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
5003 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE },
5004 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
5005 /* Samplers */
5006 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE },
5007 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE },
5008 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE },
5009 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE },
5010 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE },
5011 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE },
5012 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE },
5013 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE },
5014 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE },
5015 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE },
5016 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE },
5017 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE },
5018 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE },
5019 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE },
5020 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE },
5021 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE },
5022 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE },
5023 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE },
5024 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE },
5025 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
5026 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5029 const struct StateEntryTemplate ffp_vertexstate_template[] = {
5030 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5031 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5032 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5033 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5034 /* Clip planes */
5035 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
5036 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
5037 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
5038 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
5039 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
5040 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
5041 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
5042 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
5043 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE },
5044 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE },
5045 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE },
5046 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE },
5047 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE },
5048 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE },
5049 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE },
5050 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE },
5051 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE },
5052 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE },
5053 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE },
5054 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE },
5055 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE },
5056 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE },
5057 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE },
5058 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE },
5059 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE },
5060 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE },
5061 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE },
5062 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE },
5063 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE },
5064 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE },
5065 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE },
5066 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE },
5067 /* Lights */
5068 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE },
5069 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE },
5070 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE },
5071 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE },
5072 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE },
5073 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE },
5074 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE },
5075 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE },
5076 /* Viewport */
5077 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE },
5078 /* Transform states follow */
5079 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE },
5080 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE },
5081 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5082 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5083 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5084 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5085 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5086 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5087 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5088 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE },
5208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE },
5209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE },
5210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE },
5211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE },
5212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE },
5213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE },
5214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE },
5215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE },
5216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE },
5217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE },
5218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE },
5219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE },
5220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE },
5221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE },
5222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE },
5223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE },
5224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE },
5225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE },
5226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE },
5227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE },
5228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE },
5229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE },
5230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE },
5231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE },
5232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE },
5233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE },
5234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE },
5235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE },
5236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE },
5237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE },
5238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE },
5239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE },
5240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE },
5241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE },
5242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE },
5243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE },
5244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE },
5245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE },
5246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE },
5247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE },
5248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE },
5249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE },
5250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE },
5251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE },
5252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE },
5253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE },
5254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE },
5255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE },
5256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE },
5257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE },
5258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE },
5259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE },
5260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE },
5261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE },
5262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE },
5263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE },
5264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE },
5265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE },
5266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE },
5267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE },
5268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE },
5269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE },
5270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE },
5271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE },
5272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE },
5273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE },
5274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE },
5275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE },
5276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE },
5277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE },
5278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE },
5279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE },
5280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE },
5281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE },
5282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE },
5283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE },
5284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE },
5285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE },
5286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE },
5287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE },
5288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE },
5289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE },
5290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE },
5291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE },
5292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE },
5293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE },
5294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE },
5295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE },
5296 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE },
5297 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE },
5298 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE },
5299 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE },
5300 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE },
5301 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE },
5302 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE },
5303 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE },
5304 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE },
5305 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE },
5306 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE },
5307 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE },
5308 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE },
5309 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE },
5310 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE },
5311 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE },
5312 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE },
5313 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE },
5314 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE },
5315 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE },
5316 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE },
5317 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE },
5318 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE },
5319 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE },
5320 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE },
5321 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE },
5322 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE },
5323 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE },
5324 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE },
5325 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE },
5326 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE },
5327 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE },
5328 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE },
5329 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE },
5330 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE },
5331 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE },
5332 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE },
5333 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE },
5334 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE },
5335 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE },
5336 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE },
5337 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE },
5338 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE },
5339 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE },
5340 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE },
5341 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE },
5342 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE },
5343 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE },
5344 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE },
5345 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5346 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5347 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5348 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5349 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5350 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5351 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5352 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5353 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5354 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5355 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5356 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5357 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5358 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5359 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5360 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5361 /* Fog */
5362 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5363 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5364 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5365 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5366 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE },
5367 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5368 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5369 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE },
5370 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE },
5371 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5372 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE },
5373 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE },
5374 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5375 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5376 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5377 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5378 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5379 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE },
5380 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5381 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5382 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5383 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5384 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5385 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE },
5386 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5387 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5388 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5389 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5390 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5391 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5392 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5393 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5394 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5395 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5397 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5398 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5399 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5400 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5401 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5402 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5403 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5404 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5405 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5406 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5407 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5408 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5409 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5410 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5411 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5412 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5413 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5414 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5415 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5416 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5417 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5418 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5419 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5420 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5421 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5424 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5425 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5426 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5427 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5428 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5429 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5430 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5431 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5432 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5433 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5434 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5435 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5436 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5437 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5438 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5439 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5440 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5441 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5442 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5443 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5444 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5445 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5446 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5447 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5448 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5449 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5450 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5451 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5452 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5453 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5454 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5455 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5456 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5457 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5458 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5459 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5460 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5461 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5462 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5463 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5464 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5465 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5466 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5467 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5468 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5469 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5470 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5471 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5472 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5473 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5474 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5475 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5476 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5477 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5478 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5479 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5480 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5481 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5482 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5483 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5484 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5485 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5486 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5487 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5488 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5489 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5490 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5491 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5492 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5493 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5494 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5495 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5496 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5497 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5498 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5499 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5500 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5501 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5502 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5503 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5504 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5505 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5506 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5507 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE },
5508 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE },
5509 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE },
5510 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE },
5511 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5512 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5513 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5514 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5515 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5516 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE },
5517 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE },
5518 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE },
5519 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE },
5520 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE },
5521 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE },
5522 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE },
5523 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE },
5524 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5526 #undef GLINFO_LOCATION
5528 #define GLINFO_LOCATION (*gl_info)
5529 /* Context activation is done by the caller. */
5530 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5532 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype,
5533 const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps)
5535 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5536 WINED3DTEXOPCAPS_ADDSIGNED |
5537 WINED3DTEXOPCAPS_ADDSIGNED2X |
5538 WINED3DTEXOPCAPS_MODULATE |
5539 WINED3DTEXOPCAPS_MODULATE2X |
5540 WINED3DTEXOPCAPS_MODULATE4X |
5541 WINED3DTEXOPCAPS_SELECTARG1 |
5542 WINED3DTEXOPCAPS_SELECTARG2 |
5543 WINED3DTEXOPCAPS_DISABLE;
5545 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5546 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5547 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5548 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5549 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5550 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5551 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5552 WINED3DTEXOPCAPS_LERP |
5553 WINED3DTEXOPCAPS_SUBTRACT;
5555 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5556 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5557 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5558 WINED3DTEXOPCAPS_MULTIPLYADD |
5559 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5560 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5561 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5563 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5564 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5566 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5567 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5570 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5571 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5572 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5574 if (TRACE_ON(d3d))
5576 TRACE("Checking support for fixup:\n");
5577 dump_color_fixup_desc(fixup);
5580 /* We only support identity conversions. */
5581 if (is_identity_fixup(fixup))
5583 TRACE("[OK]\n");
5584 return TRUE;
5587 TRACE("[FAILED]\n");
5588 return FALSE;
5591 const struct fragment_pipeline ffp_fragment_pipeline = {
5592 ffp_enable,
5593 ffp_fragment_get_caps,
5594 ffp_fragment_alloc,
5595 ffp_fragment_free,
5596 ffp_color_fixup_supported,
5597 ffp_fragmentstate_template,
5598 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5601 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5603 unsigned int i;
5604 for(i = 0; funcs[i]; i++);
5605 return i;
5608 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5610 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5611 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5614 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5616 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5617 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5618 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5621 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5622 const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
5623 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5625 unsigned int i, type, handlers;
5626 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5627 const struct StateEntryTemplate *cur;
5628 BOOL set[STATE_HIGHEST + 1];
5630 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5632 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5633 StateTable[i].representative = 0;
5634 StateTable[i].apply = state_undefined;
5637 for(type = 0; type < 3; type++) {
5638 /* This switch decides the order in which the states are applied */
5639 switch(type) {
5640 case 0: cur = misc; break;
5641 case 1: cur = fragment->states; break;
5642 case 2: cur = vertex; break;
5643 default: cur = NULL; /* Stupid compiler */
5645 if(!cur) continue;
5647 /* GL extension filtering should not prevent multiple handlers being applied from different
5648 * pipeline parts
5650 memset(set, 0, sizeof(set));
5652 for(i = 0; cur[i].state; i++) {
5653 APPLYSTATEFUNC *funcs_array;
5655 /* Only use the first matching state with the available extension from one template.
5656 * e.g.
5657 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5658 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5660 * if GL_XYZ_fancy is supported, ignore the 2nd line
5662 if(set[cur[i].state]) continue;
5663 /* Skip state lines depending on unsupported extensions */
5664 if (!GL_SUPPORT(cur[i].extension)) continue;
5665 set[cur[i].state] = TRUE;
5666 /* In some cases having an extension means that nothing has to be
5667 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5668 * supported, the texture coordinate fixup can be ignored. If the
5669 * apply function is used, mark the state set(done above) to prevent
5670 * applying later lines, but do not record anything in the state
5671 * table
5673 if(!cur[i].content.apply) continue;
5675 handlers = num_handlers(multistate_funcs[cur[i].state]);
5676 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5677 switch(handlers) {
5678 case 0:
5679 StateTable[cur[i].state].apply = cur[i].content.apply;
5680 break;
5681 case 1:
5682 StateTable[cur[i].state].apply = multistate_apply_2;
5683 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5685 sizeof(**dev_multistate_funcs) * 2);
5686 if (!dev_multistate_funcs[cur[i].state]) {
5687 goto out_of_mem;
5690 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5691 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5692 break;
5693 case 2:
5694 StateTable[cur[i].state].apply = multistate_apply_3;
5695 funcs_array = HeapReAlloc(GetProcessHeap(),
5697 dev_multistate_funcs[cur[i].state],
5698 sizeof(**dev_multistate_funcs) * 3);
5699 if (!funcs_array) {
5700 goto out_of_mem;
5703 dev_multistate_funcs[cur[i].state] = funcs_array;
5704 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5705 break;
5706 default:
5707 ERR("Unexpected amount of state handlers for state %u: %u\n",
5708 cur[i].state, handlers + 1);
5711 if(StateTable[cur[i].state].representative &&
5712 StateTable[cur[i].state].representative != cur[i].content.representative) {
5713 FIXME("State %u has different representatives in different pipeline parts\n",
5714 cur[i].state);
5716 StateTable[cur[i].state].representative = cur[i].content.representative;
5720 return WINED3D_OK;
5722 out_of_mem:
5723 for (i = 0; i <= STATE_HIGHEST; ++i) {
5724 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5727 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5729 return E_OUTOFMEMORY;
5731 #undef GLINFO_LOCATION