urlmon: Make protocol_start IUri-based.
[wine/multimedia.git] / dlls / wined3d / state.c
blob5f732f94ea11ea37b8d7c40fcfca676d3fac0794
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 /* GL locking for state handlers is done by the caller. */
40 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context);
42 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
44 ERR("Undefined state.\n");
47 static void state_nop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
49 TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state));
52 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
54 WINED3DFILLMODE Value = stateblock->state.render_states[WINED3DRS_FILLMODE];
56 switch(Value) {
57 case WINED3DFILL_POINT:
58 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
59 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
60 break;
61 case WINED3DFILL_WIREFRAME:
62 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
63 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
64 break;
65 case WINED3DFILL_SOLID:
66 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
67 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
68 break;
69 default:
70 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
74 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
76 /* Lighting is not enabled if transformed vertices are drawn
77 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
78 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
79 * vertex declaration applying function calls this function for updating
82 if(isStateDirty(context, STATE_VDECL)) {
83 return;
86 if (stateblock->state.render_states[WINED3DRS_LIGHTING]
87 && !stateblock->device->strided_streams.position_transformed)
89 glEnable(GL_LIGHTING);
90 checkGLcall("glEnable GL_LIGHTING");
91 } else {
92 glDisable(GL_LIGHTING);
93 checkGLcall("glDisable GL_LIGHTING");
97 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
99 /* No z test without depth stencil buffers */
100 if (!stateblock->device->depth_stencil)
102 TRACE("No Z buffer - disabling depth test\n");
103 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
104 checkGLcall("glDisable GL_DEPTH_TEST");
105 return;
108 switch (stateblock->state.render_states[WINED3DRS_ZENABLE])
110 case WINED3DZB_FALSE:
111 glDisable(GL_DEPTH_TEST);
112 checkGLcall("glDisable GL_DEPTH_TEST");
113 break;
114 case WINED3DZB_TRUE:
115 glEnable(GL_DEPTH_TEST);
116 checkGLcall("glEnable GL_DEPTH_TEST");
117 break;
118 case WINED3DZB_USEW:
119 glEnable(GL_DEPTH_TEST);
120 checkGLcall("glEnable GL_DEPTH_TEST");
121 FIXME("W buffer is not well handled\n");
122 break;
123 default:
124 FIXME("Unrecognized D3DZBUFFERTYPE value %#x.\n",
125 stateblock->state.render_states[WINED3DRS_ZENABLE]);
129 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
131 /* glFrontFace() is set in context.c at context init and on an
132 * offscreen / onscreen rendering switch. */
133 switch (stateblock->state.render_states[WINED3DRS_CULLMODE])
135 case WINED3DCULL_NONE:
136 glDisable(GL_CULL_FACE);
137 checkGLcall("glDisable GL_CULL_FACE");
138 break;
139 case WINED3DCULL_CW:
140 glEnable(GL_CULL_FACE);
141 checkGLcall("glEnable GL_CULL_FACE");
142 glCullFace(GL_FRONT);
143 checkGLcall("glCullFace(GL_FRONT)");
144 break;
145 case WINED3DCULL_CCW:
146 glEnable(GL_CULL_FACE);
147 checkGLcall("glEnable GL_CULL_FACE");
148 glCullFace(GL_BACK);
149 checkGLcall("glCullFace(GL_BACK)");
150 break;
151 default:
152 FIXME("Unrecognized/Unhandled WINED3DCULL value %#x.\n",
153 stateblock->state.render_states[WINED3DRS_CULLMODE]);
157 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
159 switch (stateblock->state.render_states[WINED3DRS_SHADEMODE])
161 case WINED3DSHADE_FLAT:
162 glShadeModel(GL_FLAT);
163 checkGLcall("glShadeModel(GL_FLAT)");
164 break;
165 case WINED3DSHADE_GOURAUD:
166 glShadeModel(GL_SMOOTH);
167 checkGLcall("glShadeModel(GL_SMOOTH)");
168 break;
169 case WINED3DSHADE_PHONG:
170 FIXME("WINED3DSHADE_PHONG isn't supported\n");
171 break;
172 default:
173 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %#x.\n",
174 stateblock->state.render_states[WINED3DRS_SHADEMODE]);
178 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
180 if (stateblock->state.render_states[WINED3DRS_DITHERENABLE])
182 glEnable(GL_DITHER);
183 checkGLcall("glEnable GL_DITHER");
185 else
187 glDisable(GL_DITHER);
188 checkGLcall("glDisable GL_DITHER");
192 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
194 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off.
195 * If yes, this has to be merged with ZENABLE and ZFUNC. */
196 if (stateblock->state.render_states[WINED3DRS_ZWRITEENABLE])
198 glDepthMask(1);
199 checkGLcall("glDepthMask(1)");
201 else
203 glDepthMask(0);
204 checkGLcall("glDepthMask(0)");
208 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
210 GLenum depth_func = CompareFunc(stateblock->state.render_states[WINED3DRS_ZFUNC]);
212 if (!depth_func) return;
214 if (depth_func == GL_EQUAL || depth_func == GL_NOTEQUAL)
216 static BOOL once;
217 /* There are a few issues with this: First, our inability to
218 * select a proper Z depth, most of the time we're stuck with
219 * D24S8, even if the app selects D32 or D16. There seem to be
220 * some other precision problems which have to be debugged to
221 * make NOTEQUAL and EQUAL work properly. */
222 if (!once)
224 once = TRUE;
225 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet.\n");
229 glDepthFunc(depth_func);
230 checkGLcall("glDepthFunc");
233 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
235 float col[4];
236 D3DCOLORTOGLFLOAT4(stateblock->state.render_states[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 = stateblock->device->render_targets[0];
246 const struct wined3d_gl_info *gl_info = context->gl_info;
247 int srcBlend = GL_ZERO;
248 int dstBlend = GL_ZERO;
250 /* According to the red book, GL_LINE_SMOOTH needs GL_BLEND with specific
251 * blending parameters to work. */
252 if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE]
253 || stateblock->state.render_states[WINED3DRS_EDGEANTIALIAS]
254 || stateblock->state.render_states[WINED3DRS_ANTIALIASEDLINEENABLE])
256 /* Disable blending in all cases even without pixelshaders.
257 * With blending on we could face a big performance penalty.
258 * The d3d9 visual test confirms the behavior. */
259 if (context->render_offscreen
260 && !(target->resource.format->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
262 glDisable(GL_BLEND);
263 checkGLcall("glDisable GL_BLEND");
264 return;
265 } else {
266 glEnable(GL_BLEND);
267 checkGLcall("glEnable GL_BLEND");
269 } else {
270 glDisable(GL_BLEND);
271 checkGLcall("glDisable GL_BLEND");
272 /* Nothing more to do - get out */
273 return;
276 switch (stateblock->state.render_states[WINED3DRS_DESTBLEND])
278 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
279 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
280 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
281 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
282 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
283 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
284 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
285 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
287 /* To compensate the lack of format switching with backbuffer offscreen rendering,
288 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
289 * if the render target doesn't support alpha blending. A nonexistent alpha channel
290 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
292 case WINED3DBLEND_DESTALPHA :
293 dstBlend = target->resource.format->alpha_mask ? GL_DST_ALPHA : GL_ONE;
294 break;
295 case WINED3DBLEND_INVDESTALPHA :
296 dstBlend = target->resource.format->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
297 break;
299 case WINED3DBLEND_SRCALPHASAT :
300 dstBlend = GL_SRC_ALPHA_SATURATE;
301 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
302 break;
304 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
305 * values which are still valid up to d3d9. They should not occur as dest blend values
307 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
308 srcBlend = GL_SRC_ALPHA;
309 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
310 break;
312 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
313 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
314 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
315 break;
317 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
318 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
319 default:
320 FIXME("Unrecognized dst blend value %#x.\n",
321 stateblock->state.render_states[WINED3DRS_DESTBLEND]);
324 switch (stateblock->state.render_states[WINED3DRS_SRCBLEND])
326 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
327 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
328 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
329 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
330 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
331 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
332 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
333 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
334 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
336 case WINED3DBLEND_DESTALPHA :
337 srcBlend = target->resource.format->alpha_mask ? GL_DST_ALPHA : GL_ONE;
338 break;
339 case WINED3DBLEND_INVDESTALPHA :
340 srcBlend = target->resource.format->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
341 break;
343 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
344 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
345 break;
347 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
348 dstBlend = GL_SRC_ALPHA;
349 break;
351 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
352 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
353 default:
354 FIXME("Unrecognized src blend value %#x.\n",
355 stateblock->state.render_states[WINED3DRS_SRCBLEND]);
358 if (stateblock->state.render_states[WINED3DRS_EDGEANTIALIAS]
359 || stateblock->state.render_states[WINED3DRS_ANTIALIASEDLINEENABLE])
361 glEnable(GL_LINE_SMOOTH);
362 checkGLcall("glEnable(GL_LINE_SMOOTH)");
363 if(srcBlend != GL_SRC_ALPHA) {
364 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
366 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
367 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
369 } else {
370 glDisable(GL_LINE_SMOOTH);
371 checkGLcall("glDisable(GL_LINE_SMOOTH)");
374 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
375 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
376 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
379 if (stateblock->state.render_states[WINED3DRS_SEPARATEALPHABLENDENABLE])
381 int srcBlendAlpha = GL_ZERO;
382 int dstBlendAlpha = GL_ZERO;
384 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
385 if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
387 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
388 return;
391 switch (stateblock->state.render_states[WINED3DRS_DESTBLENDALPHA])
393 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
394 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
395 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
396 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
397 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
398 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
399 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
400 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
401 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
402 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
403 case WINED3DBLEND_SRCALPHASAT :
404 dstBlend = GL_SRC_ALPHA_SATURATE;
405 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
406 break;
407 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
408 * values which are still valid up to d3d9. They should not occur as dest blend values
410 case WINED3DBLEND_BOTHSRCALPHA :
411 dstBlendAlpha = GL_SRC_ALPHA;
412 srcBlendAlpha = GL_SRC_ALPHA;
413 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
414 break;
415 case WINED3DBLEND_BOTHINVSRCALPHA :
416 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
417 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
418 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
419 break;
420 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
421 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
422 default:
423 FIXME("Unrecognized dst blend alpha value %#x.\n",
424 stateblock->state.render_states[WINED3DRS_DESTBLENDALPHA]);
427 switch (stateblock->state.render_states[WINED3DRS_SRCBLENDALPHA])
429 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
430 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
431 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
432 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
433 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
434 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
435 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
436 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
437 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
438 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
439 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
440 case WINED3DBLEND_BOTHSRCALPHA :
441 srcBlendAlpha = GL_SRC_ALPHA;
442 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
443 break;
444 case WINED3DBLEND_BOTHINVSRCALPHA :
445 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
446 dstBlendAlpha = GL_SRC_ALPHA;
447 break;
448 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
449 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
450 default:
451 FIXME("Unrecognized src blend alpha value %#x.\n",
452 stateblock->state.render_states[WINED3DRS_SRCBLENDALPHA]);
455 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
456 checkGLcall("glBlendFuncSeparateEXT");
457 } else {
458 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
459 glBlendFunc(srcBlend, dstBlend);
460 checkGLcall("glBlendFunc");
463 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
464 so it may need updating */
465 if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE])
466 stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
469 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
471 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
474 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
476 const struct wined3d_gl_info *gl_info = context->gl_info;
477 float col[4];
479 TRACE("Setting blend factor to %#x.\n", stateblock->state.render_states[WINED3DRS_BLENDFACTOR]);
480 D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_BLENDFACTOR], col);
481 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
482 checkGLcall("glBlendColor");
485 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
487 int glParm = 0;
488 float ref;
489 BOOL enable_ckey = FALSE;
491 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
493 /* Find out if the texture on the first stage has a ckey set
494 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
495 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
496 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
497 * in case it finds some texture+colorkeyenable combination which needs extra care.
499 if (stateblock->state.textures[0])
501 IWineD3DBaseTextureImpl *texture = stateblock->state.textures[0];
502 GLenum texture_dimensions = texture->baseTexture.target;
504 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
506 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0];
508 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
510 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
511 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
512 * surface has alpha bits */
513 if (!surf->resource.format->alpha_mask) enable_ckey = TRUE;
518 if (enable_ckey || context->last_was_ckey)
519 stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
520 context->last_was_ckey = enable_ckey;
522 if (stateblock->state.render_states[WINED3DRS_ALPHATESTENABLE]
523 || (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && enable_ckey))
525 glEnable(GL_ALPHA_TEST);
526 checkGLcall("glEnable GL_ALPHA_TEST");
527 } else {
528 glDisable(GL_ALPHA_TEST);
529 checkGLcall("glDisable GL_ALPHA_TEST");
530 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
531 * enable call
533 return;
536 if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && enable_ckey)
538 glParm = GL_NOTEQUAL;
539 ref = 0.0f;
540 } else {
541 ref = ((float)stateblock->state.render_states[WINED3DRS_ALPHAREF]) / 255.0f;
542 glParm = CompareFunc(stateblock->state.render_states[WINED3DRS_ALPHAFUNC]);
544 if(glParm) {
545 glAlphaFunc(glParm, ref);
546 checkGLcall("glAlphaFunc");
550 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
552 const struct wined3d_gl_info *gl_info = context->gl_info;
553 DWORD enable = 0xFFFFFFFF;
554 DWORD disable = 0x00000000;
556 if (!stateblock->device->vs_clipping && use_vs(stateblock))
558 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
559 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
560 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
561 * of that - don't do anything here and keep them disabled
563 if (stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE])
565 static BOOL warned = FALSE;
566 if(!warned) {
567 FIXME("Clipping not supported with vertex shaders\n");
568 warned = TRUE;
571 return;
574 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
575 * of already set values
578 /* If enabling / disabling all
579 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
581 if (stateblock->state.render_states[WINED3DRS_CLIPPING])
583 enable = stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE];
584 disable = ~stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE];
585 if (gl_info->supported[ARB_DEPTH_CLAMP])
587 glDisable(GL_DEPTH_CLAMP);
588 checkGLcall("glDisable(GL_DEPTH_CLAMP)");
590 } else {
591 disable = 0xffffffff;
592 enable = 0x00;
593 if (gl_info->supported[ARB_DEPTH_CLAMP])
595 glEnable(GL_DEPTH_CLAMP);
596 checkGLcall("glEnable(GL_DEPTH_CLAMP)");
598 else
600 FIXME("Clipping disabled, but ARB_depth_clamp isn't supported.\n");
604 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
605 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
606 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
607 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
608 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
609 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
611 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
612 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
613 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
614 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
615 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
616 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
618 /** update clipping status */
619 if (enable) {
620 stateblock->clip_status.ClipUnion = 0;
621 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
622 } else {
623 stateblock->clip_status.ClipUnion = 0;
624 stateblock->clip_status.ClipIntersection = 0;
628 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
630 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
633 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
635 const struct wined3d_gl_info *gl_info = context->gl_info;
636 int blendEquation = GL_FUNC_ADD;
637 int blendEquationAlpha = GL_FUNC_ADD;
639 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
640 if (stateblock->state.render_states[WINED3DRS_BLENDOPALPHA]
641 && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
643 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
644 return;
647 switch (stateblock->state.render_states[WINED3DRS_BLENDOP])
649 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
650 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
651 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
652 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
653 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
654 default:
655 FIXME("Unrecognized/Unhandled D3DBLENDOP value %#x.\n",
656 stateblock->state.render_states[WINED3DRS_BLENDOP]);
659 switch (stateblock->state.render_states[WINED3DRS_BLENDOPALPHA])
661 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
662 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
663 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
664 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
665 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
666 default:
667 FIXME("Unrecognized/Unhandled D3DBLENDOP value %#x\n",
668 stateblock->state.render_states[WINED3DRS_BLENDOPALPHA]);
671 if (stateblock->state.render_states[WINED3DRS_SEPARATEALPHABLENDENABLE])
673 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
674 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
675 checkGLcall("glBlendEquationSeparateEXT");
676 } else {
677 TRACE("glBlendEquation(%x)\n", blendEquation);
678 GL_EXTCALL(glBlendEquationEXT(blendEquation));
679 checkGLcall("glBlendEquation");
683 static void state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
685 const struct wined3d_gl_info *gl_info = context->gl_info;
686 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
687 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
688 * specular color. This is wrong:
689 * Separate specular color means the specular colour is maintained separately, whereas
690 * single color means it is merged in. However in both cases they are being used to
691 * some extent.
692 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
693 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
694 * running 1.4 yet!
697 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
698 * Instead, we need to setup the FinalCombiner properly.
700 * The default setup for the FinalCombiner is:
702 * <variable> <input> <mapping> <usage>
703 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
704 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
705 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
706 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
707 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
708 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
709 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
711 * That's pretty much fine as it is, except for variable B, which needs to take
712 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
713 * whether WINED3DRS_SPECULARENABLE is enabled or not.
716 TRACE("Setting specular enable state and materials\n");
717 if (stateblock->state.render_states[WINED3DRS_SPECULARENABLE])
719 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&stateblock->state.material.Specular);
720 checkGLcall("glMaterialfv");
722 if (stateblock->state.material.Power > gl_info->limits.shininess)
724 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
725 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
726 * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the
727 * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp
728 * them, it should be safe to do so without major visual distortions.
730 WARN("Material power = %f, limit %f\n", stateblock->state.material.Power, gl_info->limits.shininess);
731 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess);
733 else
735 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->state.material.Power);
737 checkGLcall("glMaterialf(GL_SHININESS)");
739 if (gl_info->supported[EXT_SECONDARY_COLOR])
741 glEnable(GL_COLOR_SUM_EXT);
743 else
745 TRACE("Specular colors cannot be enabled in this version of opengl\n");
747 checkGLcall("glEnable(GL_COLOR_SUM)");
749 if (gl_info->supported[NV_REGISTER_COMBINERS])
751 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
752 checkGLcall("glFinalCombinerInputNV()");
754 } else {
755 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
757 /* for the case of enabled lighting: */
758 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
759 checkGLcall("glMaterialfv");
761 /* for the case of disabled lighting: */
762 if (gl_info->supported[EXT_SECONDARY_COLOR])
764 glDisable(GL_COLOR_SUM_EXT);
766 else
768 TRACE("Specular colors cannot be disabled in this version of opengl\n");
770 checkGLcall("glDisable(GL_COLOR_SUM)");
772 if (gl_info->supported[NV_REGISTER_COMBINERS])
774 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
775 checkGLcall("glFinalCombinerInputNV()");
779 TRACE("(%p) : Diffuse {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
780 stateblock->state.material.Diffuse.r, stateblock->state.material.Diffuse.g,
781 stateblock->state.material.Diffuse.b, stateblock->state.material.Diffuse.a);
782 TRACE("(%p) : Ambient {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
783 stateblock->state.material.Ambient.r, stateblock->state.material.Ambient.g,
784 stateblock->state.material.Ambient.b, stateblock->state.material.Ambient.a);
785 TRACE("(%p) : Specular {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
786 stateblock->state.material.Specular.r, stateblock->state.material.Specular.g,
787 stateblock->state.material.Specular.b, stateblock->state.material.Specular.a);
788 TRACE("(%p) : Emissive {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device,
789 stateblock->state.material.Emissive.r, stateblock->state.material.Emissive.g,
790 stateblock->state.material.Emissive.b, stateblock->state.material.Emissive.a);
792 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&stateblock->state.material.Ambient);
793 checkGLcall("glMaterialfv(GL_AMBIENT)");
794 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&stateblock->state.material.Diffuse);
795 checkGLcall("glMaterialfv(GL_DIFFUSE)");
796 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&stateblock->state.material.Emissive);
797 checkGLcall("glMaterialfv(GL_EMISSION)");
800 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
802 const struct wined3d_gl_info *gl_info = context->gl_info;
803 unsigned int i;
805 /* Note the texture color applies to all textures whereas
806 * GL_TEXTURE_ENV_COLOR applies to active only
808 float col[4];
809 D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_TEXTUREFACTOR], col);
811 /* And now the default texture color as well */
812 for (i = 0; i < gl_info->limits.texture_stages; ++i)
814 /* Note the WINED3DRS value applies to all textures, but GL has one
815 * per texture, so apply it now ready to be used!
817 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
818 checkGLcall("glActiveTextureARB");
820 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
821 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
825 static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face,
826 GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
828 const struct wined3d_gl_info *gl_info = context->gl_info;
830 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
831 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
832 GL_EXTCALL(glActiveStencilFaceEXT(face));
833 checkGLcall("glActiveStencilFaceEXT(...)");
834 glStencilFunc(func, ref, mask);
835 checkGLcall("glStencilFunc(...)");
836 glStencilOp(stencilFail, depthFail, stencilPass);
837 checkGLcall("glStencilOp(...)");
840 static void state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
842 const struct wined3d_gl_info *gl_info = context->gl_info;
843 DWORD onesided_enable = FALSE;
844 DWORD twosided_enable = FALSE;
845 GLint func = GL_ALWAYS;
846 GLint func_ccw = GL_ALWAYS;
847 GLint ref = 0;
848 GLuint mask = 0;
849 GLint stencilFail = GL_KEEP;
850 GLint depthFail = GL_KEEP;
851 GLint stencilPass = GL_KEEP;
852 GLint stencilFail_ccw = GL_KEEP;
853 GLint depthFail_ccw = GL_KEEP;
854 GLint stencilPass_ccw = GL_KEEP;
856 /* No stencil test without a stencil buffer. */
857 if (!stateblock->device->depth_stencil)
859 glDisable(GL_STENCIL_TEST);
860 checkGLcall("glDisable GL_STENCIL_TEST");
861 return;
864 onesided_enable = stateblock->state.render_states[WINED3DRS_STENCILENABLE];
865 twosided_enable = stateblock->state.render_states[WINED3DRS_TWOSIDEDSTENCILMODE];
866 if (!(func = CompareFunc(stateblock->state.render_states[WINED3DRS_STENCILFUNC])))
867 func = GL_ALWAYS;
868 if (!(func_ccw = CompareFunc(stateblock->state.render_states[WINED3DRS_CCW_STENCILFUNC])))
869 func_ccw = GL_ALWAYS;
870 ref = stateblock->state.render_states[WINED3DRS_STENCILREF];
871 mask = stateblock->state.render_states[WINED3DRS_STENCILMASK];
872 stencilFail = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILFAIL]);
873 depthFail = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILZFAIL]);
874 stencilPass = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILPASS]);
875 stencilFail_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILFAIL]);
876 depthFail_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILZFAIL]);
877 stencilPass_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILPASS]);
879 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
880 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
881 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
882 onesided_enable, twosided_enable, ref, mask,
883 func, stencilFail, depthFail, stencilPass,
884 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
886 if (twosided_enable && onesided_enable) {
887 glEnable(GL_STENCIL_TEST);
888 checkGLcall("glEnable GL_STENCIL_TEST");
890 if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
892 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
893 * which has an effect on the code below too. If we apply the front face
894 * afterwards, we are sure that the active stencil face is set to front,
895 * and other stencil functions which do not use two sided stencil do not have
896 * to set it back
898 renderstate_stencil_twosided(context, GL_BACK,
899 func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
900 renderstate_stencil_twosided(context, GL_FRONT,
901 func, ref, mask, stencilFail, depthFail, stencilPass);
903 else if (gl_info->supported[ATI_SEPARATE_STENCIL])
905 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
906 checkGLcall("glStencilFuncSeparateATI(...)");
907 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
908 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
909 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
910 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
911 } else {
912 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
915 else if(onesided_enable)
917 if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
919 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
920 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
923 /* This code disables the ATI extension as well, since the standard stencil functions are equal
924 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
926 glEnable(GL_STENCIL_TEST);
927 checkGLcall("glEnable GL_STENCIL_TEST");
928 glStencilFunc(func, ref, mask);
929 checkGLcall("glStencilFunc(...)");
930 glStencilOp(stencilFail, depthFail, stencilPass);
931 checkGLcall("glStencilOp(...)");
932 } else {
933 glDisable(GL_STENCIL_TEST);
934 checkGLcall("glDisable GL_STENCIL_TEST");
938 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
940 DWORD mask = stateblock->device->depth_stencil ? stateblock->state.render_states[WINED3DRS_STENCILWRITEMASK] : 0;
941 const struct wined3d_gl_info *gl_info = context->gl_info;
943 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
944 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
945 glStencilMask(mask);
946 checkGLcall("glStencilMask");
947 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
948 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
949 glStencilMask(mask);
952 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
954 DWORD mask = stateblock->device->depth_stencil ? stateblock->state.render_states[WINED3DRS_STENCILWRITEMASK] : 0;
956 glStencilMask(mask);
957 checkGLcall("glStencilMask");
960 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
963 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
965 if (!stateblock->state.render_states[WINED3DRS_FOGENABLE]) return;
967 /* Table fog on: Never use fog coords, and use per-fragment fog */
968 if (stateblock->state.render_states[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE)
970 glHint(GL_FOG_HINT, GL_NICEST);
971 if(context->fog_coord) {
972 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
973 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
974 context->fog_coord = FALSE;
976 return;
979 /* Otherwise use per-vertex fog in any case */
980 glHint(GL_FOG_HINT, GL_FASTEST);
982 if (stateblock->state.render_states[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw)
984 /* No fog at all, or transformed vertices: Use fog coord */
985 if(!context->fog_coord) {
986 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
987 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
988 context->fog_coord = TRUE;
990 } else {
991 /* Otherwise, use the fragment depth */
992 if(context->fog_coord) {
993 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
994 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
995 context->fog_coord = FALSE;
1000 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1002 float fogstart, fogend;
1003 union {
1004 DWORD d;
1005 float f;
1006 } tmpvalue;
1008 switch(context->fog_source) {
1009 case FOGSOURCE_VS:
1010 fogstart = 1.0f;
1011 fogend = 0.0f;
1012 break;
1014 case FOGSOURCE_COORD:
1015 fogstart = 255.0f;
1016 fogend = 0.0f;
1017 break;
1019 case FOGSOURCE_FFP:
1020 tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGSTART];
1021 fogstart = tmpvalue.f;
1022 tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGEND];
1023 fogend = tmpvalue.f;
1024 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
1025 if(fogstart == fogend) {
1026 fogstart = -1.0f / 0.0f;
1027 fogend = 0.0f;
1029 break;
1031 default:
1032 /* This should not happen.context->fog_source is set in wined3d, not the app.
1033 * Still this is needed to make the compiler happy
1035 ERR("Unexpected fog coordinate source\n");
1036 fogstart = 0.0f;
1037 fogend = 0.0f;
1040 glFogf(GL_FOG_START, fogstart);
1041 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1042 TRACE("Fog Start == %f\n", fogstart);
1044 glFogf(GL_FOG_END, fogend);
1045 checkGLcall("glFogf(GL_FOG_END, fogend)");
1046 TRACE("Fog End == %f\n", fogend);
1049 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1051 enum fogsource new_source;
1053 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
1055 if (!stateblock->state.render_states[WINED3DRS_FOGENABLE])
1057 /* No fog? Disable it, and we're done :-) */
1058 glDisableWINE(GL_FOG);
1059 checkGLcall("glDisable GL_FOG");
1060 return;
1063 /* Fog Rules:
1065 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
1066 * It can use the Z value of the vertex, or the alpha component of the specular color.
1067 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
1068 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
1069 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
1071 * FOGTABLEMODE != NONE:
1072 * The Z value is used, with the equation specified, no matter what vertex type.
1074 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1075 * Per vertex fog is calculated using the specified fog equation and the parameters
1077 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1078 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1079 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1082 * Rules for vertex fog with shaders:
1084 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1085 * the fog computation to happen during transformation while openGL expects it to happen
1086 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1087 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1088 * To solve this problem, WineD3D does:
1089 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1090 * shader,
1091 * and 2) disables the fog computation (in either the fixed function or programmable
1092 * rasterizer) if using a vertex program.
1094 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1095 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1096 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1097 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1098 * There are some GL differences between specular fog coords and vertex shaders though.
1100 * With table fog the vertex shader fog coordinate is ignored.
1102 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1103 * without shaders).
1106 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1107 * the system will apply only pixel(=table) fog effects."
1109 if (stateblock->state.render_states[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1111 if(use_vs(stateblock)) {
1112 glFogi(GL_FOG_MODE, GL_LINEAR);
1113 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1114 new_source = FOGSOURCE_VS;
1115 } else {
1116 switch (stateblock->state.render_states[WINED3DRS_FOGVERTEXMODE])
1118 /* If processed vertices are used, fall through to the NONE case */
1119 case WINED3DFOG_EXP:
1120 if(!context->last_was_rhw) {
1121 glFogi(GL_FOG_MODE, GL_EXP);
1122 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1123 new_source = FOGSOURCE_FFP;
1124 break;
1126 /* drop through */
1128 case WINED3DFOG_EXP2:
1129 if(!context->last_was_rhw) {
1130 glFogi(GL_FOG_MODE, GL_EXP2);
1131 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1132 new_source = FOGSOURCE_FFP;
1133 break;
1135 /* drop through */
1137 case WINED3DFOG_LINEAR:
1138 if(!context->last_was_rhw) {
1139 glFogi(GL_FOG_MODE, GL_LINEAR);
1140 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1141 new_source = FOGSOURCE_FFP;
1142 break;
1144 /* drop through */
1146 case WINED3DFOG_NONE:
1147 /* Both are none? According to msdn the alpha channel of the specular
1148 * color contains a fog factor. Set it in drawStridedSlow.
1149 * Same happens with Vertexfog on transformed vertices
1151 new_source = FOGSOURCE_COORD;
1152 glFogi(GL_FOG_MODE, GL_LINEAR);
1153 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1154 break;
1156 default:
1157 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %#x.\n",
1158 stateblock->state.render_states[WINED3DRS_FOGVERTEXMODE]);
1159 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1162 } else {
1163 new_source = FOGSOURCE_FFP;
1165 switch (stateblock->state.render_states[WINED3DRS_FOGTABLEMODE])
1167 case WINED3DFOG_EXP:
1168 glFogi(GL_FOG_MODE, GL_EXP);
1169 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1170 break;
1172 case WINED3DFOG_EXP2:
1173 glFogi(GL_FOG_MODE, GL_EXP2);
1174 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1175 break;
1177 case WINED3DFOG_LINEAR:
1178 glFogi(GL_FOG_MODE, GL_LINEAR);
1179 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1180 break;
1182 case WINED3DFOG_NONE: /* Won't happen */
1183 default:
1184 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %#x.\n",
1185 stateblock->state.render_states[WINED3DRS_FOGTABLEMODE]);
1189 glEnableWINE(GL_FOG);
1190 checkGLcall("glEnable GL_FOG");
1191 if(new_source != context->fog_source) {
1192 context->fog_source = new_source;
1193 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1197 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1199 if (stateblock->state.render_states[WINED3DRS_RANGEFOGENABLE])
1200 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1203 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1205 if (stateblock->state.render_states[WINED3DRS_RANGEFOGENABLE])
1207 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1208 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1209 } else {
1210 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1211 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1215 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1217 float col[4];
1218 D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_FOGCOLOR], col);
1219 glFogfv(GL_FOG_COLOR, &col[0]);
1220 checkGLcall("glFog GL_FOG_COLOR");
1223 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1225 union {
1226 DWORD d;
1227 float f;
1228 } tmpvalue;
1229 tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGDENSITY];
1230 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1231 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1234 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1236 IWineD3DDeviceImpl *device = stateblock->device;
1237 GLenum Parm = 0;
1239 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1240 * The vertex declaration will call this function if the fixed function pipeline is used.
1243 if(isStateDirty(context, STATE_VDECL)) {
1244 return;
1247 context->num_untracked_materials = 0;
1248 if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE))
1249 && stateblock->state.render_states[WINED3DRS_COLORVERTEX])
1251 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1252 stateblock->state.render_states[WINED3DRS_DIFFUSEMATERIALSOURCE],
1253 stateblock->state.render_states[WINED3DRS_AMBIENTMATERIALSOURCE],
1254 stateblock->state.render_states[WINED3DRS_EMISSIVEMATERIALSOURCE],
1255 stateblock->state.render_states[WINED3DRS_SPECULARMATERIALSOURCE]);
1257 if (stateblock->state.render_states[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1)
1259 if (stateblock->state.render_states[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1)
1261 Parm = GL_AMBIENT_AND_DIFFUSE;
1262 } else {
1263 Parm = GL_DIFFUSE;
1265 if (stateblock->state.render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1)
1267 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1268 context->num_untracked_materials++;
1270 if (stateblock->state.render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1)
1272 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1273 context->num_untracked_materials++;
1276 else if (stateblock->state.render_states[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1)
1278 Parm = GL_AMBIENT;
1279 if (stateblock->state.render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1)
1281 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1282 context->num_untracked_materials++;
1284 if (stateblock->state.render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1)
1286 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1287 context->num_untracked_materials++;
1290 else if (stateblock->state.render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1)
1292 Parm = GL_EMISSION;
1293 if (stateblock->state.render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1)
1295 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1296 context->num_untracked_materials++;
1299 else if (stateblock->state.render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1)
1301 Parm = GL_SPECULAR;
1305 /* Nothing changed, return. */
1306 if (Parm == context->tracking_parm) return;
1308 if(!Parm) {
1309 glDisable(GL_COLOR_MATERIAL);
1310 checkGLcall("glDisable GL_COLOR_MATERIAL");
1311 } else {
1312 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1313 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1314 glEnable(GL_COLOR_MATERIAL);
1315 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1318 /* Apparently calls to glMaterialfv are ignored for properties we're
1319 * tracking with glColorMaterial, so apply those here. */
1320 switch (context->tracking_parm) {
1321 case GL_AMBIENT_AND_DIFFUSE:
1322 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&device->updateStateBlock->state.material.Ambient);
1323 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&device->updateStateBlock->state.material.Diffuse);
1324 checkGLcall("glMaterialfv");
1325 break;
1327 case GL_DIFFUSE:
1328 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&device->updateStateBlock->state.material.Diffuse);
1329 checkGLcall("glMaterialfv");
1330 break;
1332 case GL_AMBIENT:
1333 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&device->updateStateBlock->state.material.Ambient);
1334 checkGLcall("glMaterialfv");
1335 break;
1337 case GL_EMISSION:
1338 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&device->updateStateBlock->state.material.Emissive);
1339 checkGLcall("glMaterialfv");
1340 break;
1342 case GL_SPECULAR:
1343 /* Only change material color if specular is enabled, otherwise it is set to black */
1344 if (device->stateBlock->state.render_states[WINED3DRS_SPECULARENABLE])
1346 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
1347 (float *)&device->updateStateBlock->state.material.Specular);
1348 checkGLcall("glMaterialfv");
1349 } else {
1350 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1351 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1352 checkGLcall("glMaterialfv");
1354 break;
1357 context->tracking_parm = Parm;
1360 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1362 union {
1363 DWORD d;
1364 WINED3DLINEPATTERN lp;
1365 } tmppattern;
1366 tmppattern.d = stateblock->state.render_states[WINED3DRS_LINEPATTERN];
1368 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1370 if (tmppattern.lp.wRepeatFactor) {
1371 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1372 checkGLcall("glLineStipple(repeat, linepattern)");
1373 glEnable(GL_LINE_STIPPLE);
1374 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1375 } else {
1376 glDisable(GL_LINE_STIPPLE);
1377 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1381 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1383 union {
1384 DWORD d;
1385 float f;
1386 } tmpvalue;
1388 if (stateblock->state.render_states[WINED3DRS_ZBIAS])
1390 tmpvalue.d = stateblock->state.render_states[WINED3DRS_ZBIAS];
1391 TRACE("ZBias value %f\n", tmpvalue.f);
1392 glPolygonOffset(0, -tmpvalue.f);
1393 checkGLcall("glPolygonOffset(0, -Value)");
1394 glEnable(GL_POLYGON_OFFSET_FILL);
1395 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1396 glEnable(GL_POLYGON_OFFSET_LINE);
1397 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1398 glEnable(GL_POLYGON_OFFSET_POINT);
1399 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1400 } else {
1401 glDisable(GL_POLYGON_OFFSET_FILL);
1402 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1403 glDisable(GL_POLYGON_OFFSET_LINE);
1404 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1405 glDisable(GL_POLYGON_OFFSET_POINT);
1406 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1411 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1413 if(isStateDirty(context, STATE_VDECL)) {
1414 return;
1416 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1417 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1418 * by zero and is not properly defined in opengl, so avoid it
1420 if (stateblock->state.render_states[WINED3DRS_NORMALIZENORMALS]
1421 && (stateblock->device->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL)))
1423 glEnable(GL_NORMALIZE);
1424 checkGLcall("glEnable(GL_NORMALIZE);");
1425 } else {
1426 glDisable(GL_NORMALIZE);
1427 checkGLcall("glDisable(GL_NORMALIZE);");
1431 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1433 union {
1434 DWORD d;
1435 float f;
1436 } tmpvalue;
1438 tmpvalue.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN];
1439 if (tmpvalue.f != 1.0f)
1441 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1443 tmpvalue.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX];
1444 if (tmpvalue.f != 64.0f)
1446 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1451 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1453 const struct wined3d_gl_info *gl_info = context->gl_info;
1454 union
1456 DWORD d;
1457 float f;
1458 } min, max;
1460 min.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN];
1461 max.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX];
1463 /* Max point size trumps min point size */
1464 if(min.f > max.f) {
1465 min.f = max.f;
1468 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1469 checkGLcall("glPointParameterfEXT(...)");
1470 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1471 checkGLcall("glPointParameterfEXT(...)");
1474 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1476 const struct wined3d_gl_info *gl_info = context->gl_info;
1477 union
1479 DWORD d;
1480 float f;
1481 } min, max;
1483 min.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN];
1484 max.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX];
1486 /* Max point size trumps min point size */
1487 if(min.f > max.f) {
1488 min.f = max.f;
1491 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1492 checkGLcall("glPointParameterfARB(...)");
1493 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1494 checkGLcall("glPointParameterfARB(...)");
1497 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1499 const struct wined3d_gl_info *gl_info = context->gl_info;
1500 /* TODO: Group this with the viewport */
1502 * POINTSCALEENABLE controls how point size value is treated. If set to
1503 * true, the point size is scaled with respect to height of viewport.
1504 * When set to false point size is in pixels.
1507 /* Default values */
1508 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1509 union {
1510 DWORD d;
1511 float f;
1512 } pointSize, A, B, C;
1514 pointSize.d = stateblock->state.render_states[WINED3DRS_POINTSIZE];
1515 A.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_A];
1516 B.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_B];
1517 C.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_C];
1519 if (stateblock->state.render_states[WINED3DRS_POINTSCALEENABLE])
1521 GLfloat scaleFactor;
1522 DWORD h = stateblock->state.viewport.Height;
1524 if (pointSize.f < gl_info->limits.pointsize_min)
1526 /* Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1527 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1528 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1529 * are less than 1.0f. scale_factor = 1.0f / point_size.
1531 scaleFactor = pointSize.f / gl_info->limits.pointsize_min;
1532 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1533 * is 1.0, but then accepts points below that and draws too small points
1535 pointSize.f = gl_info->limits.pointsize_min;
1537 else if(pointSize.f > gl_info->limits.pointsize_max)
1539 /* gl already scales the input to glPointSize,
1540 * d3d scales the result after the point size scale.
1541 * If the point size is bigger than the max size, use the
1542 * scaling to scale it bigger, and set the gl point size to max
1544 scaleFactor = pointSize.f / gl_info->limits.pointsize_max;
1545 TRACE("scale: %f\n", scaleFactor);
1546 pointSize.f = gl_info->limits.pointsize_max;
1547 } else {
1548 scaleFactor = 1.0f;
1550 scaleFactor = powf(h * scaleFactor, 2);
1552 att[0] = A.f / scaleFactor;
1553 att[1] = B.f / scaleFactor;
1554 att[2] = C.f / scaleFactor;
1557 if (gl_info->supported[ARB_POINT_PARAMETERS])
1559 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1560 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1562 else if (gl_info->supported[EXT_POINT_PARAMETERS])
1564 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1565 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1567 else if(stateblock->state.render_states[WINED3DRS_POINTSCALEENABLE])
1569 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1572 glPointSize(pointSize.f);
1573 checkGLcall("glPointSize(...);");
1576 static void state_debug_monitor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1578 WARN("token: %#x\n", stateblock->state.render_states[WINED3DRS_DEBUGMONITORTOKEN]);
1581 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1583 DWORD mask0 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE];
1584 DWORD mask1 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE1];
1585 DWORD mask2 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE2];
1586 DWORD mask3 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE3];
1588 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1589 mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1590 mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1591 mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1592 mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1593 glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1594 mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1595 mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1596 mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1597 checkGLcall("glColorMask(...)");
1599 if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0)
1600 || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf)))
1602 FIXME("WINED3DRS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n",
1603 mask0, mask1, mask2, mask3);
1604 FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n");
1608 static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask)
1610 GL_EXTCALL(glColorMaskIndexedEXT(index,
1611 mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1612 mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1613 mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1614 mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE));
1617 static void state_colorwrite0(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1619 set_color_mask(context->gl_info, 0, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE]);
1622 static void state_colorwrite1(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1624 set_color_mask(context->gl_info, 1, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE1]);
1627 static void state_colorwrite2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1629 set_color_mask(context->gl_info, 2, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE2]);
1632 static void state_colorwrite3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1634 set_color_mask(context->gl_info, 3, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE3]);
1637 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1639 if (stateblock->state.render_states[WINED3DRS_LOCALVIEWER])
1641 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1642 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1643 } else {
1644 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1645 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1649 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1651 if (stateblock->state.render_states[WINED3DRS_LASTPIXEL])
1653 TRACE("Last Pixel Drawing Enabled\n");
1654 } else {
1655 static BOOL warned;
1656 if (!warned) {
1657 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1658 warned = TRUE;
1659 } else {
1660 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1665 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1667 static BOOL warned;
1669 /* TODO: NV_POINT_SPRITE */
1670 if (!warned && stateblock->state.render_states[WINED3DRS_POINTSPRITEENABLE])
1672 /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1673 FIXME("Point sprites not supported\n");
1674 warned = TRUE;
1678 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1680 const struct wined3d_gl_info *gl_info = context->gl_info;
1682 if (stateblock->state.render_states[WINED3DRS_POINTSPRITEENABLE])
1684 static BOOL warned;
1686 if (gl_info->limits.point_sprite_units < gl_info->limits.textures && !warned)
1688 if (use_ps(stateblock) || stateblock->state.lowest_disabled_stage > gl_info->limits.point_sprite_units)
1690 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1691 warned = TRUE;
1695 glEnable(GL_POINT_SPRITE_ARB);
1696 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1697 } else {
1698 glDisable(GL_POINT_SPRITE_ARB);
1699 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1703 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1706 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1707 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1708 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1709 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1711 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1713 if (stateblock->state.render_states[WINED3DRS_WRAP0]
1714 || stateblock->state.render_states[WINED3DRS_WRAP1]
1715 || stateblock->state.render_states[WINED3DRS_WRAP2]
1716 || stateblock->state.render_states[WINED3DRS_WRAP3]
1717 || stateblock->state.render_states[WINED3DRS_WRAP4]
1718 || stateblock->state.render_states[WINED3DRS_WRAP5]
1719 || stateblock->state.render_states[WINED3DRS_WRAP6]
1720 || stateblock->state.render_states[WINED3DRS_WRAP7]
1721 || stateblock->state.render_states[WINED3DRS_WRAP8]
1722 || stateblock->state.render_states[WINED3DRS_WRAP9]
1723 || stateblock->state.render_states[WINED3DRS_WRAP10]
1724 || stateblock->state.render_states[WINED3DRS_WRAP11]
1725 || stateblock->state.render_states[WINED3DRS_WRAP12]
1726 || stateblock->state.render_states[WINED3DRS_WRAP13]
1727 || stateblock->state.render_states[WINED3DRS_WRAP14]
1728 || stateblock->state.render_states[WINED3DRS_WRAP15])
1730 FIXME("(WINED3DRS_WRAP0) Texture wrapping not yet supported.\n");
1734 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1736 if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEANTIALIAS])
1737 WARN("Multisample antialiasing not supported by gl\n");
1740 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1742 if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEANTIALIAS])
1744 glEnable(GL_MULTISAMPLE_ARB);
1745 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1746 } else {
1747 glDisable(GL_MULTISAMPLE_ARB);
1748 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1752 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1754 if (stateblock->state.render_states[WINED3DRS_SCISSORTESTENABLE])
1756 glEnable(GL_SCISSOR_TEST);
1757 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1758 } else {
1759 glDisable(GL_SCISSOR_TEST);
1760 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1764 /* The Direct3D depth bias is specified in normalized depth coordinates. In
1765 * OpenGL the bias is specified in units of "the smallest value that is
1766 * guaranteed to produce a resolvable offset for a given implementation". To
1767 * convert from D3D to GL we need to divide the D3D depth bias by that value.
1768 * There's no practical way to retrieve that value from a given GL
1769 * implementation, but the D3D application has essentially the same problem,
1770 * which makes a guess of 1e-6f seem reasonable here. Note that
1771 * SLOPESCALEDEPTHBIAS is a scaling factor for the depth slope, and doesn't
1772 * need to be scaled. */
1773 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1775 if (stateblock->state.render_states[WINED3DRS_SLOPESCALEDEPTHBIAS]
1776 || stateblock->state.render_states[WINED3DRS_DEPTHBIAS])
1778 union
1780 DWORD d;
1781 float f;
1782 } scale_bias, const_bias;
1784 scale_bias.d = stateblock->state.render_states[WINED3DRS_SLOPESCALEDEPTHBIAS];
1785 const_bias.d = stateblock->state.render_states[WINED3DRS_DEPTHBIAS];
1787 glEnable(GL_POLYGON_OFFSET_FILL);
1788 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1790 glPolygonOffset(scale_bias.f, const_bias.f * 1e6f);
1791 checkGLcall("glPolygonOffset(...)");
1792 } else {
1793 glDisable(GL_POLYGON_OFFSET_FILL);
1794 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1798 static void state_zvisible(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1800 if (stateblock->state.render_states[WINED3DRS_ZVISIBLE])
1801 FIXME("WINED3DRS_ZVISIBLE not implemented.\n");
1804 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1806 if (stateblock->state.render_states[WINED3DRS_TEXTUREPERSPECTIVE])
1808 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1809 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1810 } else {
1811 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1812 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1816 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1818 if (stateblock->state.render_states[WINED3DRS_STIPPLEDALPHA])
1819 FIXME(" Stippled Alpha not supported yet.\n");
1822 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1824 if (stateblock->state.render_states[WINED3DRS_ANTIALIAS])
1825 FIXME("Antialias not supported yet.\n");
1828 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1830 if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEMASK] != 0xffffffff)
1831 FIXME("WINED3DRS_MULTISAMPLEMASK %#x not yet implemented.\n",
1832 stateblock->state.render_states[WINED3DRS_MULTISAMPLEMASK]);
1835 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1837 if (stateblock->state.render_states[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1838 FIXME("WINED3DRS_PATCHEDGESTYLE %#x not yet implemented.\n",
1839 stateblock->state.render_states[WINED3DRS_PATCHEDGESTYLE]);
1842 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1844 union {
1845 DWORD d;
1846 float f;
1847 } tmpvalue;
1848 tmpvalue.f = 1.0f;
1850 if (stateblock->state.render_states[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1852 static BOOL displayed = FALSE;
1854 tmpvalue.d = stateblock->state.render_states[WINED3DRS_PATCHSEGMENTS];
1855 if(!displayed)
1856 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1858 displayed = TRUE;
1862 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1864 if (stateblock->state.render_states[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1865 FIXME("WINED3DRS_POSITIONDEGREE %#x not yet implemented.\n",
1866 stateblock->state.render_states[WINED3DRS_POSITIONDEGREE]);
1869 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1871 if (stateblock->state.render_states[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1872 FIXME("WINED3DRS_NORMALDEGREE %#x not yet implemented.\n",
1873 stateblock->state.render_states[WINED3DRS_NORMALDEGREE]);
1876 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1878 if (stateblock->state.render_states[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1879 FIXME("WINED3DRS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n",
1880 stateblock->state.render_states[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1883 static void state_nvdb(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1885 union {
1886 DWORD d;
1887 float f;
1888 } zmin, zmax;
1890 const struct wined3d_gl_info *gl_info = context->gl_info;
1892 if (stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_X] == WINED3DFMT_NVDB)
1894 zmin.d = stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_Z];
1895 zmax.d = stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_W];
1897 /* If zmin is larger than zmax INVALID_VALUE error is generated.
1898 * In d3d9 test is not performed in this case*/
1899 if (zmin.f <= zmax.f)
1901 glEnable(GL_DEPTH_BOUNDS_TEST_EXT);
1902 checkGLcall("glEnable(GL_DEPTH_BOUNDS_TEST_EXT)");
1903 GL_EXTCALL(glDepthBoundsEXT(zmin.f, zmax.f));
1904 checkGLcall("glDepthBoundsEXT(...)");
1906 else {
1907 glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1908 checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
1911 else {
1912 glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1913 checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
1916 state_tessellation(state, stateblock, context);
1919 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1921 if (stateblock->state.render_states[WINED3DRS_WRAPU])
1922 FIXME("Render state WINED3DRS_WRAPU not implemented yet.\n");
1925 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1927 if (stateblock->state.render_states[WINED3DRS_WRAPV])
1928 FIXME("Render state WINED3DRS_WRAPV not implemented yet.\n");
1931 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1933 if (stateblock->state.render_states[WINED3DRS_MONOENABLE])
1934 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet.\n");
1937 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1939 if (stateblock->state.render_states[WINED3DRS_ROP2])
1940 FIXME("Render state WINED3DRS_ROP2 not implemented yet.\n");
1943 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1945 if (stateblock->state.render_states[WINED3DRS_PLANEMASK])
1946 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet.\n");
1949 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1951 if (stateblock->state.render_states[WINED3DRS_SUBPIXEL])
1952 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet.\n");
1955 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1957 if (stateblock->state.render_states[WINED3DRS_SUBPIXELX])
1958 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet.\n");
1961 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1963 if (stateblock->state.render_states[WINED3DRS_STIPPLEENABLE])
1964 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet.\n");
1967 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1969 if (stateblock->state.render_states[WINED3DRS_MIPMAPLODBIAS])
1970 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet.\n");
1973 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1975 if (stateblock->state.render_states[WINED3DRS_ANISOTROPY])
1976 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet.\n");
1979 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1981 if (stateblock->state.render_states[WINED3DRS_FLUSHBATCH])
1982 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet.\n");
1985 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1987 if (stateblock->state.render_states[WINED3DRS_TRANSLUCENTSORTINDEPENDENT])
1988 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
1991 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1993 if (stateblock->state.render_states[WINED3DRS_EXTENTS])
1994 FIXME("Render state WINED3DRS_EXTENTS not implemented yet.\n");
1997 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
1999 if (stateblock->state.render_states[WINED3DRS_COLORKEYBLENDENABLE])
2000 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet.\n");
2003 static void state_swvp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
2005 if (stateblock->state.render_states[WINED3DRS_SOFTWAREVERTEXPROCESSING])
2006 FIXME("Software vertex processing not implemented.\n");
2009 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
2010 #if defined (GL_VERSION_1_3)
2011 # define useext(A) A
2012 #elif defined (GL_EXT_texture_env_combine)
2013 # define useext(A) A##_EXT
2014 #elif defined (GL_ARB_texture_env_combine)
2015 # define useext(A) A##_ARB
2016 #endif
2018 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
2019 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
2020 * input should be used for all input components. The WINED3DTA_COMPLEMENT
2021 * flag specifies the complement of the input should be used. */
2022 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
2023 BOOL complement = arg & WINED3DTA_COMPLEMENT;
2025 /* Calculate the operand */
2026 if (complement) {
2027 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
2028 else *operand = GL_ONE_MINUS_SRC_COLOR;
2029 } else {
2030 if (from_alpha) *operand = GL_SRC_ALPHA;
2031 else *operand = GL_SRC_COLOR;
2034 /* Calculate the source */
2035 switch (arg & WINED3DTA_SELECTMASK) {
2036 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
2037 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
2038 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
2039 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
2040 case WINED3DTA_SPECULAR:
2042 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
2043 * 'Secondary color' and isn't supported until base GL supports it
2044 * There is no concept of temp registers as far as I can tell
2046 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
2047 *source = GL_TEXTURE;
2048 break;
2049 default:
2050 FIXME("Unrecognized texture arg %#x\n", arg);
2051 *source = GL_TEXTURE;
2052 break;
2056 /* Setup the texture operations texture stage states */
2057 static void set_tex_op(const struct wined3d_context *context, IWineD3DDevice *iface,
2058 BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
2060 const struct wined3d_gl_info *gl_info = context->gl_info;
2061 GLenum src1, src2, src3;
2062 GLenum opr1, opr2, opr3;
2063 GLenum comb_target;
2064 GLenum src0_target, src1_target, src2_target;
2065 GLenum opr0_target, opr1_target, opr2_target;
2066 GLenum scal_target;
2067 GLenum opr=0, invopr, src3_target, opr3_target;
2068 BOOL Handled = FALSE;
2069 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2071 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
2073 /* This is called by a state handler which has the gl lock held and a context for the thread */
2075 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
2076 the form (a1 <operation> a2). However, some of the more complex operations
2077 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
2078 in a third parameter called a0. Therefore these are operations of the form
2079 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
2081 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
2082 functions below, expect their syntax to differ slightly to those listed in the
2083 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
2084 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
2086 if (isAlpha) {
2087 comb_target = useext(GL_COMBINE_ALPHA);
2088 src0_target = useext(GL_SOURCE0_ALPHA);
2089 src1_target = useext(GL_SOURCE1_ALPHA);
2090 src2_target = useext(GL_SOURCE2_ALPHA);
2091 opr0_target = useext(GL_OPERAND0_ALPHA);
2092 opr1_target = useext(GL_OPERAND1_ALPHA);
2093 opr2_target = useext(GL_OPERAND2_ALPHA);
2094 scal_target = GL_ALPHA_SCALE;
2096 else {
2097 comb_target = useext(GL_COMBINE_RGB);
2098 src0_target = useext(GL_SOURCE0_RGB);
2099 src1_target = useext(GL_SOURCE1_RGB);
2100 src2_target = useext(GL_SOURCE2_RGB);
2101 opr0_target = useext(GL_OPERAND0_RGB);
2102 opr1_target = useext(GL_OPERAND1_RGB);
2103 opr2_target = useext(GL_OPERAND2_RGB);
2104 scal_target = useext(GL_RGB_SCALE);
2107 /* If a texture stage references an invalid texture unit the stage just
2108 * passes through the result from the previous stage */
2109 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
2110 arg1 = WINED3DTA_CURRENT;
2111 op = WINED3DTOP_SELECTARG1;
2114 if (isAlpha && !This->stateBlock->state.textures[Stage] && arg1 == WINED3DTA_TEXTURE)
2116 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
2117 } else {
2118 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
2120 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
2121 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
2123 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
2125 Handled = TRUE; /* Assume will be handled */
2127 /* Other texture operations require special extensions: */
2128 if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
2130 if (isAlpha) {
2131 opr = GL_SRC_ALPHA;
2132 invopr = GL_ONE_MINUS_SRC_ALPHA;
2133 src3_target = GL_SOURCE3_ALPHA_NV;
2134 opr3_target = GL_OPERAND3_ALPHA_NV;
2135 } else {
2136 opr = GL_SRC_COLOR;
2137 invopr = GL_ONE_MINUS_SRC_COLOR;
2138 src3_target = GL_SOURCE3_RGB_NV;
2139 opr3_target = GL_OPERAND3_RGB_NV;
2141 switch (op) {
2142 case WINED3DTOP_DISABLE: /* Only for alpha */
2143 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2144 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2145 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2146 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2147 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2148 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2149 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2150 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2151 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2152 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2153 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2154 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2155 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2156 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2157 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2158 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2159 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2160 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2161 break;
2162 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
2163 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
2164 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2165 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2166 if (op == WINED3DTOP_SELECTARG1) {
2167 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2168 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2169 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2170 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2171 } else {
2172 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2173 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2174 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2175 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2177 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2178 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2179 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2180 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2181 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2182 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2183 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2184 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2185 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2186 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2187 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2188 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2189 break;
2191 case WINED3DTOP_MODULATE:
2192 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2193 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2194 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2195 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2196 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2197 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2198 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2199 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2200 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2201 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2202 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2203 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2204 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2205 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2206 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2207 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2208 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2209 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2210 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2211 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2212 break;
2213 case WINED3DTOP_MODULATE2X:
2214 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2215 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2216 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2217 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2218 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2219 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2220 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2221 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2222 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2223 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2224 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2225 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2226 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2227 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2228 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2229 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2230 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2231 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2232 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2233 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2234 break;
2235 case WINED3DTOP_MODULATE4X:
2236 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2237 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2238 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2239 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2240 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2241 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2242 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2243 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2244 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2245 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2246 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2247 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2248 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2249 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2250 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2251 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2252 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2253 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2254 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2255 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2256 break;
2258 case WINED3DTOP_ADD:
2259 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2260 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2261 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2262 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2263 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2264 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2265 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2266 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2267 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2268 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2269 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2270 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2271 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2272 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2273 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2274 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2275 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2276 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2277 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2278 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2279 break;
2281 case WINED3DTOP_ADDSIGNED:
2282 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2283 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2284 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2285 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2286 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2287 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2288 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2289 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2290 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2291 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2292 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2293 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2294 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2295 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2296 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2297 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2298 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2299 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2300 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2301 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2302 break;
2304 case WINED3DTOP_ADDSIGNED2X:
2305 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2306 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2307 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2308 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2309 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2310 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2311 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2312 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2313 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2314 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2315 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2316 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2317 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2318 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2319 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2320 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2321 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2322 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2323 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2324 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2325 break;
2327 case WINED3DTOP_ADDSMOOTH:
2328 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2329 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2330 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2331 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2332 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2333 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2334 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2335 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2336 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2337 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2338 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2339 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2340 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2341 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2342 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2343 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2344 switch (opr1) {
2345 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2346 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2347 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2348 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2350 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2351 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2352 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2353 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2354 break;
2356 case WINED3DTOP_BLENDDIFFUSEALPHA:
2357 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2358 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2359 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2360 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2361 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2362 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2363 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2364 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2365 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2366 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2367 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2368 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2369 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2370 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2371 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2372 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2373 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2374 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2375 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2376 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2377 break;
2378 case WINED3DTOP_BLENDTEXTUREALPHA:
2379 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2380 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2381 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2382 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2383 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2384 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2385 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2386 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2387 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2388 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2389 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2390 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2391 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2392 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2393 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2394 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2395 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2396 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2397 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2398 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2399 break;
2400 case WINED3DTOP_BLENDFACTORALPHA:
2401 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2402 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2403 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2404 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2405 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2406 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2407 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2408 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2409 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2410 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2411 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2412 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2413 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2414 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2415 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2416 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2417 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2418 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2419 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2420 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2421 break;
2422 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2423 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2424 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2425 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2426 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2427 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2428 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2429 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2430 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2431 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2432 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2433 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2434 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2435 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2436 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2437 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2438 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2439 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2440 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2441 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2442 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2443 break;
2444 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2445 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2446 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2447 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2448 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2449 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2450 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2451 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2452 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2453 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2454 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2455 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2456 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2457 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2458 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2459 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2460 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2461 switch (opr) {
2462 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2463 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2465 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2466 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2467 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2468 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2469 break;
2470 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2471 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2472 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2473 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2474 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2475 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2476 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2477 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2478 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2479 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2480 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2481 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2482 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2483 switch (opr1) {
2484 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2485 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2487 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2488 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2489 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2490 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2491 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2492 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2493 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2494 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2495 break;
2496 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2497 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2498 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2499 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2500 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2501 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2502 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2503 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2504 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2505 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2506 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2507 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2508 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2509 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2510 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2511 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2512 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2513 switch (opr1) {
2514 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2515 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2516 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2517 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2519 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2520 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2521 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2522 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2523 break;
2524 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2525 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2526 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2527 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2528 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2529 switch (opr1) {
2530 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2531 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2532 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2533 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2535 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2536 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2537 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2538 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2539 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2540 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2541 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2542 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2543 switch (opr1) {
2544 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2545 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2547 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2548 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2549 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2550 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2551 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2552 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2553 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2554 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2555 break;
2556 case WINED3DTOP_MULTIPLYADD:
2557 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2558 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2559 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2560 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2561 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2562 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2563 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2564 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2565 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2566 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2567 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2568 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2569 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2570 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2571 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2572 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2573 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2574 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2575 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2576 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2577 break;
2579 case WINED3DTOP_BUMPENVMAP:
2583 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2584 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2586 default:
2587 Handled = FALSE;
2589 if (Handled) {
2590 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2591 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2593 return;
2595 } /* GL_NV_texture_env_combine4 */
2597 Handled = TRUE; /* Again, assume handled */
2598 switch (op) {
2599 case WINED3DTOP_DISABLE: /* Only for alpha */
2600 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2601 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2602 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2603 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2604 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2605 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2606 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2607 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2608 break;
2609 case WINED3DTOP_SELECTARG1:
2610 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2611 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2612 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2613 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2614 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2615 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2616 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2617 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2618 break;
2619 case WINED3DTOP_SELECTARG2:
2620 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2621 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2622 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2623 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2624 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2625 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2626 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2627 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2628 break;
2629 case WINED3DTOP_MODULATE:
2630 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2631 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2632 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2633 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2634 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2635 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2636 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2637 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2638 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2639 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2640 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2641 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2642 break;
2643 case WINED3DTOP_MODULATE2X:
2644 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2645 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2646 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2647 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2648 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2649 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2650 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2651 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2652 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2653 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2654 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2655 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2656 break;
2657 case WINED3DTOP_MODULATE4X:
2658 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2659 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2660 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2661 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2662 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2663 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2664 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2665 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2666 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2667 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2668 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2669 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2670 break;
2671 case WINED3DTOP_ADD:
2672 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2673 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2674 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2675 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2676 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2677 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2678 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2679 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2680 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2681 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2682 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2683 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2684 break;
2685 case WINED3DTOP_ADDSIGNED:
2686 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2687 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2688 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2689 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2690 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2691 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2692 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2693 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2694 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2695 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2696 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2697 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2698 break;
2699 case WINED3DTOP_ADDSIGNED2X:
2700 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2701 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2702 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2703 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2704 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2705 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2706 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2707 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2708 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2709 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2710 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2711 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2712 break;
2713 case WINED3DTOP_SUBTRACT:
2714 if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE])
2716 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2717 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2718 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2719 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2720 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2721 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2722 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2723 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2724 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2725 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2726 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2727 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2728 } else {
2729 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2731 break;
2733 case WINED3DTOP_BLENDDIFFUSEALPHA:
2734 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2735 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2736 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2737 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2738 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2739 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2740 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2741 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2742 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2743 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2744 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2745 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2746 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2747 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2748 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2749 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2750 break;
2751 case WINED3DTOP_BLENDTEXTUREALPHA:
2752 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2753 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2754 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2755 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2756 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2757 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2758 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2759 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2760 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2761 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2762 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2763 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2764 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2765 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2766 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2767 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2768 break;
2769 case WINED3DTOP_BLENDFACTORALPHA:
2770 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2771 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2772 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2773 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2774 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2775 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2776 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2777 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2778 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2779 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2780 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2781 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2782 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2783 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2784 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2785 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2786 break;
2787 case WINED3DTOP_BLENDCURRENTALPHA:
2788 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2789 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2790 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2791 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2792 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2793 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2794 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2795 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2796 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2797 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2798 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2799 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2800 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2801 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2802 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2803 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2804 break;
2805 case WINED3DTOP_DOTPRODUCT3:
2806 if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
2808 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2809 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2811 else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3])
2813 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2814 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2815 } else {
2816 FIXME("This version of opengl does not support GL_DOT3\n");
2818 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2819 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2820 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2821 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2822 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2823 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2824 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2825 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2826 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2827 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2828 break;
2829 case WINED3DTOP_LERP:
2830 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2831 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2832 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2833 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2834 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2835 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2836 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2837 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2838 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2839 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2840 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2841 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2842 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2843 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2844 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2845 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2846 break;
2847 case WINED3DTOP_ADDSMOOTH:
2848 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2850 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2851 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2852 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2853 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2854 switch (opr1) {
2855 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2856 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2857 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2858 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2860 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2861 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2862 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2863 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2864 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2865 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2866 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2867 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2868 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2869 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2870 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2871 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2872 } else
2873 Handled = FALSE;
2874 break;
2875 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2876 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2878 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2879 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2880 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2881 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2882 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2883 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2884 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2885 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2886 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2887 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2888 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2889 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2890 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2891 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2892 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2893 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2894 } else
2895 Handled = FALSE;
2896 break;
2897 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2898 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2900 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2901 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2902 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2903 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2904 switch (opr1) {
2905 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2906 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2907 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2908 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2910 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2911 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2912 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2913 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2914 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2915 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2916 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2917 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2918 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2919 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2920 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2921 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2922 } else
2923 Handled = FALSE;
2924 break;
2925 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2926 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2928 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2929 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2930 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2931 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2932 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2933 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2934 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2935 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2936 switch (opr1) {
2937 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2938 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2939 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2940 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2942 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2943 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2944 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2945 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2946 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2947 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2948 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2949 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2950 } else
2951 Handled = FALSE;
2952 break;
2953 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2954 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2956 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2957 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2958 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2959 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2960 switch (opr1) {
2961 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2962 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2963 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2964 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2966 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2967 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2968 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2969 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2970 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2971 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2972 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2973 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2974 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2975 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2976 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2977 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2978 } else
2979 Handled = FALSE;
2980 break;
2981 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2982 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2984 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2985 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2986 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2987 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2988 switch (opr1) {
2989 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2990 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2991 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2992 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2994 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2995 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2996 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2997 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2998 switch (opr1) {
2999 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
3000 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
3001 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
3002 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
3004 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
3005 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
3006 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3007 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3008 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3009 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3010 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3011 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
3012 } else
3013 Handled = FALSE;
3014 break;
3015 case WINED3DTOP_MULTIPLYADD:
3016 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
3018 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
3019 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
3020 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
3021 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
3022 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
3023 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
3024 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
3025 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
3026 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
3027 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
3028 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3029 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3030 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3031 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3032 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3033 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
3034 } else
3035 Handled = FALSE;
3036 break;
3037 case WINED3DTOP_BUMPENVMAPLUMINANCE:
3038 case WINED3DTOP_BUMPENVMAP:
3039 if (gl_info->supported[NV_TEXTURE_SHADER2])
3041 /* Technically texture shader support without register combiners is possible, but not expected to occur
3042 * on real world cards, so for now a fixme should be enough
3044 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
3046 default:
3047 Handled = FALSE;
3050 if (Handled) {
3051 BOOL combineOK = TRUE;
3052 if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
3054 DWORD op2;
3056 if (isAlpha)
3057 op2 = This->stateBlock->state.texture_states[Stage][WINED3DTSS_COLOROP];
3058 else
3059 op2 = This->stateBlock->state.texture_states[Stage][WINED3DTSS_ALPHAOP];
3061 /* Note: If COMBINE4 in effect can't go back to combine! */
3062 switch (op2) {
3063 case WINED3DTOP_ADDSMOOTH:
3064 case WINED3DTOP_BLENDTEXTUREALPHAPM:
3065 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
3066 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
3067 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
3068 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
3069 case WINED3DTOP_MULTIPLYADD:
3070 /* Ignore those implemented in both cases */
3071 switch (op) {
3072 case WINED3DTOP_SELECTARG1:
3073 case WINED3DTOP_SELECTARG2:
3074 combineOK = FALSE;
3075 Handled = FALSE;
3076 break;
3077 default:
3078 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
3079 return;
3084 if (combineOK) {
3085 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
3086 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
3088 return;
3092 /* After all the extensions, if still unhandled, report fixme */
3093 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
3097 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3099 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3100 BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage);
3101 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3102 const struct wined3d_gl_info *gl_info = context->gl_info;
3104 TRACE("Setting color op for stage %d\n", stage);
3106 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
3107 if (use_ps(stateblock)) return;
3109 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
3111 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3113 if (tex_used && mapped_stage >= gl_info->limits.textures)
3115 FIXME("Attempt to enable unsupported stage!\n");
3116 return;
3118 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3119 checkGLcall("glActiveTextureARB");
3122 if (stage >= stateblock->state.lowest_disabled_stage)
3124 TRACE("Stage disabled\n");
3125 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3127 /* Disable everything here */
3128 glDisable(GL_TEXTURE_2D);
3129 checkGLcall("glDisable(GL_TEXTURE_2D)");
3130 glDisable(GL_TEXTURE_3D);
3131 checkGLcall("glDisable(GL_TEXTURE_3D)");
3132 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3134 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3135 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3137 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3139 glDisable(GL_TEXTURE_RECTANGLE_ARB);
3140 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3143 /* All done */
3144 return;
3147 /* The sampler will also activate the correct texture dimensions, so no need to do it here
3148 * if the sampler for this stage is dirty
3150 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
3151 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
3154 set_tex_op(context, (IWineD3DDevice *)stateblock->device, FALSE, stage,
3155 stateblock->state.texture_states[stage][WINED3DTSS_COLOROP],
3156 stateblock->state.texture_states[stage][WINED3DTSS_COLORARG1],
3157 stateblock->state.texture_states[stage][WINED3DTSS_COLORARG2],
3158 stateblock->state.texture_states[stage][WINED3DTSS_COLORARG0]);
3161 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3163 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3164 BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage);
3165 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3166 const struct wined3d_gl_info *gl_info = context->gl_info;
3167 DWORD op, arg1, arg2, arg0;
3169 TRACE("Setting alpha op for stage %d\n", stage);
3170 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
3171 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3173 if (tex_used && mapped_stage >= gl_info->limits.textures)
3175 FIXME("Attempt to enable unsupported stage!\n");
3176 return;
3178 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3179 checkGLcall("glActiveTextureARB");
3182 op = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAOP];
3183 arg1 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG1];
3184 arg2 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG2];
3185 arg0 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG0];
3187 if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && !stage && stateblock->state.textures[0])
3189 IWineD3DBaseTextureImpl *texture = stateblock->state.textures[0];
3190 GLenum texture_dimensions = texture->baseTexture.target;
3192 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3194 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0];
3196 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_mask)
3198 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
3199 * properly. On the other hand applications can still use texture combiners apparently. This code
3200 * takes care that apps cannot remove the texture's alpha channel entirely.
3202 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
3203 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
3204 * and alpha component of diffuse color to draw things like translucent text and perform other
3205 * blending effects.
3207 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
3208 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
3209 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
3210 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
3211 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
3212 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
3213 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
3214 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
3215 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
3216 * alpha.
3218 * What to do with multitexturing? So far no app has been found that uses color keying with
3219 * multitexturing */
3220 if (op == WINED3DTOP_DISABLE)
3222 arg1 = WINED3DTA_TEXTURE;
3223 op = WINED3DTOP_SELECTARG1;
3225 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
3227 if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE])
3229 arg2 = WINED3DTA_TEXTURE;
3230 op = WINED3DTOP_MODULATE;
3232 else arg1 = WINED3DTA_TEXTURE;
3234 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
3236 if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE])
3238 arg1 = WINED3DTA_TEXTURE;
3239 op = WINED3DTOP_MODULATE;
3241 else arg2 = WINED3DTA_TEXTURE;
3247 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3248 * this if block here, and the other code(color keying, texture unit selection) are the same
3250 TRACE("Setting alpha op for stage %d\n", stage);
3251 if (gl_info->supported[NV_REGISTER_COMBINERS])
3253 set_tex_op_nvrc((IWineD3DDevice *)stateblock->device, TRUE, stage, op, arg1, arg2, arg0,
3254 mapped_stage, stateblock->state.texture_states[stage][WINED3DTSS_RESULTARG]);
3256 else
3258 set_tex_op(context, (IWineD3DDevice *)stateblock->device, TRUE, stage, op, arg1, arg2, arg0);
3262 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3264 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3265 DWORD mapped_stage = stateblock->device->texUnitMap[texUnit];
3266 const struct wined3d_gl_info *gl_info = context->gl_info;
3267 BOOL generated;
3268 int coordIdx;
3270 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3271 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3273 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3274 return;
3277 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3278 if (mapped_stage >= gl_info->limits.textures) return;
3280 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3281 checkGLcall("glActiveTextureARB");
3282 generated = (stateblock->state.texture_states[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3283 != WINED3DTSS_TCI_PASSTHRU;
3284 coordIdx = min(stateblock->state.texture_states[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000ffff], MAX_TEXTURES - 1);
3286 set_texture_matrix(&stateblock->state.transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3287 stateblock->state.texture_states[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
3288 generated, context->last_was_rhw,
3289 stateblock->device->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
3290 ? stateblock->device->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id
3291 : WINED3DFMT_UNKNOWN,
3292 stateblock->device->frag_pipe->ffp_proj_control);
3294 /* The sampler applying function calls us if this changes */
3295 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->state.textures[texUnit])
3297 if(generated) {
3298 FIXME("Non-power2 texture being used with generated texture coords\n");
3300 /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
3301 fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3302 if (!use_ps(stateblock)) {
3303 TRACE("Non power two matrix multiply fixup\n");
3304 glMultMatrixf(stateblock->state.textures[texUnit]->baseTexture.pow2Matrix);
3309 static void unloadTexCoords(const struct wined3d_gl_info *gl_info)
3311 unsigned int texture_idx;
3313 for (texture_idx = 0; texture_idx < gl_info->limits.texture_stages; ++texture_idx)
3315 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3316 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3320 static void loadTexCoords(const struct wined3d_gl_info *gl_info, IWineD3DStateBlockImpl *stateblock,
3321 const struct wined3d_stream_info *si, GLuint *curVBO)
3323 unsigned int mapped_stage = 0;
3324 unsigned int textureNo = 0;
3326 for (textureNo = 0; textureNo < gl_info->limits.texture_stages; ++textureNo)
3328 int coordIdx = stateblock->state.texture_states[textureNo][WINED3DTSS_TEXCOORDINDEX];
3330 mapped_stage = stateblock->device->texUnitMap[textureNo];
3331 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3333 if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
3335 const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3336 const struct wined3d_stream_state *stream = &stateblock->state.streams[e->stream_idx];
3338 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3339 textureNo, mapped_stage, coordIdx, e->data);
3341 if (*curVBO != e->buffer_object)
3343 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3344 checkGLcall("glBindBufferARB");
3345 *curVBO = e->buffer_object;
3348 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3349 checkGLcall("glClientActiveTextureARB");
3351 /* The coords to supply depend completely on the fvf / vertex shader */
3352 glTexCoordPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
3353 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
3354 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3355 } else {
3356 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3359 if (gl_info->supported[NV_REGISTER_COMBINERS])
3361 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */
3362 for (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo)
3364 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3368 checkGLcall("loadTexCoords");
3371 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3373 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3374 DWORD mapped_stage = stateblock->device->texUnitMap[stage];
3375 static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3376 static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3377 static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3378 static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3379 const struct wined3d_gl_info *gl_info = context->gl_info;
3381 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3383 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3384 return;
3387 if (mapped_stage >= gl_info->limits.fragment_samplers)
3389 WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3390 return;
3392 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3393 checkGLcall("glActiveTextureARB");
3395 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3397 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3398 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3399 * means use the vertex position (camera-space) as the input texture coordinates
3400 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3401 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3402 * to the TEXCOORDINDEX value
3404 switch (stateblock->state.texture_states[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3406 case WINED3DTSS_TCI_PASSTHRU:
3407 /* Use the specified texture coordinates contained within the
3408 * vertex format. This value resolves to zero. */
3409 glDisable(GL_TEXTURE_GEN_S);
3410 glDisable(GL_TEXTURE_GEN_T);
3411 glDisable(GL_TEXTURE_GEN_R);
3412 glDisable(GL_TEXTURE_GEN_Q);
3413 checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3414 break;
3416 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3417 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3418 * as the input texture coordinates for this stage's texture transformation. This
3419 * equates roughly to EYE_LINEAR */
3421 glMatrixMode(GL_MODELVIEW);
3422 glPushMatrix();
3423 glLoadIdentity();
3424 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3425 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3426 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3427 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3428 glPopMatrix();
3429 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3431 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3432 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3433 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3434 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3436 glEnable(GL_TEXTURE_GEN_S);
3437 glEnable(GL_TEXTURE_GEN_T);
3438 glEnable(GL_TEXTURE_GEN_R);
3439 checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3441 break;
3443 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3444 /* Note that NV_TEXGEN_REFLECTION support is implied when
3445 * ARB_TEXTURE_CUBE_MAP is supported */
3446 if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3448 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3449 break;
3452 glMatrixMode(GL_MODELVIEW);
3453 glPushMatrix();
3454 glLoadIdentity();
3455 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3456 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3457 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3458 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3459 glPopMatrix();
3460 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3462 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3463 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3464 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3465 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3467 glEnable(GL_TEXTURE_GEN_S);
3468 glEnable(GL_TEXTURE_GEN_T);
3469 glEnable(GL_TEXTURE_GEN_R);
3470 checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3472 break;
3474 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3475 /* Note that NV_TEXGEN_REFLECTION support is implied when
3476 * ARB_TEXTURE_CUBE_MAP is supported */
3477 if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3479 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3480 break;
3483 glMatrixMode(GL_MODELVIEW);
3484 glPushMatrix();
3485 glLoadIdentity();
3486 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3487 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3488 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3489 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3490 glPopMatrix();
3491 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3493 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3494 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3495 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3496 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3498 glEnable(GL_TEXTURE_GEN_S);
3499 glEnable(GL_TEXTURE_GEN_T);
3500 glEnable(GL_TEXTURE_GEN_R);
3501 checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3503 break;
3505 case WINED3DTSS_TCI_SPHEREMAP:
3506 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3507 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3508 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3510 glEnable(GL_TEXTURE_GEN_S);
3511 glEnable(GL_TEXTURE_GEN_T);
3512 glDisable(GL_TEXTURE_GEN_R);
3513 checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3515 break;
3517 default:
3518 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x.\n",
3519 stateblock->state.texture_states[stage][WINED3DTSS_TEXCOORDINDEX]);
3520 glDisable(GL_TEXTURE_GEN_S);
3521 glDisable(GL_TEXTURE_GEN_T);
3522 glDisable(GL_TEXTURE_GEN_R);
3523 glDisable(GL_TEXTURE_GEN_Q);
3524 checkGLcall("Disable texgen.");
3526 break;
3529 /* Update the texture matrix */
3530 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3531 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3534 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3535 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3536 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3537 * and do all the things linked to it
3538 * TODO: Tidy that up to reload only the arrays of the changed unit
3540 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
3542 unloadTexCoords(gl_info);
3543 loadTexCoords(gl_info, stateblock, &stateblock->device->strided_streams, &curVBO);
3547 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3549 IWineD3DDeviceImpl *device = stateblock->device;
3551 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3552 * has an update pending
3554 if(isStateDirty(context, STATE_VDECL) ||
3555 isStateDirty(context, STATE_PIXELSHADER)) {
3556 return;
3559 device->shader_backend->shader_load_constants(context, use_ps(stateblock), use_vs(stateblock));
3562 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3564 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3565 IWineD3DPixelShaderImpl *ps = stateblock->state.pixel_shader;
3567 if (ps && stage && (ps->baseShader.reg_maps.luminanceparams & (1 << stage)))
3569 /* The pixel shader has to know the luminance scale. Do a constants update if it
3570 * isn't scheduled anyway
3572 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3573 !isStateDirty(context, STATE_PIXELSHADER)) {
3574 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3579 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3581 const DWORD sampler = state - STATE_SAMPLER(0);
3582 IWineD3DBaseTextureImpl *texture = stateblock->state.textures[sampler];
3584 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3586 if(!texture) return;
3587 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3588 * basetexture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3589 * scaling is reapplied or removed, the texture matrix has to be reapplied
3591 * The mapped stage is already active because the sampler() function below, which is part of the
3592 * misc pipeline
3594 if(sampler < MAX_TEXTURES) {
3595 const BOOL texIsPow2 = !texture->baseTexture.pow2Matrix_identity;
3597 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3599 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3600 else context->lastWasPow2Texture &= ~(1 << sampler);
3601 transform_texture(STATE_TEXTURESTAGE(stateblock->device->texUnitMap[sampler],
3602 WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3607 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3609 DWORD sampler = state - STATE_SAMPLER(0);
3610 DWORD mapped_stage = stateblock->device->texUnitMap[sampler];
3611 const struct wined3d_gl_info *gl_info = context->gl_info;
3612 union {
3613 float f;
3614 DWORD d;
3615 } tmpvalue;
3617 TRACE("Sampler: %d\n", sampler);
3618 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3619 * only has to bind textures and set the per texture states
3622 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3624 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3625 return;
3628 if (mapped_stage >= gl_info->limits.combined_samplers)
3630 return;
3632 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3633 checkGLcall("glActiveTextureARB");
3635 if (stateblock->state.textures[sampler])
3637 IWineD3DBaseTexture *texture = (IWineD3DBaseTexture *)stateblock->state.textures[sampler];
3638 BOOL srgb = stateblock->state.sampler_states[sampler][WINED3DSAMP_SRGBTEXTURE];
3640 IWineD3DBaseTexture_BindTexture(texture, srgb);
3641 basetexture_apply_state_changes(texture,
3642 stateblock->state.texture_states[sampler],
3643 stateblock->state.sampler_states[sampler], gl_info);
3645 if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
3647 tmpvalue.d = stateblock->state.sampler_states[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3648 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3649 GL_TEXTURE_LOD_BIAS_EXT,
3650 tmpvalue.f);
3651 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3654 if (!use_ps(stateblock) && sampler < stateblock->state.lowest_disabled_stage)
3656 if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && !sampler)
3658 /* If color keying is enabled update the alpha test, it depends on the existence
3659 * of a color key in stage 0
3661 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3665 /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3666 if (!stateblock->state.textures[sampler]->baseTexture.pow2Matrix_identity)
3668 IWineD3DDeviceImpl *d3ddevice = stateblock->device;
3669 d3ddevice->shader_backend->shader_load_np2fixup_constants(
3670 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3673 else if (mapped_stage < gl_info->limits.textures)
3675 if (sampler < stateblock->state.lowest_disabled_stage)
3677 /* TODO: What should I do with pixel shaders here ??? */
3678 if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && !sampler)
3680 /* If color keying is enabled update the alpha test, it depends on the existence
3681 * of a color key in stage 0
3683 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3685 } /* Otherwise tex_colorop disables the stage */
3686 glBindTexture(GL_TEXTURE_2D, stateblock->device->dummyTextureName[sampler]);
3687 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->device->dummyTextureName[sampler])");
3691 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3693 IWineD3DDeviceImpl *device = stateblock->device;
3694 BOOL use_pshader = use_ps(stateblock);
3695 BOOL use_vshader = use_vs(stateblock);
3696 unsigned int i;
3698 if (use_pshader) {
3699 if(!context->last_was_pshader) {
3700 /* Former draw without a pixel shader, some samplers
3701 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3702 * make sure to enable them
3704 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3705 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3706 sampler(STATE_SAMPLER(i), stateblock, context);
3709 context->last_was_pshader = TRUE;
3710 } else {
3711 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3712 * if a different texture was bound. I don't have to do anything.
3715 } else {
3716 /* Disabled the pixel shader - color ops weren't applied
3717 * while it was enabled, so re-apply them. */
3718 for (i = 0; i < context->gl_info->limits.texture_stages; ++i)
3720 if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)))
3721 stateblock_apply_state(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3723 context->last_was_pshader = FALSE;
3726 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3727 device->shader_backend->shader_select(context, use_pshader, use_vshader);
3729 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3730 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3735 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3737 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3738 IWineD3DPixelShaderImpl *ps = stateblock->state.pixel_shader;
3740 if (ps && stage && (ps->baseShader.reg_maps.bumpmat & (1 << stage)))
3742 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3743 * anyway
3745 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3746 !isStateDirty(context, STATE_PIXELSHADER)) {
3747 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3752 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3754 /* This function is called by transform_view below if the view matrix was changed too
3756 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3757 * does not always update the world matrix, only on a switch between transformed
3758 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3759 * draw, but that should be rather rare and cheaper in total.
3761 glMatrixMode(GL_MODELVIEW);
3762 checkGLcall("glMatrixMode");
3764 if(context->last_was_rhw) {
3765 glLoadIdentity();
3766 checkGLcall("glLoadIdentity()");
3767 } else {
3768 /* In the general case, the view matrix is the identity matrix */
3769 if (stateblock->device->view_ident)
3771 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3772 checkGLcall("glLoadMatrixf");
3774 else
3776 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
3777 checkGLcall("glLoadMatrixf");
3778 glMultMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3779 checkGLcall("glMultMatrixf");
3784 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3786 UINT index = state - STATE_CLIPPLANE(0);
3788 if (isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= context->gl_info->limits.clipplanes)
3790 return;
3793 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3794 if(!use_vs(stateblock)) {
3795 glMatrixMode(GL_MODELVIEW);
3796 glPushMatrix();
3797 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
3799 else
3801 /* with vertex shaders, clip planes are not transformed in direct3d,
3802 * in OpenGL they are still transformed by the model view.
3803 * Use this to swap the y coordinate if necessary
3805 glMatrixMode(GL_MODELVIEW);
3806 glPushMatrix();
3807 glLoadIdentity();
3808 if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f);
3811 TRACE("Clipplane [%f,%f,%f,%f]\n",
3812 stateblock->clipplane[index][0],
3813 stateblock->clipplane[index][1],
3814 stateblock->clipplane[index][2],
3815 stateblock->clipplane[index][3]);
3816 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3817 checkGLcall("glClipPlane");
3819 glPopMatrix();
3822 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3824 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3825 GLenum glMat;
3826 TRACE("Setting world matrix %d\n", matrix);
3828 if (matrix >= context->gl_info->limits.blends)
3830 WARN("Unsupported blend matrix set\n");
3831 return;
3832 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3833 return;
3836 /* GL_MODELVIEW0_ARB: 0x1700
3837 * GL_MODELVIEW1_ARB: 0x850a
3838 * GL_MODELVIEW2_ARB: 0x8722
3839 * GL_MODELVIEW3_ARB: 0x8723
3840 * etc
3841 * GL_MODELVIEW31_ARB: 0x873F
3843 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3844 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3846 glMatrixMode(glMat);
3847 checkGLcall("glMatrixMode(glMat)");
3849 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3850 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3852 if (stateblock->device->view_ident)
3854 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3855 checkGLcall("glLoadMatrixf");
3857 else
3859 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
3860 checkGLcall("glLoadMatrixf");
3861 glMultMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3862 checkGLcall("glMultMatrixf");
3866 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3868 WINED3DVERTEXBLENDFLAGS f = stateblock->state.render_states[WINED3DRS_VERTEXBLEND];
3869 static unsigned int once;
3871 if (f == WINED3DVBF_DISABLE) return;
3873 if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
3874 else WARN("Vertex blend flags %#x not supported.\n", f);
3877 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3879 WINED3DVERTEXBLENDFLAGS val = stateblock->state.render_states[WINED3DRS_VERTEXBLEND];
3880 const struct wined3d_gl_info *gl_info = context->gl_info;
3881 static unsigned int once;
3883 switch(val) {
3884 case WINED3DVBF_1WEIGHTS:
3885 case WINED3DVBF_2WEIGHTS:
3886 case WINED3DVBF_3WEIGHTS:
3887 glEnable(GL_VERTEX_BLEND_ARB);
3888 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3890 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3891 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3893 GL_EXTCALL(glVertexBlendARB(stateblock->state.render_states[WINED3DRS_VERTEXBLEND] + 1));
3895 if (!stateblock->device->vertexBlendUsed)
3897 unsigned int i;
3898 for (i = 1; i < gl_info->limits.blends; ++i)
3900 if (!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i))))
3902 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3905 stateblock->device->vertexBlendUsed = TRUE;
3907 break;
3909 case WINED3DVBF_TWEENING:
3910 case WINED3DVBF_0WEIGHTS: /* Indexed vertex blending, not supported. */
3911 if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val);
3912 else WARN("Vertex blend flags %#x not supported.\n", val);
3913 /* Fall through. */
3914 case WINED3DVBF_DISABLE:
3915 glDisable(GL_VERTEX_BLEND_ARB);
3916 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3917 break;
3921 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3923 const struct wined3d_gl_info *gl_info = context->gl_info;
3924 const struct wined3d_light_info *light = NULL;
3925 unsigned int k;
3927 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3928 * NOTE: We have to reset the positions even if the light/plane is not currently
3929 * enabled, since the call to enable it will not reset the position.
3930 * NOTE2: Apparently texture transforms do NOT need reapplying
3933 glMatrixMode(GL_MODELVIEW);
3934 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3935 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
3936 checkGLcall("glLoadMatrixf(...)");
3938 /* Reset lights. TODO: Call light apply func */
3939 for (k = 0; k < stateblock->device->maxConcurrentLights; ++k)
3941 light = stateblock->activeLights[k];
3942 if(!light) continue;
3943 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3944 checkGLcall("glLightfv posn");
3945 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3946 checkGLcall("glLightfv dirn");
3949 /* Reset Clipping Planes */
3950 for (k = 0; k < gl_info->limits.clipplanes; ++k)
3952 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3953 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3957 if(context->last_was_rhw) {
3958 glLoadIdentity();
3959 checkGLcall("glLoadIdentity()");
3960 /* No need to update the world matrix, the identity is fine */
3961 return;
3964 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3965 * No need to do it here if the state is scheduled for update.
3967 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3968 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3971 /* Avoid looping over a number of matrices if the app never used the functionality */
3972 if (stateblock->device->vertexBlendUsed)
3974 for (k = 1; k < gl_info->limits.blends; ++k)
3976 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3977 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3983 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
3985 glMatrixMode(GL_PROJECTION);
3986 checkGLcall("glMatrixMode(GL_PROJECTION)");
3987 glLoadIdentity();
3988 checkGLcall("glLoadIdentity");
3990 if (context->last_was_rhw)
3992 double x = stateblock->state.viewport.X;
3993 double y = stateblock->state.viewport.Y;
3994 double w = stateblock->state.viewport.Width;
3995 double h = stateblock->state.viewport.Height;
3997 TRACE("Calling glOrtho with x %.8e, y %.8e, w %.8e, h %.8e.\n", x, y, w, h);
3998 if (context->render_offscreen)
3999 glOrtho(x, x + w, -y, -y - h, 0.0, -1.0);
4000 else
4001 glOrtho(x, x + w, y + h, y, 0.0, -1.0);
4002 checkGLcall("glOrtho");
4004 /* D3D texture coordinates are flipped compared to OpenGL ones, so
4005 * render everything upside down when rendering offscreen. */
4006 if (context->render_offscreen)
4008 glScalef(1.0f, -1.0f, 1.0f);
4009 checkGLcall("glScalef");
4012 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
4013 glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f);
4014 checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)");
4016 else
4018 /* The rule is that the window coordinate 0 does not correspond to the
4019 beginning of the first pixel, but the center of the first pixel.
4020 As a consequence if you want to correctly draw one line exactly from
4021 the left to the right end of the viewport (with all matrices set to
4022 be identity), the x coords of both ends of the line would be not
4023 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
4024 instead.
4026 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
4027 divide by the Width/Height, so we need the half range(1.0) to translate by
4028 half a pixel.
4030 The other fun is that d3d's output z range after the transformation is [0;1],
4031 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
4032 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
4033 of Z buffer precision and the clear values do not match in the z test. Thus scale
4034 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
4038 * Careful with the order of operations here, we're essentially working backwards:
4039 * x = x + 1/w;
4040 * y = (y - 1/h) * flip;
4041 * z = z * 2 - 1;
4043 * Becomes:
4044 * glTranslatef(0.0, 0.0, -1.0);
4045 * glScalef(1.0, 1.0, 2.0);
4047 * glScalef(1.0, flip, 1.0);
4048 * glTranslatef(1/w, -1/h, 0.0);
4050 * This is equivalent to:
4051 * glTranslatef(1/w, -flip/h, -1.0)
4052 * glScalef(1.0, flip, 2.0);
4055 /* Translate by slightly less than a half pixel to force a top-left
4056 * filling convention. We want the difference to be large enough that
4057 * it doesn't get lost due to rounding inside the driver, but small
4058 * enough to prevent it from interfering with any anti-aliasing. */
4059 GLfloat xoffset = (63.0f / 64.0f) / stateblock->state.viewport.Width;
4060 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->state.viewport.Height;
4062 if (context->render_offscreen)
4064 /* D3D texture coordinates are flipped compared to OpenGL ones, so
4065 * render everything upside down when rendering offscreen. */
4066 glTranslatef(xoffset, -yoffset, -1.0f);
4067 checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)");
4068 glScalef(1.0f, -1.0f, 2.0f);
4069 } else {
4070 glTranslatef(xoffset, yoffset, -1.0f);
4071 checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)");
4072 glScalef(1.0f, 1.0f, 2.0f);
4074 checkGLcall("glScalef");
4076 glMultMatrixf(&stateblock->state.transforms[WINED3DTS_PROJECTION].u.m[0][0]);
4077 checkGLcall("glLoadMatrixf");
4081 /* This should match any arrays loaded in loadVertexData.
4082 * TODO: Only load / unload arrays if we have to.
4084 static inline void unloadVertexData(const struct wined3d_gl_info *gl_info)
4086 glDisableClientState(GL_VERTEX_ARRAY);
4087 glDisableClientState(GL_NORMAL_ARRAY);
4088 glDisableClientState(GL_COLOR_ARRAY);
4089 if (gl_info->supported[EXT_SECONDARY_COLOR])
4091 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4093 if (gl_info->supported[ARB_VERTEX_BLEND])
4095 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
4097 unloadTexCoords(gl_info);
4100 static inline void unload_numbered_array(struct wined3d_context *context, int i)
4102 const struct wined3d_gl_info *gl_info = context->gl_info;
4104 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
4105 checkGLcall("glDisableVertexAttribArrayARB(reg)");
4107 context->numbered_array_mask &= ~(1 << i);
4110 /* This should match any arrays loaded in loadNumberedArrays
4111 * TODO: Only load / unload arrays if we have to.
4113 static inline void unloadNumberedArrays(struct wined3d_context *context)
4115 /* disable any attribs (this is the same for both GLSL and ARB modes) */
4116 GLint maxAttribs = 16;
4117 int i;
4119 /* Leave all the attribs disabled */
4120 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
4121 /* MESA does not support it right not */
4122 if (glGetError() != GL_NO_ERROR)
4123 maxAttribs = 16;
4124 for (i = 0; i < maxAttribs; ++i) {
4125 unload_numbered_array(context, i);
4129 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
4130 const struct wined3d_stream_info *stream_info, struct wined3d_context *context)
4132 const struct wined3d_gl_info *gl_info = context->gl_info;
4133 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
4134 int i;
4135 struct wined3d_buffer *vb;
4136 DWORD_PTR shift_index;
4138 /* Default to no instancing */
4139 stateblock->device->instancedDraw = FALSE;
4141 for (i = 0; i < MAX_ATTRIBS; i++)
4143 const struct wined3d_stream_state *stream;
4145 if (!(stream_info->use_map & (1 << i)))
4147 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
4148 continue;
4151 stream = &stateblock->state.streams[stream_info->elements[i].stream_idx];
4153 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
4154 if (stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
4156 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
4157 stateblock->device->instancedDraw = TRUE;
4158 continue;
4161 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
4163 if (stream_info->elements[i].stride)
4165 if (curVBO != stream_info->elements[i].buffer_object)
4167 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
4168 checkGLcall("glBindBufferARB");
4169 curVBO = stream_info->elements[i].buffer_object;
4171 /* Use the VBO to find out if a vertex buffer exists, not the vb
4172 * pointer. vb can point to a user pointer data blob. In that case
4173 * curVBO will be 0. If there is a vertex buffer but no vbo we
4174 * won't be load converted attributes anyway. */
4175 vb = stream->buffer;
4176 if (curVBO && vb->conversion_shift)
4178 TRACE("Loading attribute from shifted buffer\n");
4179 TRACE("Attrib %d has original stride %d, new stride %d\n",
4180 i, stream_info->elements[i].stride, vb->conversion_stride);
4181 TRACE("Original offset %p, additional offset 0x%08x\n",
4182 stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
4183 TRACE("Opengl type %#x\n", stream_info->elements[i].format->gl_vtx_type);
4184 shift_index = ((DWORD_PTR)stream_info->elements[i].data + stream->offset);
4185 shift_index = shift_index % stream_info->elements[i].stride;
4186 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format->gl_vtx_format,
4187 stream_info->elements[i].format->gl_vtx_type,
4188 stream_info->elements[i].format->gl_normalized,
4189 vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
4190 + stateblock->state.load_base_vertex_index * stream_info->elements[i].stride
4191 + stream->offset));
4193 } else {
4194 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format->gl_vtx_format,
4195 stream_info->elements[i].format->gl_vtx_type,
4196 stream_info->elements[i].format->gl_normalized,
4197 stream_info->elements[i].stride, stream_info->elements[i].data
4198 + stateblock->state.load_base_vertex_index * stream_info->elements[i].stride
4199 + stream->offset));
4202 if (!(context->numbered_array_mask & (1 << i)))
4204 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
4205 context->numbered_array_mask |= (1 << i);
4208 else
4210 /* Stride = 0 means always the same values.
4211 * glVertexAttribPointerARB doesn't do that. Instead disable the
4212 * pointer and set up the attribute statically. But we have to
4213 * figure out the system memory address. */
4214 const BYTE *ptr = stream_info->elements[i].data + stream->offset;
4215 if (stream_info->elements[i].buffer_object)
4217 vb = stream->buffer;
4218 ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info);
4221 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
4223 switch (stream_info->elements[i].format->id)
4225 case WINED3DFMT_R32_FLOAT:
4226 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
4227 break;
4228 case WINED3DFMT_R32G32_FLOAT:
4229 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
4230 break;
4231 case WINED3DFMT_R32G32B32_FLOAT:
4232 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
4233 break;
4234 case WINED3DFMT_R32G32B32A32_FLOAT:
4235 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
4236 break;
4238 case WINED3DFMT_R8G8B8A8_UINT:
4239 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4240 break;
4241 case WINED3DFMT_B8G8R8A8_UNORM:
4242 if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
4244 const DWORD *src = (const DWORD *)ptr;
4245 DWORD c = *src & 0xff00ff00;
4246 c |= (*src & 0xff0000) >> 16;
4247 c |= (*src & 0xff) << 16;
4248 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
4249 break;
4251 /* else fallthrough */
4252 case WINED3DFMT_R8G8B8A8_UNORM:
4253 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
4254 break;
4256 case WINED3DFMT_R16G16_SINT:
4257 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4258 break;
4259 case WINED3DFMT_R16G16B16A16_SINT:
4260 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
4261 break;
4263 case WINED3DFMT_R16G16_SNORM:
4265 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4266 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4267 break;
4269 case WINED3DFMT_R16G16_UNORM:
4271 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4272 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4273 break;
4275 case WINED3DFMT_R16G16B16A16_SNORM:
4276 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4277 break;
4278 case WINED3DFMT_R16G16B16A16_UNORM:
4279 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4280 break;
4282 case WINED3DFMT_R10G10B10A2_UINT:
4283 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4284 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4285 break;
4286 case WINED3DFMT_R10G10B10A2_SNORM:
4287 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4288 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4289 break;
4291 case WINED3DFMT_R16G16_FLOAT:
4292 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4293 * byte float according to the IEEE standard
4295 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4296 break;
4297 case WINED3DFMT_R16G16B16A16_FLOAT:
4298 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4299 break;
4301 default:
4302 ERR("Unexpected declaration in stride 0 attributes\n");
4303 break;
4308 checkGLcall("Loading numbered arrays");
4311 /* Used from 2 different functions, and too big to justify making it inlined */
4312 static void loadVertexData(const struct wined3d_context *context, IWineD3DStateBlockImpl *stateblock,
4313 const struct wined3d_stream_info *si)
4315 const struct wined3d_gl_info *gl_info = context->gl_info;
4316 GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
4317 const struct wined3d_stream_info_element *e;
4318 const struct wined3d_stream_state *stream;
4320 TRACE("Using fast vertex array code\n");
4322 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4323 stateblock->device->instancedDraw = FALSE;
4325 /* Blend Data ---------------------------------------------- */
4326 if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
4327 || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4329 e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4330 stream = &stateblock->state.streams[e->stream_idx];
4332 if (gl_info->supported[ARB_VERTEX_BLEND])
4334 TRACE("Blend %u %p %u\n", e->format->component_count,
4335 e->data + stateblock->state.load_base_vertex_index * e->stride, e->stride + stream->offset);
4337 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4338 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4340 GL_EXTCALL(glVertexBlendARB(e->format->component_count + 1));
4342 if (curVBO != e->buffer_object)
4344 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4345 checkGLcall("glBindBufferARB");
4346 curVBO = e->buffer_object;
4349 TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n",
4350 e->format->gl_vtx_format,
4351 e->format->gl_vtx_type,
4352 e->stride,
4353 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4354 GL_EXTCALL(glWeightPointerARB(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
4355 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset));
4357 checkGLcall("glWeightPointerARB");
4359 if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
4361 static BOOL warned;
4362 if (!warned)
4364 FIXME("blendMatrixIndices support\n");
4365 warned = TRUE;
4368 } else {
4369 /* TODO: support blends in drawStridedSlow
4370 * No need to write a FIXME here, this is done after the general vertex decl decoding
4372 WARN("unsupported blending in openGl\n");
4375 else
4377 if (gl_info->supported[ARB_VERTEX_BLEND])
4379 static const GLbyte one = 1;
4380 GL_EXTCALL(glWeightbvARB(1, &one));
4381 checkGLcall("glWeightivARB(gl_info->max_blends, weights)");
4385 /* Point Size ----------------------------------------------*/
4386 if (si->use_map & (1 << WINED3D_FFP_PSIZE))
4388 /* no such functionality in the fixed function GL pipeline */
4389 TRACE("Cannot change ptSize here in openGl\n");
4390 /* TODO: Implement this function in using shaders if they are available */
4393 /* Vertex Pointers -----------------------------------------*/
4394 if (si->use_map & (1 << WINED3D_FFP_POSITION))
4396 e = &si->elements[WINED3D_FFP_POSITION];
4397 stream = &stateblock->state.streams[e->stream_idx];
4399 if (curVBO != e->buffer_object)
4401 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4402 checkGLcall("glBindBufferARB");
4403 curVBO = e->buffer_object;
4406 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4407 handling for rhw mode should not impact screen position whereas in GL it does.
4408 This may result in very slightly distorted textures in rhw mode.
4409 There's always the other option of fixing the view matrix to
4410 prevent w from having any effect.
4412 This only applies to user pointer sources, in VBOs the vertices are fixed up
4414 if (!e->buffer_object)
4416 TRACE("glVertexPointer(3, %#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride,
4417 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4418 glVertexPointer(3 /* min(e->format->gl_vtx_format, 3) */, e->format->gl_vtx_type, e->stride,
4419 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4421 else
4423 TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n",
4424 e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
4425 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4426 glVertexPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
4427 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4429 checkGLcall("glVertexPointer(...)");
4430 glEnableClientState(GL_VERTEX_ARRAY);
4431 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4434 /* Normals -------------------------------------------------*/
4435 if (si->use_map & (1 << WINED3D_FFP_NORMAL))
4437 e = &si->elements[WINED3D_FFP_NORMAL];
4438 stream = &stateblock->state.streams[e->stream_idx];
4440 if (curVBO != e->buffer_object)
4442 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4443 checkGLcall("glBindBufferARB");
4444 curVBO = e->buffer_object;
4447 TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride,
4448 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4449 glNormalPointer(e->format->gl_vtx_type, e->stride,
4450 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4451 checkGLcall("glNormalPointer(...)");
4452 glEnableClientState(GL_NORMAL_ARRAY);
4453 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4455 } else {
4456 glNormal3f(0, 0, 0);
4457 checkGLcall("glNormal3f(0, 0, 0)");
4460 /* Diffuse Colour --------------------------------------------*/
4461 /* WARNING: Data here MUST be in RGBA format, so cannot */
4462 /* go directly into fast mode from app pgm, because */
4463 /* directx requires data in BGRA format. */
4464 /* currently fixupVertices swizzles the format, but this isn't*/
4465 /* very practical when using VBOs */
4466 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4467 /* , or the user doesn't care and wants the speed advantage */
4469 if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
4471 e = &si->elements[WINED3D_FFP_DIFFUSE];
4472 stream = &stateblock->state.streams[e->stream_idx];
4474 if (curVBO != e->buffer_object)
4476 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4477 checkGLcall("glBindBufferARB");
4478 curVBO = e->buffer_object;
4481 TRACE("glColorPointer(%#x, %#x %#x, %p);\n",
4482 e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
4483 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4484 glColorPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
4485 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4486 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4487 glEnableClientState(GL_COLOR_ARRAY);
4488 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4490 } else {
4491 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4492 checkGLcall("glColor4f(1, 1, 1, 1)");
4495 /* Specular Colour ------------------------------------------*/
4496 if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
4498 TRACE("setting specular colour\n");
4500 e = &si->elements[WINED3D_FFP_SPECULAR];
4501 stream = &stateblock->state.streams[e->stream_idx];
4503 if (gl_info->supported[EXT_SECONDARY_COLOR])
4505 GLenum type = e->format->gl_vtx_type;
4506 GLint format = e->format->gl_vtx_format;
4508 if (curVBO != e->buffer_object)
4510 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4511 checkGLcall("glBindBufferARB");
4512 curVBO = e->buffer_object;
4515 if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
4517 /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
4518 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
4519 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
4520 * 4 component secondary colors use it
4522 TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride,
4523 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4524 GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride,
4525 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset));
4526 checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
4528 else
4530 switch(type)
4532 case GL_UNSIGNED_BYTE:
4533 TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride,
4534 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4535 GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride,
4536 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset));
4537 checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
4538 break;
4540 default:
4541 FIXME("Add 4 component specular color pointers for type %x\n", type);
4542 /* Make sure that the right color component is dropped */
4543 TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride,
4544 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset);
4545 GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride,
4546 e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset));
4547 checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
4550 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4551 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4553 else
4555 WARN("Specular colour is not supported in this GL implementation.\n");
4558 else
4560 if (gl_info->supported[EXT_SECONDARY_COLOR])
4562 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4563 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4565 else
4567 WARN("Specular colour is not supported in this GL implementation.\n");
4571 /* Texture coords -------------------------------------------*/
4572 loadTexCoords(gl_info, stateblock, si, &curVBO);
4575 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4577 IWineD3DDeviceImpl *device = stateblock->device;
4578 BOOL load_numbered = use_vs(stateblock) && !device->useDrawStridedSlow;
4579 BOOL load_named = !use_vs(stateblock) && !device->useDrawStridedSlow;
4581 if (context->numberedArraysLoaded && !load_numbered)
4583 unloadNumberedArrays(context);
4584 context->numberedArraysLoaded = FALSE;
4585 context->numbered_array_mask = 0;
4587 else if (context->namedArraysLoaded)
4589 unloadVertexData(context->gl_info);
4590 context->namedArraysLoaded = FALSE;
4593 if (load_numbered)
4595 TRACE("Loading numbered arrays\n");
4596 loadNumberedArrays(stateblock, &device->strided_streams, context);
4597 context->numberedArraysLoaded = TRUE;
4599 else if (load_named)
4601 TRACE("Loading vertex data\n");
4602 loadVertexData(context, stateblock, &device->strided_streams);
4603 context->namedArraysLoaded = TRUE;
4607 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4609 const struct wined3d_gl_info *gl_info = context->gl_info;
4610 BOOL updateFog = FALSE;
4611 BOOL useVertexShaderFunction = use_vs(stateblock);
4612 BOOL usePixelShaderFunction = use_ps(stateblock);
4613 IWineD3DDeviceImpl *device = stateblock->device;
4614 BOOL transformed;
4615 BOOL wasrhw = context->last_was_rhw;
4616 unsigned int i;
4618 transformed = device->strided_streams.position_transformed;
4619 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4620 updateFog = TRUE;
4623 /* Reapply lighting if it is not scheduled for reapplication already */
4624 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4625 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4628 if (transformed) {
4629 context->last_was_rhw = TRUE;
4630 } else {
4632 /* Untransformed, so relies on the view and projection matrices */
4633 context->last_was_rhw = FALSE;
4634 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4635 device->untransformed = TRUE;
4637 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4638 * Not needed as long as only hw shaders are supported
4641 /* This sets the shader output position correction constants.
4642 * TODO: Move to the viewport state
4644 if (useVertexShaderFunction)
4646 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->state.viewport.Height;
4647 device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f;
4648 device->posFixup[3] = device->posFixup[1] * yoffset;
4652 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4653 * off this function will be called again anyway to make sure they're properly set
4655 if(!useVertexShaderFunction) {
4656 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4657 * or transformed / untransformed was switched
4659 if(wasrhw != context->last_was_rhw &&
4660 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4661 !isStateDirty(context, STATE_VIEWPORT)) {
4662 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4664 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4665 * mode.
4667 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4668 * this check will fail and the matrix not applied again. This is OK because a simple
4669 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4670 * needs of the vertex declaration.
4672 * World and view matrix go into the same gl matrix, so only apply them when neither is
4673 * dirty
4675 if(transformed != wasrhw &&
4676 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4677 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4678 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4681 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4682 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4685 if(context->last_was_vshader) {
4686 updateFog = TRUE;
4687 if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4688 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4690 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4692 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4695 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4696 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4698 } else {
4699 if(!context->last_was_vshader) {
4700 static BOOL warned = FALSE;
4701 if(!device->vs_clipping) {
4702 /* Disable all clip planes to get defined results on all drivers. See comment in the
4703 * state_clipping state handler
4705 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4707 glDisable(GL_CLIP_PLANE0 + i);
4708 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4711 if (!warned && stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE])
4713 FIXME("Clipping not supported with vertex shaders\n");
4714 warned = TRUE;
4717 if(wasrhw) {
4718 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4719 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4720 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4721 * fixed function vertex processing states back in a sane state before switching to shaders
4723 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4724 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4726 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4727 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4730 updateFog = TRUE;
4732 /* Vertex shader clipping ignores the view matrix. Update all clipplanes
4733 * (Note: ARB shaders can read the clip planes for clipping emulation even if
4734 * device->vs_clipping is false.
4736 for (i = 0; i < gl_info->limits.clipplanes; ++i)
4738 clipplane(STATE_CLIPPLANE(i), stateblock, context);
4743 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4744 * application
4746 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4747 device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction);
4749 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4750 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4754 context->last_was_vshader = useVertexShaderFunction;
4756 if (updateFog) stateblock_apply_state(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4758 if(!useVertexShaderFunction) {
4759 int i;
4760 for(i = 0; i < MAX_TEXTURES; i++) {
4761 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4762 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4768 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4770 IWineD3DSurfaceImpl *target = stateblock->device->render_targets[0];
4771 UINT width, height;
4772 WINED3DVIEWPORT vp = stateblock->state.viewport;
4774 if(vp.Width > target->currentDesc.Width) vp.Width = target->currentDesc.Width;
4775 if(vp.Height > target->currentDesc.Height) vp.Height = target->currentDesc.Height;
4777 glDepthRange(vp.MinZ, vp.MaxZ);
4778 checkGLcall("glDepthRange");
4779 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4781 if (context->render_offscreen)
4783 glViewport(vp.X, vp.Y, vp.Width, vp.Height);
4784 } else {
4785 target->get_drawable_size(context, &width, &height);
4787 glViewport(vp.X,
4788 (height - (vp.Y + vp.Height)),
4789 vp.Width, vp.Height);
4792 checkGLcall("glViewport");
4795 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4797 GLfloat yoffset = -(63.0f / 64.0f) / stateblock->state.viewport.Height;
4799 stateblock->device->posFixup[2] = (63.0f / 64.0f) / stateblock->state.viewport.Width;
4800 stateblock->device->posFixup[3] = stateblock->device->posFixup[1] * yoffset;
4802 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4803 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4805 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4806 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4808 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT))
4809 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4812 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4814 UINT Index = state - STATE_ACTIVELIGHT(0);
4815 const struct wined3d_light_info *lightInfo = stateblock->activeLights[Index];
4817 if(!lightInfo) {
4818 glDisable(GL_LIGHT0 + Index);
4819 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4820 } else {
4821 float quad_att;
4822 float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
4824 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4825 glMatrixMode(GL_MODELVIEW);
4826 glPushMatrix();
4827 glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]);
4829 /* Diffuse: */
4830 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4831 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4832 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4833 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4834 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4835 checkGLcall("glLightfv");
4837 /* Specular */
4838 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4839 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4840 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4841 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4842 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4843 checkGLcall("glLightfv");
4845 /* Ambient */
4846 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4847 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4848 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4849 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4850 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4851 checkGLcall("glLightfv");
4853 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4854 quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4855 } else {
4856 quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */
4859 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4860 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4861 * Attenuation0 to NaN and crashes in the gl lib
4864 switch (lightInfo->OriginalParms.Type) {
4865 case WINED3DLIGHT_POINT:
4866 /* Position */
4867 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4868 checkGLcall("glLightfv");
4869 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4870 checkGLcall("glLightf");
4871 /* Attenuation - Are these right? guessing... */
4872 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4873 checkGLcall("glLightf");
4874 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4875 checkGLcall("glLightf");
4876 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4877 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4878 checkGLcall("glLightf");
4879 /* FIXME: Range */
4880 break;
4882 case WINED3DLIGHT_SPOT:
4883 /* Position */
4884 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4885 checkGLcall("glLightfv");
4886 /* Direction */
4887 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4888 checkGLcall("glLightfv");
4889 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4890 checkGLcall("glLightf");
4891 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4892 checkGLcall("glLightf");
4893 /* Attenuation - Are these right? guessing... */
4894 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4895 checkGLcall("glLightf");
4896 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4897 checkGLcall("glLightf");
4898 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4899 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4900 checkGLcall("glLightf");
4901 /* FIXME: Range */
4902 break;
4904 case WINED3DLIGHT_DIRECTIONAL:
4905 /* Direction */
4906 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4907 checkGLcall("glLightfv");
4908 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4909 checkGLcall("glLightf");
4910 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4911 checkGLcall("glLightf");
4912 break;
4914 default:
4915 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4918 /* Restore the modelview matrix */
4919 glPopMatrix();
4921 glEnable(GL_LIGHT0 + Index);
4922 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4926 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4928 IWineD3DSurfaceImpl *target = stateblock->device->render_targets[0];
4929 RECT *pRect = &stateblock->state.scissor_rect;
4930 UINT height;
4931 UINT width;
4933 target->get_drawable_size(context, &width, &height);
4934 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4935 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4937 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->device, pRect->left, pRect->bottom - height,
4938 pRect->right - pRect->left, pRect->bottom - pRect->top);
4940 if (context->render_offscreen)
4942 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4943 } else {
4944 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4946 checkGLcall("glScissor");
4949 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4951 const struct wined3d_gl_info *gl_info = context->gl_info;
4953 if (stateblock->state.user_stream || !stateblock->state.index_buffer)
4955 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4957 else
4959 struct wined3d_buffer *ib = stateblock->state.index_buffer;
4960 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4964 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
4966 if (context->render_offscreen)
4968 glFrontFace(GL_CCW);
4969 checkGLcall("glFrontFace(GL_CCW)");
4970 } else {
4971 glFrontFace(GL_CW);
4972 checkGLcall("glFrontFace(GL_CW)");
4976 const struct StateEntryTemplate misc_state_template[] = {
4977 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4978 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4979 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
4980 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4981 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4982 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4983 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4984 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4985 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4986 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
4987 { STATE_STREAMSRC, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE },
4988 { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE },
4989 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
4990 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
4991 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4992 * vshader loadings are untied from each other
4994 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE },
4995 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, NULL }, WINED3D_GL_EXT_NONE },
4996 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
4997 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
4998 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
4999 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5000 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5001 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5002 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5003 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5004 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5005 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5006 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5007 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5008 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5009 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5010 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5011 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5012 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5013 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5014 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5015 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5016 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5017 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5018 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5019 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5020 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5021 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5022 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5023 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5024 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE },
5025 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5026 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5027 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE },
5028 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5029 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5030 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5031 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5032 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5033 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5034 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5035 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5036 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5037 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5038 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5039 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5040 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5041 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5042 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE },
5043 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE },
5045 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
5046 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
5047 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, state_nop }, WINED3D_GL_EXT_NONE },
5048 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE },
5049 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE },
5050 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE },
5051 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE },
5052 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE },
5053 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE },
5054 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE },
5055 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE },
5056 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE },
5057 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE },
5058 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE },
5059 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE },
5060 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE },
5061 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
5062 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
5063 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
5064 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE },
5065 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE },
5066 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE },
5067 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE },
5068 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE },
5069 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE },
5070 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE },
5071 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, WINED3D_GL_EXT_NONE },
5072 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE },
5073 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE },
5074 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE },
5075 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE },
5076 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE },
5077 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE },
5078 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5079 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5080 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5081 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5082 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5083 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5084 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
5085 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE },
5086 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5087 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5088 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5089 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5090 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE },
5091 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE },
5092 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5093 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5094 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5095 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5096 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5097 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5098 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5099 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5100 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5101 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5102 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5103 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5104 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5105 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5106 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE },
5107 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE },
5108 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE },
5109 { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE },
5110 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE },
5111 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE },
5112 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE },
5113 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE },
5114 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5115 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5116 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5117 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5118 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5119 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE },
5120 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_nvdb }, EXT_DEPTH_BOUNDS_TEST },
5121 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE },
5122 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
5123 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE },
5124 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE },
5125 { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE },
5126 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite0 }, EXT_DRAW_BUFFERS2 },
5127 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE },
5128 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
5129 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE },
5130 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE },
5131 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), NULL }, WINED3D_GL_EXT_NONE },
5132 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), state_colorwrite1 }, EXT_DRAW_BUFFERS2 },
5133 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5134 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), state_colorwrite2 }, EXT_DRAW_BUFFERS2 },
5135 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5136 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), state_colorwrite3 }, EXT_DRAW_BUFFERS2 },
5137 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5138 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
5139 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE },
5140 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE },
5141 { STATE_RENDER(WINED3DRS_ZVISIBLE), { STATE_RENDER(WINED3DRS_ZVISIBLE), state_zvisible }, WINED3D_GL_EXT_NONE },
5142 /* Samplers */
5143 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE },
5144 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE },
5145 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE },
5146 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE },
5147 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE },
5148 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE },
5149 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE },
5150 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE },
5151 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE },
5152 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE },
5153 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE },
5154 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE },
5155 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE },
5156 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE },
5157 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE },
5158 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE },
5159 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE },
5160 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE },
5161 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE },
5162 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
5163 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5166 const struct StateEntryTemplate ffp_vertexstate_template[] = {
5167 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE },
5168 { STATE_VSHADER, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE },
5169 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE },
5170 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE },
5171 /* Clip planes */
5172 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE },
5173 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE },
5174 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE },
5175 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE },
5176 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE },
5177 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE },
5178 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE },
5179 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE },
5180 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE },
5181 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE },
5182 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE },
5183 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE },
5184 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE },
5185 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE },
5186 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE },
5187 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE },
5188 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE },
5189 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE },
5190 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE },
5191 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE },
5192 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE },
5193 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE },
5194 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE },
5195 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE },
5196 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE },
5197 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE },
5198 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE },
5199 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE },
5200 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE },
5201 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE },
5202 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE },
5203 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE },
5204 /* Lights */
5205 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE },
5206 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE },
5207 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE },
5208 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE },
5209 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE },
5210 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE },
5211 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE },
5212 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE },
5213 /* Viewport */
5214 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE },
5215 /* Transform states follow */
5216 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE },
5217 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE },
5218 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5219 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5220 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5221 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5222 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5223 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5224 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5225 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE },
5226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE },
5227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE },
5228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE },
5229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE },
5230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE },
5231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE },
5232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE },
5233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE },
5234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE },
5235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE },
5236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE },
5237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE },
5238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE },
5239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE },
5240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE },
5241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE },
5242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE },
5243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE },
5244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE },
5245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE },
5246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE },
5247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE },
5248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE },
5249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE },
5250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE },
5251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE },
5252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE },
5253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE },
5254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE },
5255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE },
5256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE },
5257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE },
5258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE },
5259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE },
5260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE },
5261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE },
5262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE },
5263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE },
5264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE },
5265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE },
5266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE },
5267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE },
5268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE },
5269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE },
5270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE },
5271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE },
5272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE },
5273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE },
5274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE },
5275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE },
5276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE },
5277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE },
5278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE },
5279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE },
5280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE },
5281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE },
5282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE },
5283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE },
5284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE },
5285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE },
5286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE },
5287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE },
5288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE },
5289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE },
5290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE },
5291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE },
5292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE },
5293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE },
5294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE },
5295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE },
5296 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE },
5297 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE },
5298 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE },
5299 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE },
5300 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE },
5301 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE },
5302 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE },
5303 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE },
5304 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE },
5305 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE },
5306 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE },
5307 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE },
5308 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE },
5309 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE },
5310 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE },
5311 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE },
5312 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE },
5313 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE },
5314 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE },
5315 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE },
5316 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE },
5317 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE },
5318 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE },
5319 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE },
5320 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE },
5321 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE },
5322 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE },
5323 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE },
5324 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE },
5325 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE },
5326 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE },
5327 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE },
5328 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE },
5329 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE },
5330 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE },
5331 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE },
5332 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE },
5333 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE },
5334 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE },
5335 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE },
5336 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE },
5337 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE },
5338 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE },
5339 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE },
5340 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE },
5341 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE },
5342 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE },
5343 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE },
5344 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE },
5345 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE },
5346 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE },
5347 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE },
5348 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE },
5349 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE },
5350 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE },
5351 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE },
5352 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE },
5353 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE },
5354 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE },
5355 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE },
5356 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE },
5357 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE },
5358 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE },
5359 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE },
5360 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE },
5361 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE },
5362 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE },
5363 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE },
5364 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE },
5365 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE },
5366 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE },
5367 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE },
5368 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE },
5369 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE },
5370 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE },
5371 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE },
5372 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE },
5373 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE },
5374 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE },
5375 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE },
5376 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE },
5377 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE },
5378 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE },
5379 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE },
5380 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE },
5381 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE },
5382 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE },
5383 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE },
5384 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE },
5385 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE },
5386 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE },
5387 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE },
5388 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE },
5389 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE },
5390 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE },
5391 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE },
5392 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE },
5393 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE },
5394 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE },
5395 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE },
5396 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE },
5397 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE },
5398 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE },
5399 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE },
5400 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE },
5401 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE },
5402 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE },
5403 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE },
5404 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE },
5405 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE },
5406 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE },
5407 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE },
5408 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE },
5409 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE },
5410 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE },
5411 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE },
5412 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE },
5413 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE },
5414 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE },
5415 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE },
5416 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE },
5417 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE },
5418 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE },
5419 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE },
5420 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE },
5421 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE },
5422 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE },
5423 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE },
5424 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE },
5425 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE },
5426 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE },
5427 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE },
5428 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE },
5429 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE },
5430 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE },
5431 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE },
5432 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE },
5433 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE },
5434 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE },
5435 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE },
5436 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE },
5437 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE },
5438 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE },
5439 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE },
5440 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE },
5441 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE },
5442 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE },
5443 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE },
5444 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE },
5445 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE },
5446 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE },
5447 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE },
5448 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE },
5449 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE },
5450 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE },
5451 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE },
5452 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE },
5453 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE },
5454 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE },
5455 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE },
5456 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE },
5457 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE },
5458 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE },
5459 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE },
5460 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE },
5461 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE },
5462 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE },
5463 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE },
5464 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE },
5465 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE },
5466 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE },
5467 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE },
5468 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE },
5469 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE },
5470 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE },
5471 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE },
5472 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE },
5473 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE },
5474 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE },
5475 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE },
5476 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE },
5477 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE },
5478 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE },
5479 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE },
5480 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE },
5481 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE },
5482 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5483 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5484 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5485 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5486 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5487 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5488 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5489 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE },
5490 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5491 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5492 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5493 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5494 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5495 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5496 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5497 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE },
5498 /* Fog */
5499 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE },
5500 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
5501 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
5502 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5503 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE },
5504 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE },
5505 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE },
5506 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE },
5507 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE },
5508 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE },
5509 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE },
5510 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE },
5511 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE },
5512 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE },
5513 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE },
5514 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE },
5515 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5516 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE },
5517 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5518 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5519 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5520 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE },
5521 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5522 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE },
5523 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE },
5524 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5525 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5526 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE },
5527 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, ARB_POINT_PARAMETERS },
5528 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, EXT_POINT_PARAMETERS },
5529 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE },
5530 { STATE_RENDER(WINED3DRS_TWEENFACTOR), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE },
5531 { STATE_RENDER(WINED3DRS_INDEXEDVERTEXBLENDENABLE), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE },
5533 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5534 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5535 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5537 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5538 { STATE_SAMPLER(0), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5539 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5540 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5541 { STATE_SAMPLER(1), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5542 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5543 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5544 { STATE_SAMPLER(2), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5545 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5546 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5547 { STATE_SAMPLER(3), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5548 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5549 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5550 { STATE_SAMPLER(4), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5551 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5552 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5553 { STATE_SAMPLER(5), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5554 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5555 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5556 { STATE_SAMPLER(6), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5557 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5558 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5559 { STATE_SAMPLER(7), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT },
5560 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE },
5561 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5564 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5565 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5566 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5567 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5568 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5569 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5570 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5571 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5572 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5573 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5574 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5575 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5576 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5577 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5578 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5579 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5580 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5581 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5582 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5583 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5584 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5585 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5586 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5587 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5588 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5589 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5590 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5591 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5592 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5593 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5594 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5595 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5596 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5597 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5598 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5599 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5600 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5601 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5602 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5603 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5604 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5605 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5606 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5607 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5608 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5609 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5610 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5611 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5612 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5613 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5614 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5615 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5616 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5617 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5618 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5619 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5620 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5621 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5622 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5623 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5624 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5625 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5626 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5627 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5628 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5629 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5630 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5631 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5632 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5633 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5634 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5635 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE },
5636 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5637 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5638 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE },
5639 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5640 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5641 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5642 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE },
5643 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE },
5644 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE },
5645 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE },
5646 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE },
5647 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE },
5648 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE },
5649 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE },
5650 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE },
5651 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
5652 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE },
5653 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE },
5654 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE },
5655 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE },
5656 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE },
5657 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE },
5658 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE },
5659 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE },
5660 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE },
5661 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE },
5662 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE },
5663 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
5666 /* Context activation is done by the caller. */
5667 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5669 static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *pCaps)
5671 pCaps->PrimitiveMiscCaps = 0;
5672 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5673 WINED3DTEXOPCAPS_ADDSIGNED |
5674 WINED3DTEXOPCAPS_ADDSIGNED2X |
5675 WINED3DTEXOPCAPS_MODULATE |
5676 WINED3DTEXOPCAPS_MODULATE2X |
5677 WINED3DTEXOPCAPS_MODULATE4X |
5678 WINED3DTEXOPCAPS_SELECTARG1 |
5679 WINED3DTEXOPCAPS_SELECTARG2 |
5680 WINED3DTEXOPCAPS_DISABLE;
5682 if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE]
5683 || gl_info->supported[EXT_TEXTURE_ENV_COMBINE]
5684 || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
5686 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5687 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5688 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5689 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5690 WINED3DTEXOPCAPS_LERP |
5691 WINED3DTEXOPCAPS_SUBTRACT;
5693 if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]
5694 || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
5696 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5697 WINED3DTEXOPCAPS_MULTIPLYADD |
5698 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5699 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5700 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5702 if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
5703 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5705 pCaps->MaxTextureBlendStages = gl_info->limits.textures;
5706 pCaps->MaxSimultaneousTextures = gl_info->limits.textures;
5709 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5710 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5711 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5713 if (TRACE_ON(d3d))
5715 TRACE("Checking support for fixup:\n");
5716 dump_color_fixup_desc(fixup);
5719 /* We only support identity conversions. */
5720 if (is_identity_fixup(fixup))
5722 TRACE("[OK]\n");
5723 return TRUE;
5726 TRACE("[FAILED]\n");
5727 return FALSE;
5730 const struct fragment_pipeline ffp_fragment_pipeline = {
5731 ffp_enable,
5732 ffp_fragment_get_caps,
5733 ffp_fragment_alloc,
5734 ffp_fragment_free,
5735 ffp_color_fixup_supported,
5736 ffp_fragmentstate_template,
5737 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5740 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5742 unsigned int i;
5743 for(i = 0; funcs[i]; i++);
5744 return i;
5747 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5749 stateblock->device->multistate_funcs[state][0](state, stateblock, context);
5750 stateblock->device->multistate_funcs[state][1](state, stateblock, context);
5753 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5755 stateblock->device->multistate_funcs[state][0](state, stateblock, context);
5756 stateblock->device->multistate_funcs[state][1](state, stateblock, context);
5757 stateblock->device->multistate_funcs[state][2](state, stateblock, context);
5760 static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info)
5762 unsigned int start, last, i;
5764 start = STATE_TEXTURESTAGE(gl_info->limits.texture_stages, 0);
5765 last = STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE);
5766 for (i = start; i <= last; ++i)
5768 state_table[i].representative = 0;
5769 state_table[i].apply = state_undefined;
5772 start = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + gl_info->limits.texture_stages);
5773 last = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + MAX_TEXTURES - 1);
5774 for (i = start; i <= last; ++i)
5776 state_table[i].representative = 0;
5777 state_table[i].apply = state_undefined;
5780 start = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(gl_info->limits.blends));
5781 last = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255));
5782 for (i = start; i <= last; ++i)
5784 state_table[i].representative = 0;
5785 state_table[i].apply = state_undefined;
5789 static void validate_state_table(struct StateEntry *state_table)
5791 static const struct
5793 DWORD first;
5794 DWORD last;
5796 rs_holes[] =
5798 { 1, 1},
5799 { 3, 3},
5800 { 17, 18},
5801 { 21, 21},
5802 { 42, 45},
5803 { 61, 127},
5804 {149, 150},
5805 {169, 169},
5806 {177, 177},
5807 {196, 197},
5808 { 0, 0},
5810 static const DWORD simple_states[] =
5812 STATE_MATERIAL,
5813 STATE_VDECL,
5814 STATE_STREAMSRC,
5815 STATE_INDEXBUFFER,
5816 STATE_VERTEXSHADERCONSTANT,
5817 STATE_PIXELSHADERCONSTANT,
5818 STATE_VSHADER,
5819 STATE_PIXELSHADER,
5820 STATE_VIEWPORT,
5821 STATE_SCISSORRECT,
5822 STATE_FRONTFACE,
5824 unsigned int i, current;
5826 for (i = STATE_RENDER(1), current = 0; i <= STATE_RENDER(WINEHIGHEST_RENDER_STATE); ++i)
5828 if (!rs_holes[current].first || i < STATE_RENDER(rs_holes[current].first))
5830 if (!state_table[i].representative)
5831 ERR("State %s (%#x) should have a representative.\n", debug_d3dstate(i), i);
5833 else if (state_table[i].representative)
5834 ERR("State %s (%#x) shouldn't have a representative.\n", debug_d3dstate(i), i);
5836 if (i == STATE_RENDER(rs_holes[current].last)) ++current;
5839 for (i = 0; i < sizeof(simple_states) / sizeof(*simple_states); ++i)
5841 if (!state_table[simple_states[i]].representative)
5842 ERR("State %s (%#x) should have a representative.\n",
5843 debug_d3dstate(simple_states[i]), simple_states[i]);
5846 for (i = 0; i < STATE_HIGHEST + 1; ++i)
5848 DWORD rep = state_table[i].representative;
5849 if (rep)
5851 if (state_table[rep].representative != rep)
5853 ERR("State %s (%#x) has invalid representative %s (%#x).\n",
5854 debug_d3dstate(i), i, debug_d3dstate(rep), rep);
5855 state_table[i].representative = 0;
5858 if (rep != i)
5860 if (state_table[i].apply)
5861 ERR("State %s (%#x) has both a handler and representative.\n", debug_d3dstate(i), i);
5863 else if (!state_table[i].apply)
5865 ERR("Self representing state %s (%#x) has no handler.\n", debug_d3dstate(i), i);
5871 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5872 const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
5873 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5875 unsigned int i, type, handlers;
5876 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5877 const struct StateEntryTemplate *cur;
5878 BOOL set[STATE_HIGHEST + 1];
5880 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5882 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5883 StateTable[i].representative = 0;
5884 StateTable[i].apply = state_undefined;
5887 for(type = 0; type < 3; type++) {
5888 /* This switch decides the order in which the states are applied */
5889 switch(type) {
5890 case 0: cur = misc; break;
5891 case 1: cur = fragment->states; break;
5892 case 2: cur = vertex; break;
5893 default: cur = NULL; /* Stupid compiler */
5895 if(!cur) continue;
5897 /* GL extension filtering should not prevent multiple handlers being applied from different
5898 * pipeline parts
5900 memset(set, 0, sizeof(set));
5902 for(i = 0; cur[i].state; i++) {
5903 APPLYSTATEFUNC *funcs_array;
5905 /* Only use the first matching state with the available extension from one template.
5906 * e.g.
5907 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5908 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5910 * if GL_XYZ_fancy is supported, ignore the 2nd line
5912 if(set[cur[i].state]) continue;
5913 /* Skip state lines depending on unsupported extensions */
5914 if (!gl_info->supported[cur[i].extension]) continue;
5915 set[cur[i].state] = TRUE;
5916 /* In some cases having an extension means that nothing has to be
5917 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5918 * supported, the texture coordinate fixup can be ignored. If the
5919 * apply function is used, mark the state set(done above) to prevent
5920 * applying later lines, but do not record anything in the state
5921 * table
5923 if (!cur[i].content.representative) continue;
5925 handlers = num_handlers(multistate_funcs[cur[i].state]);
5926 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5927 switch(handlers) {
5928 case 0:
5929 StateTable[cur[i].state].apply = cur[i].content.apply;
5930 break;
5931 case 1:
5932 StateTable[cur[i].state].apply = multistate_apply_2;
5933 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5935 sizeof(**dev_multistate_funcs) * 2);
5936 if (!dev_multistate_funcs[cur[i].state]) {
5937 goto out_of_mem;
5940 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5941 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5942 break;
5943 case 2:
5944 StateTable[cur[i].state].apply = multistate_apply_3;
5945 funcs_array = HeapReAlloc(GetProcessHeap(),
5947 dev_multistate_funcs[cur[i].state],
5948 sizeof(**dev_multistate_funcs) * 3);
5949 if (!funcs_array) {
5950 goto out_of_mem;
5953 dev_multistate_funcs[cur[i].state] = funcs_array;
5954 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5955 break;
5956 default:
5957 ERR("Unexpected amount of state handlers for state %u: %u\n",
5958 cur[i].state, handlers + 1);
5961 if(StateTable[cur[i].state].representative &&
5962 StateTable[cur[i].state].representative != cur[i].content.representative) {
5963 FIXME("State %u has different representatives in different pipeline parts\n",
5964 cur[i].state);
5966 StateTable[cur[i].state].representative = cur[i].content.representative;
5970 prune_invalid_states(StateTable, gl_info);
5971 validate_state_table(StateTable);
5973 return WINED3D_OK;
5975 out_of_mem:
5976 for (i = 0; i <= STATE_HIGHEST; ++i) {
5977 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5980 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5982 return E_OUTOFMEMORY;