push 6377a023768d7480eb1b17e57456824888936b43
[wine/hacks.git] / dlls / wined3d / state.c
blob44c0c064b81c093cae331471fa747bbfed4a6901
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
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
39 /* GL locking for state handlers is done by the caller. */
41 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
43 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
44 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
45 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
47 if(STATE_IS_RENDER(state)) {
48 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
49 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
50 } else {
51 /* Shouldn't have an unknown type here */
52 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
56 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
57 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
58 * list without causing confusing terminal output. Deliberately no special debug name here
59 * because its undefined.
61 WARN("undefined state %d\n", state);
64 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *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, WineD3DContext *context) {
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
93 return;
96 if (stateblock->renderState[WINED3DRS_LIGHTING]
97 && !stateblock->wineD3DDevice->strided_streams.position_transformed)
99 glEnable(GL_LIGHTING);
100 checkGLcall("glEnable GL_LIGHTING");
101 } else {
102 glDisable(GL_LIGHTING);
103 checkGLcall("glDisable GL_LIGHTING");
107 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
108 /* No z test without depth stencil buffers */
109 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
110 TRACE("No Z buffer - disabling depth test\n");
111 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
112 checkGLcall("glDisable GL_DEPTH_TEST");
113 return;
116 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
117 case WINED3DZB_FALSE:
118 glDisable(GL_DEPTH_TEST);
119 checkGLcall("glDisable GL_DEPTH_TEST");
120 break;
121 case WINED3DZB_TRUE:
122 glEnable(GL_DEPTH_TEST);
123 checkGLcall("glEnable GL_DEPTH_TEST");
124 break;
125 case WINED3DZB_USEW:
126 glEnable(GL_DEPTH_TEST);
127 checkGLcall("glEnable GL_DEPTH_TEST");
128 FIXME("W buffer is not well handled\n");
129 break;
130 default:
131 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
135 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
136 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
137 * switch
139 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
140 case WINED3DCULL_NONE:
141 glDisable(GL_CULL_FACE);
142 checkGLcall("glDisable GL_CULL_FACE");
143 break;
144 case WINED3DCULL_CW:
145 glEnable(GL_CULL_FACE);
146 checkGLcall("glEnable GL_CULL_FACE");
147 glCullFace(GL_FRONT);
148 checkGLcall("glCullFace(GL_FRONT)");
149 break;
150 case WINED3DCULL_CCW:
151 glEnable(GL_CULL_FACE);
152 checkGLcall("glEnable GL_CULL_FACE");
153 glCullFace(GL_BACK);
154 checkGLcall("glCullFace(GL_BACK)");
155 break;
156 default:
157 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
161 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
162 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
163 case WINED3DSHADE_FLAT:
164 glShadeModel(GL_FLAT);
165 checkGLcall("glShadeModel(GL_FLAT)");
166 break;
167 case WINED3DSHADE_GOURAUD:
168 glShadeModel(GL_SMOOTH);
169 checkGLcall("glShadeModel(GL_SMOOTH)");
170 break;
171 case WINED3DSHADE_PHONG:
172 FIXME("WINED3DSHADE_PHONG isn't supported\n");
173 break;
174 default:
175 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
179 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
180 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
181 glEnable(GL_DITHER);
182 checkGLcall("glEnable GL_DITHER");
183 } else {
184 glDisable(GL_DITHER);
185 checkGLcall("glDisable GL_DITHER");
189 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
190 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
191 * this has to be merged with ZENABLE and ZFUNC
193 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
194 glDepthMask(1);
195 checkGLcall("glDepthMask(1)");
196 } else {
197 glDepthMask(0);
198 checkGLcall("glDepthMask(0)");
202 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
203 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
205 if(glParm) {
206 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
207 static BOOL once = FALSE;
208 /* There are a few issues with this: First, our inability to
209 * select a proper Z depth, most of the time we're stuck with
210 * D24S8, even if the app selects D32 or D16. There seem to be
211 * some other precision problems which have to be debugged to
212 * make NOTEQUAL and EQUAL work properly
214 if(!once) {
215 once = TRUE;
216 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
220 glDepthFunc(glParm);
221 checkGLcall("glDepthFunc");
225 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
226 float col[4];
227 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
229 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
230 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
231 checkGLcall("glLightModel for MODEL_AMBIENT");
234 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
235 int srcBlend = GL_ZERO;
236 int dstBlend = GL_ZERO;
237 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
239 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
240 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
241 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
242 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
244 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
245 * The d3d9 visual test confirms the behavior. */
246 if (!(target->resource.format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
248 glDisable(GL_BLEND);
249 checkGLcall("glDisable GL_BLEND");
250 return;
251 } else {
252 glEnable(GL_BLEND);
253 checkGLcall("glEnable GL_BLEND");
255 } else {
256 glDisable(GL_BLEND);
257 checkGLcall("glDisable GL_BLEND");
258 /* Nothing more to do - get out */
259 return;
262 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
263 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
264 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
265 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
266 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
267 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
268 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
269 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
270 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
272 /* To compensate the lack of format switching with backbuffer offscreen rendering,
273 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
274 * if the render target doesn't support alpha blending. A nonexistent alpha channel
275 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
277 case WINED3DBLEND_DESTALPHA :
278 dstBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
279 break;
280 case WINED3DBLEND_INVDESTALPHA :
281 dstBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
282 break;
284 case WINED3DBLEND_SRCALPHASAT :
285 dstBlend = GL_SRC_ALPHA_SATURATE;
286 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
287 break;
289 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
290 * values which are still valid up to d3d9. They should not occur as dest blend values
292 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
293 srcBlend = GL_SRC_ALPHA;
294 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
295 break;
297 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
298 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
299 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
300 break;
302 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
303 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
304 default:
305 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
308 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
309 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
310 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
311 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
312 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
313 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
314 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
315 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
316 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
317 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
319 case WINED3DBLEND_DESTALPHA :
320 srcBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
321 break;
322 case WINED3DBLEND_INVDESTALPHA :
323 srcBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
324 break;
326 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
327 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
328 break;
330 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
331 dstBlend = GL_SRC_ALPHA;
332 break;
334 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
335 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
336 default:
337 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
340 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
341 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
342 glEnable(GL_LINE_SMOOTH);
343 checkGLcall("glEnable(GL_LINE_SMOOTH)");
344 if(srcBlend != GL_SRC_ALPHA) {
345 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
347 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
348 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
350 } else {
351 glDisable(GL_LINE_SMOOTH);
352 checkGLcall("glDisable(GL_LINE_SMOOTH)");
355 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
356 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
357 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
360 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
361 int srcBlendAlpha = GL_ZERO;
362 int dstBlendAlpha = GL_ZERO;
364 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
365 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
366 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
367 return;
370 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
371 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
372 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
373 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
374 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
375 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
376 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
377 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
378 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
379 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
380 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
381 case WINED3DBLEND_SRCALPHASAT :
382 dstBlend = GL_SRC_ALPHA_SATURATE;
383 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
384 break;
385 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
386 * values which are still valid up to d3d9. They should not occur as dest blend values
388 case WINED3DBLEND_BOTHSRCALPHA :
389 dstBlendAlpha = GL_SRC_ALPHA;
390 srcBlendAlpha = GL_SRC_ALPHA;
391 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
392 break;
393 case WINED3DBLEND_BOTHINVSRCALPHA :
394 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
395 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
396 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
397 break;
398 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
399 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
400 default:
401 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
404 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
405 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
406 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
407 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
408 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
409 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
410 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
411 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
412 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
413 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
414 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
415 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
416 case WINED3DBLEND_BOTHSRCALPHA :
417 srcBlendAlpha = GL_SRC_ALPHA;
418 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
419 break;
420 case WINED3DBLEND_BOTHINVSRCALPHA :
421 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
422 dstBlendAlpha = GL_SRC_ALPHA;
423 break;
424 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
425 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
426 default:
427 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
430 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
431 checkGLcall("glBlendFuncSeparateEXT");
432 } else {
433 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
434 glBlendFunc(srcBlend, dstBlend);
435 checkGLcall("glBlendFunc");
438 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
439 so it may need updating */
440 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
441 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
442 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
446 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
447 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
450 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
451 float col[4];
453 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
454 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
455 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
456 checkGLcall("glBlendColor");
459 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
460 int glParm = 0;
461 float ref;
462 BOOL enable_ckey = FALSE;
464 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
466 /* Find out if the texture on the first stage has a ckey set
467 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
468 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
469 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
470 * in case it finds some texture+colorkeyenable combination which needs extra care.
472 if (stateblock->textures[0])
474 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
476 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
478 IWineD3DSurfaceImpl *surf;
480 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
482 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
484 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
485 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
486 * surface has alpha bits */
487 if (!surf->resource.format_desc->alpha_mask) enable_ckey = TRUE;
492 if(enable_ckey || context->last_was_ckey) {
493 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
494 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
496 context->last_was_ckey = enable_ckey;
498 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
499 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
500 glEnable(GL_ALPHA_TEST);
501 checkGLcall("glEnable GL_ALPHA_TEST");
502 } else {
503 glDisable(GL_ALPHA_TEST);
504 checkGLcall("glDisable GL_ALPHA_TEST");
505 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
506 * enable call
508 return;
511 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
512 glParm = GL_NOTEQUAL;
513 ref = 0.0f;
514 } else {
515 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
516 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
518 if(glParm) {
519 glAlphaFunc(glParm, ref);
520 checkGLcall("glAlphaFunc");
524 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
525 DWORD enable = 0xFFFFFFFF;
526 DWORD disable = 0x00000000;
528 if (!stateblock->wineD3DDevice->vs_clipping && use_vs(stateblock))
530 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
531 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
532 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
533 * of that - don't do anything here and keep them disabled
535 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
536 static BOOL warned = FALSE;
537 if(!warned) {
538 FIXME("Clipping not supported with vertex shaders\n");
539 warned = TRUE;
542 return;
545 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
546 * of already set values
549 /* If enabling / disabling all
550 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
552 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
553 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
554 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
555 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
556 glDisable(GL_DEPTH_CLAMP_NV);
557 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
559 } else {
560 disable = 0xffffffff;
561 enable = 0x00;
562 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
563 glEnable(GL_DEPTH_CLAMP_NV);
564 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
568 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
569 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
570 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
571 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
572 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
573 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
575 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
576 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
577 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
578 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
579 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
580 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
582 /** update clipping status */
583 if (enable) {
584 stateblock->clip_status.ClipUnion = 0;
585 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
586 } else {
587 stateblock->clip_status.ClipUnion = 0;
588 stateblock->clip_status.ClipIntersection = 0;
592 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
593 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
596 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
597 int blendEquation = GL_FUNC_ADD;
598 int blendEquationAlpha = GL_FUNC_ADD;
600 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
601 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
602 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
603 return;
606 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
607 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
608 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
609 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
610 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
611 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
612 default:
613 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
616 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
617 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
618 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
619 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
620 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
621 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
622 default:
623 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
626 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
627 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
628 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
629 checkGLcall("glBlendEquationSeparateEXT");
630 } else {
631 TRACE("glBlendEquation(%x)\n", blendEquation);
632 GL_EXTCALL(glBlendEquationEXT(blendEquation));
633 checkGLcall("glBlendEquation");
637 static void
638 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
639 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
640 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
641 * specular color. This is wrong:
642 * Separate specular color means the specular colour is maintained separately, whereas
643 * single color means it is merged in. However in both cases they are being used to
644 * some extent.
645 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
646 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
647 * running 1.4 yet!
650 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
651 * Instead, we need to setup the FinalCombiner properly.
653 * The default setup for the FinalCombiner is:
655 * <variable> <input> <mapping> <usage>
656 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
657 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
658 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
659 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
660 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
661 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
662 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
664 * That's pretty much fine as it is, except for variable B, which needs to take
665 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
666 * whether WINED3DRS_SPECULARENABLE is enabled or not.
669 TRACE("Setting specular enable state and materials\n");
670 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
671 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
672 checkGLcall("glMaterialfv");
674 if(stateblock->material.Power > GL_LIMITS(shininess)) {
675 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
676 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
677 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
678 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
679 * them, it should be safe to do so without major visual distortions.
681 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
682 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
683 } else {
684 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
686 checkGLcall("glMaterialf(GL_SHININESS)");
688 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
689 glEnable(GL_COLOR_SUM_EXT);
690 } else {
691 TRACE("Specular colors cannot be enabled in this version of opengl\n");
693 checkGLcall("glEnable(GL_COLOR_SUM)");
695 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
696 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
697 checkGLcall("glFinalCombinerInputNV()");
699 } else {
700 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
702 /* for the case of enabled lighting: */
703 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
704 checkGLcall("glMaterialfv");
706 /* for the case of disabled lighting: */
707 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
708 glDisable(GL_COLOR_SUM_EXT);
709 } else {
710 TRACE("Specular colors cannot be disabled in this version of opengl\n");
712 checkGLcall("glDisable(GL_COLOR_SUM)");
714 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
715 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
716 checkGLcall("glFinalCombinerInputNV()");
720 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
721 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
722 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
723 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
724 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
725 stateblock->material.Specular.b, stateblock->material.Specular.a);
726 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
727 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
729 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
730 checkGLcall("glMaterialfv(GL_AMBIENT)");
731 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
732 checkGLcall("glMaterialfv(GL_DIFFUSE)");
733 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
734 checkGLcall("glMaterialfv(GL_EMISSION)");
737 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
738 unsigned int i;
740 /* Note the texture color applies to all textures whereas
741 * GL_TEXTURE_ENV_COLOR applies to active only
743 float col[4];
744 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
746 /* And now the default texture color as well */
747 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
748 /* Note the WINED3DRS value applies to all textures, but GL has one
749 * per texture, so apply it now ready to be used!
751 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
752 checkGLcall("glActiveTextureARB");
754 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
755 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
759 static void
760 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
761 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
762 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
763 GL_EXTCALL(glActiveStencilFaceEXT(face));
764 checkGLcall("glActiveStencilFaceEXT(...)");
765 glStencilFunc(func, ref, mask);
766 checkGLcall("glStencilFunc(...)");
767 glStencilOp(stencilFail, depthFail, stencilPass);
768 checkGLcall("glStencilOp(...)");
771 static void
772 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
773 DWORD onesided_enable = FALSE;
774 DWORD twosided_enable = FALSE;
775 GLint func = GL_ALWAYS;
776 GLint func_ccw = GL_ALWAYS;
777 GLint ref = 0;
778 GLuint mask = 0;
779 GLint stencilFail = GL_KEEP;
780 GLint depthFail = GL_KEEP;
781 GLint stencilPass = GL_KEEP;
782 GLint stencilFail_ccw = GL_KEEP;
783 GLint depthFail_ccw = GL_KEEP;
784 GLint stencilPass_ccw = GL_KEEP;
786 /* No stencil test without a stencil buffer */
787 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
788 glDisable(GL_STENCIL_TEST);
789 checkGLcall("glDisable GL_STENCIL_TEST");
790 return;
793 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
794 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
795 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
796 func = GL_ALWAYS;
797 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
798 func_ccw = GL_ALWAYS;
799 ref = stateblock->renderState[WINED3DRS_STENCILREF];
800 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
801 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
802 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
803 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
804 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
805 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
806 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
808 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
809 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
810 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
811 onesided_enable, twosided_enable, ref, mask,
812 func, stencilFail, depthFail, stencilPass,
813 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
815 if (twosided_enable && onesided_enable) {
816 glEnable(GL_STENCIL_TEST);
817 checkGLcall("glEnable GL_STENCIL_TEST");
819 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
820 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
821 * which has an effect on the code below too. If we apply the front face
822 * afterwards, we are sure that the active stencil face is set to front,
823 * and other stencil functions which do not use two sided stencil do not have
824 * to set it back
826 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
827 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
828 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
829 stencilFail, depthFail, stencilPass);
830 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
831 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
832 checkGLcall("glStencilFuncSeparateATI(...)");
833 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
834 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
835 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
836 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
837 } else {
838 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
840 } else if(onesided_enable) {
841 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
842 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
843 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
846 /* This code disables the ATI extension as well, since the standard stencil functions are equal
847 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
849 glEnable(GL_STENCIL_TEST);
850 checkGLcall("glEnable GL_STENCIL_TEST");
851 glStencilFunc(func, ref, mask);
852 checkGLcall("glStencilFunc(...)");
853 glStencilOp(stencilFail, depthFail, stencilPass);
854 checkGLcall("glStencilOp(...)");
855 } else {
856 glDisable(GL_STENCIL_TEST);
857 checkGLcall("glDisable GL_STENCIL_TEST");
861 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
862 DWORD mask;
864 if(stateblock->wineD3DDevice->stencilBufferTarget) {
865 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
866 } else {
867 mask = 0;
870 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
871 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
872 glStencilMask(mask);
873 checkGLcall("glStencilMask");
874 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
875 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
876 glStencilMask(mask);
879 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
880 DWORD mask;
882 if(stateblock->wineD3DDevice->stencilBufferTarget) {
883 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
884 } else {
885 mask = 0;
888 glStencilMask(mask);
889 checkGLcall("glStencilMask");
892 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
894 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
896 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
898 /* Table fog on: Never use fog coords, and use per-fragment fog */
899 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
900 glHint(GL_FOG_HINT, GL_NICEST);
901 if(context->fog_coord) {
902 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
903 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
904 context->fog_coord = FALSE;
906 return;
909 /* Otherwise use per-vertex fog in any case */
910 glHint(GL_FOG_HINT, GL_FASTEST);
912 if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
913 /* No fog at all, or transformed vertices: Use fog coord */
914 if(!context->fog_coord) {
915 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
916 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
917 context->fog_coord = TRUE;
919 } else {
920 /* Otherwise, use the fragment depth */
921 if(context->fog_coord) {
922 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
923 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
924 context->fog_coord = FALSE;
929 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
930 float fogstart, fogend;
931 union {
932 DWORD d;
933 float f;
934 } tmpvalue;
936 switch(context->fog_source) {
937 case FOGSOURCE_VS:
938 fogstart = 1.0f;
939 fogend = 0.0f;
940 break;
942 case FOGSOURCE_COORD:
943 fogstart = 255.0f;
944 fogend = 0.0f;
945 break;
947 case FOGSOURCE_FFP:
948 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
949 fogstart = tmpvalue.f;
950 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
951 fogend = tmpvalue.f;
952 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
953 if(fogstart == fogend) {
954 fogstart = -1.0f / 0.0f;
955 fogend = 0.0f;
957 break;
959 default:
960 /* This should not happen.context->fog_source is set in wined3d, not the app.
961 * Still this is needed to make the compiler happy
963 ERR("Unexpected fog coordinate source\n");
964 fogstart = 0.0f;
965 fogend = 0.0f;
968 glFogf(GL_FOG_START, fogstart);
969 checkGLcall("glFogf(GL_FOG_START, fogstart)");
970 TRACE("Fog Start == %f\n", fogstart);
972 glFogf(GL_FOG_END, fogend);
973 checkGLcall("glFogf(GL_FOG_END, fogend)");
974 TRACE("Fog End == %f\n", fogend);
977 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
978 enum fogsource new_source;
980 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
982 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
983 /* No fog? Disable it, and we're done :-) */
984 glDisableWINE(GL_FOG);
985 checkGLcall("glDisable GL_FOG");
986 return;
989 /* Fog Rules:
991 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
992 * It can use the Z value of the vertex, or the alpha component of the specular color.
993 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
994 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
995 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
997 * FOGTABLEMODE != NONE:
998 * The Z value is used, with the equation specified, no matter what vertex type.
1000 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1001 * Per vertex fog is calculated using the specified fog equation and the parameters
1003 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1004 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1005 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1008 * Rules for vertex fog with shaders:
1010 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1011 * the fog computation to happen during transformation while openGL expects it to happen
1012 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1013 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1014 * To solve this problem, WineD3D does:
1015 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1016 * shader,
1017 * and 2) disables the fog computation (in either the fixed function or programmable
1018 * rasterizer) if using a vertex program.
1020 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1021 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1022 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1023 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1024 * There are some GL differences between specular fog coords and vertex shaders though.
1026 * With table fog the vertex shader fog coordinate is ignored.
1028 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1029 * without shaders).
1032 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1033 * the system will apply only pixel(=table) fog effects."
1035 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1036 if(use_vs(stateblock)) {
1037 glFogi(GL_FOG_MODE, GL_LINEAR);
1038 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1039 new_source = FOGSOURCE_VS;
1040 } else {
1041 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1042 /* If processed vertices are used, fall through to the NONE case */
1043 case WINED3DFOG_EXP:
1044 if(!context->last_was_rhw) {
1045 glFogi(GL_FOG_MODE, GL_EXP);
1046 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1047 new_source = FOGSOURCE_FFP;
1048 break;
1050 /* drop through */
1052 case WINED3DFOG_EXP2:
1053 if(!context->last_was_rhw) {
1054 glFogi(GL_FOG_MODE, GL_EXP2);
1055 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1056 new_source = FOGSOURCE_FFP;
1057 break;
1059 /* drop through */
1061 case WINED3DFOG_LINEAR:
1062 if(!context->last_was_rhw) {
1063 glFogi(GL_FOG_MODE, GL_LINEAR);
1064 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1065 new_source = FOGSOURCE_FFP;
1066 break;
1068 /* drop through */
1070 case WINED3DFOG_NONE:
1071 /* Both are none? According to msdn the alpha channel of the specular
1072 * color contains a fog factor. Set it in drawStridedSlow.
1073 * Same happens with Vertexfog on transformed vertices
1075 new_source = FOGSOURCE_COORD;
1076 glFogi(GL_FOG_MODE, GL_LINEAR);
1077 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1078 break;
1080 default:
1081 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1082 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1085 } else {
1086 new_source = FOGSOURCE_FFP;
1088 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1089 case WINED3DFOG_EXP:
1090 glFogi(GL_FOG_MODE, GL_EXP);
1091 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1092 break;
1094 case WINED3DFOG_EXP2:
1095 glFogi(GL_FOG_MODE, GL_EXP2);
1096 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1097 break;
1099 case WINED3DFOG_LINEAR:
1100 glFogi(GL_FOG_MODE, GL_LINEAR);
1101 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1102 break;
1104 case WINED3DFOG_NONE: /* Won't happen */
1105 default:
1106 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1110 glEnableWINE(GL_FOG);
1111 checkGLcall("glEnable GL_FOG");
1112 if(new_source != context->fog_source) {
1113 context->fog_source = new_source;
1114 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1118 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1119 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1120 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1124 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1125 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1126 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1127 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1128 } else {
1129 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1130 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1134 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1135 float col[4];
1136 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1137 glFogfv(GL_FOG_COLOR, &col[0]);
1138 checkGLcall("glFog GL_FOG_COLOR");
1141 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1142 union {
1143 DWORD d;
1144 float f;
1145 } tmpvalue;
1146 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1147 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1148 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1151 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1152 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1153 GLenum Parm = 0;
1154 const struct wined3d_stream_info_element *diffuse = &device->strided_streams.elements[WINED3D_FFP_DIFFUSE];
1155 BOOL isDiffuseSupplied;
1157 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1158 * The vertex declaration will call this function if the fixed function pipeline is used.
1161 if(isStateDirty(context, STATE_VDECL)) {
1162 return;
1165 isDiffuseSupplied = diffuse->data || diffuse->buffer_object;
1167 context->num_untracked_materials = 0;
1168 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1169 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1170 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1171 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1172 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1173 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1175 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1176 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1177 Parm = GL_AMBIENT_AND_DIFFUSE;
1178 } else {
1179 Parm = GL_DIFFUSE;
1181 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1182 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1183 context->num_untracked_materials++;
1185 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1186 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1187 context->num_untracked_materials++;
1189 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1190 Parm = GL_AMBIENT;
1191 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1192 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1193 context->num_untracked_materials++;
1195 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1196 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1197 context->num_untracked_materials++;
1199 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1200 Parm = GL_EMISSION;
1201 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1202 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1203 context->num_untracked_materials++;
1205 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1206 Parm = GL_SPECULAR;
1210 /* Nothing changed, return. */
1211 if (Parm == context->tracking_parm) return;
1213 if(!Parm) {
1214 glDisable(GL_COLOR_MATERIAL);
1215 checkGLcall("glDisable GL_COLOR_MATERIAL");
1216 } else {
1217 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1218 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1219 glEnable(GL_COLOR_MATERIAL);
1220 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1223 /* Apparently calls to glMaterialfv are ignored for properties we're
1224 * tracking with glColorMaterial, so apply those here. */
1225 switch (context->tracking_parm) {
1226 case GL_AMBIENT_AND_DIFFUSE:
1227 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1228 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1229 checkGLcall("glMaterialfv");
1230 break;
1232 case GL_DIFFUSE:
1233 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1234 checkGLcall("glMaterialfv");
1235 break;
1237 case GL_AMBIENT:
1238 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1239 checkGLcall("glMaterialfv");
1240 break;
1242 case GL_EMISSION:
1243 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1244 checkGLcall("glMaterialfv");
1245 break;
1247 case GL_SPECULAR:
1248 /* Only change material color if specular is enabled, otherwise it is set to black */
1249 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1250 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1251 checkGLcall("glMaterialfv");
1252 } else {
1253 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1254 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1255 checkGLcall("glMaterialfv");
1257 break;
1260 context->tracking_parm = Parm;
1263 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1264 union {
1265 DWORD d;
1266 WINED3DLINEPATTERN lp;
1267 } tmppattern;
1268 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1270 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1272 if (tmppattern.lp.wRepeatFactor) {
1273 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1274 checkGLcall("glLineStipple(repeat, linepattern)");
1275 glEnable(GL_LINE_STIPPLE);
1276 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1277 } else {
1278 glDisable(GL_LINE_STIPPLE);
1279 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1283 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1284 union {
1285 DWORD d;
1286 float f;
1287 } tmpvalue;
1289 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1290 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1291 TRACE("ZBias value %f\n", tmpvalue.f);
1292 glPolygonOffset(0, -tmpvalue.f);
1293 checkGLcall("glPolygonOffset(0, -Value)");
1294 glEnable(GL_POLYGON_OFFSET_FILL);
1295 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1296 glEnable(GL_POLYGON_OFFSET_LINE);
1297 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1298 glEnable(GL_POLYGON_OFFSET_POINT);
1299 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1300 } else {
1301 glDisable(GL_POLYGON_OFFSET_FILL);
1302 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1303 glDisable(GL_POLYGON_OFFSET_LINE);
1304 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1305 glDisable(GL_POLYGON_OFFSET_POINT);
1306 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1311 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1312 if(isStateDirty(context, STATE_VDECL)) {
1313 return;
1315 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1316 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1317 * by zero and is not properly defined in opengl, so avoid it
1319 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]
1320 && (stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].data
1321 || stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].buffer_object))
1323 glEnable(GL_NORMALIZE);
1324 checkGLcall("glEnable(GL_NORMALIZE);");
1325 } else {
1326 glDisable(GL_NORMALIZE);
1327 checkGLcall("glDisable(GL_NORMALIZE);");
1331 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1332 union {
1333 DWORD d;
1334 float f;
1335 } tmpvalue;
1337 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1338 if (tmpvalue.f != 1.0f)
1340 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1342 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1343 if (tmpvalue.f != 64.0f)
1345 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1350 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1351 union {
1352 DWORD d;
1353 float f;
1354 } min, max;
1356 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1357 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1359 /* Max point size trumps min point size */
1360 if(min.f > max.f) {
1361 min.f = max.f;
1364 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1365 checkGLcall("glPointParameterfEXT(...)");
1366 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1367 checkGLcall("glPointParameterfEXT(...)");
1370 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1371 union {
1372 DWORD d;
1373 float f;
1374 } min, max;
1376 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1377 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1379 /* Max point size trumps min point size */
1380 if(min.f > max.f) {
1381 min.f = max.f;
1384 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1385 checkGLcall("glPointParameterfARB(...)");
1386 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1387 checkGLcall("glPointParameterfARB(...)");
1390 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1391 /* TODO: Group this with the viewport */
1393 * POINTSCALEENABLE controls how point size value is treated. If set to
1394 * true, the point size is scaled with respect to height of viewport.
1395 * When set to false point size is in pixels.
1398 /* Default values */
1399 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1400 union {
1401 DWORD d;
1402 float f;
1403 } pointSize, A, B, C;
1405 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1406 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1407 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1408 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1410 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1411 GLfloat scaleFactor;
1412 float h = stateblock->viewport.Height;
1414 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1416 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1417 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1418 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1419 * are less than 1.0f. scale_factor = 1.0f / point_size.
1421 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1422 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1423 * is 1.0, but then accepts points below that and draws too small points
1425 pointSize.f = GL_LIMITS(pointsizemin);
1426 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1427 /* gl already scales the input to glPointSize,
1428 * d3d scales the result after the point size scale.
1429 * If the point size is bigger than the max size, use the
1430 * scaling to scale it bigger, and set the gl point size to max
1432 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1433 TRACE("scale: %f\n", scaleFactor);
1434 pointSize.f = GL_LIMITS(pointsize);
1435 } else {
1436 scaleFactor = 1.0f;
1438 scaleFactor = pow(h * scaleFactor, 2);
1440 att[0] = A.f / scaleFactor;
1441 att[1] = B.f / scaleFactor;
1442 att[2] = C.f / scaleFactor;
1445 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1446 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1447 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1449 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1450 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1451 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1452 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1453 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1456 glPointSize(pointSize.f);
1457 checkGLcall("glPointSize(...);");
1460 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1461 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1463 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1464 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1465 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1466 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1467 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1468 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1469 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1470 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1471 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1472 checkGLcall("glColorMask(...)");
1474 /* depends on WINED3DRS_COLORWRITEENABLE. */
1475 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1476 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1477 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1478 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1479 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1480 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1481 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1485 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1486 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1489 } else {
1490 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1491 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1495 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1496 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1497 TRACE("Last Pixel Drawing Enabled\n");
1498 } else {
1499 static BOOL warned;
1500 if (!warned) {
1501 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1502 warned = TRUE;
1503 } else {
1504 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1509 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1510 BOOL warned = FALSE;
1511 /* TODO: NV_POINT_SPRITE */
1512 if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1513 /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1514 FIXME("Point sprites not supported\n");
1515 warned = TRUE;
1519 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1520 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1521 BOOL warned = FALSE;
1522 if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) {
1523 if(use_ps(stateblock) || stateblock->lowest_disabled_stage > GL_LIMITS(point_sprite_units)) {
1524 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1525 warned = TRUE;
1529 glEnable(GL_POINT_SPRITE_ARB);
1530 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1531 } else {
1532 glDisable(GL_POINT_SPRITE_ARB);
1533 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1537 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1539 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1540 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1541 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1542 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1544 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1546 TRACE("Stub\n");
1547 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1548 stateblock->renderState[WINED3DRS_WRAP1] ||
1549 stateblock->renderState[WINED3DRS_WRAP2] ||
1550 stateblock->renderState[WINED3DRS_WRAP3] ||
1551 stateblock->renderState[WINED3DRS_WRAP4] ||
1552 stateblock->renderState[WINED3DRS_WRAP5] ||
1553 stateblock->renderState[WINED3DRS_WRAP6] ||
1554 stateblock->renderState[WINED3DRS_WRAP7] ||
1555 stateblock->renderState[WINED3DRS_WRAP8] ||
1556 stateblock->renderState[WINED3DRS_WRAP9] ||
1557 stateblock->renderState[WINED3DRS_WRAP10] ||
1558 stateblock->renderState[WINED3DRS_WRAP11] ||
1559 stateblock->renderState[WINED3DRS_WRAP12] ||
1560 stateblock->renderState[WINED3DRS_WRAP13] ||
1561 stateblock->renderState[WINED3DRS_WRAP14] ||
1562 stateblock->renderState[WINED3DRS_WRAP15] ) {
1563 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1567 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1568 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1569 WARN("Multisample antialiasing not supported by gl\n");
1573 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1574 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1575 glEnable(GL_MULTISAMPLE_ARB);
1576 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1577 } else {
1578 glDisable(GL_MULTISAMPLE_ARB);
1579 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1583 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1584 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1585 glEnable(GL_SCISSOR_TEST);
1586 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1587 } else {
1588 glDisable(GL_SCISSOR_TEST);
1589 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1593 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1594 union {
1595 DWORD d;
1596 float f;
1597 } tmpvalue;
1599 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1600 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1601 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1602 glEnable(GL_POLYGON_OFFSET_FILL);
1603 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1604 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1605 checkGLcall("glPolygonOffset(...)");
1606 } else {
1607 glDisable(GL_POLYGON_OFFSET_FILL);
1608 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1612 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1613 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1614 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1615 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1616 } else {
1617 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1618 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1622 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1623 TRACE("Stub\n");
1624 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1625 FIXME(" Stippled Alpha not supported yet.\n");
1628 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1629 TRACE("Stub\n");
1630 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1631 FIXME(" Antialias not supported yet.\n");
1634 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1635 TRACE("Stub\n");
1636 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1637 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1640 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1641 TRACE("Stub\n");
1642 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1643 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1646 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1647 union {
1648 DWORD d;
1649 float f;
1650 } tmpvalue;
1651 tmpvalue.f = 1.0f;
1653 TRACE("Stub\n");
1654 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1656 static BOOL displayed = FALSE;
1658 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1659 if(!displayed)
1660 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1662 displayed = TRUE;
1666 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1667 TRACE("Stub\n");
1668 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1669 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1672 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1673 TRACE("Stub\n");
1674 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1675 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1678 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1679 TRACE("Stub\n");
1680 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1681 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1684 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1685 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1686 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1690 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1691 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1692 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1696 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1697 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1698 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1702 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1703 if(stateblock->renderState[WINED3DRS_ROP2]) {
1704 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1708 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1709 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1710 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1714 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1715 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1716 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1720 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1721 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1722 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1726 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1727 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1728 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1732 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1733 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1734 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1738 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1739 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1740 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1744 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1745 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1746 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1750 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1751 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1752 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1756 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1757 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1758 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1762 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1763 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1764 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1768 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1769 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1770 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1774 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1775 #if defined (GL_VERSION_1_3)
1776 # define useext(A) A
1777 #elif defined (GL_EXT_texture_env_combine)
1778 # define useext(A) A##_EXT
1779 #elif defined (GL_ARB_texture_env_combine)
1780 # define useext(A) A##_ARB
1781 #endif
1783 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1784 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1785 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1786 * flag specifies the complement of the input should be used. */
1787 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1788 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1790 /* Calculate the operand */
1791 if (complement) {
1792 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1793 else *operand = GL_ONE_MINUS_SRC_COLOR;
1794 } else {
1795 if (from_alpha) *operand = GL_SRC_ALPHA;
1796 else *operand = GL_SRC_COLOR;
1799 /* Calculate the source */
1800 switch (arg & WINED3DTA_SELECTMASK) {
1801 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1802 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1803 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1804 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1805 case WINED3DTA_SPECULAR:
1807 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1808 * 'Secondary color' and isn't supported until base GL supports it
1809 * There is no concept of temp registers as far as I can tell
1811 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1812 *source = GL_TEXTURE;
1813 break;
1814 default:
1815 FIXME("Unrecognized texture arg %#x\n", arg);
1816 *source = GL_TEXTURE;
1817 break;
1821 /* Setup the texture operations texture stage states */
1822 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1824 GLenum src1, src2, src3;
1825 GLenum opr1, opr2, opr3;
1826 GLenum comb_target;
1827 GLenum src0_target, src1_target, src2_target;
1828 GLenum opr0_target, opr1_target, opr2_target;
1829 GLenum scal_target;
1830 GLenum opr=0, invopr, src3_target, opr3_target;
1831 BOOL Handled = FALSE;
1832 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1833 IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1835 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1837 /* This is called by a state handler which has the gl lock held and a context for the thread */
1839 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1840 the form (a1 <operation> a2). However, some of the more complex operations
1841 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1842 in a third parameter called a0. Therefore these are operations of the form
1843 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1845 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1846 functions below, expect their syntax to differ slightly to those listed in the
1847 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1848 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1850 if (isAlpha) {
1851 comb_target = useext(GL_COMBINE_ALPHA);
1852 src0_target = useext(GL_SOURCE0_ALPHA);
1853 src1_target = useext(GL_SOURCE1_ALPHA);
1854 src2_target = useext(GL_SOURCE2_ALPHA);
1855 opr0_target = useext(GL_OPERAND0_ALPHA);
1856 opr1_target = useext(GL_OPERAND1_ALPHA);
1857 opr2_target = useext(GL_OPERAND2_ALPHA);
1858 scal_target = GL_ALPHA_SCALE;
1860 else {
1861 comb_target = useext(GL_COMBINE_RGB);
1862 src0_target = useext(GL_SOURCE0_RGB);
1863 src1_target = useext(GL_SOURCE1_RGB);
1864 src2_target = useext(GL_SOURCE2_RGB);
1865 opr0_target = useext(GL_OPERAND0_RGB);
1866 opr1_target = useext(GL_OPERAND1_RGB);
1867 opr2_target = useext(GL_OPERAND2_RGB);
1868 scal_target = useext(GL_RGB_SCALE);
1871 /* If a texture stage references an invalid texture unit the stage just
1872 * passes through the result from the previous stage */
1873 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1874 arg1 = WINED3DTA_CURRENT;
1875 op = WINED3DTOP_SELECTARG1;
1878 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1879 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1880 } else {
1881 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1883 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1884 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1886 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1888 Handled = TRUE; /* Assume will be handled */
1890 /* Other texture operations require special extensions: */
1891 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1892 if (isAlpha) {
1893 opr = GL_SRC_ALPHA;
1894 invopr = GL_ONE_MINUS_SRC_ALPHA;
1895 src3_target = GL_SOURCE3_ALPHA_NV;
1896 opr3_target = GL_OPERAND3_ALPHA_NV;
1897 } else {
1898 opr = GL_SRC_COLOR;
1899 invopr = GL_ONE_MINUS_SRC_COLOR;
1900 src3_target = GL_SOURCE3_RGB_NV;
1901 opr3_target = GL_OPERAND3_RGB_NV;
1903 switch (op) {
1904 case WINED3DTOP_DISABLE: /* Only for alpha */
1905 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1906 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1907 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1908 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1909 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1910 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1911 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1912 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1913 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1914 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1915 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1916 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1917 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1918 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1919 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1920 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1921 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1922 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1923 break;
1924 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1925 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1926 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1927 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1928 if (op == WINED3DTOP_SELECTARG1) {
1929 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1930 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1931 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1932 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1933 } else {
1934 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1935 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1936 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1937 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1939 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1940 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1941 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1942 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1943 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1944 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1945 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1946 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1947 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1948 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1949 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1950 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1951 break;
1953 case WINED3DTOP_MODULATE:
1954 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1955 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1956 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1957 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1958 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1959 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1960 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1961 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1962 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1963 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1964 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1965 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1966 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1967 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1968 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1969 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1970 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1971 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1972 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1973 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1974 break;
1975 case WINED3DTOP_MODULATE2X:
1976 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1977 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1978 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1979 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1980 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1981 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1982 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1983 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1984 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1985 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1986 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1987 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1988 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1989 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1990 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1991 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1992 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1993 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1994 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1995 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1996 break;
1997 case WINED3DTOP_MODULATE4X:
1998 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1999 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2000 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2001 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2002 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2003 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2004 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2005 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2006 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2007 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2008 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2009 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2010 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2011 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2012 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2013 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2014 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2015 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2016 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2017 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2018 break;
2020 case WINED3DTOP_ADD:
2021 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2022 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2023 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2024 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2025 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2026 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2027 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2028 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2029 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2030 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2031 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2032 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2033 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2034 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2035 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2036 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2037 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2038 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2039 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2040 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2041 break;
2043 case WINED3DTOP_ADDSIGNED:
2044 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2045 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2046 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2047 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2048 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2049 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2050 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2051 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2052 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2053 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2054 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2055 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2056 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2057 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2058 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2059 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2060 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2061 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2062 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2063 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2064 break;
2066 case WINED3DTOP_ADDSIGNED2X:
2067 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2068 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2069 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2070 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2071 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2072 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2073 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2074 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2075 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2076 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2077 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2078 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2079 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2080 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2081 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2082 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2083 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2084 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2085 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2086 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2087 break;
2089 case WINED3DTOP_ADDSMOOTH:
2090 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2091 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2092 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2093 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2094 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2095 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2096 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2097 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2098 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2099 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2100 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2101 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2102 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2103 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2104 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2105 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2106 switch (opr1) {
2107 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2108 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2109 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2110 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2112 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2113 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2114 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2115 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2116 break;
2118 case WINED3DTOP_BLENDDIFFUSEALPHA:
2119 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2120 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2121 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2122 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2123 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2124 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2125 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2126 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2127 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2128 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2129 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2130 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2131 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2132 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2133 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2134 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2135 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2136 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2137 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2138 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2139 break;
2140 case WINED3DTOP_BLENDTEXTUREALPHA:
2141 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2142 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2143 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2144 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2145 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2146 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2147 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2148 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2149 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2150 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2151 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2152 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2153 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2154 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2155 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2156 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2157 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2158 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2159 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2160 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2161 break;
2162 case WINED3DTOP_BLENDFACTORALPHA:
2163 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2164 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2165 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2166 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2167 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2168 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2169 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2170 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2171 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2172 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2173 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2174 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2175 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2176 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2177 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2178 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2179 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2180 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2181 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2182 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2183 break;
2184 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2185 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2186 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2187 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2188 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2189 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2190 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2191 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2192 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2193 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2194 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2195 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2196 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2197 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2198 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2199 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2200 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2201 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2202 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2203 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2204 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2205 break;
2206 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2207 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2208 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2209 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2210 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2211 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2212 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2213 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2214 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2215 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2216 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2217 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2218 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2219 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2220 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2221 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2222 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2223 switch (opr) {
2224 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2225 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2227 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2228 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2229 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2230 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2231 break;
2232 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2233 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2234 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2235 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2236 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2237 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2238 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2239 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2240 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2241 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2242 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2243 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2244 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2245 switch (opr1) {
2246 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2247 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2249 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2250 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2251 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2252 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2253 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2254 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2255 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2256 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2257 break;
2258 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2259 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2260 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2261 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2262 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2263 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2264 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2265 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2266 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2267 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2268 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2269 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2270 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2271 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2272 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2273 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2274 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2275 switch (opr1) {
2276 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2277 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2278 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2279 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2281 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2282 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2283 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2284 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2285 break;
2286 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2287 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2288 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2289 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2290 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2291 switch (opr1) {
2292 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2293 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2294 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2295 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2297 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2298 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2299 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2300 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2301 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2302 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2303 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2304 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2305 switch (opr1) {
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, opr2_target, opr);
2310 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2311 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2312 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2313 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2314 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2315 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2316 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2317 break;
2318 case WINED3DTOP_MULTIPLYADD:
2319 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2320 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2321 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2322 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2323 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2324 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2325 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2326 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2327 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2328 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2329 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2330 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2331 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2332 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2333 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2334 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2335 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2336 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2337 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2338 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2339 break;
2341 case WINED3DTOP_BUMPENVMAP:
2345 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2346 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2348 default:
2349 Handled = FALSE;
2351 if (Handled) {
2352 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2353 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2355 return;
2357 } /* GL_NV_texture_env_combine4 */
2359 Handled = TRUE; /* Again, assume handled */
2360 switch (op) {
2361 case WINED3DTOP_DISABLE: /* Only for alpha */
2362 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2363 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2364 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2365 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2366 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2367 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2368 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2369 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2370 break;
2371 case WINED3DTOP_SELECTARG1:
2372 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2373 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2374 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2375 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2376 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2377 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2378 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2379 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2380 break;
2381 case WINED3DTOP_SELECTARG2:
2382 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2383 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2384 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2385 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2386 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2387 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2388 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2389 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2390 break;
2391 case WINED3DTOP_MODULATE:
2392 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2393 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2394 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2395 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2396 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2397 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2398 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2399 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2400 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2401 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2402 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2403 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2404 break;
2405 case WINED3DTOP_MODULATE2X:
2406 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2407 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2408 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2409 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2410 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2411 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2412 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2413 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2414 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2415 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2416 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2417 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2418 break;
2419 case WINED3DTOP_MODULATE4X:
2420 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2421 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2422 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2423 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2424 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2425 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2426 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2427 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2428 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2429 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2430 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2431 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2432 break;
2433 case WINED3DTOP_ADD:
2434 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2435 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2436 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2437 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2438 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2439 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2440 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2441 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2442 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2443 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2444 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2445 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2446 break;
2447 case WINED3DTOP_ADDSIGNED:
2448 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2449 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2450 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2451 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2452 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2453 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2454 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2455 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2456 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2457 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2458 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2459 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2460 break;
2461 case WINED3DTOP_ADDSIGNED2X:
2462 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2463 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2464 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2465 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2466 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2467 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2468 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2469 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2470 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2471 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2472 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2473 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2474 break;
2475 case WINED3DTOP_SUBTRACT:
2476 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2477 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2478 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2479 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2480 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2481 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2482 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2483 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2484 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2485 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2486 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2487 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2488 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2489 } else {
2490 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2492 break;
2494 case WINED3DTOP_BLENDDIFFUSEALPHA:
2495 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2496 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2497 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2498 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2499 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2500 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2501 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2502 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2503 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2504 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2505 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2506 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2507 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2508 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2509 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2510 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2511 break;
2512 case WINED3DTOP_BLENDTEXTUREALPHA:
2513 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2514 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2515 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2516 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2517 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2518 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2519 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2520 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2521 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2522 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2523 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2524 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2525 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2526 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2527 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2528 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2529 break;
2530 case WINED3DTOP_BLENDFACTORALPHA:
2531 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2532 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2533 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2534 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2535 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2536 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2537 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2538 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2539 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2540 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2541 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2542 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2543 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2544 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2545 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2546 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2547 break;
2548 case WINED3DTOP_BLENDCURRENTALPHA:
2549 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2550 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2551 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2552 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2553 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2554 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2555 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2556 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2557 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2558 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2559 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2560 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2561 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2562 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2563 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2564 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2565 break;
2566 case WINED3DTOP_DOTPRODUCT3:
2567 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2568 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2569 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2570 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2571 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2572 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2573 } else {
2574 FIXME("This version of opengl does not support GL_DOT3\n");
2576 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2577 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2578 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2579 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2580 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2581 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2582 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2583 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2584 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2585 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2586 break;
2587 case WINED3DTOP_LERP:
2588 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2589 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2590 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2591 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2592 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2593 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2594 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2595 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2596 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2597 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2598 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2599 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2600 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2601 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2602 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2603 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2604 break;
2605 case WINED3DTOP_ADDSMOOTH:
2606 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2607 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2608 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2609 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2610 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2611 switch (opr1) {
2612 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2613 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2614 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2615 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2617 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2618 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2619 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2620 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2621 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2622 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2623 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2624 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2625 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2626 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2627 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2628 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2629 } else
2630 Handled = FALSE;
2631 break;
2632 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2633 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2634 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2635 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2636 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2637 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2638 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2639 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2640 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2641 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2642 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2643 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2644 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2645 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2646 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2647 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2648 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2649 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2650 } else
2651 Handled = FALSE;
2652 break;
2653 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2654 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2655 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2656 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2657 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2658 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2659 switch (opr1) {
2660 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2661 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2662 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2663 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2665 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2666 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2667 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2668 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2669 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2670 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2671 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2672 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2673 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2674 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2675 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2676 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2677 } else
2678 Handled = FALSE;
2679 break;
2680 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2681 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2682 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2683 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2684 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2685 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2686 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2687 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2688 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2689 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2690 switch (opr1) {
2691 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2692 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2693 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2694 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2696 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2697 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2698 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2699 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2700 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2701 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2702 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2703 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2704 } else
2705 Handled = FALSE;
2706 break;
2707 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2708 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2709 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2710 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2711 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2712 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2713 switch (opr1) {
2714 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2715 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2716 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2717 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2719 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2720 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2721 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2722 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2723 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2724 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2725 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2726 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2727 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2728 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2729 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2730 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2731 } else
2732 Handled = FALSE;
2733 break;
2734 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2735 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2736 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2737 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2738 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2739 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2740 switch (opr1) {
2741 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2742 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2743 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2744 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2746 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2747 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2748 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2749 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2750 switch (opr1) {
2751 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2752 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2753 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2754 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2756 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2757 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2758 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2759 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2760 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2761 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2762 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2763 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2764 } else
2765 Handled = FALSE;
2766 break;
2767 case WINED3DTOP_MULTIPLYADD:
2768 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2769 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2770 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2771 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2772 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2773 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2774 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2775 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2776 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2777 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2778 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2779 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2780 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2781 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2782 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2783 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2784 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2785 } else
2786 Handled = FALSE;
2787 break;
2788 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2789 case WINED3DTOP_BUMPENVMAP:
2790 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2791 /* Technically texture shader support without register combiners is possible, but not expected to occur
2792 * on real world cards, so for now a fixme should be enough
2794 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2796 default:
2797 Handled = FALSE;
2800 if (Handled) {
2801 BOOL combineOK = TRUE;
2802 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2803 DWORD op2;
2805 if (isAlpha) {
2806 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2807 } else {
2808 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2811 /* Note: If COMBINE4 in effect can't go back to combine! */
2812 switch (op2) {
2813 case WINED3DTOP_ADDSMOOTH:
2814 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2815 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2816 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2817 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2818 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2819 case WINED3DTOP_MULTIPLYADD:
2820 /* Ignore those implemented in both cases */
2821 switch (op) {
2822 case WINED3DTOP_SELECTARG1:
2823 case WINED3DTOP_SELECTARG2:
2824 combineOK = FALSE;
2825 Handled = FALSE;
2826 break;
2827 default:
2828 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2829 return;
2834 if (combineOK) {
2835 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2836 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2838 return;
2842 /* After all the extensions, if still unhandled, report fixme */
2843 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2847 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2848 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2849 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2850 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2852 TRACE("Setting color op for stage %d\n", stage);
2854 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2855 if (use_ps(stateblock)) return;
2857 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2859 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2861 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2862 FIXME("Attempt to enable unsupported stage!\n");
2863 return;
2865 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2866 checkGLcall("glActiveTextureARB");
2869 if(stage >= stateblock->lowest_disabled_stage) {
2870 TRACE("Stage disabled\n");
2871 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2873 /* Disable everything here */
2874 glDisable(GL_TEXTURE_2D);
2875 checkGLcall("glDisable(GL_TEXTURE_2D)");
2876 glDisable(GL_TEXTURE_3D);
2877 checkGLcall("glDisable(GL_TEXTURE_3D)");
2878 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2879 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2880 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2882 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2883 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2884 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2887 /* All done */
2888 return;
2891 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2892 * if the sampler for this stage is dirty
2894 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2895 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2898 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2899 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2900 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2901 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2902 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2905 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2906 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2907 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2908 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2909 DWORD op, arg1, arg2, arg0;
2911 TRACE("Setting alpha op for stage %d\n", stage);
2912 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2913 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2915 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2916 FIXME("Attempt to enable unsupported stage!\n");
2917 return;
2919 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2920 checkGLcall("glActiveTextureARB");
2923 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2924 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2925 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2926 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2928 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2930 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2932 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2934 IWineD3DSurfaceImpl *surf;
2936 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2938 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
2940 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2941 * properly. On the other hand applications can still use texture combiners apparently. This code
2942 * takes care that apps cannot remove the texture's alpha channel entirely.
2944 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2945 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2946 * and alpha component of diffuse color to draw things like translucent text and perform other
2947 * blending effects.
2949 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2950 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2951 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2952 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2953 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2954 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2955 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2956 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2957 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2958 * alpha.
2960 * What to do with multitexturing? So far no app has been found that uses color keying with
2961 * multitexturing */
2962 if (op == WINED3DTOP_DISABLE)
2964 arg1 = WINED3DTA_TEXTURE;
2965 op = WINED3DTOP_SELECTARG1;
2967 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
2969 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2971 arg2 = WINED3DTA_TEXTURE;
2972 op = WINED3DTOP_MODULATE;
2974 else arg1 = WINED3DTA_TEXTURE;
2976 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
2978 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2980 arg1 = WINED3DTA_TEXTURE;
2981 op = WINED3DTOP_MODULATE;
2983 else arg2 = WINED3DTA_TEXTURE;
2989 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
2990 * this if block here, and the other code(color keying, texture unit selection) are the same
2992 TRACE("Setting alpha op for stage %d\n", stage);
2993 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2994 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2995 op, arg1, arg2, arg0,
2996 mapped_stage,
2997 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
2998 } else {
2999 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3000 op, arg1, arg2, arg0);
3004 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3005 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3006 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3007 BOOL generated;
3008 int coordIdx;
3010 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3011 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3013 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3014 return;
3017 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3019 if(mapped_stage >= GL_LIMITS(textures)) {
3020 return;
3022 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3023 checkGLcall("glActiveTextureARB");
3024 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3025 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3027 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3028 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3029 stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].stride
3030 ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format
3031 : WINED3DFMT_UNKNOWN,
3032 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3034 /* The sampler applying function calls us if this changes */
3035 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3037 if(generated) {
3038 FIXME("Non-power2 texture being used with generated texture coords\n");
3040 /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
3041 fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3042 if (!use_ps(stateblock)) {
3043 TRACE("Non power two matrix multiply fixup\n");
3044 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3049 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3050 unsigned int texture_idx;
3052 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3053 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3054 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3058 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si, GLuint *curVBO)
3060 const UINT *offset = stateblock->streamOffset;
3061 unsigned int mapped_stage = 0;
3062 unsigned int textureNo = 0;
3064 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3065 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3066 const struct wined3d_stream_info_element *e;
3068 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3069 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3071 e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3072 if (coordIdx < MAX_TEXTURES && (e->data || e->buffer_object))
3074 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3075 textureNo, mapped_stage, coordIdx, e->data);
3077 if (*curVBO != e->buffer_object)
3079 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3080 checkGLcall("glBindBufferARB");
3081 *curVBO = e->buffer_object;
3084 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3085 checkGLcall("glClientActiveTextureARB");
3087 /* The coords to supply depend completely on the fvf / vertex shader */
3088 glTexCoordPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
3089 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3090 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3091 } else {
3092 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3095 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3096 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3097 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3098 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3102 checkGLcall("loadTexCoords");
3105 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3106 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3107 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3108 static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3109 static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3110 static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3111 static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3113 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3115 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3116 return;
3119 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3120 WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3121 return;
3123 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3124 checkGLcall("glActiveTextureARB");
3126 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3128 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3129 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3130 * means use the vertex position (camera-space) as the input texture coordinates
3131 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3132 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3133 * to the TEXCOORDINDEX value
3135 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3137 case WINED3DTSS_TCI_PASSTHRU:
3138 /* Use the specified texture coordinates contained within the
3139 * vertex format. This value resolves to zero. */
3140 glDisable(GL_TEXTURE_GEN_S);
3141 glDisable(GL_TEXTURE_GEN_T);
3142 glDisable(GL_TEXTURE_GEN_R);
3143 glDisable(GL_TEXTURE_GEN_Q);
3144 checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3145 break;
3147 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3148 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3149 * as the input texture coordinates for this stage's texture transformation. This
3150 * equates roughly to EYE_LINEAR */
3152 glMatrixMode(GL_MODELVIEW);
3153 glPushMatrix();
3154 glLoadIdentity();
3155 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3156 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3157 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3158 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3159 glPopMatrix();
3160 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3162 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3163 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3164 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3165 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3167 glEnable(GL_TEXTURE_GEN_S);
3168 glEnable(GL_TEXTURE_GEN_T);
3169 glEnable(GL_TEXTURE_GEN_R);
3170 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3172 break;
3174 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3175 /* Note that NV_TEXGEN_REFLECTION support is implied when
3176 * ARB_TEXTURE_CUBE_MAP is supported */
3177 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3179 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3180 break;
3183 glMatrixMode(GL_MODELVIEW);
3184 glPushMatrix();
3185 glLoadIdentity();
3186 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3187 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3188 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3189 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3190 glPopMatrix();
3191 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3193 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3194 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3195 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3196 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3198 glEnable(GL_TEXTURE_GEN_S);
3199 glEnable(GL_TEXTURE_GEN_T);
3200 glEnable(GL_TEXTURE_GEN_R);
3201 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3203 break;
3205 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3206 /* Note that NV_TEXGEN_REFLECTION support is implied when
3207 * ARB_TEXTURE_CUBE_MAP is supported */
3208 if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3210 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3211 break;
3214 glMatrixMode(GL_MODELVIEW);
3215 glPushMatrix();
3216 glLoadIdentity();
3217 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3218 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3219 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3220 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3221 glPopMatrix();
3222 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3224 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3225 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3226 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3227 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3229 glEnable(GL_TEXTURE_GEN_S);
3230 glEnable(GL_TEXTURE_GEN_T);
3231 glEnable(GL_TEXTURE_GEN_R);
3232 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3234 break;
3236 case WINED3DTSS_TCI_SPHEREMAP:
3237 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3238 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3239 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3241 glEnable(GL_TEXTURE_GEN_S);
3242 glEnable(GL_TEXTURE_GEN_T);
3243 glDisable(GL_TEXTURE_GEN_R);
3244 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3246 break;
3248 default:
3249 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3250 stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3251 glDisable(GL_TEXTURE_GEN_S);
3252 glDisable(GL_TEXTURE_GEN_T);
3253 glDisable(GL_TEXTURE_GEN_R);
3254 glDisable(GL_TEXTURE_GEN_Q);
3255 checkGLcall("Disable texgen.");
3257 break;
3260 /* Update the texture matrix */
3261 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3262 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3265 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3266 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3267 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3268 * and do all the things linked to it
3269 * TODO: Tidy that up to reload only the arrays of the changed unit
3271 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3273 unloadTexCoords(stateblock);
3274 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3278 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3279 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3281 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3282 * has an update pending
3284 if(isStateDirty(context, STATE_VDECL) ||
3285 isStateDirty(context, STATE_PIXELSHADER)) {
3286 return;
3289 device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock));
3292 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3293 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3295 if(stateblock->pixelShader && stage != 0 &&
3296 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3297 /* The pixel shader has to know the luminance scale. Do a constants update if it
3298 * isn't scheduled anyway
3300 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3301 !isStateDirty(context, STATE_PIXELSHADER)) {
3302 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3307 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3308 const DWORD sampler = state - STATE_SAMPLER(0);
3309 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3311 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3313 if(!texture) return;
3314 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3315 * basetexture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3316 * scaling is reapplied or removed, the texture matrix has to be reapplied
3318 * The mapped stage is already active because the sampler() function below, which is part of the
3319 * misc pipeline
3321 if(sampler < MAX_TEXTURES) {
3322 const BOOL texIsPow2 = !((IWineD3DBaseTextureImpl *)texture)->baseTexture.pow2Matrix_identity;
3324 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3326 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3327 else context->lastWasPow2Texture &= ~(1 << sampler);
3328 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3333 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3334 DWORD sampler = state - STATE_SAMPLER(0);
3335 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3336 union {
3337 float f;
3338 DWORD d;
3339 } tmpvalue;
3341 TRACE("Sampler: %d\n", sampler);
3342 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3343 * only has to bind textures and set the per texture states
3346 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3348 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3349 return;
3352 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3353 return;
3355 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3356 checkGLcall("glActiveTextureARB");
3358 if(stateblock->textures[sampler]) {
3359 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3360 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3361 tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3362 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3363 basetexture_apply_state_changes(stateblock->textures[sampler],
3364 stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3366 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3367 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3368 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3369 GL_TEXTURE_LOD_BIAS_EXT,
3370 tmpvalue.f);
3371 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3374 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3376 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3377 /* If color keying is enabled update the alpha test, it depends on the existence
3378 * of a color key in stage 0
3380 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3384 /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3385 if (!tex_impl->baseTexture.pow2Matrix_identity) {
3386 IWineD3DDeviceImpl* d3ddevice = stateblock->wineD3DDevice;
3387 d3ddevice->shader_backend->shader_load_np2fixup_constants(
3388 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3390 } else if(mapped_stage < GL_LIMITS(textures)) {
3391 if(sampler < stateblock->lowest_disabled_stage) {
3392 /* TODO: What should I do with pixel shaders here ??? */
3393 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3394 /* If color keying is enabled update the alpha test, it depends on the existence
3395 * of a color key in stage 0
3397 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3399 } /* Otherwise tex_colorop disables the stage */
3400 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3401 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3405 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3406 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3407 BOOL use_pshader = use_ps(stateblock);
3408 BOOL use_vshader = use_vs(stateblock);
3409 int i;
3411 if (use_pshader) {
3412 if(!context->last_was_pshader) {
3413 /* Former draw without a pixel shader, some samplers
3414 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3415 * make sure to enable them
3417 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3418 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3419 sampler(STATE_SAMPLER(i), stateblock, context);
3422 context->last_was_pshader = TRUE;
3423 } else {
3424 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3425 * if a different texture was bound. I don't have to do anything.
3428 } else {
3429 /* Disabled the pixel shader - color ops weren't applied
3430 * while it was enabled, so re-apply them.
3432 for(i=0; i < MAX_TEXTURES; i++) {
3433 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3434 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3435 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3438 context->last_was_pshader = FALSE;
3441 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3442 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3444 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3445 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3450 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3451 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3452 if(stateblock->pixelShader && stage != 0 &&
3453 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3454 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3455 * anyway
3457 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3458 !isStateDirty(context, STATE_PIXELSHADER)) {
3459 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3464 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3465 /* This function is called by transform_view below if the view matrix was changed too
3467 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3468 * does not always update the world matrix, only on a switch between transformed
3469 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3470 * draw, but that should be rather rare and cheaper in total.
3472 glMatrixMode(GL_MODELVIEW);
3473 checkGLcall("glMatrixMode");
3475 if(context->last_was_rhw) {
3476 glLoadIdentity();
3477 checkGLcall("glLoadIdentity()");
3478 } else {
3479 /* In the general case, the view matrix is the identity matrix */
3480 if (stateblock->wineD3DDevice->view_ident) {
3481 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3482 checkGLcall("glLoadMatrixf");
3483 } else {
3484 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3485 checkGLcall("glLoadMatrixf");
3486 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3487 checkGLcall("glMultMatrixf");
3492 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3493 UINT index = state - STATE_CLIPPLANE(0);
3495 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3496 return;
3499 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3500 if(!use_vs(stateblock)) {
3501 glMatrixMode(GL_MODELVIEW);
3502 glPushMatrix();
3503 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3504 } else {
3505 /* with vertex shaders, clip planes are not transformed in direct3d,
3506 * in OpenGL they are still transformed by the model view.
3507 * Use this to swap the y coordinate if necessary
3509 glMatrixMode(GL_MODELVIEW);
3510 glPushMatrix();
3511 glLoadIdentity();
3512 if(stateblock->wineD3DDevice->render_offscreen) {
3513 glScalef(1.0f, -1.0f, 1.0f);
3517 TRACE("Clipplane [%f,%f,%f,%f]\n",
3518 stateblock->clipplane[index][0],
3519 stateblock->clipplane[index][1],
3520 stateblock->clipplane[index][2],
3521 stateblock->clipplane[index][3]);
3522 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3523 checkGLcall("glClipPlane");
3525 glPopMatrix();
3528 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3529 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3530 GLenum glMat;
3531 TRACE("Setting world matrix %d\n", matrix);
3533 if(matrix >= GL_LIMITS(blends)) {
3534 WARN("Unsupported blend matrix set\n");
3535 return;
3536 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3537 return;
3540 /* GL_MODELVIEW0_ARB: 0x1700
3541 * GL_MODELVIEW1_ARB: 0x850a
3542 * GL_MODELVIEW2_ARB: 0x8722
3543 * GL_MODELVIEW3_ARB: 0x8723
3544 * etc
3545 * GL_MODELVIEW31_ARB: 0x873F
3547 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3548 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3550 glMatrixMode(glMat);
3551 checkGLcall("glMatrixMode(glMat)");
3553 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3554 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3556 if(stateblock->wineD3DDevice->view_ident) {
3557 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3558 checkGLcall("glLoadMatrixf");
3559 } else {
3560 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3561 checkGLcall("glLoadMatrixf");
3562 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3563 checkGLcall("glMultMatrixf");
3567 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3568 static BOOL once = FALSE;
3570 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3571 case WINED3DVBF_1WEIGHTS:
3572 case WINED3DVBF_2WEIGHTS:
3573 case WINED3DVBF_3WEIGHTS:
3574 if(!once) {
3575 once = TRUE;
3576 /* TODO: Implement vertex blending in drawStridedSlow */
3577 FIXME("Vertex blending enabled, but not supported by hardware\n");
3579 break;
3581 case WINED3DVBF_TWEENING:
3582 WARN("Tweening not supported yet\n");
3586 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3587 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3589 switch(val) {
3590 case WINED3DVBF_1WEIGHTS:
3591 case WINED3DVBF_2WEIGHTS:
3592 case WINED3DVBF_3WEIGHTS:
3593 glEnable(GL_VERTEX_BLEND_ARB);
3594 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3596 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3597 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3599 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3601 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3602 unsigned int i;
3603 for(i = 1; i < GL_LIMITS(blends); i++) {
3604 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3605 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3608 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3610 break;
3612 case WINED3DVBF_DISABLE:
3613 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3614 glDisable(GL_VERTEX_BLEND_ARB);
3615 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3616 break;
3618 case WINED3DVBF_TWEENING:
3619 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3620 * vertex weights in the vertices?
3621 * For now we don't report that as supported, so a warn should suffice
3623 WARN("Tweening not supported yet\n");
3624 break;
3628 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3629 unsigned int k;
3631 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3632 * NOTE: We have to reset the positions even if the light/plane is not currently
3633 * enabled, since the call to enable it will not reset the position.
3634 * NOTE2: Apparently texture transforms do NOT need reapplying
3637 const PLIGHTINFOEL *light = NULL;
3639 glMatrixMode(GL_MODELVIEW);
3640 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3641 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3642 checkGLcall("glLoadMatrixf(...)");
3644 /* Reset lights. TODO: Call light apply func */
3645 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3646 light = stateblock->activeLights[k];
3647 if(!light) continue;
3648 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3649 checkGLcall("glLightfv posn");
3650 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3651 checkGLcall("glLightfv dirn");
3654 /* Reset Clipping Planes */
3655 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3656 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3657 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3661 if(context->last_was_rhw) {
3662 glLoadIdentity();
3663 checkGLcall("glLoadIdentity()");
3664 /* No need to update the world matrix, the identity is fine */
3665 return;
3668 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3669 * No need to do it here if the state is scheduled for update.
3671 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3672 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3675 /* Avoid looping over a number of matrices if the app never used the functionality */
3676 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3677 for(k = 1; k < GL_LIMITS(blends); k++) {
3678 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3679 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3685 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3686 glMatrixMode(GL_PROJECTION);
3687 checkGLcall("glMatrixMode(GL_PROJECTION)");
3688 glLoadIdentity();
3689 checkGLcall("glLoadIdentity");
3691 if(context->last_was_rhw) {
3692 double X, Y, height, width, minZ, maxZ;
3694 X = stateblock->viewport.X;
3695 Y = stateblock->viewport.Y;
3696 height = stateblock->viewport.Height;
3697 width = stateblock->viewport.Width;
3698 minZ = stateblock->viewport.MinZ;
3699 maxZ = stateblock->viewport.MaxZ;
3701 if(!stateblock->wineD3DDevice->untransformed) {
3702 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3703 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3704 * suppress depth clipping. This can be done because it is an orthogonal projection and
3705 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3706 * Persia 3D need this.
3708 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3709 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3710 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3711 * to the viewer.
3713 * Also note that this breaks z comparison against z values filled in with clear,
3714 * but no app depending on that and disabled clipping has been found yet. Comparing
3715 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3716 * surface removal.
3718 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3719 * but this would break Z buffer operation. Raising the range to something less than
3720 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3721 * problem either.
3723 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3724 if(stateblock->wineD3DDevice->render_offscreen) {
3725 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3726 } else {
3727 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3729 } else {
3730 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3731 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3732 * unmodified to opengl.
3734 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3735 * replacement shader.
3737 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3738 if(stateblock->wineD3DDevice->render_offscreen) {
3739 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3740 } else {
3741 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3744 checkGLcall("glOrtho");
3746 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3747 glTranslatef(0.5f, 0.5f, 0.0f);
3748 checkGLcall("glTranslatef(0.5f, 0.5f, 0.0f)");
3749 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3750 * render everything upside down when rendering offscreen. */
3751 if (stateblock->wineD3DDevice->render_offscreen) {
3752 glScalef(1.0f, -1.0f, 1.0f);
3753 checkGLcall("glScalef");
3755 } else {
3756 /* The rule is that the window coordinate 0 does not correspond to the
3757 beginning of the first pixel, but the center of the first pixel.
3758 As a consequence if you want to correctly draw one line exactly from
3759 the left to the right end of the viewport (with all matrices set to
3760 be identity), the x coords of both ends of the line would be not
3761 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3762 instead.
3764 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3765 divide by the Width/Height, so we need the half range(1.0) to translate by
3766 half a pixel.
3768 The other fun is that d3d's output z range after the transformation is [0;1],
3769 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3770 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3771 of Z buffer precision and the clear values do not match in the z test. Thus scale
3772 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3776 * Careful with the order of operations here, we're essentially working backwards:
3777 * x = x + 1/w;
3778 * y = (y - 1/h) * flip;
3779 * z = z * 2 - 1;
3781 * Becomes:
3782 * glTranslatef(0.0, 0.0, -1.0);
3783 * glScalef(1.0, 1.0, 2.0);
3785 * glScalef(1.0, flip, 1.0);
3786 * glTranslatef(1/w, -1/h, 0.0);
3788 * This is equivalent to:
3789 * glTranslatef(1/w, -flip/h, -1.0)
3790 * glScalef(1.0, flip, 2.0);
3793 if (stateblock->wineD3DDevice->render_offscreen) {
3794 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3795 * render everything upside down when rendering offscreen. */
3796 glTranslatef(1.0f / stateblock->viewport.Width, 1.0f / stateblock->viewport.Height, -1.0f);
3797 checkGLcall("glTranslatef(1.0f / width, 1.0f / height, -1.0f)");
3798 glScalef(1.0f, -1.0f, 2.0f);
3799 } else {
3800 glTranslatef(1.0f / stateblock->viewport.Width, -1.0f / stateblock->viewport.Height, -1.0f);
3801 checkGLcall("glTranslatef(1.0f / width, -1.0f / height, -1.0f)");
3802 glScalef(1.0f, 1.0f, 2.0f);
3804 checkGLcall("glScalef");
3806 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3807 checkGLcall("glLoadMatrixf");
3811 /* This should match any arrays loaded in loadVertexData.
3812 * stateblock impl is required for GL_SUPPORT
3813 * TODO: Only load / unload arrays if we have to.
3815 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3816 glDisableClientState(GL_VERTEX_ARRAY);
3817 glDisableClientState(GL_NORMAL_ARRAY);
3818 glDisableClientState(GL_COLOR_ARRAY);
3819 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3820 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3822 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3823 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3825 unloadTexCoords(stateblock);
3828 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3830 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3831 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3833 context->numbered_array_mask &= ~(1 << i);
3836 /* This should match any arrays loaded in loadNumberedArrays
3837 * TODO: Only load / unload arrays if we have to.
3839 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3841 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3842 GLint maxAttribs = 16;
3843 int i;
3845 /* Leave all the attribs disabled */
3846 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3847 /* MESA does not support it right not */
3848 if (glGetError() != GL_NO_ERROR)
3849 maxAttribs = 16;
3850 for (i = 0; i < maxAttribs; ++i) {
3851 unload_numbered_array(stateblock, context, i);
3855 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3856 const struct wined3d_stream_info *stream_info, WineD3DContext *context)
3858 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3859 int i;
3860 const UINT *offset = stateblock->streamOffset;
3861 struct wined3d_buffer *vb;
3862 DWORD_PTR shift_index;
3864 /* Default to no instancing */
3865 stateblock->wineD3DDevice->instancedDraw = FALSE;
3867 for (i = 0; i < MAX_ATTRIBS; i++) {
3868 if (!(stream_info->use_map & (1 << i)))
3870 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3871 continue;
3874 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3875 if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
3877 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3878 stateblock->wineD3DDevice->instancedDraw = TRUE;
3879 continue;
3882 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
3884 if (stream_info->elements[i].stride)
3886 if (curVBO != stream_info->elements[i].buffer_object)
3888 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
3889 checkGLcall("glBindBufferARB");
3890 curVBO = stream_info->elements[i].buffer_object;
3892 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3893 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3894 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3895 * vbo we won't be load converted attributes anyway
3897 if (curVBO && vb->conversion_shift)
3899 TRACE("Loading attribute from shifted buffer\n");
3900 TRACE("Attrib %d has original stride %d, new stride %d\n",
3901 i, stream_info->elements[i].stride, vb->conversion_stride);
3902 TRACE("Original offset %p, additional offset 0x%08x\n",
3903 stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
3904 TRACE("Opengl type %#x\n", stream_info->elements[i].format_desc->gl_vtx_type);
3905 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
3906 shift_index = shift_index % stream_info->elements[i].stride;
3907 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
3908 stream_info->elements[i].format_desc->gl_vtx_type,
3909 stream_info->elements[i].format_desc->gl_normalized,
3910 vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
3911 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3912 + offset[stream_info->elements[i].stream_idx]));
3914 } else {
3915 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
3916 stream_info->elements[i].format_desc->gl_vtx_type,
3917 stream_info->elements[i].format_desc->gl_normalized,
3918 stream_info->elements[i].stride, stream_info->elements[i].data
3919 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3920 + offset[stream_info->elements[i].stream_idx]));
3923 if (!(context->numbered_array_mask & (1 << i)))
3925 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3926 context->numbered_array_mask |= (1 << i);
3928 } else {
3929 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3930 * set up the attribute statically. But we have to figure out the system memory address.
3932 const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
3933 if (stream_info->elements[i].buffer_object)
3935 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3936 ptr += (long) buffer_get_sysmem(vb);
3939 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3941 switch (stream_info->elements[i].format_desc->format)
3943 case WINED3DFMT_R32_FLOAT:
3944 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3945 break;
3946 case WINED3DFMT_R32G32_FLOAT:
3947 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3948 break;
3949 case WINED3DFMT_R32G32B32_FLOAT:
3950 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3951 break;
3952 case WINED3DFMT_R32G32B32A32_FLOAT:
3953 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3954 break;
3956 case WINED3DFMT_R8G8B8A8_UINT:
3957 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3958 break;
3959 case WINED3DFMT_A8R8G8B8:
3960 if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
3962 const DWORD *src = (const DWORD *)ptr;
3963 DWORD c = *src & 0xff00ff00;
3964 c |= (*src & 0xff0000) >> 16;
3965 c |= (*src & 0xff) << 16;
3966 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
3967 break;
3969 /* else fallthrough */
3970 case WINED3DFMT_R8G8B8A8_UNORM:
3971 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3972 break;
3974 case WINED3DFMT_R16G16_SINT:
3975 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3976 break;
3977 case WINED3DFMT_R16G16B16A16_SINT:
3978 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3979 break;
3981 case WINED3DFMT_R16G16_SNORM:
3983 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
3984 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3985 break;
3987 case WINED3DFMT_R16G16_UNORM:
3989 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
3990 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3991 break;
3993 case WINED3DFMT_R16G16B16A16_SNORM:
3994 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
3995 break;
3996 case WINED3DFMT_R16G16B16A16_UNORM:
3997 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
3998 break;
4000 case WINED3DFMT_R10G10B10A2_UINT:
4001 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4002 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4003 break;
4004 case WINED3DFMT_R10G10B10A2_SNORM:
4005 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4006 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4007 break;
4009 case WINED3DFMT_R16G16_FLOAT:
4010 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4011 * byte float according to the IEEE standard
4013 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4014 break;
4015 case WINED3DFMT_R16G16B16A16_FLOAT:
4016 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4017 break;
4019 default:
4020 ERR("Unexpected declaration in stride 0 attributes\n");
4021 break;
4026 checkGLcall("Loading numbered arrays");
4029 /* Used from 2 different functions, and too big to justify making it inlined */
4030 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si)
4032 const UINT *offset = stateblock->streamOffset;
4033 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4034 const struct wined3d_stream_info_element *e;
4036 TRACE("Using fast vertex array code\n");
4038 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4039 stateblock->wineD3DDevice->instancedDraw = FALSE;
4041 /* Blend Data ---------------------------------------------- */
4042 e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4043 if (e->data || e->buffer_object
4044 || si->elements[WINED3D_FFP_BLENDINDICES].data
4045 || si->elements[WINED3D_FFP_BLENDINDICES].buffer_object)
4047 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4048 TRACE("Blend %d %p %d\n", e->format_desc->component_count,
4049 e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4051 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4052 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4054 GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1));
4056 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4057 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4058 sd->u.s.blendWeights.dwStride,
4059 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4061 if (curVBO != e->buffer_object)
4063 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4064 checkGLcall("glBindBufferARB");
4065 curVBO = e->buffer_object;
4068 GL_EXTCALL(glWeightPointerARB)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4069 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4071 checkGLcall("glWeightPointerARB");
4073 if (si->elements[WINED3D_FFP_BLENDINDICES].data
4074 || (si->elements[WINED3D_FFP_BLENDINDICES].buffer_object))
4076 static BOOL warned;
4077 if (!warned)
4079 FIXME("blendMatrixIndices support\n");
4080 warned = TRUE;
4083 } else {
4084 /* TODO: support blends in drawStridedSlow
4085 * No need to write a FIXME here, this is done after the general vertex decl decoding
4087 WARN("unsupported blending in openGl\n");
4089 } else {
4090 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4091 static const GLbyte one = 1;
4092 GL_EXTCALL(glWeightbvARB(1, &one));
4093 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4097 /* Point Size ----------------------------------------------*/
4098 e = &si->elements[WINED3D_FFP_PSIZE];
4099 if (e->data || e->buffer_object)
4101 /* no such functionality in the fixed function GL pipeline */
4102 TRACE("Cannot change ptSize here in openGl\n");
4103 /* TODO: Implement this function in using shaders if they are available */
4106 /* Vertex Pointers -----------------------------------------*/
4107 e = &si->elements[WINED3D_FFP_POSITION];
4108 if (e->data || e->buffer_object)
4110 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data));
4112 if (curVBO != e->buffer_object)
4114 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4115 checkGLcall("glBindBufferARB");
4116 curVBO = e->buffer_object;
4119 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4120 handling for rhw mode should not impact screen position whereas in GL it does.
4121 This may result in very slightly distorted textures in rhw mode.
4122 There's always the other option of fixing the view matrix to
4123 prevent w from having any effect.
4125 This only applies to user pointer sources, in VBOs the vertices are fixed up
4127 if (!e->buffer_object)
4129 glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride,
4130 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4131 } else {
4132 glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4133 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4135 checkGLcall("glVertexPointer(...)");
4136 glEnableClientState(GL_VERTEX_ARRAY);
4137 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4140 /* Normals -------------------------------------------------*/
4141 e = &si->elements[WINED3D_FFP_NORMAL];
4142 if (e->data || e->buffer_object)
4144 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data));
4145 if (curVBO != e->buffer_object)
4147 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4148 checkGLcall("glBindBufferARB");
4149 curVBO = e->buffer_object;
4151 glNormalPointer(e->format_desc->gl_vtx_type, e->stride,
4152 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4153 checkGLcall("glNormalPointer(...)");
4154 glEnableClientState(GL_NORMAL_ARRAY);
4155 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4157 } else {
4158 glNormal3f(0, 0, 0);
4159 checkGLcall("glNormal3f(0, 0, 0)");
4162 /* Diffuse Colour --------------------------------------------*/
4163 /* WARNING: Data here MUST be in RGBA format, so cannot */
4164 /* go directly into fast mode from app pgm, because */
4165 /* directx requires data in BGRA format. */
4166 /* currently fixupVertices swizzles the format, but this isn't*/
4167 /* very practical when using VBOs */
4168 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4169 /* , or the user doesn't care and wants the speed advantage */
4171 e = &si->elements[WINED3D_FFP_DIFFUSE];
4172 if (e->data || e->buffer_object)
4174 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4176 if (curVBO != e->buffer_object)
4178 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4179 checkGLcall("glBindBufferARB");
4180 curVBO = e->buffer_object;
4183 glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4184 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4185 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4186 glEnableClientState(GL_COLOR_ARRAY);
4187 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4189 } else {
4190 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4191 checkGLcall("glColor4f(1, 1, 1, 1)");
4194 /* Specular Colour ------------------------------------------*/
4195 e = &si->elements[WINED3D_FFP_SPECULAR];
4196 if (e->data || e->buffer_object)
4198 TRACE("setting specular colour\n");
4199 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4201 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4202 GLenum type = e->format_desc->gl_vtx_type;
4203 GLint format = e->format_desc->gl_vtx_format;
4205 if (curVBO != e->buffer_object)
4207 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4208 checkGLcall("glBindBufferARB");
4209 curVBO = e->buffer_object;
4212 if(format != 4 || (GLINFO_LOCATION.quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
4214 /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
4215 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
4216 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
4217 * 4 component secondary colors use it
4219 GL_EXTCALL(glSecondaryColorPointerEXT)(format, type,
4220 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4221 checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
4223 else
4225 switch(type)
4227 case GL_UNSIGNED_BYTE:
4228 GL_EXTCALL(glSecondaryColorPointerEXT)(3, GL_UNSIGNED_BYTE,
4229 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4230 checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
4231 break;
4233 default:
4234 FIXME("Add 4 component specular color pointers for type %x\n", type);
4235 /* Make sure that the right color component is dropped */
4236 GL_EXTCALL(glSecondaryColorPointerEXT)(3, type,
4237 e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4238 checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
4241 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4242 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4243 } else {
4245 /* Missing specular color is not critical, no warnings */
4246 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4249 } else {
4250 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4251 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4252 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4253 } else {
4255 /* Missing specular color is not critical, no warnings */
4256 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4260 /* Texture coords -------------------------------------------*/
4261 loadTexCoords(stateblock, si, &curVBO);
4264 static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations)
4266 /* Dump out what parts we have supplied */
4267 TRACE("Strided Data:\n");
4268 TRACE_STRIDED((dataLocations), WINED3D_FFP_POSITION);
4269 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDWEIGHT);
4270 TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDINDICES);
4271 TRACE_STRIDED((dataLocations), WINED3D_FFP_NORMAL);
4272 TRACE_STRIDED((dataLocations), WINED3D_FFP_PSIZE);
4273 TRACE_STRIDED((dataLocations), WINED3D_FFP_DIFFUSE);
4274 TRACE_STRIDED((dataLocations), WINED3D_FFP_SPECULAR);
4275 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD0);
4276 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD1);
4277 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD2);
4278 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD3);
4279 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD4);
4280 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD5);
4281 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD6);
4282 TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD7);
4284 return;
4287 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4288 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4289 BOOL fixup = FALSE;
4290 struct wined3d_stream_info *dataLocations = &device->strided_streams;
4291 BOOL useVertexShaderFunction;
4292 BOOL load_numbered = FALSE;
4293 BOOL load_named = FALSE;
4295 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4297 if(device->up_strided) {
4298 /* Note: this is a ddraw fixed-function code path */
4299 TRACE("================ Strided Input ===================\n");
4300 device_stream_info_from_strided(device, device->up_strided, dataLocations);
4302 if(TRACE_ON(d3d)) {
4303 drawPrimitiveTraceDataLocations(dataLocations);
4305 } else {
4306 /* Note: This is a fixed function or shader codepath.
4307 * This means it must handle both types of strided data.
4308 * Shaders must go through here to zero the strided data, even if they
4309 * don't set any declaration at all
4311 TRACE("================ Vertex Declaration ===================\n");
4312 device_stream_info_from_declaration(device, useVertexShaderFunction, dataLocations, &fixup);
4315 if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4317 if(useVertexShaderFunction) {
4318 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4319 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4320 device->useDrawStridedSlow = TRUE;
4321 } else {
4322 load_numbered = TRUE;
4323 device->useDrawStridedSlow = FALSE;
4326 else if (fixup || (!dataLocations->elements[WINED3D_FFP_PSIZE].data
4327 && !dataLocations->position_transformed
4328 && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)
4329 || (!dataLocations->elements[WINED3D_FFP_DIFFUSE].data
4330 && !dataLocations->elements[WINED3D_FFP_SPECULAR].data))))
4332 /* Load the vertex data using named arrays */
4333 load_named = TRUE;
4334 device->useDrawStridedSlow = FALSE;
4335 } else {
4336 TRACE("Not loading vertex data\n");
4337 device->useDrawStridedSlow = TRUE;
4340 if (context->numberedArraysLoaded && !load_numbered)
4342 unloadNumberedArrays(stateblock, context);
4343 context->numberedArraysLoaded = FALSE;
4344 context->numbered_array_mask = 0;
4346 else if (context->namedArraysLoaded)
4348 unloadVertexData(stateblock);
4349 context->namedArraysLoaded = FALSE;
4352 if (load_numbered)
4354 TRACE("Loading numbered arrays\n");
4355 loadNumberedArrays(stateblock, dataLocations, context);
4356 context->numberedArraysLoaded = TRUE;
4358 else if (load_named)
4360 TRACE("Loading vertex data\n");
4361 loadVertexData(stateblock, dataLocations);
4362 context->namedArraysLoaded = TRUE;
4366 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4367 BOOL updateFog = FALSE;
4368 BOOL useVertexShaderFunction = use_vs(stateblock);
4369 BOOL usePixelShaderFunction = use_ps(stateblock);
4370 BOOL transformed;
4371 /* Some stuff is in the device until we have per context tracking */
4372 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4373 BOOL wasrhw = context->last_was_rhw;
4374 unsigned int i;
4376 transformed = device->strided_streams.position_transformed;
4377 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4378 updateFog = TRUE;
4381 /* Reapply lighting if it is not scheduled for reapplication already */
4382 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4383 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4386 if (transformed) {
4387 context->last_was_rhw = TRUE;
4388 } else {
4390 /* Untransformed, so relies on the view and projection matrices */
4391 context->last_was_rhw = FALSE;
4392 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4393 device->untransformed = TRUE;
4395 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4396 * Not needed as long as only hw shaders are supported
4399 /* This sets the shader output position correction constants.
4400 * TODO: Move to the viewport state
4402 if (useVertexShaderFunction) {
4403 device->posFixup[1] = device->render_offscreen ? -1.0f : 1.0f;
4404 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4408 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4409 * off this function will be called again anyway to make sure they're properly set
4411 if(!useVertexShaderFunction) {
4412 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4413 * or transformed / untransformed was switched
4415 if(wasrhw != context->last_was_rhw &&
4416 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4417 !isStateDirty(context, STATE_VIEWPORT)) {
4418 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4420 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4421 * mode.
4423 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4424 * this check will fail and the matrix not applied again. This is OK because a simple
4425 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4426 * needs of the vertex declaration.
4428 * World and view matrix go into the same gl matrix, so only apply them when neither is
4429 * dirty
4431 if(transformed != wasrhw &&
4432 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4433 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4434 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4437 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4438 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4441 if(context->last_was_vshader) {
4442 updateFog = TRUE;
4443 if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4444 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4446 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4447 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4450 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4451 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4453 } else {
4454 if(!context->last_was_vshader) {
4455 static BOOL warned = FALSE;
4456 if(!device->vs_clipping) {
4457 /* Disable all clip planes to get defined results on all drivers. See comment in the
4458 * state_clipping state handler
4460 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4461 glDisable(GL_CLIP_PLANE0 + i);
4462 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4465 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4466 FIXME("Clipping not supported with vertex shaders\n");
4467 warned = TRUE;
4470 if(wasrhw) {
4471 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4472 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4473 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4474 * fixed function vertex processing states back in a sane state before switching to shaders
4476 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4477 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4479 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4480 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4483 updateFog = TRUE;
4485 /* Vertex shader clipping ignores the view matrix. Update all clipplanes
4486 * (Note: ARB shaders can read the clip planes for clipping emulation even if
4487 * device->vs_clipping is false.
4489 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4490 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4495 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4496 * application
4498 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4499 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4501 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4502 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4506 context->last_was_vshader = useVertexShaderFunction;
4508 if(updateFog) {
4509 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4511 if(!useVertexShaderFunction) {
4512 int i;
4513 for(i = 0; i < MAX_TEXTURES; i++) {
4514 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4515 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4521 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4522 UINT width, height;
4523 IWineD3DSurfaceImpl *target;
4525 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4526 checkGLcall("glDepthRange");
4527 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4529 if(stateblock->wineD3DDevice->render_offscreen) {
4530 glViewport(stateblock->viewport.X,
4531 stateblock->viewport.Y,
4532 stateblock->viewport.Width, stateblock->viewport.Height);
4533 } else {
4534 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4535 target->get_drawable_size(context, &width, &height);
4537 glViewport(stateblock->viewport.X,
4538 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4539 stateblock->viewport.Width, stateblock->viewport.Height);
4542 checkGLcall("glViewport");
4545 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4546 stateblock->wineD3DDevice->posFixup[2] = 1.0f / stateblock->viewport.Width;
4547 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4548 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4549 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4551 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4552 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4556 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4557 UINT Index = state - STATE_ACTIVELIGHT(0);
4558 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4560 if(!lightInfo) {
4561 glDisable(GL_LIGHT0 + Index);
4562 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4563 } else {
4564 float quad_att;
4565 float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
4567 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4568 glMatrixMode(GL_MODELVIEW);
4569 glPushMatrix();
4570 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4572 /* Diffuse: */
4573 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4574 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4575 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4576 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4577 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4578 checkGLcall("glLightfv");
4580 /* Specular */
4581 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4582 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4583 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4584 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4585 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4586 checkGLcall("glLightfv");
4588 /* Ambient */
4589 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4590 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4591 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4592 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4593 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4594 checkGLcall("glLightfv");
4596 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4597 quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4598 } else {
4599 quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */
4602 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4603 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4604 * Attenuation0 to NaN and crashes in the gl lib
4607 switch (lightInfo->OriginalParms.Type) {
4608 case WINED3DLIGHT_POINT:
4609 /* Position */
4610 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4611 checkGLcall("glLightfv");
4612 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4613 checkGLcall("glLightf");
4614 /* Attenuation - Are these right? guessing... */
4615 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4616 checkGLcall("glLightf");
4617 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4618 checkGLcall("glLightf");
4619 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4620 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4621 checkGLcall("glLightf");
4622 /* FIXME: Range */
4623 break;
4625 case WINED3DLIGHT_SPOT:
4626 /* Position */
4627 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4628 checkGLcall("glLightfv");
4629 /* Direction */
4630 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4631 checkGLcall("glLightfv");
4632 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4633 checkGLcall("glLightf");
4634 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4635 checkGLcall("glLightf");
4636 /* Attenuation - Are these right? guessing... */
4637 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4638 checkGLcall("glLightf");
4639 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4640 checkGLcall("glLightf");
4641 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4642 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4643 checkGLcall("glLightf");
4644 /* FIXME: Range */
4645 break;
4647 case WINED3DLIGHT_DIRECTIONAL:
4648 /* Direction */
4649 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4650 checkGLcall("glLightfv");
4651 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4652 checkGLcall("glLightf");
4653 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4654 checkGLcall("glLightf");
4655 break;
4657 default:
4658 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4661 /* Restore the modelview matrix */
4662 glPopMatrix();
4664 glEnable(GL_LIGHT0 + Index);
4665 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4668 return;
4671 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4672 RECT *pRect = &stateblock->scissorRect;
4673 UINT height;
4674 UINT width;
4675 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4677 target->get_drawable_size(context, &width, &height);
4678 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4679 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4681 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4682 pRect->right - pRect->left, pRect->bottom - pRect->top);
4684 if (stateblock->wineD3DDevice->render_offscreen) {
4685 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4686 } else {
4687 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4689 checkGLcall("glScissor");
4692 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4693 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4694 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4695 } else {
4696 struct wined3d_buffer *ib = (struct wined3d_buffer *) stateblock->pIndexData;
4697 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4701 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4702 if(stateblock->wineD3DDevice->render_offscreen) {
4703 glFrontFace(GL_CCW);
4704 checkGLcall("glFrontFace(GL_CCW)");
4705 } else {
4706 glFrontFace(GL_CW);
4707 checkGLcall("glFrontFace(GL_CW)");
4711 const struct StateEntryTemplate misc_state_template[] = {
4712 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4713 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4714 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4715 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4716 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4717 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4718 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4719 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4720 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4721 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4722 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4723 { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4724 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
4725 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
4726 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4727 * vshader loadings are untied from each other
4729 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4730 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4731 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4732 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4733 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4734 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4735 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4736 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4737 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4738 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4739 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4740 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4741 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4742 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4743 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4744 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4745 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4746 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4747 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4748 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4749 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4750 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4751 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4752 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4753 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4754 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4755 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4756 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4757 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4758 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4759 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4760 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4761 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4762 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4763 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4764 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4765 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4766 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4767 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4768 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4769 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4770 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4771 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4772 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4773 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4774 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4775 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4776 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4777 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4778 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4780 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
4781 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4782 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE },
4783 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE },
4784 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE },
4785 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE },
4786 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE },
4787 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE },
4788 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
4789 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE },
4790 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE },
4791 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE },
4792 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE },
4793 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE },
4794 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4795 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4796 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4797 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4798 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE },
4799 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE },
4800 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE },
4801 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE },
4802 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE },
4803 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE },
4804 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE },
4805 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE },
4806 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE },
4807 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE },
4808 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE },
4809 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE },
4810 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE },
4811 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4812 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4813 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4814 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4815 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4816 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4817 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4818 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4819 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE },
4820 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4821 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4822 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4823 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4824 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4825 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4826 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4827 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4828 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4829 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4830 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4831 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4832 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4833 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4834 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4835 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4836 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4837 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4838 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4839 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4840 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4841 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE },
4842 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE },
4843 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE },
4844 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE },
4845 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE },
4846 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE },
4847 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4848 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4849 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4850 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4851 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4852 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4853 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
4854 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4855 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE },
4856 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE },
4857 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4858 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4859 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE },
4860 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE },
4861 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
4862 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4863 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4864 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
4865 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
4866 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE },
4867 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
4868 /* Samplers */
4869 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE },
4870 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE },
4871 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE },
4872 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE },
4873 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE },
4874 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE },
4875 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE },
4876 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE },
4877 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE },
4878 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE },
4879 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE },
4880 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE },
4881 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE },
4882 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE },
4883 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE },
4884 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE },
4885 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE },
4886 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE },
4887 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE },
4888 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
4889 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
4892 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4893 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
4894 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
4895 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
4896 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
4897 /* Clip planes */
4898 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
4899 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
4900 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
4901 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
4902 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
4903 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
4904 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
4905 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
4906 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE },
4907 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE },
4908 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE },
4909 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE },
4910 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE },
4911 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE },
4912 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE },
4913 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE },
4914 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE },
4915 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE },
4916 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE },
4917 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE },
4918 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE },
4919 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE },
4920 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE },
4921 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE },
4922 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE },
4923 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE },
4924 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE },
4925 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE },
4926 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE },
4927 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE },
4928 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE },
4929 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE },
4930 /* Lights */
4931 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE },
4932 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE },
4933 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE },
4934 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE },
4935 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE },
4936 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE },
4937 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE },
4938 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE },
4939 /* Viewport */
4940 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE },
4941 /* Transform states follow */
4942 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE },
4943 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE },
4944 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4945 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4946 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4947 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4948 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4949 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4950 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4951 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
4952 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE },
4953 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE },
4954 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE },
4955 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE },
4956 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE },
4957 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE },
4958 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE },
4959 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE },
4960 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE },
4961 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE },
4962 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE },
4963 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE },
4964 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE },
4965 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE },
4966 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE },
4967 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE },
4968 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE },
4969 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE },
4970 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE },
4971 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE },
4972 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE },
4973 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE },
4974 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE },
4975 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE },
4976 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE },
4977 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE },
4978 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE },
4979 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE },
4980 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE },
4981 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE },
4982 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE },
4983 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE },
4984 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE },
4985 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE },
4986 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE },
4987 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE },
4988 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE },
4989 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE },
4990 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE },
4991 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE },
4992 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE },
4993 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE },
4994 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE },
4995 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE },
4996 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE },
4997 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE },
4998 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE },
4999 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE },
5000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE },
5001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE },
5002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE },
5003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE },
5004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE },
5005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE },
5006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE },
5007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE },
5008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE },
5009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE },
5010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE },
5011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE },
5012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE },
5013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE },
5014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE },
5015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE },
5016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE },
5017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE },
5018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE },
5019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE },
5020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE },
5021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE },
5022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE },
5023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE },
5024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE },
5025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE },
5026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE },
5027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE },
5028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE },
5029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE },
5030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE },
5031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE },
5032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE },
5033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE },
5034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE },
5035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE },
5036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE },
5037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE },
5038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE },
5039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE },
5040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE },
5041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE },
5042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE },
5043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE },
5044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE },
5045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE },
5046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE },
5047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE },
5048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE },
5049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE },
5050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE },
5051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE },
5052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE },
5053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE },
5054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE },
5055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE },
5056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE },
5057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE },
5058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE },
5059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE },
5060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE },
5061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE },
5062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE },
5063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE },
5064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE },
5065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE },
5066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE },
5067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE },
5068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE },
5069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE },
5070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE },
5071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE },
5072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE },
5073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE },
5074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE },
5075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE },
5076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE },
5077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE },
5078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE },
5079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE },
5080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE },
5081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE },
5082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE },
5083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE },
5084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE },
5085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE },
5086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE },
5087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE },
5208 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5209 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5210 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5211 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5212 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5213 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5214 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5215 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5216 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5217 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5218 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5219 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5220 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5221 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5222 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5223 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5224 /* Fog */
5225 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5226 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5227 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5228 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5229 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE },
5230 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5231 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5232 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE },
5233 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE },
5234 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5235 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE },
5236 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE },
5237 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5238 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5239 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5240 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5241 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5242 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE },
5243 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5244 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5245 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5246 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5247 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5248 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE },
5249 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5250 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5251 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5252 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5253 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5254 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5255 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5256 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5257 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5258 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5260 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5261 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5262 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5263 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5264 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5265 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5266 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5267 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5268 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5269 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5270 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5271 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5272 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5273 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5274 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5275 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5276 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5277 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5278 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5279 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5280 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5281 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5282 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5283 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5284 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5287 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5288 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5289 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5290 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5291 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5292 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5293 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5294 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5295 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5296 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5297 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5298 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5299 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5300 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5301 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5302 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5303 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5304 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5305 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5306 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5307 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5308 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5309 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5310 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5311 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5312 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5313 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5314 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5315 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5316 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5317 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5318 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5319 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5320 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5321 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5322 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5323 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5324 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5325 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5326 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5327 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5328 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5329 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5330 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5331 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5332 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5333 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5334 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5335 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5336 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5337 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5338 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5339 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5340 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5341 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5342 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5343 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5344 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5345 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5346 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5347 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5348 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5349 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5350 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5351 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5352 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5353 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5354 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5355 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5356 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5357 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5358 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5359 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5360 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5361 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5362 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5363 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5364 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5365 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5366 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5367 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5368 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5369 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5370 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE },
5371 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE },
5372 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE },
5373 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE },
5374 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5375 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5376 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5377 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5378 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5379 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE },
5380 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE },
5381 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE },
5382 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE },
5383 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE },
5384 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE },
5385 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE },
5386 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE },
5387 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5389 #undef GLINFO_LOCATION
5391 #define GLINFO_LOCATION (*gl_info)
5392 /* Context activation is done by the caller. */
5393 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5395 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype,
5396 const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps)
5398 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5399 WINED3DTEXOPCAPS_ADDSIGNED |
5400 WINED3DTEXOPCAPS_ADDSIGNED2X |
5401 WINED3DTEXOPCAPS_MODULATE |
5402 WINED3DTEXOPCAPS_MODULATE2X |
5403 WINED3DTEXOPCAPS_MODULATE4X |
5404 WINED3DTEXOPCAPS_SELECTARG1 |
5405 WINED3DTEXOPCAPS_SELECTARG2 |
5406 WINED3DTEXOPCAPS_DISABLE;
5408 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5409 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5410 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5411 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5412 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5413 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5414 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5415 WINED3DTEXOPCAPS_LERP |
5416 WINED3DTEXOPCAPS_SUBTRACT;
5418 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5419 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5420 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5421 WINED3DTEXOPCAPS_MULTIPLYADD |
5422 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5423 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5424 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5426 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5427 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5429 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5430 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5433 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5434 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5435 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5437 if (TRACE_ON(d3d))
5439 TRACE("Checking support for fixup:\n");
5440 dump_color_fixup_desc(fixup);
5443 /* We only support identity conversions. */
5444 if (is_identity_fixup(fixup))
5446 TRACE("[OK]\n");
5447 return TRUE;
5450 TRACE("[FAILED]\n");
5451 return FALSE;
5454 const struct fragment_pipeline ffp_fragment_pipeline = {
5455 ffp_enable,
5456 ffp_fragment_get_caps,
5457 ffp_fragment_alloc,
5458 ffp_fragment_free,
5459 ffp_color_fixup_supported,
5460 ffp_fragmentstate_template,
5461 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5464 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5466 unsigned int i;
5467 for(i = 0; funcs[i]; i++);
5468 return i;
5471 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5472 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5473 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5476 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5477 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5478 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5479 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5482 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5483 const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
5484 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5486 unsigned int i, type, handlers;
5487 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5488 const struct StateEntryTemplate *cur;
5489 BOOL set[STATE_HIGHEST + 1];
5491 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5493 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5494 StateTable[i].representative = 0;
5495 StateTable[i].apply = state_undefined;
5498 for(type = 0; type < 3; type++) {
5499 /* This switch decides the order in which the states are applied */
5500 switch(type) {
5501 case 0: cur = misc; break;
5502 case 1: cur = fragment->states; break;
5503 case 2: cur = vertex; break;
5504 default: cur = NULL; /* Stupid compiler */
5506 if(!cur) continue;
5508 /* GL extension filtering should not prevent multiple handlers being applied from different
5509 * pipeline parts
5511 memset(set, 0, sizeof(set));
5513 for(i = 0; cur[i].state; i++) {
5514 APPLYSTATEFUNC *funcs_array;
5516 /* Only use the first matching state with the available extension from one template.
5517 * e.g.
5518 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5519 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5521 * if GL_XYZ_fancy is supported, ignore the 2nd line
5523 if(set[cur[i].state]) continue;
5524 /* Skip state lines depending on unsupported extensions */
5525 if (!GL_SUPPORT(cur[i].extension)) continue;
5526 set[cur[i].state] = TRUE;
5527 /* In some cases having an extension means that nothing has to be
5528 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5529 * supported, the texture coordinate fixup can be ignored. If the
5530 * apply function is used, mark the state set(done above) to prevent
5531 * applying later lines, but do not record anything in the state
5532 * table
5534 if(!cur[i].content.apply) continue;
5536 handlers = num_handlers(multistate_funcs[cur[i].state]);
5537 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5538 switch(handlers) {
5539 case 0:
5540 StateTable[cur[i].state].apply = cur[i].content.apply;
5541 break;
5542 case 1:
5543 StateTable[cur[i].state].apply = multistate_apply_2;
5544 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5546 sizeof(**dev_multistate_funcs) * 2);
5547 if (!dev_multistate_funcs[cur[i].state]) {
5548 goto out_of_mem;
5551 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5552 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5553 break;
5554 case 2:
5555 StateTable[cur[i].state].apply = multistate_apply_3;
5556 funcs_array = HeapReAlloc(GetProcessHeap(),
5558 dev_multistate_funcs[cur[i].state],
5559 sizeof(**dev_multistate_funcs) * 3);
5560 if (!funcs_array) {
5561 goto out_of_mem;
5564 dev_multistate_funcs[cur[i].state] = funcs_array;
5565 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5566 break;
5567 default:
5568 ERR("Unexpected amount of state handlers for state %u: %u\n",
5569 cur[i].state, handlers + 1);
5572 if(StateTable[cur[i].state].representative &&
5573 StateTable[cur[i].state].representative != cur[i].content.representative) {
5574 FIXME("State %u has different representatives in different pipeline parts\n",
5575 cur[i].state);
5577 StateTable[cur[i].state].representative = cur[i].content.representative;
5581 return WINED3D_OK;
5583 out_of_mem:
5584 for (i = 0; i <= STATE_HIGHEST; ++i) {
5585 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5588 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5590 return E_OUTOFMEMORY;
5592 #undef GLINFO_LOCATION