wined3d: Print a FIXME/WARN for all unsupported vertex blend flags.
[wine.git] / dlls / wined3d / state.c
blobd3be2c54994906ae72a8cbea281b9707bc684346
1 /*
2 * Direct3D state management
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11 * Copyright 2009 Henri Verbeet for CodeWeavers
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "config.h"
29 #include <stdio.h>
30 #ifdef HAVE_FLOAT_H
31 # include <float.h>
32 #endif
33 #include "wined3d_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
36 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
38 #define GLINFO_LOCATION (*context->gl_info)
40 /* GL locking for state handlers is done by the caller. */
42 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context);
44 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
46 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
47 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
49 if(STATE_IS_RENDER(state)) {
50 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
51 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
52 } else {
53 /* Shouldn't have an unknown type here */
54 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
58 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
60 ERR("Undefined state.\n");
63 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
65 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
67 switch(Value) {
68 case WINED3DFILL_POINT:
69 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
70 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
71 break;
72 case WINED3DFILL_WIREFRAME:
73 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
74 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
75 break;
76 case WINED3DFILL_SOLID:
77 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
78 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 break;
80 default:
81 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
85 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
87 /* Lighting is not enabled if transformed vertices are drawn
88 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
89 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
90 * vertex declaration applying function calls this function for updating
93 if(isStateDirty(context, STATE_VDECL)) {
94 return;
97 if (stateblock->renderState[WINED3DRS_LIGHTING]
98 && !stateblock->device->strided_streams.position_transformed)
100 glEnable(GL_LIGHTING);
101 checkGLcall("glEnable GL_LIGHTING");
102 } else {
103 glDisable(GL_LIGHTING);
104 checkGLcall("glDisable GL_LIGHTING");
108 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
110 /* No z test without depth stencil buffers */
111 if (!stateblock->device->stencilBufferTarget)
113 TRACE("No Z buffer - disabling depth test\n");
114 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
115 checkGLcall("glDisable GL_DEPTH_TEST");
116 return;
119 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
120 case WINED3DZB_FALSE:
121 glDisable(GL_DEPTH_TEST);
122 checkGLcall("glDisable GL_DEPTH_TEST");
123 break;
124 case WINED3DZB_TRUE:
125 glEnable(GL_DEPTH_TEST);
126 checkGLcall("glEnable GL_DEPTH_TEST");
127 break;
128 case WINED3DZB_USEW:
129 glEnable(GL_DEPTH_TEST);
130 checkGLcall("glEnable GL_DEPTH_TEST");
131 FIXME("W buffer is not well handled\n");
132 break;
133 default:
134 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
138 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
140 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
141 * switch
143 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
144 case WINED3DCULL_NONE:
145 glDisable(GL_CULL_FACE);
146 checkGLcall("glDisable GL_CULL_FACE");
147 break;
148 case WINED3DCULL_CW:
149 glEnable(GL_CULL_FACE);
150 checkGLcall("glEnable GL_CULL_FACE");
151 glCullFace(GL_FRONT);
152 checkGLcall("glCullFace(GL_FRONT)");
153 break;
154 case WINED3DCULL_CCW:
155 glEnable(GL_CULL_FACE);
156 checkGLcall("glEnable GL_CULL_FACE");
157 glCullFace(GL_BACK);
158 checkGLcall("glCullFace(GL_BACK)");
159 break;
160 default:
161 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
165 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
167 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
168 case WINED3DSHADE_FLAT:
169 glShadeModel(GL_FLAT);
170 checkGLcall("glShadeModel(GL_FLAT)");
171 break;
172 case WINED3DSHADE_GOURAUD:
173 glShadeModel(GL_SMOOTH);
174 checkGLcall("glShadeModel(GL_SMOOTH)");
175 break;
176 case WINED3DSHADE_PHONG:
177 FIXME("WINED3DSHADE_PHONG isn't supported\n");
178 break;
179 default:
180 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
184 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
186 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
187 glEnable(GL_DITHER);
188 checkGLcall("glEnable GL_DITHER");
189 } else {
190 glDisable(GL_DITHER);
191 checkGLcall("glDisable GL_DITHER");
195 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
197 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
198 * this has to be merged with ZENABLE and ZFUNC
200 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
201 glDepthMask(1);
202 checkGLcall("glDepthMask(1)");
203 } else {
204 glDepthMask(0);
205 checkGLcall("glDepthMask(0)");
209 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
211 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
213 if(glParm) {
214 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
215 static BOOL once = FALSE;
216 /* There are a few issues with this: First, our inability to
217 * select a proper Z depth, most of the time we're stuck with
218 * D24S8, even if the app selects D32 or D16. There seem to be
219 * some other precision problems which have to be debugged to
220 * make NOTEQUAL and EQUAL work properly
222 if(!once) {
223 once = TRUE;
224 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
228 glDepthFunc(glParm);
229 checkGLcall("glDepthFunc");
233 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
235 float col[4];
236 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
238 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
239 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
240 checkGLcall("glLightModel for MODEL_AMBIENT");
243 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
245 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0];
246 int srcBlend = GL_ZERO;
247 int dstBlend = GL_ZERO;
249 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
250 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
251 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
252 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
254 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
255 * The d3d9 visual test confirms the behavior. */
256 if (context->render_offscreen
257 && !(target->resource.format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
259 glDisable(GL_BLEND);
260 checkGLcall("glDisable GL_BLEND");
261 return;
262 } else {
263 glEnable(GL_BLEND);
264 checkGLcall("glEnable GL_BLEND");
266 } else {
267 glDisable(GL_BLEND);
268 checkGLcall("glDisable GL_BLEND");
269 /* Nothing more to do - get out */
270 return;
273 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
274 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
275 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
276 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
277 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
278 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
279 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
280 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
281 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
283 /* To compensate the lack of format switching with backbuffer offscreen rendering,
284 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
285 * if the render target doesn't support alpha blending. A nonexistent alpha channel
286 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
288 case WINED3DBLEND_DESTALPHA :
289 dstBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
290 break;
291 case WINED3DBLEND_INVDESTALPHA :
292 dstBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
293 break;
295 case WINED3DBLEND_SRCALPHASAT :
296 dstBlend = GL_SRC_ALPHA_SATURATE;
297 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
298 break;
300 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
301 * values which are still valid up to d3d9. They should not occur as dest blend values
303 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
304 srcBlend = GL_SRC_ALPHA;
305 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
306 break;
308 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
309 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
310 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
311 break;
313 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
314 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
315 default:
316 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
319 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
320 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
321 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
322 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
323 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
324 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
325 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
326 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
327 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
328 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
330 case WINED3DBLEND_DESTALPHA :
331 srcBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
332 break;
333 case WINED3DBLEND_INVDESTALPHA :
334 srcBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
335 break;
337 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
338 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
339 break;
341 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
342 dstBlend = GL_SRC_ALPHA;
343 break;
345 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
346 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
347 default:
348 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
351 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
352 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
353 glEnable(GL_LINE_SMOOTH);
354 checkGLcall("glEnable(GL_LINE_SMOOTH)");
355 if(srcBlend != GL_SRC_ALPHA) {
356 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
358 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
359 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
361 } else {
362 glDisable(GL_LINE_SMOOTH);
363 checkGLcall("glDisable(GL_LINE_SMOOTH)");
366 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
367 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
368 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
371 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
372 int srcBlendAlpha = GL_ZERO;
373 int dstBlendAlpha = GL_ZERO;
375 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
376 if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
378 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
379 return;
382 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
383 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
384 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
385 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
386 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
387 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
388 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
389 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
390 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
391 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
392 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
393 case WINED3DBLEND_SRCALPHASAT :
394 dstBlend = GL_SRC_ALPHA_SATURATE;
395 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
396 break;
397 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
398 * values which are still valid up to d3d9. They should not occur as dest blend values
400 case WINED3DBLEND_BOTHSRCALPHA :
401 dstBlendAlpha = GL_SRC_ALPHA;
402 srcBlendAlpha = GL_SRC_ALPHA;
403 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
404 break;
405 case WINED3DBLEND_BOTHINVSRCALPHA :
406 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
407 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
408 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
409 break;
410 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
411 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
412 default:
413 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
416 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
417 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
418 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
419 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
420 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
421 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
422 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
423 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
424 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
425 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
426 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
427 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
428 case WINED3DBLEND_BOTHSRCALPHA :
429 srcBlendAlpha = GL_SRC_ALPHA;
430 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
431 break;
432 case WINED3DBLEND_BOTHINVSRCALPHA :
433 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
434 dstBlendAlpha = GL_SRC_ALPHA;
435 break;
436 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
437 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
438 default:
439 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
442 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
443 checkGLcall("glBlendFuncSeparateEXT");
444 } else {
445 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
446 glBlendFunc(srcBlend, dstBlend);
447 checkGLcall("glBlendFunc");
450 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
451 so it may need updating */
452 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE])
454 const struct StateEntry *StateTable = stateblock->device->StateTable;
455 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
459 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
461 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
464 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
466 float col[4];
468 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
469 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
470 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
471 checkGLcall("glBlendColor");
474 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
476 int glParm = 0;
477 float ref;
478 BOOL enable_ckey = FALSE;
480 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
482 /* Find out if the texture on the first stage has a ckey set
483 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
484 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
485 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
486 * in case it finds some texture+colorkeyenable combination which needs extra care.
488 if (stateblock->textures[0])
490 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
492 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
494 IWineD3DSurfaceImpl *surf;
496 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
498 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
500 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
501 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
502 * surface has alpha bits */
503 if (!surf->resource.format_desc->alpha_mask) enable_ckey = TRUE;
508 if (enable_ckey || context->last_was_ckey)
510 const struct StateEntry *StateTable = stateblock->device->StateTable;
511 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
513 context->last_was_ckey = enable_ckey;
515 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
516 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
517 glEnable(GL_ALPHA_TEST);
518 checkGLcall("glEnable GL_ALPHA_TEST");
519 } else {
520 glDisable(GL_ALPHA_TEST);
521 checkGLcall("glDisable GL_ALPHA_TEST");
522 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
523 * enable call
525 return;
528 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
529 glParm = GL_NOTEQUAL;
530 ref = 0.0f;
531 } else {
532 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
533 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
535 if(glParm) {
536 glAlphaFunc(glParm, ref);
537 checkGLcall("glAlphaFunc");
541 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
543 const struct wined3d_gl_info *gl_info = context->gl_info;
544 DWORD enable = 0xFFFFFFFF;
545 DWORD disable = 0x00000000;
547 if (!stateblock->device->vs_clipping && use_vs(stateblock))
549 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
550 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
551 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
552 * of that - don't do anything here and keep them disabled
554 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
555 static BOOL warned = FALSE;
556 if(!warned) {
557 FIXME("Clipping not supported with vertex shaders\n");
558 warned = TRUE;
561 return;
564 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
565 * of already set values
568 /* If enabling / disabling all
569 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
571 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
572 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
573 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
574 if (gl_info->supported[ARB_DEPTH_CLAMP])
576 glDisable(GL_DEPTH_CLAMP);
577 checkGLcall("glDisable(GL_DEPTH_CLAMP)");
579 } else {
580 disable = 0xffffffff;
581 enable = 0x00;
582 if (gl_info->supported[ARB_DEPTH_CLAMP])
584 glEnable(GL_DEPTH_CLAMP);
585 checkGLcall("glEnable(GL_DEPTH_CLAMP)");
587 else
589 FIXME("Clipping disabled, but ARB_depth_clamp isn't supported.\n");
593 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
594 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
595 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
596 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
597 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
598 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
600 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
601 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
602 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
603 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
604 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
605 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
607 /** update clipping status */
608 if (enable) {
609 stateblock->clip_status.ClipUnion = 0;
610 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
611 } else {
612 stateblock->clip_status.ClipUnion = 0;
613 stateblock->clip_status.ClipIntersection = 0;
617 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
619 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
622 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
624 int blendEquation = GL_FUNC_ADD;
625 int blendEquationAlpha = GL_FUNC_ADD;
627 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
628 if (stateblock->renderState[WINED3DRS_BLENDOPALPHA]
629 && !context->gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
631 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
632 return;
635 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
636 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
637 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
638 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
639 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
640 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
641 default:
642 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
645 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
646 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
647 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
648 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
649 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
650 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
651 default:
652 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
655 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
656 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
657 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
658 checkGLcall("glBlendEquationSeparateEXT");
659 } else {
660 TRACE("glBlendEquation(%x)\n", blendEquation);
661 GL_EXTCALL(glBlendEquationEXT(blendEquation));
662 checkGLcall("glBlendEquation");
666 static void state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
668 const struct wined3d_gl_info *gl_info = context->gl_info;
669 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
670 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
671 * specular color. This is wrong:
672 * Separate specular color means the specular colour is maintained separately, whereas
673 * single color means it is merged in. However in both cases they are being used to
674 * some extent.
675 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
676 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
677 * running 1.4 yet!
680 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
681 * Instead, we need to setup the FinalCombiner properly.
683 * The default setup for the FinalCombiner is:
685 * <variable> <input> <mapping> <usage>
686 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
687 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
688 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
689 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
690 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
691 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
692 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
694 * That's pretty much fine as it is, except for variable B, which needs to take
695 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
696 * whether WINED3DRS_SPECULARENABLE is enabled or not.
699 TRACE("Setting specular enable state and materials\n");
700 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
701 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
702 checkGLcall("glMaterialfv");
704 if (stateblock->material.Power > gl_info->limits.shininess)
706 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
707 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
708 * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the
709 * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp
710 * them, it should be safe to do so without major visual distortions.
712 WARN("Material power = %f, limit %f\n", stateblock->material.Power, gl_info->limits.shininess);
713 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess);
714 } else {
715 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
717 checkGLcall("glMaterialf(GL_SHININESS)");
719 if (gl_info->supported[EXT_SECONDARY_COLOR])
721 glEnable(GL_COLOR_SUM_EXT);
723 else
725 TRACE("Specular colors cannot be enabled in this version of opengl\n");
727 checkGLcall("glEnable(GL_COLOR_SUM)");
729 if (gl_info->supported[NV_REGISTER_COMBINERS])
731 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
732 checkGLcall("glFinalCombinerInputNV()");
734 } else {
735 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
737 /* for the case of enabled lighting: */
738 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
739 checkGLcall("glMaterialfv");
741 /* for the case of disabled lighting: */
742 if (gl_info->supported[EXT_SECONDARY_COLOR])
744 glDisable(GL_COLOR_SUM_EXT);
746 else
748 TRACE("Specular colors cannot be disabled in this version of opengl\n");
750 checkGLcall("glDisable(GL_COLOR_SUM)");
752 if (gl_info->supported[NV_REGISTER_COMBINERS])
754 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
755 checkGLcall("glFinalCombinerInputNV()");
759 TRACE("(%p) : Diffuse {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
760 stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
761 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
762 TRACE("(%p) : Ambient {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
763 stateblock->material.Ambient.r, stateblock->material.Ambient.g,
764 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
765 TRACE("(%p) : Specular {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
766 stateblock->material.Specular.r, stateblock->material.Specular.g,
767 stateblock->material.Specular.b, stateblock->material.Specular.a);
768 TRACE("(%p) : Emissive {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
769 stateblock->material.Emissive.r, stateblock->material.Emissive.g,
770 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
772 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
773 checkGLcall("glMaterialfv(GL_AMBIENT)");
774 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
775 checkGLcall("glMaterialfv(GL_DIFFUSE)");
776 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
777 checkGLcall("glMaterialfv(GL_EMISSION)");
780 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
782 unsigned int i;
784 /* Note the texture color applies to all textures whereas
785 * GL_TEXTURE_ENV_COLOR applies to active only
787 float col[4];
788 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
790 /* And now the default texture color as well */
791 for (i = 0; i < context->gl_info->limits.texture_stages; ++i)
793 /* Note the WINED3DRS value applies to all textures, but GL has one
794 * per texture, so apply it now ready to be used!
796 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
797 checkGLcall("glActiveTextureARB");
799 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
800 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
804 static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face,
805 GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
807 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
808 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
809 GL_EXTCALL(glActiveStencilFaceEXT(face));
810 checkGLcall("glActiveStencilFaceEXT(...)");
811 glStencilFunc(func, ref, mask);
812 checkGLcall("glStencilFunc(...)");
813 glStencilOp(stencilFail, depthFail, stencilPass);
814 checkGLcall("glStencilOp(...)");
817 static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
819 const struct wined3d_gl_info *gl_info = context->gl_info;
820 DWORD onesided_enable = FALSE;
821 DWORD twosided_enable = FALSE;
822 GLint func = GL_ALWAYS;
823 GLint func_ccw = GL_ALWAYS;
824 GLint ref = 0;
825 GLuint mask = 0;
826 GLint stencilFail = GL_KEEP;
827 GLint depthFail = GL_KEEP;
828 GLint stencilPass = GL_KEEP;
829 GLint stencilFail_ccw = GL_KEEP;
830 GLint depthFail_ccw = GL_KEEP;
831 GLint stencilPass_ccw = GL_KEEP;
833 /* No stencil test without a stencil buffer. */
834 if (!stateblock->device->stencilBufferTarget)
836 glDisable(GL_STENCIL_TEST);
837 checkGLcall("glDisable GL_STENCIL_TEST");
838 return;
841 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
842 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
843 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
844 func = GL_ALWAYS;
845 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
846 func_ccw = GL_ALWAYS;
847 ref = stateblock->renderState[WINED3DRS_STENCILREF];
848 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
849 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
850 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
851 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
852 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
853 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
854 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
856 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
857 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
858 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
859 onesided_enable, twosided_enable, ref, mask,
860 func, stencilFail, depthFail, stencilPass,
861 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
863 if (twosided_enable && onesided_enable) {
864 glEnable(GL_STENCIL_TEST);
865 checkGLcall("glEnable GL_STENCIL_TEST");
867 if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
869 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
870 * which has an effect on the code below too. If we apply the front face
871 * afterwards, we are sure that the active stencil face is set to front,
872 * and other stencil functions which do not use two sided stencil do not have
873 * to set it back
875 renderstate_stencil_twosided(context, GL_BACK,
876 func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
877 renderstate_stencil_twosided(context, GL_FRONT,
878 func, ref, mask, stencilFail, depthFail, stencilPass);
880 else if (gl_info->supported[ATI_SEPARATE_STENCIL])
882 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
883 checkGLcall("glStencilFuncSeparateATI(...)");
884 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
885 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
886 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
887 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
888 } else {
889 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
892 else if(onesided_enable)
894 if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
896 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
897 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
900 /* This code disables the ATI extension as well, since the standard stencil functions are equal
901 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
903 glEnable(GL_STENCIL_TEST);
904 checkGLcall("glEnable GL_STENCIL_TEST");
905 glStencilFunc(func, ref, mask);
906 checkGLcall("glStencilFunc(...)");
907 glStencilOp(stencilFail, depthFail, stencilPass);
908 checkGLcall("glStencilOp(...)");
909 } else {
910 glDisable(GL_STENCIL_TEST);
911 checkGLcall("glDisable GL_STENCIL_TEST");
915 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
917 DWORD mask = stateblock->device->stencilBufferTarget ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0;
919 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
920 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
921 glStencilMask(mask);
922 checkGLcall("glStencilMask");
923 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
924 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
925 glStencilMask(mask);
928 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
930 DWORD mask = stateblock->device->stencilBufferTarget ? stateblock->renderState[WINED3DRS_STENCILWRITEMASK] : 0;
932 glStencilMask(mask);
933 checkGLcall("glStencilMask");
936 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
939 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
941 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
943 /* Table fog on: Never use fog coords, and use per-fragment fog */
944 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
945 glHint(GL_FOG_HINT, GL_NICEST);
946 if(context->fog_coord) {
947 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
948 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
949 context->fog_coord = FALSE;
951 return;
954 /* Otherwise use per-vertex fog in any case */
955 glHint(GL_FOG_HINT, GL_FASTEST);
957 if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
958 /* No fog at all, or transformed vertices: Use fog coord */
959 if(!context->fog_coord) {
960 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
961 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
962 context->fog_coord = TRUE;
964 } else {
965 /* Otherwise, use the fragment depth */
966 if(context->fog_coord) {
967 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
968 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
969 context->fog_coord = FALSE;
974 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
976 float fogstart, fogend;
977 union {
978 DWORD d;
979 float f;
980 } tmpvalue;
982 switch(context->fog_source) {
983 case FOGSOURCE_VS:
984 fogstart = 1.0f;
985 fogend = 0.0f;
986 break;
988 case FOGSOURCE_COORD:
989 fogstart = 255.0f;
990 fogend = 0.0f;
991 break;
993 case FOGSOURCE_FFP:
994 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
995 fogstart = tmpvalue.f;
996 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
997 fogend = tmpvalue.f;
998 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
999 if(fogstart == fogend) {
1000 fogstart = -1.0f / 0.0f;
1001 fogend = 0.0f;
1003 break;
1005 default:
1006 /* This should not happen.context->fog_source is set in wined3d, not the app.
1007 * Still this is needed to make the compiler happy
1009 ERR("Unexpected fog coordinate source\n");
1010 fogstart = 0.0f;
1011 fogend = 0.0f;
1014 glFogf(GL_FOG_START, fogstart);
1015 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1016 TRACE("Fog Start == %f\n", fogstart);
1018 glFogf(GL_FOG_END, fogend);
1019 checkGLcall("glFogf(GL_FOG_END, fogend)");
1020 TRACE("Fog End == %f\n", fogend);
1023 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1025 enum fogsource new_source;
1027 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
1029 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
1030 /* No fog? Disable it, and we're done :-) */
1031 glDisableWINE(GL_FOG);
1032 checkGLcall("glDisable GL_FOG");
1033 return;
1036 /* Fog Rules:
1038 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
1039 * It can use the Z value of the vertex, or the alpha component of the specular color.
1040 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
1041 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
1042 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
1044 * FOGTABLEMODE != NONE:
1045 * The Z value is used, with the equation specified, no matter what vertex type.
1047 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1048 * Per vertex fog is calculated using the specified fog equation and the parameters
1050 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1051 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1052 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1055 * Rules for vertex fog with shaders:
1057 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1058 * the fog computation to happen during transformation while openGL expects it to happen
1059 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1060 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1061 * To solve this problem, WineD3D does:
1062 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1063 * shader,
1064 * and 2) disables the fog computation (in either the fixed function or programmable
1065 * rasterizer) if using a vertex program.
1067 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1068 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1069 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1070 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1071 * There are some GL differences between specular fog coords and vertex shaders though.
1073 * With table fog the vertex shader fog coordinate is ignored.
1075 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1076 * without shaders).
1079 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1080 * the system will apply only pixel(=table) fog effects."
1082 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1083 if(use_vs(stateblock)) {
1084 glFogi(GL_FOG_MODE, GL_LINEAR);
1085 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1086 new_source = FOGSOURCE_VS;
1087 } else {
1088 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1089 /* If processed vertices are used, fall through to the NONE case */
1090 case WINED3DFOG_EXP:
1091 if(!context->last_was_rhw) {
1092 glFogi(GL_FOG_MODE, GL_EXP);
1093 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1094 new_source = FOGSOURCE_FFP;
1095 break;
1097 /* drop through */
1099 case WINED3DFOG_EXP2:
1100 if(!context->last_was_rhw) {
1101 glFogi(GL_FOG_MODE, GL_EXP2);
1102 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1103 new_source = FOGSOURCE_FFP;
1104 break;
1106 /* drop through */
1108 case WINED3DFOG_LINEAR:
1109 if(!context->last_was_rhw) {
1110 glFogi(GL_FOG_MODE, GL_LINEAR);
1111 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1112 new_source = FOGSOURCE_FFP;
1113 break;
1115 /* drop through */
1117 case WINED3DFOG_NONE:
1118 /* Both are none? According to msdn the alpha channel of the specular
1119 * color contains a fog factor. Set it in drawStridedSlow.
1120 * Same happens with Vertexfog on transformed vertices
1122 new_source = FOGSOURCE_COORD;
1123 glFogi(GL_FOG_MODE, GL_LINEAR);
1124 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1125 break;
1127 default:
1128 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1129 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1132 } else {
1133 new_source = FOGSOURCE_FFP;
1135 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1136 case WINED3DFOG_EXP:
1137 glFogi(GL_FOG_MODE, GL_EXP);
1138 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1139 break;
1141 case WINED3DFOG_EXP2:
1142 glFogi(GL_FOG_MODE, GL_EXP2);
1143 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1144 break;
1146 case WINED3DFOG_LINEAR:
1147 glFogi(GL_FOG_MODE, GL_LINEAR);
1148 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1149 break;
1151 case WINED3DFOG_NONE: /* Won't happen */
1152 default:
1153 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1157 glEnableWINE(GL_FOG);
1158 checkGLcall("glEnable GL_FOG");
1159 if(new_source != context->fog_source) {
1160 context->fog_source = new_source;
1161 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1165 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1167 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1168 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1172 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1174 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1175 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1176 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1177 } else {
1178 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1179 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1183 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1185 float col[4];
1186 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1187 glFogfv(GL_FOG_COLOR, &col[0]);
1188 checkGLcall("glFog GL_FOG_COLOR");
1191 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1193 union {
1194 DWORD d;
1195 float f;
1196 } tmpvalue;
1197 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1198 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1199 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1202 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1204 IWineD3DDeviceImpl *device = stateblock->device;
1205 GLenum Parm = 0;
1207 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1208 * The vertex declaration will call this function if the fixed function pipeline is used.
1211 if(isStateDirty(context, STATE_VDECL)) {
1212 return;
1215 context->num_untracked_materials = 0;
1216 if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE))
1217 && stateblock->renderState[WINED3DRS_COLORVERTEX])
1219 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1220 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1221 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1222 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1223 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1225 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1226 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1227 Parm = GL_AMBIENT_AND_DIFFUSE;
1228 } else {
1229 Parm = GL_DIFFUSE;
1231 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1232 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1233 context->num_untracked_materials++;
1235 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1236 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1237 context->num_untracked_materials++;
1239 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1240 Parm = GL_AMBIENT;
1241 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1242 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1243 context->num_untracked_materials++;
1245 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1246 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1247 context->num_untracked_materials++;
1249 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1250 Parm = GL_EMISSION;
1251 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1252 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1253 context->num_untracked_materials++;
1255 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1256 Parm = GL_SPECULAR;
1260 /* Nothing changed, return. */
1261 if (Parm == context->tracking_parm) return;
1263 if(!Parm) {
1264 glDisable(GL_COLOR_MATERIAL);
1265 checkGLcall("glDisable GL_COLOR_MATERIAL");
1266 } else {
1267 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1268 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1269 glEnable(GL_COLOR_MATERIAL);
1270 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1273 /* Apparently calls to glMaterialfv are ignored for properties we're
1274 * tracking with glColorMaterial, so apply those here. */
1275 switch (context->tracking_parm) {
1276 case GL_AMBIENT_AND_DIFFUSE:
1277 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1278 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1279 checkGLcall("glMaterialfv");
1280 break;
1282 case GL_DIFFUSE:
1283 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1284 checkGLcall("glMaterialfv");
1285 break;
1287 case GL_AMBIENT:
1288 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1289 checkGLcall("glMaterialfv");
1290 break;
1292 case GL_EMISSION:
1293 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1294 checkGLcall("glMaterialfv");
1295 break;
1297 case GL_SPECULAR:
1298 /* Only change material color if specular is enabled, otherwise it is set to black */
1299 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1300 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1301 checkGLcall("glMaterialfv");
1302 } else {
1303 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1304 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1305 checkGLcall("glMaterialfv");
1307 break;
1310 context->tracking_parm = Parm;
1313 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1315 union {
1316 DWORD d;
1317 WINED3DLINEPATTERN lp;
1318 } tmppattern;
1319 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1321 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1323 if (tmppattern.lp.wRepeatFactor) {
1324 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1325 checkGLcall("glLineStipple(repeat, linepattern)");
1326 glEnable(GL_LINE_STIPPLE);
1327 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1328 } else {
1329 glDisable(GL_LINE_STIPPLE);
1330 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1334 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1336 union {
1337 DWORD d;
1338 float f;
1339 } tmpvalue;
1341 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1342 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1343 TRACE("ZBias value %f\n", tmpvalue.f);
1344 glPolygonOffset(0, -tmpvalue.f);
1345 checkGLcall("glPolygonOffset(0, -Value)");
1346 glEnable(GL_POLYGON_OFFSET_FILL);
1347 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1348 glEnable(GL_POLYGON_OFFSET_LINE);
1349 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1350 glEnable(GL_POLYGON_OFFSET_POINT);
1351 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1352 } else {
1353 glDisable(GL_POLYGON_OFFSET_FILL);
1354 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1355 glDisable(GL_POLYGON_OFFSET_LINE);
1356 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1357 glDisable(GL_POLYGON_OFFSET_POINT);
1358 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1363 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1365 if(isStateDirty(context, STATE_VDECL)) {
1366 return;
1368 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1369 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1370 * by zero and is not properly defined in opengl, so avoid it
1372 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]
1373 && (stateblock->device->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL)))
1375 glEnable(GL_NORMALIZE);
1376 checkGLcall("glEnable(GL_NORMALIZE);");
1377 } else {
1378 glDisable(GL_NORMALIZE);
1379 checkGLcall("glDisable(GL_NORMALIZE);");
1383 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1385 union {
1386 DWORD d;
1387 float f;
1388 } tmpvalue;
1390 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1391 if (tmpvalue.f != 1.0f)
1393 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1395 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1396 if (tmpvalue.f != 64.0f)
1398 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1403 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1405 union {
1406 DWORD d;
1407 float f;
1408 } min, max;
1410 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1411 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1413 /* Max point size trumps min point size */
1414 if(min.f > max.f) {
1415 min.f = max.f;
1418 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1419 checkGLcall("glPointParameterfEXT(...)");
1420 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1421 checkGLcall("glPointParameterfEXT(...)");
1424 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1426 union {
1427 DWORD d;
1428 float f;
1429 } min, max;
1431 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1432 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1434 /* Max point size trumps min point size */
1435 if(min.f > max.f) {
1436 min.f = max.f;
1439 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1440 checkGLcall("glPointParameterfARB(...)");
1441 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1442 checkGLcall("glPointParameterfARB(...)");
1445 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1447 const struct wined3d_gl_info *gl_info = context->gl_info;
1448 /* TODO: Group this with the viewport */
1450 * POINTSCALEENABLE controls how point size value is treated. If set to
1451 * true, the point size is scaled with respect to height of viewport.
1452 * When set to false point size is in pixels.
1455 /* Default values */
1456 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1457 union {
1458 DWORD d;
1459 float f;
1460 } pointSize, A, B, C;
1462 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1463 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1464 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1465 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1467 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1468 GLfloat scaleFactor;
1469 float h = stateblock->viewport.Height;
1471 if (pointSize.f < gl_info->limits.pointsize_min)
1473 /* Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1474 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1475 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1476 * are less than 1.0f. scale_factor = 1.0f / point_size.
1478 scaleFactor = pointSize.f / gl_info->limits.pointsize_min;
1479 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1480 * is 1.0, but then accepts points below that and draws too small points
1482 pointSize.f = gl_info->limits.pointsize_min;
1484 else if(pointSize.f > gl_info->limits.pointsize_max)
1486 /* gl already scales the input to glPointSize,
1487 * d3d scales the result after the point size scale.
1488 * If the point size is bigger than the max size, use the
1489 * scaling to scale it bigger, and set the gl point size to max
1491 scaleFactor = pointSize.f / gl_info->limits.pointsize_max;
1492 TRACE("scale: %f\n", scaleFactor);
1493 pointSize.f = gl_info->limits.pointsize_max;
1494 } else {
1495 scaleFactor = 1.0f;
1497 scaleFactor = pow(h * scaleFactor, 2);
1499 att[0] = A.f / scaleFactor;
1500 att[1] = B.f / scaleFactor;
1501 att[2] = C.f / scaleFactor;
1504 if (gl_info->supported[ARB_POINT_PARAMETERS])
1506 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1507 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1509 else if (gl_info->supported[EXT_POINT_PARAMETERS])
1511 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1512 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1513 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1514 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1517 glPointSize(pointSize.f);
1518 checkGLcall("glPointSize(...);");
1521 static void state_debug_monitor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1523 WARN("token: %#x\n", stateblock->renderState[WINED3DRS_DEBUGMONITORTOKEN]);
1526 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1528 DWORD mask0 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1529 DWORD mask1 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE1];
1530 DWORD mask2 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE2];
1531 DWORD mask3 = stateblock->renderState[WINED3DRS_COLORWRITEENABLE3];
1533 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1534 mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1535 mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1536 mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1537 mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1538 glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1539 mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1540 mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1541 mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1542 checkGLcall("glColorMask(...)");
1544 if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0)
1545 || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf)))
1547 FIXME("WINED3DRS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n",
1548 mask0, mask1, mask2, mask3);
1549 FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n");
1553 static void set_color_mask(struct wined3d_context *context, UINT index, DWORD mask)
1555 GL_EXTCALL(glColorMaskIndexedEXT(index,
1556 mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1557 mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1558 mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1559 mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE));
1562 static void state_colorwrite0(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1564 set_color_mask(context, 0, stateblock->renderState[WINED3DRS_COLORWRITEENABLE]);
1567 static void state_colorwrite1(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1569 set_color_mask(context, 1, stateblock->renderState[WINED3DRS_COLORWRITEENABLE1]);
1572 static void state_colorwrite2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1574 set_color_mask(context, 2, stateblock->renderState[WINED3DRS_COLORWRITEENABLE2]);
1577 static void state_colorwrite3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1579 set_color_mask(context, 3, stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1582 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1584 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1585 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1586 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1587 } else {
1588 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1589 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1593 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1595 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1596 TRACE("Last Pixel Drawing Enabled\n");
1597 } else {
1598 static BOOL warned;
1599 if (!warned) {
1600 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1601 warned = TRUE;
1602 } else {
1603 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1608 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1610 static BOOL warned;
1612 /* TODO: NV_POINT_SPRITE */
1613 if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1614 /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1615 FIXME("Point sprites not supported\n");
1616 warned = TRUE;
1620 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1622 const struct wined3d_gl_info *gl_info = context->gl_info;
1624 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE])
1626 static BOOL warned;
1628 if (gl_info->limits.point_sprite_units < gl_info->limits.textures && !warned)
1630 if (use_ps(stateblock) || stateblock->lowest_disabled_stage > gl_info->limits.point_sprite_units)
1632 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1633 warned = TRUE;
1637 glEnable(GL_POINT_SPRITE_ARB);
1638 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1639 } else {
1640 glDisable(GL_POINT_SPRITE_ARB);
1641 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1645 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1648 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1649 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1650 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1651 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1653 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1655 TRACE("Stub\n");
1656 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1657 stateblock->renderState[WINED3DRS_WRAP1] ||
1658 stateblock->renderState[WINED3DRS_WRAP2] ||
1659 stateblock->renderState[WINED3DRS_WRAP3] ||
1660 stateblock->renderState[WINED3DRS_WRAP4] ||
1661 stateblock->renderState[WINED3DRS_WRAP5] ||
1662 stateblock->renderState[WINED3DRS_WRAP6] ||
1663 stateblock->renderState[WINED3DRS_WRAP7] ||
1664 stateblock->renderState[WINED3DRS_WRAP8] ||
1665 stateblock->renderState[WINED3DRS_WRAP9] ||
1666 stateblock->renderState[WINED3DRS_WRAP10] ||
1667 stateblock->renderState[WINED3DRS_WRAP11] ||
1668 stateblock->renderState[WINED3DRS_WRAP12] ||
1669 stateblock->renderState[WINED3DRS_WRAP13] ||
1670 stateblock->renderState[WINED3DRS_WRAP14] ||
1671 stateblock->renderState[WINED3DRS_WRAP15] ) {
1672 FIXME("(WINED3DRS_WRAP0) Texture wrapping not yet supported\n");
1676 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1678 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1679 WARN("Multisample antialiasing not supported by gl\n");
1683 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1685 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1686 glEnable(GL_MULTISAMPLE_ARB);
1687 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1688 } else {
1689 glDisable(GL_MULTISAMPLE_ARB);
1690 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1694 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1696 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1697 glEnable(GL_SCISSOR_TEST);
1698 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1699 } else {
1700 glDisable(GL_SCISSOR_TEST);
1701 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1705 /* The Direct3D depth bias is specified in normalized depth coordinates. In
1706 * OpenGL the bias is specified in units of "the smallest value that is
1707 * guaranteed to produce a resolvable offset for a given implementation". To
1708 * convert from D3D to GL we need to divide the D3D depth bias by that value.
1709 * There's no practical way to retrieve that value from a given GL
1710 * implementation, but the D3D application has essentially the same problem,
1711 * which makes a guess of 1e-6f seem reasonable here. Note that
1712 * SLOPESCALEDEPTHBIAS is a scaling factor for the depth slope, and doesn't
1713 * need to be scaled. */
1714 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1716 if (stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]
1717 || stateblock->renderState[WINED3DRS_DEPTHBIAS])
1719 union
1721 DWORD d;
1722 float f;
1723 } scale_bias, const_bias;
1725 scale_bias.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1726 const_bias.d = stateblock->renderState[WINED3DRS_DEPTHBIAS];
1728 glEnable(GL_POLYGON_OFFSET_FILL);
1729 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1731 glPolygonOffset(scale_bias.f, const_bias.f * 1e6f);
1732 checkGLcall("glPolygonOffset(...)");
1733 } else {
1734 glDisable(GL_POLYGON_OFFSET_FILL);
1735 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1739 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1741 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1742 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1743 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1744 } else {
1745 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1746 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1750 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1752 TRACE("Stub\n");
1753 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1754 FIXME(" Stippled Alpha not supported yet.\n");
1757 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1759 TRACE("Stub\n");
1760 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1761 FIXME(" Antialias not supported yet.\n");
1764 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1766 TRACE("Stub\n");
1767 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1768 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1771 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1773 TRACE("Stub\n");
1774 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1775 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1778 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1780 union {
1781 DWORD d;
1782 float f;
1783 } tmpvalue;
1784 tmpvalue.f = 1.0f;
1786 TRACE("Stub\n");
1787 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1789 static BOOL displayed = FALSE;
1791 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1792 if(!displayed)
1793 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1795 displayed = TRUE;
1799 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1801 TRACE("Stub\n");
1802 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1803 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1806 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1808 TRACE("Stub\n");
1809 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1810 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1813 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1815 TRACE("Stub\n");
1816 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1817 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1820 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1822 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1823 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1827 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1829 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1830 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1834 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1836 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1837 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1841 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1843 if(stateblock->renderState[WINED3DRS_ROP2]) {
1844 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1848 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1850 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1851 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1855 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1857 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1858 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1862 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1864 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1865 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1869 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1871 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1872 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1876 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1878 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1879 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1883 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1885 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1886 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1890 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1892 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1893 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1897 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1899 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1900 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1904 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1906 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1907 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1911 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1913 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1914 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1918 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1920 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1921 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1925 static void state_swvp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1927 if (stateblock->renderState[WINED3DRS_SOFTWAREVERTEXPROCESSING])
1929 FIXME("Software vertex processing not implemented.\n");
1933 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1934 #if defined (GL_VERSION_1_3)
1935 # define useext(A) A
1936 #elif defined (GL_EXT_texture_env_combine)
1937 # define useext(A) A##_EXT
1938 #elif defined (GL_ARB_texture_env_combine)
1939 # define useext(A) A##_ARB
1940 #endif
1942 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1943 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1944 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1945 * flag specifies the complement of the input should be used. */
1946 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1947 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1949 /* Calculate the operand */
1950 if (complement) {
1951 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1952 else *operand = GL_ONE_MINUS_SRC_COLOR;
1953 } else {
1954 if (from_alpha) *operand = GL_SRC_ALPHA;
1955 else *operand = GL_SRC_COLOR;
1958 /* Calculate the source */
1959 switch (arg & WINED3DTA_SELECTMASK) {
1960 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1961 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1962 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1963 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1964 case WINED3DTA_SPECULAR:
1966 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1967 * 'Secondary color' and isn't supported until base GL supports it
1968 * There is no concept of temp registers as far as I can tell
1970 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1971 *source = GL_TEXTURE;
1972 break;
1973 default:
1974 FIXME("Unrecognized texture arg %#x\n", arg);
1975 *source = GL_TEXTURE;
1976 break;
1980 /* Setup the texture operations texture stage states */
1981 static void set_tex_op(const struct wined3d_context *context, IWineD3DDevice *iface,
1982 BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1984 const struct wined3d_gl_info *gl_info = context->gl_info;
1985 GLenum src1, src2, src3;
1986 GLenum opr1, opr2, opr3;
1987 GLenum comb_target;
1988 GLenum src0_target, src1_target, src2_target;
1989 GLenum opr0_target, opr1_target, opr2_target;
1990 GLenum scal_target;
1991 GLenum opr=0, invopr, src3_target, opr3_target;
1992 BOOL Handled = FALSE;
1993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1995 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1997 /* This is called by a state handler which has the gl lock held and a context for the thread */
1999 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
2000 the form (a1 <operation> a2). However, some of the more complex operations
2001 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
2002 in a third parameter called a0. Therefore these are operations of the form
2003 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
2005 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
2006 functions below, expect their syntax to differ slightly to those listed in the
2007 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
2008 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
2010 if (isAlpha) {
2011 comb_target = useext(GL_COMBINE_ALPHA);
2012 src0_target = useext(GL_SOURCE0_ALPHA);
2013 src1_target = useext(GL_SOURCE1_ALPHA);
2014 src2_target = useext(GL_SOURCE2_ALPHA);
2015 opr0_target = useext(GL_OPERAND0_ALPHA);
2016 opr1_target = useext(GL_OPERAND1_ALPHA);
2017 opr2_target = useext(GL_OPERAND2_ALPHA);
2018 scal_target = GL_ALPHA_SCALE;
2020 else {
2021 comb_target = useext(GL_COMBINE_RGB);
2022 src0_target = useext(GL_SOURCE0_RGB);
2023 src1_target = useext(GL_SOURCE1_RGB);
2024 src2_target = useext(GL_SOURCE2_RGB);
2025 opr0_target = useext(GL_OPERAND0_RGB);
2026 opr1_target = useext(GL_OPERAND1_RGB);
2027 opr2_target = useext(GL_OPERAND2_RGB);
2028 scal_target = useext(GL_RGB_SCALE);
2031 /* If a texture stage references an invalid texture unit the stage just
2032 * passes through the result from the previous stage */
2033 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
2034 arg1 = WINED3DTA_CURRENT;
2035 op = WINED3DTOP_SELECTARG1;
2038 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
2039 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
2040 } else {
2041 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
2043 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
2044 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
2046 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
2048 Handled = TRUE; /* Assume will be handled */
2050 /* Other texture operations require special extensions: */
2051 if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
2053 if (isAlpha) {
2054 opr = GL_SRC_ALPHA;
2055 invopr = GL_ONE_MINUS_SRC_ALPHA;
2056 src3_target = GL_SOURCE3_ALPHA_NV;
2057 opr3_target = GL_OPERAND3_ALPHA_NV;
2058 } else {
2059 opr = GL_SRC_COLOR;
2060 invopr = GL_ONE_MINUS_SRC_COLOR;
2061 src3_target = GL_SOURCE3_RGB_NV;
2062 opr3_target = GL_OPERAND3_RGB_NV;
2064 switch (op) {
2065 case WINED3DTOP_DISABLE: /* Only for alpha */
2066 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2067 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2068 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2069 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2070 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2071 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2072 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2073 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2074 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2075 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2076 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2077 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2078 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2079 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2080 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2081 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2082 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2083 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2084 break;
2085 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
2086 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
2087 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2088 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2089 if (op == WINED3DTOP_SELECTARG1) {
2090 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2091 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2092 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2093 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2094 } else {
2095 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2096 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2097 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2098 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2100 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2101 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2102 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2103 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2104 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2105 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2106 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2107 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2108 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2109 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2110 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2111 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2112 break;
2114 case WINED3DTOP_MODULATE:
2115 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2116 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2117 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2118 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2119 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2120 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2121 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2122 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2123 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2124 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2125 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2126 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2127 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2128 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2129 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2130 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2131 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2132 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2133 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2134 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2135 break;
2136 case WINED3DTOP_MODULATE2X:
2137 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2138 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2139 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2140 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2141 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2142 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2143 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2144 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2145 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2146 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2147 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2148 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2149 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2150 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2151 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2152 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2153 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2154 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2155 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2156 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2157 break;
2158 case WINED3DTOP_MODULATE4X:
2159 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2160 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2161 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2162 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2163 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2164 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2165 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2166 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2167 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2168 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2169 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2170 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2171 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2172 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2173 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2174 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2175 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2176 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2177 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2178 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2179 break;
2181 case WINED3DTOP_ADD:
2182 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2183 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2184 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2185 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2186 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2187 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2188 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2189 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2190 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2191 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2192 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2193 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2194 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2195 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2196 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2197 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2198 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2199 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2200 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2201 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2202 break;
2204 case WINED3DTOP_ADDSIGNED:
2205 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2206 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2207 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2208 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2209 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2210 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2211 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2212 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2213 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2214 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2215 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2216 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2217 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2218 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2219 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2220 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2221 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2222 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2223 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2224 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2225 break;
2227 case WINED3DTOP_ADDSIGNED2X:
2228 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2229 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2230 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2231 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2232 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2233 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2234 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2235 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2236 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2237 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2238 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2239 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2240 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2241 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2242 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2243 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2244 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2245 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2246 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2247 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2248 break;
2250 case WINED3DTOP_ADDSMOOTH:
2251 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2252 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2253 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2254 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2255 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2256 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2257 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2258 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2259 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2260 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2261 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2262 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2263 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2264 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2265 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2266 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2267 switch (opr1) {
2268 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2269 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2270 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2271 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2273 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2274 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2275 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2276 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2277 break;
2279 case WINED3DTOP_BLENDDIFFUSEALPHA:
2280 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2281 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2282 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2283 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2284 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2285 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2286 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2287 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2288 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2289 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2290 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2291 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2292 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2293 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2294 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2295 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2296 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2297 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2298 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2299 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2300 break;
2301 case WINED3DTOP_BLENDTEXTUREALPHA:
2302 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2303 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2304 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2305 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2306 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2307 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2308 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2309 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2310 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2311 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2312 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2313 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2314 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2315 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2316 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2317 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2318 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2319 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2320 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2321 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2322 break;
2323 case WINED3DTOP_BLENDFACTORALPHA:
2324 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2325 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2326 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2327 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2328 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2329 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2330 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2331 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2332 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2333 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2334 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2335 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2336 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2337 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2338 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2339 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2340 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2341 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2342 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2343 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2344 break;
2345 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2346 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2347 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2348 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2349 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2350 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2351 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2352 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2353 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2354 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2355 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2356 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2357 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2358 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2359 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2360 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2361 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2362 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2363 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2364 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2365 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2366 break;
2367 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2368 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2369 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2370 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2371 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2372 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2373 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2374 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2375 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2376 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2377 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2378 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2379 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2380 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2381 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2382 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2383 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2384 switch (opr) {
2385 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2386 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2388 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2389 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2390 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2391 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2392 break;
2393 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2394 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2395 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2396 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2397 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2398 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2399 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2400 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2401 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2402 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2403 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2404 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2405 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2406 switch (opr1) {
2407 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2408 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2410 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2411 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2412 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2413 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2414 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2415 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2416 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2417 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2418 break;
2419 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2420 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2421 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
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, GL_ZERO);
2427 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2428 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2429 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2430 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2431 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2432 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2433 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2434 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2435 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2436 switch (opr1) {
2437 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2438 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2439 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2440 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2442 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2443 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2444 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2445 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2446 break;
2447 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2448 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2449 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2450 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2451 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2452 switch (opr1) {
2453 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2454 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2455 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2456 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2458 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2459 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2460 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2461 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2462 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2463 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2464 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2465 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2466 switch (opr1) {
2467 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2468 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2470 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2471 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2472 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2473 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2474 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2475 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2476 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2477 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2478 break;
2479 case WINED3DTOP_MULTIPLYADD:
2480 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2481 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2482 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2483 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2484 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2485 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2486 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2487 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2488 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2489 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2490 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2491 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2492 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2493 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2494 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2495 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2496 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2497 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2498 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2499 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2500 break;
2502 case WINED3DTOP_BUMPENVMAP:
2506 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2507 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2509 default:
2510 Handled = FALSE;
2512 if (Handled) {
2513 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2514 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2516 return;
2518 } /* GL_NV_texture_env_combine4 */
2520 Handled = TRUE; /* Again, assume handled */
2521 switch (op) {
2522 case WINED3DTOP_DISABLE: /* Only for alpha */
2523 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2524 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2525 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2526 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2527 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2528 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2529 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2530 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2531 break;
2532 case WINED3DTOP_SELECTARG1:
2533 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2534 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2535 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2536 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2537 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2538 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2539 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2540 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2541 break;
2542 case WINED3DTOP_SELECTARG2:
2543 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2544 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2545 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2546 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2547 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2548 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2549 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2550 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2551 break;
2552 case WINED3DTOP_MODULATE:
2553 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2554 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2555 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2556 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2557 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2558 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2559 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2560 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2561 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2562 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2563 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2564 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2565 break;
2566 case WINED3DTOP_MODULATE2X:
2567 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2568 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2569 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2570 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2571 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2572 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2573 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2574 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2575 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2576 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2577 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2578 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2579 break;
2580 case WINED3DTOP_MODULATE4X:
2581 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2582 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2583 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2584 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2585 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2586 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2587 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2588 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2589 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2590 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2591 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2592 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2593 break;
2594 case WINED3DTOP_ADD:
2595 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2596 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2597 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2598 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2599 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2600 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2601 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2602 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2603 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2604 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2605 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2606 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2607 break;
2608 case WINED3DTOP_ADDSIGNED:
2609 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2610 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2611 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2612 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2613 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2614 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2615 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2616 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2617 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2618 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2619 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2620 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2621 break;
2622 case WINED3DTOP_ADDSIGNED2X:
2623 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2624 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2625 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2626 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2627 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2628 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2629 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2630 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2631 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2632 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2633 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2634 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2635 break;
2636 case WINED3DTOP_SUBTRACT:
2637 if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE])
2639 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2640 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2641 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2642 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2643 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2644 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2645 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2646 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2647 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2648 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2649 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2650 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2651 } else {
2652 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2654 break;
2656 case WINED3DTOP_BLENDDIFFUSEALPHA:
2657 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2658 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2659 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2660 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2661 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2662 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2663 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2664 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2665 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2666 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2667 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2668 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2669 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2670 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2671 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2672 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2673 break;
2674 case WINED3DTOP_BLENDTEXTUREALPHA:
2675 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2676 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2677 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2678 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2679 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2680 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2681 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2682 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2683 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2684 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2685 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2686 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2687 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2688 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2689 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2690 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2691 break;
2692 case WINED3DTOP_BLENDFACTORALPHA:
2693 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2694 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2695 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2696 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2697 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2698 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2699 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2700 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2701 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2702 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2703 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2704 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2705 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2706 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2707 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2708 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2709 break;
2710 case WINED3DTOP_BLENDCURRENTALPHA:
2711 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2712 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2713 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2714 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2715 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2716 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2717 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2718 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2719 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2720 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2721 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2722 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2723 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2724 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2725 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2726 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2727 break;
2728 case WINED3DTOP_DOTPRODUCT3:
2729 if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
2731 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2732 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2734 else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3])
2736 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2737 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2738 } else {
2739 FIXME("This version of opengl does not support GL_DOT3\n");
2741 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2742 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2743 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2744 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2745 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2746 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2747 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2748 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2749 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2750 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2751 break;
2752 case WINED3DTOP_LERP:
2753 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2754 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2755 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2756 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2757 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2758 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2759 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2760 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2761 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2762 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2763 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2764 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2765 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2766 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2767 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2768 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2769 break;
2770 case WINED3DTOP_ADDSMOOTH:
2771 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2773 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2774 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2775 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2776 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2777 switch (opr1) {
2778 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2779 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2780 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2781 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2783 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2784 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2785 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2786 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2787 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2788 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2789 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2790 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2791 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2792 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2793 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2794 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2795 } else
2796 Handled = FALSE;
2797 break;
2798 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2799 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2801 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2802 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2803 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2804 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2805 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2806 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2807 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2808 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2809 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2810 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2811 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2812 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2813 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2814 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2815 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2816 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2817 } else
2818 Handled = FALSE;
2819 break;
2820 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2821 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2823 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2824 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2825 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2826 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2827 switch (opr1) {
2828 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2829 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2830 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2831 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2833 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2834 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2835 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2836 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2837 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2838 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2839 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2840 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2841 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2842 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2843 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2844 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2845 } else
2846 Handled = FALSE;
2847 break;
2848 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2849 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2851 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2852 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2853 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2854 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2855 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2856 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2857 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2858 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2859 switch (opr1) {
2860 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2861 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2862 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2863 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2865 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2866 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2867 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2868 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2869 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2870 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2871 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2872 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2873 } else
2874 Handled = FALSE;
2875 break;
2876 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2877 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2879 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2880 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2881 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2882 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2883 switch (opr1) {
2884 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2885 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2886 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2887 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2889 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2890 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2891 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2892 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2893 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2894 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2895 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2896 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2897 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2898 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2899 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2900 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2901 } else
2902 Handled = FALSE;
2903 break;
2904 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2905 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2907 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2908 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2909 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2910 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2911 switch (opr1) {
2912 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2913 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2914 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2915 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2917 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2918 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2919 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2920 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2921 switch (opr1) {
2922 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2923 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2924 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2925 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2927 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2928 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2929 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2930 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2931 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2932 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2933 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2934 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2935 } else
2936 Handled = FALSE;
2937 break;
2938 case WINED3DTOP_MULTIPLYADD:
2939 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2941 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2942 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2943 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2944 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2945 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2946 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2947 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2948 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2949 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2950 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2951 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2952 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2953 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2954 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2955 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2956 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2957 } else
2958 Handled = FALSE;
2959 break;
2960 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2961 case WINED3DTOP_BUMPENVMAP:
2962 if (gl_info->supported[NV_TEXTURE_SHADER2])
2964 /* Technically texture shader support without register combiners is possible, but not expected to occur
2965 * on real world cards, so for now a fixme should be enough
2967 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2969 default:
2970 Handled = FALSE;
2973 if (Handled) {
2974 BOOL combineOK = TRUE;
2975 if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
2977 DWORD op2;
2979 if (isAlpha) {
2980 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2981 } else {
2982 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2985 /* Note: If COMBINE4 in effect can't go back to combine! */
2986 switch (op2) {
2987 case WINED3DTOP_ADDSMOOTH:
2988 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2989 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2990 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2991 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2992 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2993 case WINED3DTOP_MULTIPLYADD:
2994 /* Ignore those implemented in both cases */
2995 switch (op) {
2996 case WINED3DTOP_SELECTARG1:
2997 case WINED3DTOP_SELECTARG2:
2998 combineOK = FALSE;
2999 Handled = FALSE;
3000 break;
3001 default:
3002 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
3003 return;
3008 if (combineOK) {
3009 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
3010 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
3012 return;
3016 /* After all the extensions, if still unhandled, report fixme */
3017 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
3021 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3023 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3024 BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage);
3025 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3026 const struct wined3d_gl_info *gl_info = context->gl_info;
3028 TRACE("Setting color op for stage %d\n", stage);
3030 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
3031 if (use_ps(stateblock)) return;
3033 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
3035 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3037 if (tex_used && mapped_stage >= gl_info->limits.textures)
3039 FIXME("Attempt to enable unsupported stage!\n");
3040 return;
3042 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3043 checkGLcall("glActiveTextureARB");
3046 if(stage >= stateblock->lowest_disabled_stage) {
3047 TRACE("Stage disabled\n");
3048 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3050 /* Disable everything here */
3051 glDisable(GL_TEXTURE_2D);
3052 checkGLcall("glDisable(GL_TEXTURE_2D)");
3053 glDisable(GL_TEXTURE_3D);
3054 checkGLcall("glDisable(GL_TEXTURE_3D)");
3055 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3057 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3058 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3060 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3062 glDisable(GL_TEXTURE_RECTANGLE_ARB);
3063 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3066 /* All done */
3067 return;
3070 /* The sampler will also activate the correct texture dimensions, so no need to do it here
3071 * if the sampler for this stage is dirty
3073 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
3074 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
3077 set_tex_op(context, (IWineD3DDevice *)stateblock->device, FALSE, stage,
3078 stateblock->textureState[stage][WINED3DTSS_COLOROP],
3079 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
3080 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
3081 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
3084 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3086 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3087 BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage);
3088 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3089 const struct wined3d_gl_info *gl_info = context->gl_info;
3090 DWORD op, arg1, arg2, arg0;
3092 TRACE("Setting alpha op for stage %d\n", stage);
3093 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
3094 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3096 if (tex_used && mapped_stage >= gl_info->limits.textures)
3098 FIXME("Attempt to enable unsupported stage!\n");
3099 return;
3101 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3102 checkGLcall("glActiveTextureARB");
3105 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
3106 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
3107 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
3108 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
3110 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
3112 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
3114 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3116 IWineD3DSurfaceImpl *surf;
3118 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
3120 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
3122 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
3123 * properly. On the other hand applications can still use texture combiners apparently. This code
3124 * takes care that apps cannot remove the texture's alpha channel entirely.
3126 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
3127 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
3128 * and alpha component of diffuse color to draw things like translucent text and perform other
3129 * blending effects.
3131 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
3132 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
3133 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
3134 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
3135 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
3136 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
3137 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
3138 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
3139 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
3140 * alpha.
3142 * What to do with multitexturing? So far no app has been found that uses color keying with
3143 * multitexturing */
3144 if (op == WINED3DTOP_DISABLE)
3146 arg1 = WINED3DTA_TEXTURE;
3147 op = WINED3DTOP_SELECTARG1;
3149 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
3151 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3153 arg2 = WINED3DTA_TEXTURE;
3154 op = WINED3DTOP_MODULATE;
3156 else arg1 = WINED3DTA_TEXTURE;
3158 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
3160 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3162 arg1 = WINED3DTA_TEXTURE;
3163 op = WINED3DTOP_MODULATE;
3165 else arg2 = WINED3DTA_TEXTURE;
3171 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3172 * this if block here, and the other code(color keying, texture unit selection) are the same
3174 TRACE("Setting alpha op for stage %d\n", stage);
3175 if (gl_info->supported[NV_REGISTER_COMBINERS])
3177 set_tex_op_nvrc((IWineD3DDevice *)stateblock->device, TRUE, stage, op, arg1, arg2, arg0,
3178 mapped_stage, stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
3180 else
3182 set_tex_op(context, (IWineD3DDevice *)stateblock->device, TRUE, stage, op, arg1, arg2, arg0);
3186 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3188 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3189 DWORD mapped_stage = stateblock->device->texUnitMap[texUnit];
3190 BOOL generated;
3191 int coordIdx;
3193 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3194 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3196 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3197 return;
3200 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3201 if (mapped_stage >= context->gl_info->limits.textures) return;
3203 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3204 checkGLcall("glActiveTextureARB");
3205 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3206 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3208 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3209 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3210 stateblock->device->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
3211 ? stateblock->device->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format
3212 : WINED3DFMT_UNKNOWN,
3213 stateblock->device->frag_pipe->ffp_proj_control);
3215 /* The sampler applying function calls us if this changes */
3216 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3218 if(generated) {
3219 FIXME("Non-power2 texture being used with generated texture coords\n");
3221 /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
3222 fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3223 if (!use_ps(stateblock)) {
3224 TRACE("Non power two matrix multiply fixup\n");
3225 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3230 static void unloadTexCoords(const struct wined3d_context *context)
3232 unsigned int texture_idx;
3234 for (texture_idx = 0; texture_idx < context->gl_info->limits.texture_stages; ++texture_idx)
3236 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3237 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3241 static void loadTexCoords(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
3242 const struct wined3d_stream_info *si, GLuint *curVBO)
3244 const struct wined3d_gl_info *gl_info = context->gl_info;
3245 const UINT *offset = stateblock->streamOffset;
3246 unsigned int mapped_stage = 0;
3247 unsigned int textureNo = 0;
3249 for (textureNo = 0; textureNo < gl_info->limits.texture_stages; ++textureNo)
3251 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3253 mapped_stage = stateblock->device->texUnitMap[textureNo];
3254 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3256 if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
3258 const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3260 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3261 textureNo, mapped_stage, coordIdx, e->data);
3263 if (*curVBO != e->buffer_object)
3265 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3266 checkGLcall("glBindBufferARB");
3267 *curVBO = e->buffer_object;
3270 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3271 checkGLcall("glClientActiveTextureARB");
3273 /* The coords to supply depend completely on the fvf / vertex shader */
3274 glTexCoordPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
3275 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3276 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3277 } else {
3278 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3281 if (gl_info->supported[NV_REGISTER_COMBINERS])
3283 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */
3284 for (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo)
3286 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3290 checkGLcall("loadTexCoords");
3293 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3295 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3296 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3297 static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3298 static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3299 static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3300 static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3301 const struct wined3d_gl_info *gl_info = context->gl_info;
3303 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3305 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3306 return;
3309 if (mapped_stage >= gl_info->limits.fragment_samplers)
3311 WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3312 return;
3314 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3315 checkGLcall("glActiveTextureARB");
3317 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3319 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3320 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3321 * means use the vertex position (camera-space) as the input texture coordinates
3322 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3323 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3324 * to the TEXCOORDINDEX value
3326 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3328 case WINED3DTSS_TCI_PASSTHRU:
3329 /* Use the specified texture coordinates contained within the
3330 * vertex format. This value resolves to zero. */
3331 glDisable(GL_TEXTURE_GEN_S);
3332 glDisable(GL_TEXTURE_GEN_T);
3333 glDisable(GL_TEXTURE_GEN_R);
3334 glDisable(GL_TEXTURE_GEN_Q);
3335 checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3336 break;
3338 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3339 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3340 * as the input texture coordinates for this stage's texture transformation. This
3341 * equates roughly to EYE_LINEAR */
3343 glMatrixMode(GL_MODELVIEW);
3344 glPushMatrix();
3345 glLoadIdentity();
3346 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3347 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3348 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3349 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3350 glPopMatrix();
3351 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3353 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3354 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3355 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3356 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3358 glEnable(GL_TEXTURE_GEN_S);
3359 glEnable(GL_TEXTURE_GEN_T);
3360 glEnable(GL_TEXTURE_GEN_R);
3361 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3363 break;
3365 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3366 /* Note that NV_TEXGEN_REFLECTION support is implied when
3367 * ARB_TEXTURE_CUBE_MAP is supported */
3368 if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3370 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3371 break;
3374 glMatrixMode(GL_MODELVIEW);
3375 glPushMatrix();
3376 glLoadIdentity();
3377 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3378 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3379 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3380 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3381 glPopMatrix();
3382 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3384 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3385 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3386 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3387 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3389 glEnable(GL_TEXTURE_GEN_S);
3390 glEnable(GL_TEXTURE_GEN_T);
3391 glEnable(GL_TEXTURE_GEN_R);
3392 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3394 break;
3396 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3397 /* Note that NV_TEXGEN_REFLECTION support is implied when
3398 * ARB_TEXTURE_CUBE_MAP is supported */
3399 if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3401 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3402 break;
3405 glMatrixMode(GL_MODELVIEW);
3406 glPushMatrix();
3407 glLoadIdentity();
3408 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3409 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3410 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3411 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3412 glPopMatrix();
3413 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3415 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3416 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3417 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3418 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3420 glEnable(GL_TEXTURE_GEN_S);
3421 glEnable(GL_TEXTURE_GEN_T);
3422 glEnable(GL_TEXTURE_GEN_R);
3423 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3425 break;
3427 case WINED3DTSS_TCI_SPHEREMAP:
3428 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3429 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3430 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3432 glEnable(GL_TEXTURE_GEN_S);
3433 glEnable(GL_TEXTURE_GEN_T);
3434 glDisable(GL_TEXTURE_GEN_R);
3435 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3437 break;
3439 default:
3440 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3441 stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3442 glDisable(GL_TEXTURE_GEN_S);
3443 glDisable(GL_TEXTURE_GEN_T);
3444 glDisable(GL_TEXTURE_GEN_R);
3445 glDisable(GL_TEXTURE_GEN_Q);
3446 checkGLcall("Disable texgen.");
3448 break;
3451 /* Update the texture matrix */
3452 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3453 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3456 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3457 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3458 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3459 * and do all the things linked to it
3460 * TODO: Tidy that up to reload only the arrays of the changed unit
3462 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
3464 unloadTexCoords(context);
3465 loadTexCoords(context, stateblock, &stateblock->device->strided_streams, &curVBO);
3469 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3471 IWineD3DDeviceImpl *device = stateblock->device;
3473 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3474 * has an update pending
3476 if(isStateDirty(context, STATE_VDECL) ||
3477 isStateDirty(context, STATE_PIXELSHADER)) {
3478 return;
3481 device->shader_backend->shader_load_constants(context, use_ps(stateblock), use_vs(stateblock));
3484 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3486 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3488 if (stateblock->pixelShader && stage != 0
3489 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage)))
3491 /* The pixel shader has to know the luminance scale. Do a constants update if it
3492 * isn't scheduled anyway
3494 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3495 !isStateDirty(context, STATE_PIXELSHADER)) {
3496 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3501 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3503 const DWORD sampler = state - STATE_SAMPLER(0);
3504 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3506 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3508 if(!texture) return;
3509 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3510 * basetexture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3511 * scaling is reapplied or removed, the texture matrix has to be reapplied
3513 * The mapped stage is already active because the sampler() function below, which is part of the
3514 * misc pipeline
3516 if(sampler < MAX_TEXTURES) {
3517 const BOOL texIsPow2 = !((IWineD3DBaseTextureImpl *)texture)->baseTexture.pow2Matrix_identity;
3519 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3521 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3522 else context->lastWasPow2Texture &= ~(1 << sampler);
3523 transform_texture(STATE_TEXTURESTAGE(stateblock->device->texUnitMap[sampler],
3524 WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3529 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3531 DWORD sampler = state - STATE_SAMPLER(0);
3532 DWORD mapped_stage = stateblock->device->texUnitMap[sampler];
3533 const struct wined3d_gl_info *gl_info = context->gl_info;
3534 union {
3535 float f;
3536 DWORD d;
3537 } tmpvalue;
3539 TRACE("Sampler: %d\n", sampler);
3540 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3541 * only has to bind textures and set the per texture states
3544 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3546 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3547 return;
3550 if (mapped_stage >= gl_info->limits.combined_samplers)
3552 return;
3554 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3555 checkGLcall("glActiveTextureARB");
3557 if(stateblock->textures[sampler]) {
3558 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3559 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3560 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3561 basetexture_apply_state_changes(stateblock->textures[sampler],
3562 stateblock->textureState[sampler], stateblock->samplerState[sampler], gl_info);
3564 if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
3566 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3567 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3568 GL_TEXTURE_LOD_BIAS_EXT,
3569 tmpvalue.f);
3570 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3573 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3575 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3576 /* If color keying is enabled update the alpha test, it depends on the existence
3577 * of a color key in stage 0
3579 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3583 /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3584 if (!tex_impl->baseTexture.pow2Matrix_identity)
3586 IWineD3DDeviceImpl *d3ddevice = stateblock->device;
3587 d3ddevice->shader_backend->shader_load_np2fixup_constants(
3588 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3591 else if (mapped_stage < gl_info->limits.textures)
3593 if(sampler < stateblock->lowest_disabled_stage) {
3594 /* TODO: What should I do with pixel shaders here ??? */
3595 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3596 /* If color keying is enabled update the alpha test, it depends on the existence
3597 * of a color key in stage 0
3599 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3601 } /* Otherwise tex_colorop disables the stage */
3602 glBindTexture(GL_TEXTURE_2D, stateblock->device->dummyTextureName[sampler]);
3603 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->device->dummyTextureName[sampler])");
3607 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3609 IWineD3DDeviceImpl *device = stateblock->device;
3610 BOOL use_pshader = use_ps(stateblock);
3611 BOOL use_vshader = use_vs(stateblock);
3612 int i;
3614 if (use_pshader) {
3615 if(!context->last_was_pshader) {
3616 /* Former draw without a pixel shader, some samplers
3617 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3618 * make sure to enable them
3620 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3621 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3622 sampler(STATE_SAMPLER(i), stateblock, context);
3625 context->last_was_pshader = TRUE;
3626 } else {
3627 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3628 * if a different texture was bound. I don't have to do anything.
3631 } else {
3632 /* Disabled the pixel shader - color ops weren't applied
3633 * while it was enabled, so re-apply them. */
3634 for (i = 0; i < context->gl_info->limits.texture_stages; ++i)
3636 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3637 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3638 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3641 context->last_was_pshader = FALSE;
3644 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3645 device->shader_backend->shader_select(context, use_pshader, use_vshader);
3647 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3648 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3653 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3655 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3656 if (stateblock->pixelShader && stage != 0
3657 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage)))
3659 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3660 * anyway
3662 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3663 !isStateDirty(context, STATE_PIXELSHADER)) {
3664 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3669 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3671 /* This function is called by transform_view below if the view matrix was changed too
3673 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3674 * does not always update the world matrix, only on a switch between transformed
3675 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3676 * draw, but that should be rather rare and cheaper in total.
3678 glMatrixMode(GL_MODELVIEW);
3679 checkGLcall("glMatrixMode");
3681 if(context->last_was_rhw) {
3682 glLoadIdentity();
3683 checkGLcall("glLoadIdentity()");
3684 } else {
3685 /* In the general case, the view matrix is the identity matrix */
3686 if (stateblock->device->view_ident)
3688 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3689 checkGLcall("glLoadMatrixf");
3691 else
3693 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3694 checkGLcall("glLoadMatrixf");
3695 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3696 checkGLcall("glMultMatrixf");
3701 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3703 UINT index = state - STATE_CLIPPLANE(0);
3705 if (isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= context->gl_info->limits.clipplanes)
3707 return;
3710 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3711 if(!use_vs(stateblock)) {
3712 glMatrixMode(GL_MODELVIEW);
3713 glPushMatrix();
3714 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3715 } else {
3716 /* with vertex shaders, clip planes are not transformed in direct3d,
3717 * in OpenGL they are still transformed by the model view.
3718 * Use this to swap the y coordinate if necessary
3720 glMatrixMode(GL_MODELVIEW);
3721 glPushMatrix();
3722 glLoadIdentity();
3723 if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f);
3726 TRACE("Clipplane [%f,%f,%f,%f]\n",
3727 stateblock->clipplane[index][0],
3728 stateblock->clipplane[index][1],
3729 stateblock->clipplane[index][2],
3730 stateblock->clipplane[index][3]);
3731 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3732 checkGLcall("glClipPlane");
3734 glPopMatrix();
3737 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3739 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3740 GLenum glMat;
3741 TRACE("Setting world matrix %d\n", matrix);
3743 if (matrix >= context->gl_info->limits.blends)
3745 WARN("Unsupported blend matrix set\n");
3746 return;
3747 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3748 return;
3751 /* GL_MODELVIEW0_ARB: 0x1700
3752 * GL_MODELVIEW1_ARB: 0x850a
3753 * GL_MODELVIEW2_ARB: 0x8722
3754 * GL_MODELVIEW3_ARB: 0x8723
3755 * etc
3756 * GL_MODELVIEW31_ARB: 0x873F
3758 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3759 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3761 glMatrixMode(glMat);
3762 checkGLcall("glMatrixMode(glMat)");
3764 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3765 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3767 if (stateblock->device->view_ident)
3769 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3770 checkGLcall("glLoadMatrixf");
3772 else
3774 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3775 checkGLcall("glLoadMatrixf");
3776 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3777 checkGLcall("glMultMatrixf");
3781 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3783 WINED3DVERTEXBLENDFLAGS f = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3784 static unsigned int once;
3786 if (f == WINED3DVBF_DISABLE) return;
3788 if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
3789 else WARN("Vertex blend flags %#x not supported.\n", f);
3792 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3794 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3795 static unsigned int once;
3797 switch(val) {
3798 case WINED3DVBF_1WEIGHTS:
3799 case WINED3DVBF_2WEIGHTS:
3800 case WINED3DVBF_3WEIGHTS:
3801 glEnable(GL_VERTEX_BLEND_ARB);
3802 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3804 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3805 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3807 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3809 if (!stateblock->device->vertexBlendUsed)
3811 unsigned int i;
3812 for (i = 1; i < context->gl_info->limits.blends; ++i)
3814 if (!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i))))
3816 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3819 stateblock->device->vertexBlendUsed = TRUE;
3821 break;
3823 case WINED3DVBF_TWEENING:
3824 case WINED3DVBF_0WEIGHTS: /* Indexed vertex blending, not supported. */
3825 if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val);
3826 else WARN("Vertex blend flags %#x not supported.\n", val);
3827 /* Fall through. */
3828 case WINED3DVBF_DISABLE:
3829 glDisable(GL_VERTEX_BLEND_ARB);
3830 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3831 break;
3835 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3837 const struct wined3d_gl_info *gl_info = context->gl_info;
3838 const struct wined3d_light_info *light = NULL;
3839 unsigned int k;
3841 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3842 * NOTE: We have to reset the positions even if the light/plane is not currently
3843 * enabled, since the call to enable it will not reset the position.
3844 * NOTE2: Apparently texture transforms do NOT need reapplying
3847 glMatrixMode(GL_MODELVIEW);
3848 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3849 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3850 checkGLcall("glLoadMatrixf(...)");
3852 /* Reset lights. TODO: Call light apply func */
3853 for (k = 0; k < stateblock->device->maxConcurrentLights; ++k)
3855 light = stateblock->activeLights[k];
3856 if(!light) continue;
3857 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3858 checkGLcall("glLightfv posn");
3859 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3860 checkGLcall("glLightfv dirn");
3863 /* Reset Clipping Planes */
3864 for (k = 0; k < gl_info->limits.clipplanes; ++k)
3866 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3867 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3871 if(context->last_was_rhw) {
3872 glLoadIdentity();
3873 checkGLcall("glLoadIdentity()");
3874 /* No need to update the world matrix, the identity is fine */
3875 return;
3878 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3879 * No need to do it here if the state is scheduled for update.
3881 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3882 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3885 /* Avoid looping over a number of matrices if the app never used the functionality */
3886 if (stateblock->device->vertexBlendUsed)
3888 for (k = 1; k < gl_info->limits.blends; ++k)
3890 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3891 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3897 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3899 glMatrixMode(GL_PROJECTION);
3900 checkGLcall("glMatrixMode(GL_PROJECTION)");
3901 glLoadIdentity();
3902 checkGLcall("glLoadIdentity");
3904 if (context->last_was_rhw)
3906 double x = stateblock->viewport.X;
3907 double y = stateblock->viewport.Y;
3908 double w = stateblock->viewport.Width;
3909 double h = stateblock->viewport.Height;
3911 TRACE("Calling glOrtho with x %.8e, y %.8e, w %.8e, h %.8e.\n", x, y, w, h);
3912 if (context->render_offscreen)
3913 glOrtho(x, x + w, -y, -y - h, 0.0, -1.0);
3914 else
3915 glOrtho(x, x + w, y + h, y, 0.0, -1.0);
3916 checkGLcall("glOrtho");
3918 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3919 glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f);
3920 checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)");
3922 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3923 * render everything upside down when rendering offscreen. */
3924 if (context->render_offscreen)
3926 glScalef(1.0f, -1.0f, 1.0f);
3927 checkGLcall("glScalef");
3929 } else {
3930 /* The rule is that the window coordinate 0 does not correspond to the
3931 beginning of the first pixel, but the center of the first pixel.
3932 As a consequence if you want to correctly draw one line exactly from
3933 the left to the right end of the viewport (with all matrices set to
3934 be identity), the x coords of both ends of the line would be not
3935 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3936 instead.
3938 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3939 divide by the Width/Height, so we need the half range(1.0) to translate by
3940 half a pixel.
3942 The other fun is that d3d's output z range after the transformation is [0;1],
3943 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3944 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3945 of Z buffer precision and the clear values do not match in the z test. Thus scale
3946 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3950 * Careful with the order of operations here, we're essentially working backwards:
3951 * x = x + 1/w;
3952 * y = (y - 1/h) * flip;
3953 * z = z * 2 - 1;
3955 * Becomes:
3956 * glTranslatef(0.0, 0.0, -1.0);
3957 * glScalef(1.0, 1.0, 2.0);
3959 * glScalef(1.0, flip, 1.0);
3960 * glTranslatef(1/w, -1/h, 0.0);
3962 * This is equivalent to:
3963 * glTranslatef(1/w, -flip/h, -1.0)
3964 * glScalef(1.0, flip, 2.0);
3967 /* Translate by slightly less than a half pixel to force a top-left
3968 * filling convention. We want the difference to be large enough that
3969 * it doesn't get lost due to rounding inside the driver, but small
3970 * enough to prevent it from interfering with any anti-aliasing. */
3971 GLfloat xoffset = (63.0f / 64.0f) / stateblock->viewport.Width;
3972 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
3974 if (context->render_offscreen)
3976 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3977 * render everything upside down when rendering offscreen. */
3978 glTranslatef(xoffset, -yoffset, -1.0f);
3979 checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)");
3980 glScalef(1.0f, -1.0f, 2.0f);
3981 } else {
3982 glTranslatef(xoffset, yoffset, -1.0f);
3983 checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)");
3984 glScalef(1.0f, 1.0f, 2.0f);
3986 checkGLcall("glScalef");
3988 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3989 checkGLcall("glLoadMatrixf");
3993 /* This should match any arrays loaded in loadVertexData.
3994 * TODO: Only load / unload arrays if we have to.
3996 static inline void unloadVertexData(const struct wined3d_context *context)
3998 const struct wined3d_gl_info *gl_info = context->gl_info;
4000 glDisableClientState(GL_VERTEX_ARRAY);
4001 glDisableClientState(GL_NORMAL_ARRAY);
4002 glDisableClientState(GL_COLOR_ARRAY);
4003 if (gl_info->supported[EXT_SECONDARY_COLOR])
4005 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4007 if (gl_info->supported[ARB_VERTEX_BLEND])
4009 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
4011 unloadTexCoords(context);
4014 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context, int i)
4016 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
4017 checkGLcall("glDisableVertexAttribArrayARB(reg)");
4019 context->numbered_array_mask &= ~(1 << i);
4022 /* This should match any arrays loaded in loadNumberedArrays
4023 * TODO: Only load / unload arrays if we have to.
4025 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4027 /* disable any attribs (this is the same for both GLSL and ARB modes) */
4028 GLint maxAttribs = 16;
4029 int i;
4031 /* Leave all the attribs disabled */
4032 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
4033 /* MESA does not support it right not */
4034 if (glGetError() != GL_NO_ERROR)
4035 maxAttribs = 16;
4036 for (i = 0; i < maxAttribs; ++i) {
4037 unload_numbered_array(stateblock, context, i);
4041 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
4042 const struct wined3d_stream_info *stream_info, struct wined3d_context *context)
4044 const struct wined3d_gl_info *gl_info = context->gl_info;
4045 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
4046 int i;
4047 const UINT *offset = stateblock->streamOffset;
4048 struct wined3d_buffer *vb;
4049 DWORD_PTR shift_index;
4051 /* Default to no instancing */
4052 stateblock->device->instancedDraw = FALSE;
4054 for (i = 0; i < MAX_ATTRIBS; i++) {
4055 if (!(stream_info->use_map & (1 << i)))
4057 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
4058 continue;
4061 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
4062 if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
4064 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
4065 stateblock->device->instancedDraw = TRUE;
4066 continue;
4069 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
4071 if (stream_info->elements[i].stride)
4073 if (curVBO != stream_info->elements[i].buffer_object)
4075 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
4076 checkGLcall("glBindBufferARB");
4077 curVBO = stream_info->elements[i].buffer_object;
4079 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4080 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
4081 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
4082 * vbo we won't be load converted attributes anyway
4084 if (curVBO && vb->conversion_shift)
4086 TRACE("Loading attribute from shifted buffer\n");
4087 TRACE("Attrib %d has original stride %d, new stride %d\n",
4088 i, stream_info->elements[i].stride, vb->conversion_stride);
4089 TRACE("Original offset %p, additional offset 0x%08x\n",
4090 stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
4091 TRACE("Opengl type %#x\n", stream_info->elements[i].format_desc->gl_vtx_type);
4092 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
4093 shift_index = shift_index % stream_info->elements[i].stride;
4094 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4095 stream_info->elements[i].format_desc->gl_vtx_type,
4096 stream_info->elements[i].format_desc->gl_normalized,
4097 vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
4098 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4099 + offset[stream_info->elements[i].stream_idx]));
4101 } else {
4102 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
4103 stream_info->elements[i].format_desc->gl_vtx_type,
4104 stream_info->elements[i].format_desc->gl_normalized,
4105 stream_info->elements[i].stride, stream_info->elements[i].data
4106 + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
4107 + offset[stream_info->elements[i].stream_idx]));
4110 if (!(context->numbered_array_mask & (1 << i)))
4112 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
4113 context->numbered_array_mask |= (1 << i);
4115 } else {
4116 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
4117 * set up the attribute statically. But we have to figure out the system memory address.
4119 const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
4120 if (stream_info->elements[i].buffer_object)
4122 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
4123 ptr += (long) buffer_get_sysmem(vb);
4126 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
4128 switch (stream_info->elements[i].format_desc->format)
4130 case WINED3DFMT_R32_FLOAT:
4131 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
4132 break;
4133 case WINED3DFMT_R32G32_FLOAT:
4134 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
4135 break;
4136 case WINED3DFMT_R32G32B32_FLOAT:
4137 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
4138 break;
4139 case WINED3DFMT_R32G32B32A32_FLOAT:
4140 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
4141 break;
4143 case WINED3DFMT_R8G8B8A8_UINT:
4144 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4145 break;
4146 case WINED3DFMT_B8G8R8A8_UNORM:
4147 if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
4149 const DWORD *src = (const DWORD *)ptr;
4150 DWORD c = *src & 0xff00ff00;
4151 c |= (*src & 0xff0000) >> 16;
4152 c |= (*src & 0xff) << 16;
4153 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
4154 break;
4156 /* else fallthrough */
4157 case WINED3DFMT_R8G8B8A8_UNORM:
4158 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4159 break;
4161 case WINED3DFMT_R16G16_SINT:
4162 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4163 break;
4164 case WINED3DFMT_R16G16B16A16_SINT:
4165 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4166 break;
4168 case WINED3DFMT_R16G16_SNORM:
4170 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4171 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4172 break;
4174 case WINED3DFMT_R16G16_UNORM:
4176 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4177 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4178 break;
4180 case WINED3DFMT_R16G16B16A16_SNORM:
4181 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4182 break;
4183 case WINED3DFMT_R16G16B16A16_UNORM:
4184 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4185 break;
4187 case WINED3DFMT_R10G10B10A2_UINT:
4188 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4189 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4190 break;
4191 case WINED3DFMT_R10G10B10A2_SNORM:
4192 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4193 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4194 break;
4196 case WINED3DFMT_R16G16_FLOAT:
4197 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4198 * byte float according to the IEEE standard
4200 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4201 break;
4202 case WINED3DFMT_R16G16B16A16_FLOAT:
4203 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4204 break;
4206 default:
4207 ERR("Unexpected declaration in stride 0 attributes\n");
4208 break;
4213 checkGLcall("Loading numbered arrays");
4216 /* Used from 2 different functions, and too big to justify making it inlined */
4217 static void loadVertexData(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
4218 const struct wined3d_stream_info *si)
4220 const struct wined3d_gl_info *gl_info = context->gl_info;
4221 const UINT *offset = stateblock->streamOffset;
4222 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
4223 const struct wined3d_stream_info_element *e;
4225 TRACE("Using fast vertex array code\n");
4227 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4228 stateblock->device->instancedDraw = FALSE;
4230 /* Blend Data ---------------------------------------------- */
4231 if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
4232 || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4234 e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4236 if (gl_info->supported[ARB_VERTEX_BLEND])
4238 TRACE("Blend %d %p %d\n", e->format_desc->component_count,
4239 e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4241 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4242 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4244 GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1));
4246 if (curVBO != e->buffer_object)
4248 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4249 checkGLcall("glBindBufferARB");
4250 curVBO = e->buffer_object;
4253 TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n",
4254 e->format_desc->gl_vtx_format,
4255 e->format_desc->gl_vtx_type,
4256 e->stride,
4257 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4258 GL_EXTCALL(glWeightPointerARB(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4259 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]));
4261 checkGLcall("glWeightPointerARB");
4263 if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4265 static BOOL warned;
4266 if (!warned)
4268 FIXME("blendMatrixIndices support\n");
4269 warned = TRUE;
4272 } else {
4273 /* TODO: support blends in drawStridedSlow
4274 * No need to write a FIXME here, this is done after the general vertex decl decoding
4276 WARN("unsupported blending in openGl\n");
4279 else
4281 if (gl_info->supported[ARB_VERTEX_BLEND])
4283 static const GLbyte one = 1;
4284 GL_EXTCALL(glWeightbvARB(1, &one));
4285 checkGLcall("glWeightivARB(gl_info->max_blends, weights)");
4289 /* Point Size ----------------------------------------------*/
4290 if (si->use_map & (1 << WINED3D_FFP_PSIZE))
4292 /* no such functionality in the fixed function GL pipeline */
4293 TRACE("Cannot change ptSize here in openGl\n");
4294 /* TODO: Implement this function in using shaders if they are available */
4297 /* Vertex Pointers -----------------------------------------*/
4298 if (si->use_map & (1 << WINED3D_FFP_POSITION))
4300 e = &si->elements[WINED3D_FFP_POSITION];
4301 if (curVBO != e->buffer_object)
4303 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4304 checkGLcall("glBindBufferARB");
4305 curVBO = e->buffer_object;
4308 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4309 handling for rhw mode should not impact screen position whereas in GL it does.
4310 This may result in very slightly distorted textures in rhw mode.
4311 There's always the other option of fixing the view matrix to
4312 prevent w from having any effect.
4314 This only applies to user pointer sources, in VBOs the vertices are fixed up
4316 if (!e->buffer_object)
4318 TRACE("glVertexPointer(3, %#x, %#x, %p);\n", e->format_desc->gl_vtx_type, e->stride,
4319 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4320 glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride,
4321 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4323 else
4325 TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n",
4326 e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4327 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4328 glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4329 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4331 checkGLcall("glVertexPointer(...)");
4332 glEnableClientState(GL_VERTEX_ARRAY);
4333 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4336 /* Normals -------------------------------------------------*/
4337 if (si->use_map & (1 << WINED3D_FFP_NORMAL))
4339 e = &si->elements[WINED3D_FFP_NORMAL];
4340 if (curVBO != e->buffer_object)
4342 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4343 checkGLcall("glBindBufferARB");
4344 curVBO = e->buffer_object;
4347 TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format_desc->gl_vtx_type, e->stride,
4348 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4349 glNormalPointer(e->format_desc->gl_vtx_type, e->stride,
4350 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4351 checkGLcall("glNormalPointer(...)");
4352 glEnableClientState(GL_NORMAL_ARRAY);
4353 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4355 } else {
4356 glNormal3f(0, 0, 0);
4357 checkGLcall("glNormal3f(0, 0, 0)");
4360 /* Diffuse Colour --------------------------------------------*/
4361 /* WARNING: Data here MUST be in RGBA format, so cannot */
4362 /* go directly into fast mode from app pgm, because */
4363 /* directx requires data in BGRA format. */
4364 /* currently fixupVertices swizzles the format, but this isn't*/
4365 /* very practical when using VBOs */
4366 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4367 /* , or the user doesn't care and wants the speed advantage */
4369 if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
4371 e = &si->elements[WINED3D_FFP_DIFFUSE];
4372 if (curVBO != e->buffer_object)
4374 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4375 checkGLcall("glBindBufferARB");
4376 curVBO = e->buffer_object;
4379 TRACE("glColorPointer(%#x, %#x %#x, %p);\n",
4380 e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4381 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4382 glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4383 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4384 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4385 glEnableClientState(GL_COLOR_ARRAY);
4386 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4388 } else {
4389 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4390 checkGLcall("glColor4f(1, 1, 1, 1)");
4393 /* Specular Colour ------------------------------------------*/
4394 if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
4396 TRACE("setting specular colour\n");
4398 e = &si->elements[WINED3D_FFP_SPECULAR];
4399 if (gl_info->supported[EXT_SECONDARY_COLOR])
4401 GLenum type = e->format_desc->gl_vtx_type;
4402 GLint format = e->format_desc->gl_vtx_format;
4404 if (curVBO != e->buffer_object)
4406 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4407 checkGLcall("glBindBufferARB");
4408 curVBO = e->buffer_object;
4411 if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
4413 /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
4414 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
4415 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
4416 * 4 component secondary colors use it
4418 TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride,
4419 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4420 GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride,
4421 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]));
4422 checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
4424 else
4426 switch(type)
4428 case GL_UNSIGNED_BYTE:
4429 TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride,
4430 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4431 GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride,
4432 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]));
4433 checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
4434 break;
4436 default:
4437 FIXME("Add 4 component specular color pointers for type %x\n", type);
4438 /* Make sure that the right color component is dropped */
4439 TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride,
4440 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4441 GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride,
4442 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]));
4443 checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
4446 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4447 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4449 else
4451 WARN("Specular colour is not supported in this GL implementation.\n");
4454 else
4456 if (gl_info->supported[EXT_SECONDARY_COLOR])
4458 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4459 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4461 else
4463 WARN("Specular colour is not supported in this GL implementation.\n");
4467 /* Texture coords -------------------------------------------*/
4468 loadTexCoords(context, stateblock, si, &curVBO);
4471 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4473 IWineD3DDeviceImpl *device = stateblock->device;
4474 BOOL load_numbered = use_vs(stateblock) && !device->useDrawStridedSlow;
4475 BOOL load_named = !use_vs(stateblock) && !device->useDrawStridedSlow;
4477 if (context->numberedArraysLoaded && !load_numbered)
4479 unloadNumberedArrays(stateblock, context);
4480 context->numberedArraysLoaded = FALSE;
4481 context->numbered_array_mask = 0;
4483 else if (context->namedArraysLoaded)
4485 unloadVertexData(context);
4486 context->namedArraysLoaded = FALSE;
4489 if (load_numbered)
4491 TRACE("Loading numbered arrays\n");
4492 loadNumberedArrays(stateblock, &device->strided_streams, context);
4493 context->numberedArraysLoaded = TRUE;
4495 else if (load_named)
4497 TRACE("Loading vertex data\n");
4498 loadVertexData(context, stateblock, &device->strided_streams);
4499 context->namedArraysLoaded = TRUE;
4503 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4505 const struct wined3d_gl_info *gl_info = context->gl_info;
4506 BOOL updateFog = FALSE;
4507 BOOL useVertexShaderFunction = use_vs(stateblock);
4508 BOOL usePixelShaderFunction = use_ps(stateblock);
4509 IWineD3DDeviceImpl *device = stateblock->device;
4510 BOOL transformed;
4511 BOOL wasrhw = context->last_was_rhw;
4512 unsigned int i;
4514 transformed = device->strided_streams.position_transformed;
4515 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4516 updateFog = TRUE;
4519 /* Reapply lighting if it is not scheduled for reapplication already */
4520 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4521 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4524 if (transformed) {
4525 context->last_was_rhw = TRUE;
4526 } else {
4528 /* Untransformed, so relies on the view and projection matrices */
4529 context->last_was_rhw = FALSE;
4530 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4531 device->untransformed = TRUE;
4533 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4534 * Not needed as long as only hw shaders are supported
4537 /* This sets the shader output position correction constants.
4538 * TODO: Move to the viewport state
4540 if (useVertexShaderFunction)
4542 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4543 device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f;
4544 device->posFixup[3] = device->posFixup[1] * yoffset;
4548 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4549 * off this function will be called again anyway to make sure they're properly set
4551 if(!useVertexShaderFunction) {
4552 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4553 * or transformed / untransformed was switched
4555 if(wasrhw != context->last_was_rhw &&
4556 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4557 !isStateDirty(context, STATE_VIEWPORT)) {
4558 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4560 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4561 * mode.
4563 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4564 * this check will fail and the matrix not applied again. This is OK because a simple
4565 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4566 * needs of the vertex declaration.
4568 * World and view matrix go into the same gl matrix, so only apply them when neither is
4569 * dirty
4571 if(transformed != wasrhw &&
4572 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4573 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4574 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4577 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4578 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4581 if(context->last_was_vshader) {
4582 updateFog = TRUE;
4583 if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4584 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4586 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4588 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4591 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4592 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4594 } else {
4595 if(!context->last_was_vshader) {
4596 static BOOL warned = FALSE;
4597 if(!device->vs_clipping) {
4598 /* Disable all clip planes to get defined results on all drivers. See comment in the
4599 * state_clipping state handler
4601 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4603 glDisable(GL_CLIP_PLANE0 + i);
4604 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4607 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4608 FIXME("Clipping not supported with vertex shaders\n");
4609 warned = TRUE;
4612 if(wasrhw) {
4613 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4614 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4615 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4616 * fixed function vertex processing states back in a sane state before switching to shaders
4618 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4619 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4621 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4622 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4625 updateFog = TRUE;
4627 /* Vertex shader clipping ignores the view matrix. Update all clipplanes
4628 * (Note: ARB shaders can read the clip planes for clipping emulation even if
4629 * device->vs_clipping is false.
4631 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4633 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4638 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4639 * application
4641 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4642 device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction);
4644 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4645 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4649 context->last_was_vshader = useVertexShaderFunction;
4651 if(updateFog) {
4652 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4654 if(!useVertexShaderFunction) {
4655 int i;
4656 for(i = 0; i < MAX_TEXTURES; i++) {
4657 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4658 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4664 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4666 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0];
4667 UINT width, height;
4668 WINED3DVIEWPORT vp = stateblock->viewport;
4670 if(vp.Width > target->currentDesc.Width) vp.Width = target->currentDesc.Width;
4671 if(vp.Height > target->currentDesc.Height) vp.Height = target->currentDesc.Height;
4673 glDepthRange(vp.MinZ, vp.MaxZ);
4674 checkGLcall("glDepthRange");
4675 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4677 if (context->render_offscreen)
4679 glViewport(vp.X, vp.Y, vp.Width, vp.Height);
4680 } else {
4681 target->get_drawable_size(context, &width, &height);
4683 glViewport(vp.X,
4684 (height - (vp.Y + vp.Height)),
4685 vp.Width, vp.Height);
4688 checkGLcall("glViewport");
4691 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4693 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->viewport.Height;
4695 stateblock->device->posFixup[2] = (63.0f / 64.0f) / stateblock->viewport.Width;
4696 stateblock->device->posFixup[3] = stateblock->device->posFixup[1] * yoffset;
4698 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4699 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4701 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4702 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4706 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4708 UINT Index = state - STATE_ACTIVELIGHT(0);
4709 const struct wined3d_light_info *lightInfo = stateblock->activeLights[Index];
4711 if(!lightInfo) {
4712 glDisable(GL_LIGHT0 + Index);
4713 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4714 } else {
4715 float quad_att;
4716 float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
4718 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4719 glMatrixMode(GL_MODELVIEW);
4720 glPushMatrix();
4721 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4723 /* Diffuse: */
4724 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4725 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4726 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4727 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4728 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4729 checkGLcall("glLightfv");
4731 /* Specular */
4732 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4733 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4734 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4735 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4736 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4737 checkGLcall("glLightfv");
4739 /* Ambient */
4740 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4741 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4742 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4743 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4744 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4745 checkGLcall("glLightfv");
4747 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4748 quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4749 } else {
4750 quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */
4753 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4754 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4755 * Attenuation0 to NaN and crashes in the gl lib
4758 switch (lightInfo->OriginalParms.Type) {
4759 case WINED3DLIGHT_POINT:
4760 /* Position */
4761 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4762 checkGLcall("glLightfv");
4763 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4764 checkGLcall("glLightf");
4765 /* Attenuation - Are these right? guessing... */
4766 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4767 checkGLcall("glLightf");
4768 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4769 checkGLcall("glLightf");
4770 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4771 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4772 checkGLcall("glLightf");
4773 /* FIXME: Range */
4774 break;
4776 case WINED3DLIGHT_SPOT:
4777 /* Position */
4778 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4779 checkGLcall("glLightfv");
4780 /* Direction */
4781 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4782 checkGLcall("glLightfv");
4783 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4784 checkGLcall("glLightf");
4785 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4786 checkGLcall("glLightf");
4787 /* Attenuation - Are these right? guessing... */
4788 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4789 checkGLcall("glLightf");
4790 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4791 checkGLcall("glLightf");
4792 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4793 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4794 checkGLcall("glLightf");
4795 /* FIXME: Range */
4796 break;
4798 case WINED3DLIGHT_DIRECTIONAL:
4799 /* Direction */
4800 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4801 checkGLcall("glLightfv");
4802 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4803 checkGLcall("glLightf");
4804 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4805 checkGLcall("glLightf");
4806 break;
4808 default:
4809 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4812 /* Restore the modelview matrix */
4813 glPopMatrix();
4815 glEnable(GL_LIGHT0 + Index);
4816 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4820 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4822 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)stateblock->device->render_targets[0];
4823 RECT *pRect = &stateblock->scissorRect;
4824 UINT height;
4825 UINT width;
4827 target->get_drawable_size(context, &width, &height);
4828 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4829 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4831 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->device, pRect->left, pRect->bottom - height,
4832 pRect->right - pRect->left, pRect->bottom - pRect->top);
4834 if (context->render_offscreen)
4836 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4837 } else {
4838 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4840 checkGLcall("glScissor");
4843 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4845 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4846 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4847 } else {
4848 struct wined3d_buffer *ib = (struct wined3d_buffer *) stateblock->pIndexData;
4849 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4853 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4855 if (context->render_offscreen)
4857 glFrontFace(GL_CCW);
4858 checkGLcall("glFrontFace(GL_CCW)");
4859 } else {
4860 glFrontFace(GL_CW);
4861 checkGLcall("glFrontFace(GL_CW)");
4865 const struct StateEntryTemplate misc_state_template[] = {
4866 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4867 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4868 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4869 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4870 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4871 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4872 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4873 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4874 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4875 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4876 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4877 { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4878 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
4879 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
4880 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4881 * vshader loadings are untied from each other
4883 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4884 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4885 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4886 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4887 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4888 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4889 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4890 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4891 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4892 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4893 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4894 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4895 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4896 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4897 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4898 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4899 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4900 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4901 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4902 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4903 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4904 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4905 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4906 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4907 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4908 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4909 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4910 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4911 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4912 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4913 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4914 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4915 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4916 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4917 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4918 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4919 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4920 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4921 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4922 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4923 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4924 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4925 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4926 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4927 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4928 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4929 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4930 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4931 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4932 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
4934 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
4935 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4936 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE },
4937 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE },
4938 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE },
4939 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE },
4940 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE },
4941 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE },
4942 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
4943 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE },
4944 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE },
4945 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE },
4946 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE },
4947 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE },
4948 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4949 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4950 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4951 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
4952 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE },
4953 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE },
4954 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE },
4955 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE },
4956 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE },
4957 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE },
4958 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE },
4959 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE },
4960 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE },
4961 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE },
4962 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE },
4963 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE },
4964 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE },
4965 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4966 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4967 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4968 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4969 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4970 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4971 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4972 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4973 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE },
4974 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4975 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4976 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4977 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4978 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
4979 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4980 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4981 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4982 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4983 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4984 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4985 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4986 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4987 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4988 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4989 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4990 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4991 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4992 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4993 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4994 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
4995 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE },
4996 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE },
4997 { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE },
4998 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE },
4999 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE },
5000 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE },
5001 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE },
5002 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5003 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5004 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5005 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5006 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5007 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5008 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5009 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
5010 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE },
5011 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE },
5012 { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE },
5013 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite0 }, EXT_DRAW_BUFFERS2 },
5014 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5015 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
5016 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE },
5017 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE },
5018 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
5019 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), state_colorwrite1 }, EXT_DRAW_BUFFERS2 },
5020 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5021 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), state_colorwrite2 }, EXT_DRAW_BUFFERS2 },
5022 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5023 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), state_colorwrite3 }, EXT_DRAW_BUFFERS2 },
5024 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5025 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
5026 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE },
5027 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
5028 /* Samplers */
5029 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE },
5030 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE },
5031 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE },
5032 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE },
5033 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE },
5034 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE },
5035 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE },
5036 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE },
5037 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE },
5038 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE },
5039 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE },
5040 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE },
5041 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE },
5042 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE },
5043 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE },
5044 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE },
5045 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE },
5046 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE },
5047 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE },
5048 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
5049 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5052 const struct StateEntryTemplate ffp_vertexstate_template[] = {
5053 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5054 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5055 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5056 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5057 /* Clip planes */
5058 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
5059 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
5060 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
5061 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
5062 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
5063 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
5064 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
5065 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
5066 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE },
5067 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE },
5068 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE },
5069 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE },
5070 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE },
5071 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE },
5072 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE },
5073 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE },
5074 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE },
5075 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE },
5076 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE },
5077 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE },
5078 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE },
5079 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE },
5080 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE },
5081 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE },
5082 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE },
5083 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE },
5084 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE },
5085 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE },
5086 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE },
5087 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE },
5088 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE },
5089 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE },
5090 /* Lights */
5091 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE },
5092 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE },
5093 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE },
5094 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE },
5095 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE },
5096 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE },
5097 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE },
5098 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE },
5099 /* Viewport */
5100 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE },
5101 /* Transform states follow */
5102 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE },
5103 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE },
5104 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5105 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5106 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5107 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5108 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5109 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5110 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5111 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, WINED3D_GL_EXT_NONE },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE },
5208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE },
5209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE },
5210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE },
5211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE },
5212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE },
5213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE },
5214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE },
5215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE },
5216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE },
5217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE },
5218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE },
5219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE },
5220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE },
5221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE },
5222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE },
5223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE },
5224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE },
5225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE },
5226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE },
5227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE },
5228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE },
5229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE },
5230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE },
5231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE },
5232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE },
5233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE },
5234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE },
5235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE },
5236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE },
5237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE },
5238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE },
5239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE },
5240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE },
5241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE },
5242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE },
5243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE },
5244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE },
5245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE },
5246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE },
5247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE },
5248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE },
5249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE },
5250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE },
5251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE },
5252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE },
5253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE },
5254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE },
5255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE },
5256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE },
5257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE },
5258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE },
5259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE },
5260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE },
5261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE },
5262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE },
5263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE },
5264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE },
5265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE },
5266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE },
5267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE },
5268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE },
5269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE },
5270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE },
5271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE },
5272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE },
5273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE },
5274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE },
5275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE },
5276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE },
5277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE },
5278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE },
5279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE },
5280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE },
5281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE },
5282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE },
5283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE },
5284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE },
5285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE },
5286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE },
5287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE },
5288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE },
5289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE },
5290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE },
5291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE },
5292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE },
5293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE },
5294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE },
5295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE },
5296 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE },
5297 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE },
5298 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE },
5299 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE },
5300 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE },
5301 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE },
5302 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE },
5303 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE },
5304 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE },
5305 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE },
5306 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE },
5307 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE },
5308 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE },
5309 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE },
5310 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE },
5311 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE },
5312 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE },
5313 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE },
5314 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE },
5315 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE },
5316 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE },
5317 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE },
5318 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE },
5319 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE },
5320 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE },
5321 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE },
5322 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE },
5323 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE },
5324 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE },
5325 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE },
5326 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE },
5327 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE },
5328 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE },
5329 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE },
5330 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE },
5331 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE },
5332 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE },
5333 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE },
5334 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE },
5335 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE },
5336 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE },
5337 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE },
5338 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE },
5339 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE },
5340 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE },
5341 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE },
5342 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE },
5343 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE },
5344 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE },
5345 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE },
5346 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE },
5347 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE },
5348 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE },
5349 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE },
5350 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE },
5351 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE },
5352 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE },
5353 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE },
5354 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE },
5355 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE },
5356 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE },
5357 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE },
5358 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE },
5359 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE },
5360 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE },
5361 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE },
5362 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE },
5363 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE },
5364 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE },
5365 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE },
5366 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE },
5367 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE },
5368 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5369 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5370 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5371 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5372 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5373 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5374 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5375 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5376 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5377 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5378 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5379 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5380 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5381 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5382 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5383 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5384 /* Fog */
5385 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5386 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5387 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5388 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5389 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE },
5390 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5391 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5392 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE },
5393 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE },
5394 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5395 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE },
5396 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE },
5397 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5398 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5399 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5400 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5401 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5402 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE },
5403 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5404 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5405 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5406 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5407 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5408 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE },
5409 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5410 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5411 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5412 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5413 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5414 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5415 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5416 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5417 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5418 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5420 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5421 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5422 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5423 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5424 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5425 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5426 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5427 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5428 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5429 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5430 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5431 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5432 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5433 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5434 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5435 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5436 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5437 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5438 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5439 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5440 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5441 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5442 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5443 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5444 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5447 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5448 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5449 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5450 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5451 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5452 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5453 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5454 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5455 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5456 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5457 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5458 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5459 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5460 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5461 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5462 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5463 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5464 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5465 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5466 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5467 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5468 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5469 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5470 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5471 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5472 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5473 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5474 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5475 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5476 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5477 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5478 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5479 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5480 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5481 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5482 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5483 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5484 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5485 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5486 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5487 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5488 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5489 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5490 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5491 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5492 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5493 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5494 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5495 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5496 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5497 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5498 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5499 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5500 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5501 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5502 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5503 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5504 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5505 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5506 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5507 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5508 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5509 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5510 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5511 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5512 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5513 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5514 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5515 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5516 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5517 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5518 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5519 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5520 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5521 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5522 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5523 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5524 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5525 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5526 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5527 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, WINED3D_GL_EXT_NONE },
5528 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5529 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5530 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, WINED3D_GL_EXT_NONE },
5531 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE },
5532 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE },
5533 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE },
5534 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5535 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5536 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5537 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5538 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5539 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE },
5540 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE },
5541 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE },
5542 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE },
5543 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE },
5544 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE },
5545 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE },
5546 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE },
5547 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5549 #undef GLINFO_LOCATION
5551 /* Context activation is done by the caller. */
5552 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5554 static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps)
5556 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5557 WINED3DTEXOPCAPS_ADDSIGNED |
5558 WINED3DTEXOPCAPS_ADDSIGNED2X |
5559 WINED3DTEXOPCAPS_MODULATE |
5560 WINED3DTEXOPCAPS_MODULATE2X |
5561 WINED3DTEXOPCAPS_MODULATE4X |
5562 WINED3DTEXOPCAPS_SELECTARG1 |
5563 WINED3DTEXOPCAPS_SELECTARG2 |
5564 WINED3DTEXOPCAPS_DISABLE;
5566 if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE]
5567 || gl_info->supported[EXT_TEXTURE_ENV_COMBINE]
5568 || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
5570 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5571 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5572 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5573 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5574 WINED3DTEXOPCAPS_LERP |
5575 WINED3DTEXOPCAPS_SUBTRACT;
5577 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]
5578 || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
5580 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5581 WINED3DTEXOPCAPS_MULTIPLYADD |
5582 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5583 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5584 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5586 if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
5587 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5589 pCaps->MaxTextureBlendStages = gl_info->limits.textures;
5590 pCaps->MaxSimultaneousTextures = gl_info->limits.textures;
5593 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5594 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5595 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5597 if (TRACE_ON(d3d))
5599 TRACE("Checking support for fixup:\n");
5600 dump_color_fixup_desc(fixup);
5603 /* We only support identity conversions. */
5604 if (is_identity_fixup(fixup))
5606 TRACE("[OK]\n");
5607 return TRUE;
5610 TRACE("[FAILED]\n");
5611 return FALSE;
5614 const struct fragment_pipeline ffp_fragment_pipeline = {
5615 ffp_enable,
5616 ffp_fragment_get_caps,
5617 ffp_fragment_alloc,
5618 ffp_fragment_free,
5619 ffp_color_fixup_supported,
5620 ffp_fragmentstate_template,
5621 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5624 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5626 unsigned int i;
5627 for(i = 0; funcs[i]; i++);
5628 return i;
5631 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5633 stateblock->device->multistate_funcs[state][0](state, stateblock, context);
5634 stateblock->device->multistate_funcs[state][1](state, stateblock, context);
5637 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5639 stateblock->device->multistate_funcs[state][0](state, stateblock, context);
5640 stateblock->device->multistate_funcs[state][1](state, stateblock, context);
5641 stateblock->device->multistate_funcs[state][2](state, stateblock, context);
5644 static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info)
5646 unsigned int start, last, i;
5648 start = STATE_TEXTURESTAGE(gl_info->limits.texture_stages, 0);
5649 last = STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE);
5650 for (i = start; i <= last; ++i)
5652 state_table[i].representative = 0;
5653 state_table[i].apply = state_undefined;
5656 start = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + gl_info->limits.texture_stages);
5657 last = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + MAX_TEXTURES - 1);
5658 for (i = start; i <= last; ++i)
5660 state_table[i].representative = 0;
5661 state_table[i].apply = state_undefined;
5665 static void validate_state_table(struct StateEntry *state_table)
5667 unsigned int i;
5669 for (i = 0; i < STATE_HIGHEST + 1; ++i)
5671 DWORD rep = state_table[i].representative;
5672 if (rep && !state_table[rep].representative)
5674 ERR("State %s (%#x) has invalid representative %s (%#x).\n",
5675 debug_d3dstate(i), i, debug_d3dstate(rep), rep);
5676 state_table[i].representative = 0;
5681 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5682 const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
5683 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5685 unsigned int i, type, handlers;
5686 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5687 const struct StateEntryTemplate *cur;
5688 BOOL set[STATE_HIGHEST + 1];
5690 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5692 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5693 StateTable[i].representative = 0;
5694 StateTable[i].apply = state_undefined;
5697 for(type = 0; type < 3; type++) {
5698 /* This switch decides the order in which the states are applied */
5699 switch(type) {
5700 case 0: cur = misc; break;
5701 case 1: cur = fragment->states; break;
5702 case 2: cur = vertex; break;
5703 default: cur = NULL; /* Stupid compiler */
5705 if(!cur) continue;
5707 /* GL extension filtering should not prevent multiple handlers being applied from different
5708 * pipeline parts
5710 memset(set, 0, sizeof(set));
5712 for(i = 0; cur[i].state; i++) {
5713 APPLYSTATEFUNC *funcs_array;
5715 /* Only use the first matching state with the available extension from one template.
5716 * e.g.
5717 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5718 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5720 * if GL_XYZ_fancy is supported, ignore the 2nd line
5722 if(set[cur[i].state]) continue;
5723 /* Skip state lines depending on unsupported extensions */
5724 if (!gl_info->supported[cur[i].extension]) continue;
5725 set[cur[i].state] = TRUE;
5726 /* In some cases having an extension means that nothing has to be
5727 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5728 * supported, the texture coordinate fixup can be ignored. If the
5729 * apply function is used, mark the state set(done above) to prevent
5730 * applying later lines, but do not record anything in the state
5731 * table
5733 if(!cur[i].content.apply) continue;
5735 handlers = num_handlers(multistate_funcs[cur[i].state]);
5736 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5737 switch(handlers) {
5738 case 0:
5739 StateTable[cur[i].state].apply = cur[i].content.apply;
5740 break;
5741 case 1:
5742 StateTable[cur[i].state].apply = multistate_apply_2;
5743 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5745 sizeof(**dev_multistate_funcs) * 2);
5746 if (!dev_multistate_funcs[cur[i].state]) {
5747 goto out_of_mem;
5750 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5751 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5752 break;
5753 case 2:
5754 StateTable[cur[i].state].apply = multistate_apply_3;
5755 funcs_array = HeapReAlloc(GetProcessHeap(),
5757 dev_multistate_funcs[cur[i].state],
5758 sizeof(**dev_multistate_funcs) * 3);
5759 if (!funcs_array) {
5760 goto out_of_mem;
5763 dev_multistate_funcs[cur[i].state] = funcs_array;
5764 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5765 break;
5766 default:
5767 ERR("Unexpected amount of state handlers for state %u: %u\n",
5768 cur[i].state, handlers + 1);
5771 if(StateTable[cur[i].state].representative &&
5772 StateTable[cur[i].state].representative != cur[i].content.representative) {
5773 FIXME("State %u has different representatives in different pipeline parts\n",
5774 cur[i].state);
5776 StateTable[cur[i].state].representative = cur[i].content.representative;
5780 prune_invalid_states(StateTable, gl_info);
5781 validate_state_table(StateTable);
5783 return WINED3D_OK;
5785 out_of_mem:
5786 for (i = 0; i <= STATE_HIGHEST; ++i) {
5787 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5790 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5792 return E_OUTOFMEMORY;