2 * Direct3D state management
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
39 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
45 if(STATE_IS_RENDER(state)) {
46 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
49 /* Shouldn't have an unknown type here */
50 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56 * list without causing confusing terminal output. Deliberately no special debug name here
57 * because its undefined.
59 WARN("undefined state %d\n", state);
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
66 case WINED3DFILL_POINT:
67 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
70 case WINED3DFILL_WIREFRAME:
71 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
74 case WINED3DFILL_SOLID:
75 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
96 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
97 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
98 stateblock->wineD3DDevice->strided_streams.position_transformed) ? TRUE : FALSE;
100 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
101 glEnable(GL_LIGHTING);
102 checkGLcall("glEnable GL_LIGHTING");
104 glDisable(GL_LIGHTING);
105 checkGLcall("glDisable GL_LIGHTING");
109 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
110 /* No z test without depth stencil buffers */
111 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
112 TRACE("No Z buffer - disabling depth test\n");
113 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
114 checkGLcall("glDisable GL_DEPTH_TEST");
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
138 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
141 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
142 case WINED3DCULL_NONE:
143 glDisable(GL_CULL_FACE);
144 checkGLcall("glDisable GL_CULL_FACE");
147 glEnable(GL_CULL_FACE);
148 checkGLcall("glEnable GL_CULL_FACE");
149 glCullFace(GL_FRONT);
150 checkGLcall("glCullFace(GL_FRONT)");
152 case WINED3DCULL_CCW:
153 glEnable(GL_CULL_FACE);
154 checkGLcall("glEnable GL_CULL_FACE");
156 checkGLcall("glCullFace(GL_BACK)");
159 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
163 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
164 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
165 case WINED3DSHADE_FLAT:
166 glShadeModel(GL_FLAT);
167 checkGLcall("glShadeModel(GL_FLAT)");
169 case WINED3DSHADE_GOURAUD:
170 glShadeModel(GL_SMOOTH);
171 checkGLcall("glShadeModel(GL_SMOOTH)");
173 case WINED3DSHADE_PHONG:
174 FIXME("WINED3DSHADE_PHONG isn't supported\n");
177 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
181 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
182 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
184 checkGLcall("glEnable GL_DITHER");
186 glDisable(GL_DITHER);
187 checkGLcall("glDisable GL_DITHER");
191 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
192 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
193 * this has to be merged with ZENABLE and ZFUNC
195 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
197 checkGLcall("glDepthMask(1)");
200 checkGLcall("glDepthMask(0)");
204 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
205 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
208 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
209 static BOOL once = FALSE;
210 /* There are a few issues with this: First, our inability to
211 * select a proper Z depth, most of the time we're stuck with
212 * D24S8, even if the app selects D32 or D16. There seem to be
213 * some other precision problems which have to be debugged to
214 * make NOTEQUAL and EQUAL work properly
218 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
223 checkGLcall("glDepthFunc");
227 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
229 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
231 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
232 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
233 checkGLcall("glLightModel for MODEL_AMBIENT");
236 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
237 int srcBlend = GL_ZERO;
238 int dstBlend = GL_ZERO;
239 const StaticPixelFormatDesc *rtFormat;
240 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
242 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
243 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
244 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
245 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
247 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
248 * The d3d9 visual test confirms the behavior. */
249 if (!(target->resource.format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
252 checkGLcall("glDisable GL_BLEND");
256 checkGLcall("glEnable GL_BLEND");
260 checkGLcall("glDisable GL_BLEND");
261 /* Nothing more to do - get out */
265 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
266 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
267 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
268 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
269 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
270 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
271 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
272 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
273 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
275 /* To compensate the lack of format switching with backbuffer offscreen rendering,
276 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
277 * if the render target doesn't support alpha blending. A nonexistent alpha channel
278 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
280 case WINED3DBLEND_DESTALPHA :
281 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
282 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
284 case WINED3DBLEND_INVDESTALPHA :
285 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
286 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
289 case WINED3DBLEND_SRCALPHASAT :
290 dstBlend = GL_SRC_ALPHA_SATURATE;
291 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
294 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
295 * values which are still valid up to d3d9. They should not occur as dest blend values
297 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
298 srcBlend = GL_SRC_ALPHA;
299 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
302 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
303 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
304 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
307 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
308 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
310 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
313 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
314 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
315 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
316 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
317 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
318 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
319 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
320 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
321 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
322 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
324 case WINED3DBLEND_DESTALPHA :
325 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
326 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
328 case WINED3DBLEND_INVDESTALPHA :
329 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
330 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
333 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
334 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
337 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
338 dstBlend = GL_SRC_ALPHA;
341 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
342 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
344 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
347 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
348 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
349 glEnable(GL_LINE_SMOOTH);
350 checkGLcall("glEnable(GL_LINE_SMOOTH)");
351 if(srcBlend != GL_SRC_ALPHA) {
352 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
354 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
355 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
358 glDisable(GL_LINE_SMOOTH);
359 checkGLcall("glDisable(GL_LINE_SMOOTH)");
362 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
363 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
364 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
367 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
368 int srcBlendAlpha = GL_ZERO;
369 int dstBlendAlpha = GL_ZERO;
371 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
372 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
373 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
377 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
378 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
379 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
380 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
381 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
382 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
383 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
384 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
385 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
386 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
387 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
388 case WINED3DBLEND_SRCALPHASAT :
389 dstBlend = GL_SRC_ALPHA_SATURATE;
390 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
392 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
393 * values which are still valid up to d3d9. They should not occur as dest blend values
395 case WINED3DBLEND_BOTHSRCALPHA :
396 dstBlendAlpha = GL_SRC_ALPHA;
397 srcBlendAlpha = GL_SRC_ALPHA;
398 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
400 case WINED3DBLEND_BOTHINVSRCALPHA :
401 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
402 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
403 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
405 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
406 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
408 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
411 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
412 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
413 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
414 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
415 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
416 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
417 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
418 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
419 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
420 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
421 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
422 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
423 case WINED3DBLEND_BOTHSRCALPHA :
424 srcBlendAlpha = GL_SRC_ALPHA;
425 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
427 case WINED3DBLEND_BOTHINVSRCALPHA :
428 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
429 dstBlendAlpha = GL_SRC_ALPHA;
431 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
432 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
434 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
437 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
438 checkGLcall("glBlendFuncSeparateEXT");
440 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
441 glBlendFunc(srcBlend, dstBlend);
442 checkGLcall("glBlendFunc");
445 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
446 so it may need updating */
447 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
448 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
449 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
453 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
454 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
457 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
460 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
461 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
462 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
463 checkGLcall("glBlendColor");
466 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
469 BOOL enable_ckey = FALSE;
471 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
473 /* Find out if the texture on the first stage has a ckey set
474 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
475 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
476 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
477 * in case it finds some texture+colorkeyenable combination which needs extra care.
479 if (stateblock->textures[0])
481 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
483 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
485 IWineD3DSurfaceImpl *surf;
487 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
489 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
491 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
492 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
493 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
494 * surface has alpha bits */
495 if (fmt->alphaMask == 0x00000000) enable_ckey = TRUE;
500 if(enable_ckey || context->last_was_ckey) {
501 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
502 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
504 context->last_was_ckey = enable_ckey;
506 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
507 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
508 glEnable(GL_ALPHA_TEST);
509 checkGLcall("glEnable GL_ALPHA_TEST");
511 glDisable(GL_ALPHA_TEST);
512 checkGLcall("glDisable GL_ALPHA_TEST");
513 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
519 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
520 glParm = GL_NOTEQUAL;
523 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
524 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
527 glAlphaFunc(glParm, ref);
528 checkGLcall("glAlphaFunc");
532 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
533 DWORD enable = 0xFFFFFFFF;
534 DWORD disable = 0x00000000;
536 if (use_vs(stateblock))
538 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
539 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
540 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
541 * of that - don't do anything here and keep them disabled
543 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
544 static BOOL warned = FALSE;
546 FIXME("Clipping not supported with vertex shaders\n");
553 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
554 * of already set values
557 /* If enabling / disabling all
558 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
560 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
561 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
562 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
563 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
564 glDisable(GL_DEPTH_CLAMP_NV);
565 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
568 disable = 0xffffffff;
570 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
571 glEnable(GL_DEPTH_CLAMP_NV);
572 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
576 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
577 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
578 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
579 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
580 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
581 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
583 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
584 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
585 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
586 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
587 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
588 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
590 /** update clipping status */
592 stateblock->clip_status.ClipUnion = 0;
593 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
595 stateblock->clip_status.ClipUnion = 0;
596 stateblock->clip_status.ClipIntersection = 0;
600 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
601 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
604 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
605 int blendEquation = GL_FUNC_ADD;
606 int blendEquationAlpha = GL_FUNC_ADD;
608 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
609 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
610 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
614 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
615 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
616 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
617 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
618 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
619 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
621 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
624 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
625 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
626 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
627 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
628 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
629 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
631 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
634 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
635 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
636 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
637 checkGLcall("glBlendEquationSeparateEXT");
639 TRACE("glBlendEquation(%x)\n", blendEquation);
640 GL_EXTCALL(glBlendEquationEXT(blendEquation));
641 checkGLcall("glBlendEquation");
646 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
647 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
648 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
649 * specular color. This is wrong:
650 * Separate specular color means the specular colour is maintained separately, whereas
651 * single color means it is merged in. However in both cases they are being used to
653 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
654 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
658 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
659 * Instead, we need to setup the FinalCombiner properly.
661 * The default setup for the FinalCombiner is:
663 * <variable> <input> <mapping> <usage>
664 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
665 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
667 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
668 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
669 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
670 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
672 * That's pretty much fine as it is, except for variable B, which needs to take
673 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
674 * whether WINED3DRS_SPECULARENABLE is enabled or not.
677 TRACE("Setting specular enable state and materials\n");
678 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
679 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
680 checkGLcall("glMaterialfv");
682 if(stateblock->material.Power > GL_LIMITS(shininess)) {
683 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
684 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
685 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
686 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
687 * them, it should be safe to do so without major visual distortions.
689 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
690 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
692 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
694 checkGLcall("glMaterialf(GL_SHININESS)");
696 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
697 glEnable(GL_COLOR_SUM_EXT);
699 TRACE("Specular colors cannot be enabled in this version of opengl\n");
701 checkGLcall("glEnable(GL_COLOR_SUM)");
703 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
704 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
705 checkGLcall("glFinalCombinerInputNV()");
708 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
710 /* for the case of enabled lighting: */
711 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
712 checkGLcall("glMaterialfv");
714 /* for the case of disabled lighting: */
715 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
716 glDisable(GL_COLOR_SUM_EXT);
718 TRACE("Specular colors cannot be disabled in this version of opengl\n");
720 checkGLcall("glDisable(GL_COLOR_SUM)");
722 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
723 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
724 checkGLcall("glFinalCombinerInputNV()");
728 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
729 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
730 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
731 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
732 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
733 stateblock->material.Specular.b, stateblock->material.Specular.a);
734 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
735 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
737 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
738 checkGLcall("glMaterialfv(GL_AMBIENT)");
739 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
740 checkGLcall("glMaterialfv(GL_DIFFUSE)");
741 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
742 checkGLcall("glMaterialfv(GL_EMISSION)");
745 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
748 /* Note the texture color applies to all textures whereas
749 * GL_TEXTURE_ENV_COLOR applies to active only
752 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
754 /* And now the default texture color as well */
755 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
756 /* Note the WINED3DRS value applies to all textures, but GL has one
757 * per texture, so apply it now ready to be used!
759 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
760 checkGLcall("glActiveTextureARB");
762 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
763 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
768 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
769 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
770 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
771 GL_EXTCALL(glActiveStencilFaceEXT(face));
772 checkGLcall("glActiveStencilFaceEXT(...)");
773 glStencilFunc(func, ref, mask);
774 checkGLcall("glStencilFunc(...)");
775 glStencilOp(stencilFail, depthFail, stencilPass);
776 checkGLcall("glStencilOp(...)");
780 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
781 DWORD onesided_enable = FALSE;
782 DWORD twosided_enable = FALSE;
783 GLint func = GL_ALWAYS;
784 GLint func_ccw = GL_ALWAYS;
787 GLint stencilFail = GL_KEEP;
788 GLint depthFail = GL_KEEP;
789 GLint stencilPass = GL_KEEP;
790 GLint stencilFail_ccw = GL_KEEP;
791 GLint depthFail_ccw = GL_KEEP;
792 GLint stencilPass_ccw = GL_KEEP;
794 /* No stencil test without a stencil buffer */
795 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
796 glDisable(GL_STENCIL_TEST);
797 checkGLcall("glDisable GL_STENCIL_TEST");
801 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
802 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
803 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
805 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
806 func_ccw = GL_ALWAYS;
807 ref = stateblock->renderState[WINED3DRS_STENCILREF];
808 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
809 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
810 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
811 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
812 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
813 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
814 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
816 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
817 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
818 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
819 onesided_enable, twosided_enable, ref, mask,
820 func, stencilFail, depthFail, stencilPass,
821 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
823 if (twosided_enable && onesided_enable) {
824 glEnable(GL_STENCIL_TEST);
825 checkGLcall("glEnable GL_STENCIL_TEST");
827 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
828 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
829 * which has an effect on the code below too. If we apply the front face
830 * afterwards, we are sure that the active stencil face is set to front,
831 * and other stencil functions which do not use two sided stencil do not have
834 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
835 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
836 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
837 stencilFail, depthFail, stencilPass);
838 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
839 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
840 checkGLcall("glStencilFuncSeparateATI(...)");
841 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
842 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
843 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
844 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
846 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
848 } else if(onesided_enable) {
849 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
850 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
851 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
854 /* This code disables the ATI extension as well, since the standard stencil functions are equal
855 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
857 glEnable(GL_STENCIL_TEST);
858 checkGLcall("glEnable GL_STENCIL_TEST");
859 glStencilFunc(func, ref, mask);
860 checkGLcall("glStencilFunc(...)");
861 glStencilOp(stencilFail, depthFail, stencilPass);
862 checkGLcall("glStencilOp(...)");
864 glDisable(GL_STENCIL_TEST);
865 checkGLcall("glDisable GL_STENCIL_TEST");
869 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
872 if(stateblock->wineD3DDevice->stencilBufferTarget) {
873 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
878 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
879 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
881 checkGLcall("glStencilMask");
882 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
883 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
887 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
890 if(stateblock->wineD3DDevice->stencilBufferTarget) {
891 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
897 checkGLcall("glStencilMask");
900 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
902 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
904 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
906 /* Table fog on: Never use fog coords, and use per-fragment fog */
907 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
908 glHint(GL_FOG_HINT, GL_NICEST);
909 if(context->fog_coord) {
910 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
911 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
912 context->fog_coord = FALSE;
917 /* Otherwise use per-vertex fog in any case */
918 glHint(GL_FOG_HINT, GL_FASTEST);
920 if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
921 /* No fog at all, or transformed vertices: Use fog coord */
922 if(!context->fog_coord) {
923 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
924 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
925 context->fog_coord = TRUE;
928 /* Otherwise, use the fragment depth */
929 if(context->fog_coord) {
930 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
931 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
932 context->fog_coord = FALSE;
937 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
938 float fogstart, fogend;
944 switch(context->fog_source) {
950 case FOGSOURCE_COORD:
956 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
957 fogstart = tmpvalue.f;
958 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
960 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
961 if(fogstart == fogend) {
962 fogstart = -1.0 / 0.0;
968 /* This should not happen.context->fog_source is set in wined3d, not the app.
969 * Still this is needed to make the compiler happy
971 ERR("Unexpected fog coordinate source\n");
976 glFogf(GL_FOG_START, fogstart);
977 checkGLcall("glFogf(GL_FOG_START, fogstart)");
978 TRACE("Fog Start == %f\n", fogstart);
980 glFogf(GL_FOG_END, fogend);
981 checkGLcall("glFogf(GL_FOG_END, fogend)");
982 TRACE("Fog End == %f\n", fogend);
985 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
986 enum fogsource new_source;
988 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
990 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
991 /* No fog? Disable it, and we're done :-) */
992 glDisableWINE(GL_FOG);
993 checkGLcall("glDisable GL_FOG");
999 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
1000 * It can use the Z value of the vertex, or the alpha component of the specular color.
1001 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
1002 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
1003 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
1005 * FOGTABLEMODE != NONE:
1006 * The Z value is used, with the equation specified, no matter what vertex type.
1008 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1009 * Per vertex fog is calculated using the specified fog equation and the parameters
1011 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1012 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1013 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1016 * Rules for vertex fog with shaders:
1018 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1019 * the fog computation to happen during transformation while openGL expects it to happen
1020 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1021 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1022 * To solve this problem, WineD3D does:
1023 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1025 * and 2) disables the fog computation (in either the fixed function or programmable
1026 * rasterizer) if using a vertex program.
1028 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1029 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1030 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1031 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1032 * There are some GL differences between specular fog coords and vertex shaders though.
1034 * With table fog the vertex shader fog coordinate is ignored.
1036 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1040 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1041 * the system will apply only pixel(=table) fog effects."
1043 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1044 if(use_vs(stateblock)) {
1045 glFogi(GL_FOG_MODE, GL_LINEAR);
1046 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1047 new_source = FOGSOURCE_VS;
1049 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1050 /* If processed vertices are used, fall through to the NONE case */
1051 case WINED3DFOG_EXP:
1052 if(!context->last_was_rhw) {
1053 glFogi(GL_FOG_MODE, GL_EXP);
1054 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1055 new_source = FOGSOURCE_FFP;
1060 case WINED3DFOG_EXP2:
1061 if(!context->last_was_rhw) {
1062 glFogi(GL_FOG_MODE, GL_EXP2);
1063 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1064 new_source = FOGSOURCE_FFP;
1069 case WINED3DFOG_LINEAR:
1070 if(!context->last_was_rhw) {
1071 glFogi(GL_FOG_MODE, GL_LINEAR);
1072 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1073 new_source = FOGSOURCE_FFP;
1078 case WINED3DFOG_NONE:
1079 /* Both are none? According to msdn the alpha channel of the specular
1080 * color contains a fog factor. Set it in drawStridedSlow.
1081 * Same happens with Vertexfog on transformed vertices
1083 new_source = FOGSOURCE_COORD;
1084 glFogi(GL_FOG_MODE, GL_LINEAR);
1085 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1089 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1090 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1094 new_source = FOGSOURCE_FFP;
1096 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1097 case WINED3DFOG_EXP:
1098 glFogi(GL_FOG_MODE, GL_EXP);
1099 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1102 case WINED3DFOG_EXP2:
1103 glFogi(GL_FOG_MODE, GL_EXP2);
1104 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1107 case WINED3DFOG_LINEAR:
1108 glFogi(GL_FOG_MODE, GL_LINEAR);
1109 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1112 case WINED3DFOG_NONE: /* Won't happen */
1114 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1118 glEnableWINE(GL_FOG);
1119 checkGLcall("glEnable GL_FOG");
1120 if(new_source != context->fog_source) {
1121 context->fog_source = new_source;
1122 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1126 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1127 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1128 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1132 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1133 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1134 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1135 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1137 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1138 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1142 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1144 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1145 glFogfv(GL_FOG_COLOR, &col[0]);
1146 checkGLcall("glFog GL_FOG_COLOR");
1149 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1154 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1155 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1156 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1159 /* TODO: Merge with primitive type + init_materials()!! */
1160 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1161 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1163 const WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1164 BOOL isDiffuseSupplied;
1166 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1167 * The vertex declaration will call this function if the fixed function pipeline is used.
1170 if(isStateDirty(context, STATE_VDECL)) {
1174 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1176 context->num_untracked_materials = 0;
1177 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1178 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1179 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1180 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1181 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1182 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1184 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1185 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1186 Parm = GL_AMBIENT_AND_DIFFUSE;
1190 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1191 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1192 context->num_untracked_materials++;
1194 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1195 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1196 context->num_untracked_materials++;
1198 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1200 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1201 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1202 context->num_untracked_materials++;
1204 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1205 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1206 context->num_untracked_materials++;
1208 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1210 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1211 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1212 context->num_untracked_materials++;
1214 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1219 /* Nothing changed, return. */
1220 if (Parm == context->tracking_parm) return;
1223 glDisable(GL_COLOR_MATERIAL);
1224 checkGLcall("glDisable GL_COLOR_MATERIAL");
1226 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1227 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1228 glEnable(GL_COLOR_MATERIAL);
1229 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1232 /* Apparently calls to glMaterialfv are ignored for properties we're
1233 * tracking with glColorMaterial, so apply those here. */
1234 switch (context->tracking_parm) {
1235 case GL_AMBIENT_AND_DIFFUSE:
1236 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1237 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1238 checkGLcall("glMaterialfv");
1242 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1243 checkGLcall("glMaterialfv");
1247 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1248 checkGLcall("glMaterialfv");
1252 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1253 checkGLcall("glMaterialfv");
1257 /* Only change material color if specular is enabled, otherwise it is set to black */
1258 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1259 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1260 checkGLcall("glMaterialfv");
1262 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1263 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1264 checkGLcall("glMaterialfv");
1269 context->tracking_parm = Parm;
1272 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1275 WINED3DLINEPATTERN lp;
1277 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1279 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1281 if (tmppattern.lp.wRepeatFactor) {
1282 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1283 checkGLcall("glLineStipple(repeat, linepattern)");
1284 glEnable(GL_LINE_STIPPLE);
1285 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1287 glDisable(GL_LINE_STIPPLE);
1288 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1292 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1298 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1299 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1300 TRACE("ZBias value %f\n", tmpvalue.f);
1301 glPolygonOffset(0, -tmpvalue.f);
1302 checkGLcall("glPolygonOffset(0, -Value)");
1303 glEnable(GL_POLYGON_OFFSET_FILL);
1304 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1305 glEnable(GL_POLYGON_OFFSET_LINE);
1306 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1307 glEnable(GL_POLYGON_OFFSET_POINT);
1308 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1310 glDisable(GL_POLYGON_OFFSET_FILL);
1311 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1312 glDisable(GL_POLYGON_OFFSET_LINE);
1313 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1314 glDisable(GL_POLYGON_OFFSET_POINT);
1315 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1320 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1321 if(isStateDirty(context, STATE_VDECL)) {
1324 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1325 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1326 * by zero and is not properly defined in opengl, so avoid it
1328 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1329 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1330 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1331 glEnable(GL_NORMALIZE);
1332 checkGLcall("glEnable(GL_NORMALIZE);");
1334 glDisable(GL_NORMALIZE);
1335 checkGLcall("glDisable(GL_NORMALIZE);");
1339 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1345 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1346 if(tmpvalue.f != 1.0) {
1347 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1349 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1350 if(tmpvalue.f != 64.0) {
1351 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1356 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1362 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1363 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1365 /* Max point size trumps min point size */
1370 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1371 checkGLcall("glPointParameterfEXT(...)");
1372 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1373 checkGLcall("glPointParameterfEXT(...)");
1376 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1382 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1383 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1385 /* Max point size trumps min point size */
1390 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1391 checkGLcall("glPointParameterfARB(...)");
1392 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1393 checkGLcall("glPointParameterfARB(...)");
1396 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1397 /* TODO: Group this with the viewport */
1399 * POINTSCALEENABLE controls how point size value is treated. If set to
1400 * true, the point size is scaled with respect to height of viewport.
1401 * When set to false point size is in pixels.
1404 /* Default values */
1405 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1409 } pointSize, A, B, C;
1411 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1412 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1413 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1414 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1416 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1417 GLfloat scaleFactor;
1418 float h = stateblock->viewport.Height;
1420 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1422 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1423 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1424 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1425 * are less than 1.0f. scale_factor = 1.0f / point_size.
1427 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1428 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1429 * is 1.0, but then accepts points below that and draws too small points
1431 pointSize.f = GL_LIMITS(pointsizemin);
1432 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1433 /* gl already scales the input to glPointSize,
1434 * d3d scales the result after the point size scale.
1435 * If the point size is bigger than the max size, use the
1436 * scaling to scale it bigger, and set the gl point size to max
1438 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1439 TRACE("scale: %f\n", scaleFactor);
1440 pointSize.f = GL_LIMITS(pointsize);
1444 scaleFactor = pow(h * scaleFactor, 2);
1446 att[0] = A.f / scaleFactor;
1447 att[1] = B.f / scaleFactor;
1448 att[2] = C.f / scaleFactor;
1451 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1452 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1453 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1455 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1456 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1457 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1458 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1459 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1462 glPointSize(pointSize.f);
1463 checkGLcall("glPointSize(...);");
1466 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1467 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1469 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1470 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1471 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1472 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1473 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1474 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1475 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1476 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1477 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1478 checkGLcall("glColorMask(...)");
1480 /* depends on WINED3DRS_COLORWRITEENABLE. */
1481 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1482 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1483 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1484 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1485 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1486 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1487 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1491 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1492 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1493 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1494 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1496 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1497 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1501 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1502 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1503 TRACE("Last Pixel Drawing Enabled\n");
1507 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1510 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1515 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1516 /* TODO: NV_POINT_SPRITE */
1517 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1518 TRACE("Point sprites not supported\n");
1522 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1523 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1524 glEnable(GL_POINT_SPRITE_ARB);
1525 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1527 glDisable(GL_POINT_SPRITE_ARB);
1528 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1532 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1534 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1535 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1536 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1537 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1539 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1542 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1543 stateblock->renderState[WINED3DRS_WRAP1] ||
1544 stateblock->renderState[WINED3DRS_WRAP2] ||
1545 stateblock->renderState[WINED3DRS_WRAP3] ||
1546 stateblock->renderState[WINED3DRS_WRAP4] ||
1547 stateblock->renderState[WINED3DRS_WRAP5] ||
1548 stateblock->renderState[WINED3DRS_WRAP6] ||
1549 stateblock->renderState[WINED3DRS_WRAP7] ||
1550 stateblock->renderState[WINED3DRS_WRAP8] ||
1551 stateblock->renderState[WINED3DRS_WRAP9] ||
1552 stateblock->renderState[WINED3DRS_WRAP10] ||
1553 stateblock->renderState[WINED3DRS_WRAP11] ||
1554 stateblock->renderState[WINED3DRS_WRAP12] ||
1555 stateblock->renderState[WINED3DRS_WRAP13] ||
1556 stateblock->renderState[WINED3DRS_WRAP14] ||
1557 stateblock->renderState[WINED3DRS_WRAP15] ) {
1558 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1562 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1563 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1564 WARN("Multisample antialiasing not supported by gl\n");
1568 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1569 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1570 glEnable(GL_MULTISAMPLE_ARB);
1571 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1573 glDisable(GL_MULTISAMPLE_ARB);
1574 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1578 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1579 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1580 glEnable(GL_SCISSOR_TEST);
1581 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1583 glDisable(GL_SCISSOR_TEST);
1584 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1588 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1594 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1595 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1596 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1597 glEnable(GL_POLYGON_OFFSET_FILL);
1598 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1599 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1600 checkGLcall("glPolygonOffset(...)");
1602 glDisable(GL_POLYGON_OFFSET_FILL);
1603 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1607 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1608 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1609 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1610 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1612 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1613 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1617 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1619 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1620 FIXME(" Stippled Alpha not supported yet.\n");
1623 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1625 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1626 FIXME(" Antialias not supported yet.\n");
1629 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1631 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1632 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1635 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1637 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1638 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1641 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1649 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1651 static BOOL displayed = FALSE;
1653 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1655 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1661 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1663 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1664 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1667 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1669 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1670 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1673 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1675 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1676 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1679 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1680 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1681 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1685 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1686 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1687 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1691 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1692 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1693 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1697 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1698 if(stateblock->renderState[WINED3DRS_ROP2]) {
1699 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1703 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1704 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1705 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1709 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1710 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1711 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1715 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1716 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1717 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1721 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1722 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1723 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1727 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1728 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1729 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1733 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1734 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1735 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1739 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1740 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1741 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1745 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1746 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1747 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1751 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1752 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1753 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1757 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1758 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1759 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1763 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1764 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1765 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1769 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1770 #if defined (GL_VERSION_1_3)
1771 # define useext(A) A
1772 #elif defined (GL_EXT_texture_env_combine)
1773 # define useext(A) A##_EXT
1774 #elif defined (GL_ARB_texture_env_combine)
1775 # define useext(A) A##_ARB
1778 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1779 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1780 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1781 * flag specifies the complement of the input should be used. */
1782 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1783 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1785 /* Calculate the operand */
1787 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1788 else *operand = GL_ONE_MINUS_SRC_COLOR;
1790 if (from_alpha) *operand = GL_SRC_ALPHA;
1791 else *operand = GL_SRC_COLOR;
1794 /* Calculate the source */
1795 switch (arg & WINED3DTA_SELECTMASK) {
1796 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1797 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1798 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1799 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1800 case WINED3DTA_SPECULAR:
1802 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1803 * 'Secondary color' and isn't supported until base GL supports it
1804 * There is no concept of temp registers as far as I can tell
1806 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1807 *source = GL_TEXTURE;
1810 FIXME("Unrecognized texture arg %#x\n", arg);
1811 *source = GL_TEXTURE;
1816 /* Setup the texture operations texture stage states */
1817 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1819 GLenum src1, src2, src3;
1820 GLenum opr1, opr2, opr3;
1822 GLenum src0_target, src1_target, src2_target;
1823 GLenum opr0_target, opr1_target, opr2_target;
1825 GLenum opr=0, invopr, src3_target, opr3_target;
1826 BOOL Handled = FALSE;
1827 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1828 IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1830 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1832 /* This is called by a state handler which has the gl lock held and a context for the thread */
1834 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1835 the form (a1 <operation> a2). However, some of the more complex operations
1836 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1837 in a third parameter called a0. Therefore these are operations of the form
1838 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1840 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1841 functions below, expect their syntax to differ slightly to those listed in the
1842 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1843 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1846 comb_target = useext(GL_COMBINE_ALPHA);
1847 src0_target = useext(GL_SOURCE0_ALPHA);
1848 src1_target = useext(GL_SOURCE1_ALPHA);
1849 src2_target = useext(GL_SOURCE2_ALPHA);
1850 opr0_target = useext(GL_OPERAND0_ALPHA);
1851 opr1_target = useext(GL_OPERAND1_ALPHA);
1852 opr2_target = useext(GL_OPERAND2_ALPHA);
1853 scal_target = GL_ALPHA_SCALE;
1856 comb_target = useext(GL_COMBINE_RGB);
1857 src0_target = useext(GL_SOURCE0_RGB);
1858 src1_target = useext(GL_SOURCE1_RGB);
1859 src2_target = useext(GL_SOURCE2_RGB);
1860 opr0_target = useext(GL_OPERAND0_RGB);
1861 opr1_target = useext(GL_OPERAND1_RGB);
1862 opr2_target = useext(GL_OPERAND2_RGB);
1863 scal_target = useext(GL_RGB_SCALE);
1866 /* If a texture stage references an invalid texture unit the stage just
1867 * passes through the result from the previous stage */
1868 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1869 arg1 = WINED3DTA_CURRENT;
1870 op = WINED3DTOP_SELECTARG1;
1873 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1874 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1876 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1878 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1879 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1881 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1883 Handled = TRUE; /* Assume will be handled */
1885 /* Other texture operations require special extensions: */
1886 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1889 invopr = GL_ONE_MINUS_SRC_ALPHA;
1890 src3_target = GL_SOURCE3_ALPHA_NV;
1891 opr3_target = GL_OPERAND3_ALPHA_NV;
1894 invopr = GL_ONE_MINUS_SRC_COLOR;
1895 src3_target = GL_SOURCE3_RGB_NV;
1896 opr3_target = GL_OPERAND3_RGB_NV;
1899 case WINED3DTOP_DISABLE: /* Only for alpha */
1900 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1901 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1902 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1903 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1904 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1905 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1906 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1907 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1908 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1909 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1910 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1911 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1912 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1913 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1914 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1915 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1916 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1917 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1919 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1920 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1921 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1922 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1923 if (op == WINED3DTOP_SELECTARG1) {
1924 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1925 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1926 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1927 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1929 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1930 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1931 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1932 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1934 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1935 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1936 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1937 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1938 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1939 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1940 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1941 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1942 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1943 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1944 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1945 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1948 case WINED3DTOP_MODULATE:
1949 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1950 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1951 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1952 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1953 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1954 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1955 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1956 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1957 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1958 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1959 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1960 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1961 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1962 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1963 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1964 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1965 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1966 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1967 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1968 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1970 case WINED3DTOP_MODULATE2X:
1971 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1972 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1973 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1974 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1975 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1976 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1977 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1978 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1979 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1980 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1981 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1982 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1983 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1984 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1985 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1986 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1987 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1988 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1989 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1990 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1992 case WINED3DTOP_MODULATE4X:
1993 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1994 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1995 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1996 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1997 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1998 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1999 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2000 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2001 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2002 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2003 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2004 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2005 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2006 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2007 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2008 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2009 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2010 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2011 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2012 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2015 case WINED3DTOP_ADD:
2016 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2017 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2018 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2019 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2020 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2021 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2022 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2023 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2024 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2025 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2026 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2027 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2028 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2029 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2030 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2031 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2032 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2033 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2034 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2035 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2038 case WINED3DTOP_ADDSIGNED:
2039 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2040 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2041 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2042 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2043 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2044 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2045 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2046 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2047 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2048 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2049 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2050 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2051 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2052 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2053 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2054 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2055 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2056 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2057 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2058 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2061 case WINED3DTOP_ADDSIGNED2X:
2062 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2063 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2064 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2065 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2066 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2067 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2068 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2069 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2070 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2071 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2072 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2073 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2074 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2075 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2076 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2077 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2078 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2079 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2080 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2081 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2084 case WINED3DTOP_ADDSMOOTH:
2085 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2086 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2087 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2088 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2089 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2090 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2091 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2092 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2093 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2094 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2095 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2096 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2097 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2098 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2099 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2100 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2102 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2103 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2104 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2105 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2107 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2108 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2109 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2110 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2113 case WINED3DTOP_BLENDDIFFUSEALPHA:
2114 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2115 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2116 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2117 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2118 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2119 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2120 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2121 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2122 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2123 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2124 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2125 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2126 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2127 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2128 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2129 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2130 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2131 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2132 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2133 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2135 case WINED3DTOP_BLENDTEXTUREALPHA:
2136 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2137 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2138 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2139 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2140 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2141 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2142 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2143 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2144 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2145 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2146 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2147 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2148 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2149 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2150 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2151 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2152 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2153 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2154 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2155 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2157 case WINED3DTOP_BLENDFACTORALPHA:
2158 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2159 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2160 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2161 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2162 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2163 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2164 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2165 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2166 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2167 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2168 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2169 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2170 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2171 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2172 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2173 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2174 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2175 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2176 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2177 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2179 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2180 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2181 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2182 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2183 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2184 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2185 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2186 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2187 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2188 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2189 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2190 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2191 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2192 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2193 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2194 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2195 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2196 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2197 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2198 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2199 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2201 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2202 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2203 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2204 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2205 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2206 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2207 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2208 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2209 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2210 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2211 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2212 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2213 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2214 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2215 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2216 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2217 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2219 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2220 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2222 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2223 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2224 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2225 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2227 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2228 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2229 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2230 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2231 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2232 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2233 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2234 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2235 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2236 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2237 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2238 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2239 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2241 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2242 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2244 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2245 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2246 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2247 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2248 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2249 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2250 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2251 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2253 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2254 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2255 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2256 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2257 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2258 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2259 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2260 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2261 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2262 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2263 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2264 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2265 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2266 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2267 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2268 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2269 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2271 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2272 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2273 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2274 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2276 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2277 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2278 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2279 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2281 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2282 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2283 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2284 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2285 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2287 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2288 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2289 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2290 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2292 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2293 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2294 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2295 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2296 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2297 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2298 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2299 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2301 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2302 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2304 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2305 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2306 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2307 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2308 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2309 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2310 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2311 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2313 case WINED3DTOP_MULTIPLYADD:
2314 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2315 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2316 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2317 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2318 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2319 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2320 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2321 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2322 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2323 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2324 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2325 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2326 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2327 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2328 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2329 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2330 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2331 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2332 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2333 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2336 case WINED3DTOP_BUMPENVMAP:
2340 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2341 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2347 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2348 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2352 } /* GL_NV_texture_env_combine4 */
2354 Handled = TRUE; /* Again, assume handled */
2356 case WINED3DTOP_DISABLE: /* Only for alpha */
2357 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2358 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2359 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2360 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2361 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2362 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2363 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2364 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2366 case WINED3DTOP_SELECTARG1:
2367 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2368 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2369 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2370 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2371 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2372 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2373 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2374 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2376 case WINED3DTOP_SELECTARG2:
2377 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2378 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2379 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2380 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2381 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2382 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2383 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2384 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2386 case WINED3DTOP_MODULATE:
2387 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2388 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2389 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2390 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2391 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2392 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2393 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2394 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2395 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2396 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2397 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2398 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2400 case WINED3DTOP_MODULATE2X:
2401 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2402 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
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, src2);
2408 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2409 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2410 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2411 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2412 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2414 case WINED3DTOP_MODULATE4X:
2415 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2416 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2417 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2418 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2419 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2420 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2421 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2422 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2423 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2424 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2425 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2426 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2428 case WINED3DTOP_ADD:
2429 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2430 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2431 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2432 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2433 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2434 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2435 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2436 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2437 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2438 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2439 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2440 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2442 case WINED3DTOP_ADDSIGNED:
2443 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2444 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2445 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2446 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2447 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2448 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2449 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2450 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2451 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2452 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2453 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2454 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2456 case WINED3DTOP_ADDSIGNED2X:
2457 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2458 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2459 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2460 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2461 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2462 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2463 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2464 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2465 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2466 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2467 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2468 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2470 case WINED3DTOP_SUBTRACT:
2471 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2472 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2473 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2474 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2475 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2476 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2477 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2478 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2479 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2480 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2481 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2482 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2483 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2485 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2489 case WINED3DTOP_BLENDDIFFUSEALPHA:
2490 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2491 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2492 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2493 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2494 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2495 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2496 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2497 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2498 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2499 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2500 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2501 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2502 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2503 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2504 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2505 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2507 case WINED3DTOP_BLENDTEXTUREALPHA:
2508 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2509 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2510 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2511 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2512 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2513 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2514 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2515 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2516 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2517 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2518 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2519 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2520 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2521 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2522 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2523 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2525 case WINED3DTOP_BLENDFACTORALPHA:
2526 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2527 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2528 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2529 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2530 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2531 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2532 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2533 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2534 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2535 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2536 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2537 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2538 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2539 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2540 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2541 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2543 case WINED3DTOP_BLENDCURRENTALPHA:
2544 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2545 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2546 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2547 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2548 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2549 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2550 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2551 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2552 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2553 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2554 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2555 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2556 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2557 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2558 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2559 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2561 case WINED3DTOP_DOTPRODUCT3:
2562 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2563 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2564 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2565 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2566 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2567 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2569 FIXME("This version of opengl does not support GL_DOT3\n");
2571 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2572 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2573 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2574 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2575 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2576 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2577 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2578 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2579 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2580 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2582 case WINED3DTOP_LERP:
2583 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2584 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2585 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2586 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2587 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2588 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2589 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2590 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2591 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2592 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2593 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2594 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2595 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2596 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2597 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2598 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2600 case WINED3DTOP_ADDSMOOTH:
2601 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2602 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2603 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2604 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2605 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2607 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2608 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2609 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2610 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2612 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2613 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2614 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2615 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2616 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2617 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2618 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2619 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2620 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2621 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2622 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2623 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2627 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2628 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2629 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2630 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2631 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2632 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2633 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2634 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2635 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2636 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2637 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2638 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2639 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2640 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2641 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2642 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2643 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2644 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2648 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2649 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2650 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2651 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2652 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2653 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2655 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2656 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2657 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2658 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2660 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2661 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2662 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2663 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2664 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2665 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2666 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2667 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2668 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2669 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2670 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2671 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2675 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2676 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2677 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2678 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2679 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2680 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2681 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2682 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2683 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2684 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2686 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2687 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2688 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2689 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2691 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2692 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2693 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2694 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2695 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2696 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2697 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2698 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2702 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2703 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2704 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2705 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2706 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2707 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2709 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2710 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2711 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2712 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2714 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2715 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2716 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2717 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2718 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2719 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2720 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2721 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2722 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2723 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2724 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2725 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2729 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2730 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2731 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2732 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2733 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2734 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2736 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2737 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2738 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2739 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2741 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2742 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2743 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2744 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2746 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2747 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2748 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2749 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2751 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2752 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2753 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2754 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2755 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2756 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2757 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2758 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2762 case WINED3DTOP_MULTIPLYADD:
2763 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2764 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2765 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2766 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2767 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2768 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2769 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2770 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2771 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2772 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2773 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2774 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2775 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2776 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2777 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2778 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2779 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2783 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2784 case WINED3DTOP_BUMPENVMAP:
2785 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2786 /* Technically texture shader support without register combiners is possible, but not expected to occur
2787 * on real world cards, so for now a fixme should be enough
2789 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2796 BOOL combineOK = TRUE;
2797 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2801 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2803 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2806 /* Note: If COMBINE4 in effect can't go back to combine! */
2808 case WINED3DTOP_ADDSMOOTH:
2809 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2810 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2811 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2812 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2813 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2814 case WINED3DTOP_MULTIPLYADD:
2815 /* Ignore those implemented in both cases */
2817 case WINED3DTOP_SELECTARG1:
2818 case WINED3DTOP_SELECTARG2:
2823 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2830 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2831 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2837 /* After all the extensions, if still unhandled, report fixme */
2838 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2842 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2843 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2844 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2845 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2847 TRACE("Setting color op for stage %d\n", stage);
2849 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2850 if (use_ps(stateblock)) return;
2852 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2854 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2856 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2857 FIXME("Attempt to enable unsupported stage!\n");
2860 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2861 checkGLcall("glActiveTextureARB");
2864 if(stage >= stateblock->lowest_disabled_stage) {
2865 TRACE("Stage disabled\n");
2866 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2868 /* Disable everything here */
2869 glDisable(GL_TEXTURE_2D);
2870 checkGLcall("glDisable(GL_TEXTURE_2D)");
2871 glDisable(GL_TEXTURE_3D);
2872 checkGLcall("glDisable(GL_TEXTURE_3D)");
2873 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2874 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2875 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2877 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2878 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2879 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2886 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2887 * if the sampler for this stage is dirty
2889 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2890 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2893 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2894 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2895 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2896 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2897 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2900 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2901 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2902 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2903 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2904 DWORD op, arg1, arg2, arg0;
2906 TRACE("Setting alpha op for stage %d\n", stage);
2907 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2908 if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2910 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2911 FIXME("Attempt to enable unsupported stage!\n");
2914 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2915 checkGLcall("glActiveTextureARB");
2918 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2919 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2920 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2921 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2923 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2925 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2927 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2929 IWineD3DSurfaceImpl *surf;
2931 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2933 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT
2934 && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000)
2936 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2937 * properly. On the other hand applications can still use texture combiners apparently. This code
2938 * takes care that apps cannot remove the texture's alpha channel entirely.
2940 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2941 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2942 * and alpha component of diffuse color to draw things like translucent text and perform other
2945 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2946 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2947 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2948 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2949 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2950 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2951 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2952 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2953 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2956 * What to do with multitexturing? So far no app has been found that uses color keying with
2958 if (op == WINED3DTOP_DISABLE)
2960 arg1 = WINED3DTA_TEXTURE;
2961 op = WINED3DTOP_SELECTARG1;
2963 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
2965 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2967 arg2 = WINED3DTA_TEXTURE;
2968 op = WINED3DTOP_MODULATE;
2970 else arg1 = WINED3DTA_TEXTURE;
2972 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
2974 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2976 arg1 = WINED3DTA_TEXTURE;
2977 op = WINED3DTOP_MODULATE;
2979 else arg2 = WINED3DTA_TEXTURE;
2985 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
2986 * this if block here, and the other code(color keying, texture unit selection) are the same
2988 TRACE("Setting alpha op for stage %d\n", stage);
2989 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2990 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2991 op, arg1, arg2, arg0,
2993 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
2995 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2996 op, arg1, arg2, arg0);
3000 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3001 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3002 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3006 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3007 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3009 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3013 if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3015 if(mapped_stage >= GL_LIMITS(textures)) {
3018 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3019 checkGLcall("glActiveTextureARB");
3020 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3021 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3023 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3024 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
3026 context->last_was_rhw,
3027 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwStride ?
3028 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwType:
3029 WINED3DDECLTYPE_UNUSED,
3030 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3032 /* The sampler applying function calls us if this changes */
3033 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3036 FIXME("Non-power2 texture being used with generated texture coords\n");
3038 TRACE("Non power two matrix multiply fixup\n");
3039 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3043 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3046 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3047 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3048 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3052 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd, GLuint *curVBO)
3054 const UINT *offset = stateblock->streamOffset;
3055 unsigned int mapped_stage = 0;
3056 unsigned int textureNo = 0;
3058 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3059 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3061 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3062 if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3064 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
3065 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3066 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
3068 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
3069 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
3070 checkGLcall("glBindBufferARB");
3071 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
3074 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3075 checkGLcall("glClientActiveTextureARB");
3077 /* The coords to supply depend completely on the fvf / vertex shader */
3079 WINED3D_ATR_FORMAT(sd->u.s.texCoords[coordIdx].dwType),
3080 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
3081 sd->u.s.texCoords[coordIdx].dwStride,
3082 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
3083 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3085 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3088 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3089 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3090 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3091 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3095 checkGLcall("loadTexCoords");
3098 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3099 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3100 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3101 static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3102 static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3103 static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3104 static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3106 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3108 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3112 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3115 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3116 checkGLcall("glActiveTextureARB");
3118 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3120 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3121 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3122 * means use the vertex position (camera-space) as the input texture coordinates
3123 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3124 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3125 * to the TEXCOORDINDEX value
3129 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3131 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
3132 case WINED3DTSS_TCI_PASSTHRU:
3133 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3134 glDisable(GL_TEXTURE_GEN_S);
3135 glDisable(GL_TEXTURE_GEN_T);
3136 glDisable(GL_TEXTURE_GEN_R);
3137 glDisable(GL_TEXTURE_GEN_Q);
3138 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3141 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3142 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3143 * as the input texture coordinates for this stage's texture transformation. This
3144 * equates roughly to EYE_LINEAR
3147 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3149 glMatrixMode(GL_MODELVIEW);
3152 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3153 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3154 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3155 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3158 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3159 glEnable(GL_TEXTURE_GEN_S);
3160 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3161 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3162 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3163 glEnable(GL_TEXTURE_GEN_T);
3164 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3165 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3166 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3167 glEnable(GL_TEXTURE_GEN_R);
3168 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3169 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3170 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3174 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3176 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3177 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3179 glMatrixMode(GL_MODELVIEW);
3182 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3183 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3184 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3185 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3188 glEnable(GL_TEXTURE_GEN_S);
3189 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3190 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3191 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3192 glEnable(GL_TEXTURE_GEN_T);
3193 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3194 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3195 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3196 glEnable(GL_TEXTURE_GEN_R);
3197 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3198 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3199 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3204 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3206 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3207 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3209 glMatrixMode(GL_MODELVIEW);
3212 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3213 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3214 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3215 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3218 glEnable(GL_TEXTURE_GEN_S);
3219 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3220 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3221 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3222 glEnable(GL_TEXTURE_GEN_T);
3223 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3224 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3225 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3226 glEnable(GL_TEXTURE_GEN_R);
3227 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3228 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3229 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3234 /* Unhandled types: */
3237 /* ? disable GL_TEXTURE_GEN_n ? */
3238 glDisable(GL_TEXTURE_GEN_S);
3239 glDisable(GL_TEXTURE_GEN_T);
3240 glDisable(GL_TEXTURE_GEN_R);
3241 glDisable(GL_TEXTURE_GEN_Q);
3242 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3246 /* Update the texture matrix */
3247 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3248 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3251 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3252 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3253 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3254 * and do all the things linked to it
3255 * TODO: Tidy that up to reload only the arrays of the changed unit
3257 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3259 unloadTexCoords(stateblock);
3260 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3264 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3265 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3267 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3268 * has an update pending
3270 if(isStateDirty(context, STATE_VDECL) ||
3271 isStateDirty(context, STATE_PIXELSHADER)) {
3275 device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock));
3278 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3279 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3281 if(stateblock->pixelShader && stage != 0 &&
3282 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3283 /* The pixel shader has to know the luminance scale. Do a constants update if it
3284 * isn't scheduled anyway
3286 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3287 !isStateDirty(context, STATE_PIXELSHADER)) {
3288 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3293 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3294 BOOL texIsPow2 = FALSE;
3295 DWORD sampler = state - STATE_SAMPLER(0);
3296 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3298 TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3300 if(!texture) return;
3301 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3302 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3303 * scaling is reapplied or removed, the texture matrix has to be reapplied
3305 * The mapped stage is already active because the sampler() function below, which is part of the
3308 if(sampler < MAX_TEXTURES) {
3309 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
3311 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3313 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
3314 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
3318 else if (texture_dimensions == GL_TEXTURE_CUBE_MAP_ARB)
3320 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
3325 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3327 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3328 else context->lastWasPow2Texture &= ~(1 << sampler);
3329 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3334 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3335 DWORD sampler = state - STATE_SAMPLER(0);
3336 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3342 TRACE("Sampler: %d\n", sampler);
3343 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3344 * only has to bind textures and set the per texture states
3347 if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3349 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3353 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3356 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3357 checkGLcall("glActiveTextureARB");
3359 if(stateblock->textures[sampler]) {
3360 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3361 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3362 tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3363 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3364 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3366 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3367 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3368 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3369 GL_TEXTURE_LOD_BIAS_EXT,
3371 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3374 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3376 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3377 /* If color keying is enabled update the alpha test, it depends on the existence
3378 * of a color key in stage 0
3380 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3383 } else if(mapped_stage < GL_LIMITS(textures)) {
3384 if(sampler < stateblock->lowest_disabled_stage) {
3385 /* TODO: What should I do with pixel shaders here ??? */
3386 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3387 /* If color keying is enabled update the alpha test, it depends on the existence
3388 * of a color key in stage 0
3390 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3392 } /* Otherwise tex_colorop disables the stage */
3393 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3394 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3398 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3399 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3400 BOOL use_pshader = use_ps(stateblock);
3401 BOOL use_vshader = use_vs(stateblock);
3405 if(!context->last_was_pshader) {
3406 /* Former draw without a pixel shader, some samplers
3407 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3408 * make sure to enable them
3410 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3411 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3412 sampler(STATE_SAMPLER(i), stateblock, context);
3415 context->last_was_pshader = TRUE;
3417 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3418 * if a different texture was bound. I don't have to do anything.
3422 /* Disabled the pixel shader - color ops weren't applied
3423 * while it was enabled, so re-apply them.
3425 for(i=0; i < MAX_TEXTURES; i++) {
3426 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3427 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3428 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3431 context->last_was_pshader = FALSE;
3434 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3435 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3437 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3438 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3443 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3444 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3445 if(stateblock->pixelShader && stage != 0 &&
3446 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3447 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3450 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3451 !isStateDirty(context, STATE_PIXELSHADER)) {
3452 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3457 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3458 /* This function is called by transform_view below if the view matrix was changed too
3460 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3461 * does not always update the world matrix, only on a switch between transformed
3462 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3463 * draw, but that should be rather rare and cheaper in total.
3465 glMatrixMode(GL_MODELVIEW);
3466 checkGLcall("glMatrixMode");
3468 if(context->last_was_rhw) {
3470 checkGLcall("glLoadIdentity()");
3472 /* In the general case, the view matrix is the identity matrix */
3473 if (stateblock->wineD3DDevice->view_ident) {
3474 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3475 checkGLcall("glLoadMatrixf");
3477 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3478 checkGLcall("glLoadMatrixf");
3479 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3480 checkGLcall("glMultMatrixf");
3485 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3486 UINT index = state - STATE_CLIPPLANE(0);
3488 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3492 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3493 glMatrixMode(GL_MODELVIEW);
3495 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3497 TRACE("Clipplane [%f,%f,%f,%f]\n",
3498 stateblock->clipplane[index][0],
3499 stateblock->clipplane[index][1],
3500 stateblock->clipplane[index][2],
3501 stateblock->clipplane[index][3]);
3502 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3503 checkGLcall("glClipPlane");
3508 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3509 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3511 TRACE("Setting world matrix %d\n", matrix);
3513 if(matrix >= GL_LIMITS(blends)) {
3514 WARN("Unsupported blend matrix set\n");
3516 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3520 /* GL_MODELVIEW0_ARB: 0x1700
3521 * GL_MODELVIEW1_ARB: 0x850a
3522 * GL_MODELVIEW2_ARB: 0x8722
3523 * GL_MODELVIEW3_ARB: 0x8723
3525 * GL_MODELVIEW31_ARB: 0x873F
3527 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3528 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3530 glMatrixMode(glMat);
3531 checkGLcall("glMatrixMode(glMat)");
3533 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3534 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3536 if(stateblock->wineD3DDevice->view_ident) {
3537 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3538 checkGLcall("glLoadMatrixf");
3540 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3541 checkGLcall("glLoadMatrixf");
3542 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3543 checkGLcall("glMultMatrixf");
3547 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3548 static BOOL once = FALSE;
3550 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3551 case WINED3DVBF_1WEIGHTS:
3552 case WINED3DVBF_2WEIGHTS:
3553 case WINED3DVBF_3WEIGHTS:
3556 /* TODO: Implement vertex blending in drawStridedSlow */
3557 FIXME("Vertex blending enabled, but not supported by hardware\n");
3561 case WINED3DVBF_TWEENING:
3562 WARN("Tweening not supported yet\n");
3566 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3567 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3570 case WINED3DVBF_1WEIGHTS:
3571 case WINED3DVBF_2WEIGHTS:
3572 case WINED3DVBF_3WEIGHTS:
3573 glEnable(GL_VERTEX_BLEND_ARB);
3574 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3576 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3577 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3579 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3581 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3583 for(i = 1; i < GL_LIMITS(blends); i++) {
3584 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3585 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3588 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3592 case WINED3DVBF_DISABLE:
3593 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3594 glDisable(GL_VERTEX_BLEND_ARB);
3595 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3598 case WINED3DVBF_TWEENING:
3599 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3600 * vertex weights in the vertices?
3601 * For now we don't report that as supported, so a warn should suffice
3603 WARN("Tweening not supported yet\n");
3608 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3611 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3612 * NOTE: We have to reset the positions even if the light/plane is not currently
3613 * enabled, since the call to enable it will not reset the position.
3614 * NOTE2: Apparently texture transforms do NOT need reapplying
3617 const PLIGHTINFOEL *light = NULL;
3619 glMatrixMode(GL_MODELVIEW);
3620 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3621 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3622 checkGLcall("glLoadMatrixf(...)");
3624 /* Reset lights. TODO: Call light apply func */
3625 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3626 light = stateblock->activeLights[k];
3627 if(!light) continue;
3628 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3629 checkGLcall("glLightfv posn");
3630 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3631 checkGLcall("glLightfv dirn");
3634 /* Reset Clipping Planes */
3635 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3636 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3637 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3641 if(context->last_was_rhw) {
3643 checkGLcall("glLoadIdentity()");
3644 /* No need to update the world matrix, the identity is fine */
3648 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3649 * No need to do it here if the state is scheduled for update.
3651 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3652 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3655 /* Avoid looping over a number of matrices if the app never used the functionality */
3656 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3657 for(k = 1; k < GL_LIMITS(blends); k++) {
3658 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3659 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3665 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3666 glMatrixMode(GL_PROJECTION);
3667 checkGLcall("glMatrixMode(GL_PROJECTION)");
3669 checkGLcall("glLoadIdentity");
3671 if(context->last_was_rhw) {
3672 double X, Y, height, width, minZ, maxZ;
3674 X = stateblock->viewport.X;
3675 Y = stateblock->viewport.Y;
3676 height = stateblock->viewport.Height;
3677 width = stateblock->viewport.Width;
3678 minZ = stateblock->viewport.MinZ;
3679 maxZ = stateblock->viewport.MaxZ;
3681 if(!stateblock->wineD3DDevice->untransformed) {
3682 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3683 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3684 * suppress depth clipping. This can be done because it is an orthogonal projection and
3685 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3686 * Persia 3D need this.
3688 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3689 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3690 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3693 * Also note that this breaks z comparison against z values filled in with clear,
3694 * but no app depending on that and disabled clipping has been found yet. Comparing
3695 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3698 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3699 * but this would break Z buffer operation. Raising the range to something less than
3700 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3703 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3704 if(stateblock->wineD3DDevice->render_offscreen) {
3705 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3707 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3710 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3711 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3712 * unmodified to opengl.
3714 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3715 * replacement shader.
3717 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3718 if(stateblock->wineD3DDevice->render_offscreen) {
3719 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3721 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3724 checkGLcall("glOrtho");
3726 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3727 glTranslatef(0.5, 0.5, 0);
3728 checkGLcall("glTranslatef(0.5, 0.5, 0)");
3729 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3730 * render everything upside down when rendering offscreen. */
3731 if (stateblock->wineD3DDevice->render_offscreen) {
3732 glScalef(1.0, -1.0, 1.0);
3733 checkGLcall("glScalef");
3736 /* The rule is that the window coordinate 0 does not correspond to the
3737 beginning of the first pixel, but the center of the first pixel.
3738 As a consequence if you want to correctly draw one line exactly from
3739 the left to the right end of the viewport (with all matrices set to
3740 be identity), the x coords of both ends of the line would be not
3741 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3744 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3745 divide by the Width/Height, so we need the half range(1.0) to translate by
3748 The other fun is that d3d's output z range after the transformation is [0;1],
3749 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3750 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3751 of Z buffer precision and the clear values do not match in the z test. Thus scale
3752 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3756 * Careful with the order of operations here, we're essentially working backwards:
3758 * y = (y - 1/h) * flip;
3762 * glTranslatef(0.0, 0.0, -1.0);
3763 * glScalef(1.0, 1.0, 2.0);
3765 * glScalef(1.0, flip, 1.0);
3766 * glTranslatef(1/w, -1/h, 0.0);
3768 * This is equivalent to:
3769 * glTranslatef(1/w, -flip/h, -1.0)
3770 * glScalef(1.0, flip, 2.0);
3773 if (stateblock->wineD3DDevice->render_offscreen) {
3774 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3775 * render everything upside down when rendering offscreen. */
3776 glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3777 checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3778 glScalef(1.0, -1.0, 2.0);
3780 glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3781 checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3782 glScalef(1.0, 1.0, 2.0);
3784 checkGLcall("glScalef");
3786 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3787 checkGLcall("glLoadMatrixf");
3791 /* This should match any arrays loaded in loadVertexData.
3792 * stateblock impl is required for GL_SUPPORT
3793 * TODO: Only load / unload arrays if we have to.
3795 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3796 glDisableClientState(GL_VERTEX_ARRAY);
3797 glDisableClientState(GL_NORMAL_ARRAY);
3798 glDisableClientState(GL_COLOR_ARRAY);
3799 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3800 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3802 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3803 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3805 unloadTexCoords(stateblock);
3808 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3810 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3811 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3812 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3813 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3814 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3815 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3816 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3818 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3819 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3821 context->numbered_array_mask &= ~(1 << i);
3824 /* This should match any arrays loaded in loadNumberedArrays
3825 * TODO: Only load / unload arrays if we have to.
3827 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3829 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3830 GLint maxAttribs = 16;
3833 /* Leave all the attribs disabled */
3834 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3835 /* MESA does not support it right not */
3836 if (glGetError() != GL_NO_ERROR)
3838 for (i = 0; i < maxAttribs; ++i) {
3839 unload_numbered_array(stateblock, context, i);
3843 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3844 const WineDirect3DVertexStridedData *strided, WineD3DContext *context)
3846 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3848 const UINT *offset = stateblock->streamOffset;
3849 struct wined3d_buffer *vb;
3850 DWORD_PTR shift_index;
3852 /* Default to no instancing */
3853 stateblock->wineD3DDevice->instancedDraw = FALSE;
3855 for (i = 0; i < MAX_ATTRIBS; i++) {
3856 if (!(strided->use_map & (1 << i)))
3858 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3862 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3863 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3864 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3865 stateblock->wineD3DDevice->instancedDraw = TRUE;
3869 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3871 if(strided->u.input[i].dwStride) {
3872 if(curVBO != strided->u.input[i].VBO) {
3873 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3874 checkGLcall("glBindBufferARB");
3875 curVBO = strided->u.input[i].VBO;
3877 vb = (struct wined3d_buffer *)stateblock->streamSource[strided->u.input[i].streamNo];
3878 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3879 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3880 * vbo we won't be load converted attributes anyway
3882 if (curVBO && vb->conversion_shift)
3884 TRACE("Loading attribute from shifted buffer\n");
3885 TRACE("Attrib %d has original stride %d, new stride %d\n",
3886 i, strided->u.input[i].dwStride, vb->conversion_stride);
3887 TRACE("Original offset %p, additional offset 0x%08x\n",
3888 strided->u.input[i].lpData, vb->conversion_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3889 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3890 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3891 shift_index = shift_index % strided->u.input[i].dwStride;
3892 GL_EXTCALL(glVertexAttribPointerARB(i, WINED3D_ATR_FORMAT(strided->u.input[i].dwType),
3893 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3894 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3895 vb->conversion_stride,
3896 strided->u.input[i].lpData + vb->conversion_shift[shift_index]
3897 + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride
3898 + offset[strided->u.input[i].streamNo]));
3901 GL_EXTCALL(glVertexAttribPointerARB(i,
3902 WINED3D_ATR_FORMAT(strided->u.input[i].dwType),
3903 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3904 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3905 strided->u.input[i].dwStride,
3907 strided->u.input[i].lpData +
3908 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3909 offset[strided->u.input[i].streamNo]) );
3912 if (!(context->numbered_array_mask & (1 << i)))
3914 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3915 context->numbered_array_mask |= (1 << i);
3918 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3919 * set up the attribute statically. But we have to figure out the system memory address.
3921 const BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3922 if(strided->u.input[i].VBO) {
3923 vb = (struct wined3d_buffer *)stateblock->streamSource[strided->u.input[i].streamNo];
3924 ptr += (long) vb->resource.allocatedMemory;
3927 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3929 switch(strided->u.input[i].dwType) {
3930 case WINED3DDECLTYPE_FLOAT1:
3931 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3933 case WINED3DDECLTYPE_FLOAT2:
3934 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3936 case WINED3DDECLTYPE_FLOAT3:
3937 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3939 case WINED3DDECLTYPE_FLOAT4:
3940 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3943 case WINED3DDECLTYPE_UBYTE4:
3944 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3946 case WINED3DDECLTYPE_D3DCOLOR:
3947 if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
3949 const DWORD *src = (const DWORD *)ptr;
3950 DWORD c = *src & 0xff00ff00;
3951 c |= (*src & 0xff0000) >> 16;
3952 c |= (*src & 0xff) << 16;
3953 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
3956 /* else fallthrough */
3957 case WINED3DDECLTYPE_UBYTE4N:
3958 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3961 case WINED3DDECLTYPE_SHORT2:
3962 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3964 case WINED3DDECLTYPE_SHORT4:
3965 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3968 case WINED3DDECLTYPE_SHORT2N:
3970 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
3971 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3974 case WINED3DDECLTYPE_USHORT2N:
3976 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
3977 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3980 case WINED3DDECLTYPE_SHORT4N:
3981 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
3983 case WINED3DDECLTYPE_USHORT4N:
3984 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
3987 case WINED3DDECLTYPE_UDEC3:
3988 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3989 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
3991 case WINED3DDECLTYPE_DEC3N:
3992 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3993 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
3996 case WINED3DDECLTYPE_FLOAT16_2:
3997 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3998 * byte float according to the IEEE standard
4000 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4002 case WINED3DDECLTYPE_FLOAT16_4:
4003 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4006 case WINED3DDECLTYPE_UNUSED:
4008 ERR("Unexpected declaration in stride 0 attributes\n");
4014 checkGLcall("Loading numbered arrays");
4017 /* Used from 2 different functions, and too big to justify making it inlined */
4018 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd)
4020 const UINT *offset = stateblock->streamOffset;
4021 GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4023 TRACE("Using fast vertex array code\n");
4025 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4026 stateblock->wineD3DDevice->instancedDraw = FALSE;
4028 /* Blend Data ---------------------------------------------- */
4029 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
4030 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
4032 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4033 TRACE("Blend %d %p %d\n", WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType),
4034 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4036 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4037 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4039 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) + 1));
4041 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4042 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4043 sd->u.s.blendWeights.dwStride,
4044 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4046 if(curVBO != sd->u.s.blendWeights.VBO) {
4047 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
4048 checkGLcall("glBindBufferARB");
4049 curVBO = sd->u.s.blendWeights.VBO;
4052 GL_EXTCALL(glWeightPointerARB)(
4053 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType),
4054 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
4055 sd->u.s.blendWeights.dwStride,
4056 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4058 checkGLcall("glWeightPointerARB");
4060 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
4064 FIXME("blendMatrixIndices support\n");
4069 /* TODO: support blends in drawStridedSlow
4070 * No need to write a FIXME here, this is done after the general vertex decl decoding
4072 WARN("unsupported blending in openGl\n");
4075 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4076 static const GLbyte one = 1;
4077 GL_EXTCALL(glWeightbvARB(1, &one));
4078 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4082 /* Point Size ----------------------------------------------*/
4083 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
4085 /* no such functionality in the fixed function GL pipeline */
4086 TRACE("Cannot change ptSize here in openGl\n");
4087 /* TODO: Implement this function in using shaders if they are available */
4091 /* Vertex Pointers -----------------------------------------*/
4092 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
4093 /* Note dwType == float3 or float4 == 2 or 3 */
4094 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
4095 sd->u.s.position.dwStride,
4096 sd->u.s.position.dwType + 1,
4097 sd->u.s.position.lpData));
4099 if(curVBO != sd->u.s.position.VBO) {
4100 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
4101 checkGLcall("glBindBufferARB");
4102 curVBO = sd->u.s.position.VBO;
4105 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4106 handling for rhw mode should not impact screen position whereas in GL it does.
4107 This may result in very slightly distorted textures in rhw mode.
4108 There's always the other option of fixing the view matrix to
4109 prevent w from having any effect.
4111 This only applies to user pointer sources, in VBOs the vertices are fixed up
4113 if(sd->u.s.position.VBO == 0) {
4114 glVertexPointer(3 /* min(WINED3D_ATR_FORMAT(sd->u.s.position.dwType),3) */,
4115 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4116 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4119 WINED3D_ATR_FORMAT(sd->u.s.position.dwType),
4120 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4121 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4123 checkGLcall("glVertexPointer(...)");
4124 glEnableClientState(GL_VERTEX_ARRAY);
4125 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4128 /* Normals -------------------------------------------------*/
4129 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
4130 /* Note dwType == float3 or float4 == 2 or 3 */
4131 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
4132 sd->u.s.normal.dwStride,
4133 sd->u.s.normal.lpData));
4134 if(curVBO != sd->u.s.normal.VBO) {
4135 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
4136 checkGLcall("glBindBufferARB");
4137 curVBO = sd->u.s.normal.VBO;
4140 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
4141 sd->u.s.normal.dwStride,
4142 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
4143 checkGLcall("glNormalPointer(...)");
4144 glEnableClientState(GL_NORMAL_ARRAY);
4145 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4148 glNormal3f(0, 0, 0);
4149 checkGLcall("glNormal3f(0, 0, 0)");
4152 /* Diffuse Colour --------------------------------------------*/
4153 /* WARNING: Data here MUST be in RGBA format, so cannot */
4154 /* go directly into fast mode from app pgm, because */
4155 /* directx requires data in BGRA format. */
4156 /* currently fixupVertices swizzles the format, but this isn't*/
4157 /* very practical when using VBOs */
4158 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4159 /* , or the user doesn't care and wants the speed advantage */
4161 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
4162 /* Note dwType == float3 or float4 == 2 or 3 */
4163 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4164 sd->u.s.diffuse.dwStride,
4165 sd->u.s.diffuse.lpData));
4167 if(curVBO != sd->u.s.diffuse.VBO) {
4168 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
4169 checkGLcall("glBindBufferARB");
4170 curVBO = sd->u.s.diffuse.VBO;
4173 glColorPointer(WINED3D_ATR_FORMAT(sd->u.s.diffuse.dwType),
4174 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
4175 sd->u.s.diffuse.dwStride,
4176 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
4177 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4178 glEnableClientState(GL_COLOR_ARRAY);
4179 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4182 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4183 checkGLcall("glColor4f(1, 1, 1, 1)");
4186 /* Specular Colour ------------------------------------------*/
4187 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
4188 TRACE("setting specular colour\n");
4189 /* Note dwType == float3 or float4 == 2 or 3 */
4190 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4191 sd->u.s.specular.dwStride,
4192 sd->u.s.specular.lpData));
4193 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4194 if(curVBO != sd->u.s.specular.VBO) {
4195 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
4196 checkGLcall("glBindBufferARB");
4197 curVBO = sd->u.s.specular.VBO;
4199 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_FORMAT(sd->u.s.specular.dwType),
4200 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
4201 sd->u.s.specular.dwStride,
4202 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
4203 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4204 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4205 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4208 /* Missing specular color is not critical, no warnings */
4209 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4213 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4214 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4215 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4218 /* Missing specular color is not critical, no warnings */
4219 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4223 /* Texture coords -------------------------------------------*/
4224 loadTexCoords(stateblock, sd, &curVBO);
4227 static inline void drawPrimitiveTraceDataLocations(const WineDirect3DVertexStridedData *dataLocations)
4229 /* Dump out what parts we have supplied */
4230 TRACE("Strided Data:\n");
4231 TRACE_STRIDED((dataLocations), position);
4232 TRACE_STRIDED((dataLocations), blendWeights);
4233 TRACE_STRIDED((dataLocations), blendMatrixIndices);
4234 TRACE_STRIDED((dataLocations), normal);
4235 TRACE_STRIDED((dataLocations), pSize);
4236 TRACE_STRIDED((dataLocations), diffuse);
4237 TRACE_STRIDED((dataLocations), specular);
4238 TRACE_STRIDED((dataLocations), texCoords[0]);
4239 TRACE_STRIDED((dataLocations), texCoords[1]);
4240 TRACE_STRIDED((dataLocations), texCoords[2]);
4241 TRACE_STRIDED((dataLocations), texCoords[3]);
4242 TRACE_STRIDED((dataLocations), texCoords[4]);
4243 TRACE_STRIDED((dataLocations), texCoords[5]);
4244 TRACE_STRIDED((dataLocations), texCoords[6]);
4245 TRACE_STRIDED((dataLocations), texCoords[7]);
4246 TRACE_STRIDED((dataLocations), position2);
4247 TRACE_STRIDED((dataLocations), normal2);
4248 TRACE_STRIDED((dataLocations), tangent);
4249 TRACE_STRIDED((dataLocations), binormal);
4250 TRACE_STRIDED((dataLocations), tessFactor);
4251 TRACE_STRIDED((dataLocations), fog);
4252 TRACE_STRIDED((dataLocations), depth);
4253 TRACE_STRIDED((dataLocations), sample);
4258 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4259 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4261 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
4262 BOOL useVertexShaderFunction;
4263 BOOL load_numbered = FALSE;
4264 BOOL load_named = FALSE;
4266 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4268 if(device->up_strided) {
4269 /* Note: this is a ddraw fixed-function code path */
4270 TRACE("================ Strided Input ===================\n");
4271 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
4274 drawPrimitiveTraceDataLocations(dataLocations);
4277 /* Note: This is a fixed function or shader codepath.
4278 * This means it must handle both types of strided data.
4279 * Shaders must go through here to zero the strided data, even if they
4280 * don't set any declaration at all
4282 TRACE("================ Vertex Declaration ===================\n");
4283 memset(dataLocations, 0, sizeof(*dataLocations));
4284 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
4285 useVertexShaderFunction, dataLocations, &fixup);
4288 if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4290 if(useVertexShaderFunction) {
4291 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4292 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4293 device->useDrawStridedSlow = TRUE;
4295 load_numbered = TRUE;
4296 device->useDrawStridedSlow = FALSE;
4298 } else if (fixup || (!dataLocations->u.s.pSize.lpData
4299 && !dataLocations->position_transformed
4300 && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)
4301 || (!dataLocations->u.s.diffuse.lpData
4302 && !dataLocations->u.s.specular.lpData))))
4304 /* Load the vertex data using named arrays */
4306 device->useDrawStridedSlow = FALSE;
4308 TRACE("Not loading vertex data\n");
4309 device->useDrawStridedSlow = TRUE;
4312 if (context->numberedArraysLoaded && !load_numbered)
4314 unloadNumberedArrays(stateblock, context);
4315 context->numberedArraysLoaded = FALSE;
4316 context->numbered_array_mask = 0;
4318 else if (context->namedArraysLoaded)
4320 unloadVertexData(stateblock);
4321 context->namedArraysLoaded = FALSE;
4326 TRACE("Loading numbered arrays\n");
4327 loadNumberedArrays(stateblock, dataLocations, context);
4328 context->numberedArraysLoaded = TRUE;
4330 else if (load_named)
4332 TRACE("Loading vertex data\n");
4333 loadVertexData(stateblock, dataLocations);
4334 context->namedArraysLoaded = TRUE;
4337 /* Generate some fixme's if unsupported functionality is being used */
4338 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
4339 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
4340 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
4341 FIXME("Tweening is only valid with vertex shaders\n");
4343 if (!useVertexShaderFunction && BUFFER_OR_DATA(binormal)) {
4344 FIXME("Binormal bump mapping is only valid with vertex shaders\n");
4346 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
4347 FIXME("Extended attributes are only valid with vertex shaders\n");
4349 #undef BUFFER_OR_DATA
4352 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4353 BOOL updateFog = FALSE;
4354 BOOL useVertexShaderFunction = use_vs(stateblock);
4355 BOOL usePixelShaderFunction = use_ps(stateblock);
4357 /* Some stuff is in the device until we have per context tracking */
4358 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4359 BOOL wasrhw = context->last_was_rhw;
4361 transformed = device->strided_streams.position_transformed;
4362 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4366 /* Reapply lighting if it is not scheduled for reapplication already */
4367 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4368 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4372 context->last_was_rhw = TRUE;
4375 /* Untransformed, so relies on the view and projection matrices */
4376 context->last_was_rhw = FALSE;
4377 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4378 device->untransformed = TRUE;
4380 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4381 * Not needed as long as only hw shaders are supported
4384 /* This sets the shader output position correction constants.
4385 * TODO: Move to the viewport state
4387 if (useVertexShaderFunction) {
4388 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4389 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4393 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4394 * off this function will be called again anyway to make sure they're properly set
4396 if(!useVertexShaderFunction) {
4397 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4398 * or transformed / untransformed was switched
4400 if(wasrhw != context->last_was_rhw &&
4401 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4402 !isStateDirty(context, STATE_VIEWPORT)) {
4403 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4405 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4408 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4409 * this check will fail and the matrix not applied again. This is OK because a simple
4410 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4411 * needs of the vertex declaration.
4413 * World and view matrix go into the same gl matrix, so only apply them when neither is
4416 if(transformed != wasrhw &&
4417 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4418 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4419 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4422 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4423 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4426 if(context->last_was_vshader) {
4428 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4429 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4432 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4433 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4436 if(!context->last_was_vshader) {
4438 static BOOL warned = FALSE;
4439 /* Disable all clip planes to get defined results on all drivers. See comment in the
4440 * state_clipping state handler
4442 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4443 glDisable(GL_CLIP_PLANE0 + i);
4444 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4447 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4448 FIXME("Clipping not supported with vertex shaders\n");
4452 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4453 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4454 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4455 * fixed function vertex processing states back in a sane state before switching to shaders
4457 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4458 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4460 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4461 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4468 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4471 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4472 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4474 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4475 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4479 context->last_was_vshader = useVertexShaderFunction;
4482 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4484 if(!useVertexShaderFunction) {
4486 for(i = 0; i < MAX_TEXTURES; i++) {
4487 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4488 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4494 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4496 IWineD3DSurfaceImpl *target;
4498 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4499 checkGLcall("glDepthRange");
4500 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4502 if(stateblock->wineD3DDevice->render_offscreen) {
4503 glViewport(stateblock->viewport.X,
4504 stateblock->viewport.Y,
4505 stateblock->viewport.Width, stateblock->viewport.Height);
4507 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4508 target->get_drawable_size(target, &width, &height);
4510 glViewport(stateblock->viewport.X,
4511 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4512 stateblock->viewport.Width, stateblock->viewport.Height);
4515 checkGLcall("glViewport");
4518 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4519 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4520 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4521 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4522 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4524 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4525 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4529 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4530 UINT Index = state - STATE_ACTIVELIGHT(0);
4531 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4534 glDisable(GL_LIGHT0 + Index);
4535 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4538 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4540 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4541 glMatrixMode(GL_MODELVIEW);
4543 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4546 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4547 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4548 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4549 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4550 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4551 checkGLcall("glLightfv");
4554 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4555 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4556 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4557 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4558 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4559 checkGLcall("glLightfv");
4562 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4563 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4564 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4565 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4566 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4567 checkGLcall("glLightfv");
4569 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4570 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4572 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
4575 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4576 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4577 * Attenuation0 to NaN and crashes in the gl lib
4580 switch (lightInfo->OriginalParms.Type) {
4581 case WINED3DLIGHT_POINT:
4583 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4584 checkGLcall("glLightfv");
4585 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4586 checkGLcall("glLightf");
4587 /* Attenuation - Are these right? guessing... */
4588 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4589 checkGLcall("glLightf");
4590 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4591 checkGLcall("glLightf");
4592 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4593 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4594 checkGLcall("glLightf");
4598 case WINED3DLIGHT_SPOT:
4600 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4601 checkGLcall("glLightfv");
4603 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4604 checkGLcall("glLightfv");
4605 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4606 checkGLcall("glLightf");
4607 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4608 checkGLcall("glLightf");
4609 /* Attenuation - Are these right? guessing... */
4610 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4611 checkGLcall("glLightf");
4612 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4613 checkGLcall("glLightf");
4614 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4615 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4616 checkGLcall("glLightf");
4620 case WINED3DLIGHT_DIRECTIONAL:
4622 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4623 checkGLcall("glLightfv");
4624 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4625 checkGLcall("glLightf");
4626 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4627 checkGLcall("glLightf");
4631 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4634 /* Restore the modelview matrix */
4637 glEnable(GL_LIGHT0 + Index);
4638 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4644 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4645 RECT *pRect = &stateblock->scissorRect;
4648 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4650 target->get_drawable_size(target, &width, &height);
4651 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4652 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4654 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4655 pRect->right - pRect->left, pRect->bottom - pRect->top);
4657 if (stateblock->wineD3DDevice->render_offscreen) {
4658 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4660 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4662 checkGLcall("glScissor");
4665 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4666 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4667 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4669 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
4670 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
4674 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4675 if(stateblock->wineD3DDevice->render_offscreen) {
4676 glFrontFace(GL_CCW);
4677 checkGLcall("glFrontFace(GL_CCW)");
4680 checkGLcall("glFrontFace(GL_CW)");
4684 const struct StateEntryTemplate misc_state_template[] = {
4685 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4686 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4687 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4688 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4689 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4690 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4691 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4692 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4693 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4694 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4695 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
4696 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
4697 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
4698 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
4699 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4700 * vshader loadings are untied from each other
4702 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4703 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4704 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4705 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4706 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4707 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4708 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4709 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4710 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4711 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4712 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4713 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4714 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4715 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4716 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4717 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4718 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4719 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4720 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4721 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4722 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4723 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4724 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4725 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4726 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4727 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4728 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4729 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4730 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4731 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4732 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4733 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4734 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4735 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4736 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4737 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4738 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4739 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4740 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4741 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4742 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4743 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4744 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4745 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4746 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4747 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4748 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4749 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4750 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4751 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4753 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
4754 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4755 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
4756 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
4757 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
4758 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
4759 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
4760 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
4761 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
4762 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
4763 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
4764 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
4765 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
4766 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
4767 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4768 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4769 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4770 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4771 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
4772 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
4773 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
4774 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
4775 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
4776 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
4777 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
4778 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
4779 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
4780 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
4781 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
4782 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
4783 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
4784 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4785 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4786 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4787 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4788 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4789 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4790 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4791 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4792 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
4793 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4794 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4795 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4796 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4797 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4798 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4799 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4800 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4801 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4802 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4803 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4804 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4805 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4806 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4807 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4808 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4809 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4810 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4811 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4812 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4813 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4814 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
4815 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
4816 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
4817 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
4818 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
4819 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
4820 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4821 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4822 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4823 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4824 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4825 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4826 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4827 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4828 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 },
4829 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
4830 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4831 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4832 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 },
4833 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
4834 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4835 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4836 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4837 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4838 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
4839 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 },
4840 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4842 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
4843 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
4844 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
4845 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
4846 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
4847 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
4848 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
4849 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
4850 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
4851 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
4852 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
4853 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
4854 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
4855 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
4856 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
4857 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
4858 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
4859 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
4860 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
4861 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
4862 {0 /* Terminate */, { 0, 0 }, 0 },
4865 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4866 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
4867 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
4868 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4869 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4871 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
4872 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
4873 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
4874 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
4875 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
4876 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
4877 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
4878 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
4879 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
4880 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
4881 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
4882 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
4883 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
4884 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
4885 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
4886 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
4887 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
4888 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
4889 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
4890 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
4891 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
4892 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
4893 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
4894 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
4895 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
4896 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
4897 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
4898 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
4899 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
4900 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
4901 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
4902 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
4904 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
4905 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
4906 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
4907 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
4908 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
4909 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
4910 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
4911 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
4913 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
4914 /* Transform states follow */
4915 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
4916 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
4917 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4918 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4919 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4920 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4921 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4922 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4923 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4924 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4925 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4926 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, 0 },
4927 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, 0 },
4928 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, 0 },
4929 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, 0 },
4930 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, 0 },
4931 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, 0 },
4932 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, 0 },
4933 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, 0 },
4934 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, 0 },
4935 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, 0 },
4936 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, 0 },
4937 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, 0 },
4938 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, 0 },
4939 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, 0 },
4940 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, 0 },
4941 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, 0 },
4942 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, 0 },
4943 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, 0 },
4944 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, 0 },
4945 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, 0 },
4946 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, 0 },
4947 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, 0 },
4948 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, 0 },
4949 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, 0 },
4950 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, 0 },
4951 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, 0 },
4952 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, 0 },
4953 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, 0 },
4954 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, 0 },
4955 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, 0 },
4956 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, 0 },
4957 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, 0 },
4958 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, 0 },
4959 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, 0 },
4960 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, 0 },
4961 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, 0 },
4962 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, 0 },
4963 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, 0 },
4964 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, 0 },
4965 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, 0 },
4966 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, 0 },
4967 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, 0 },
4968 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, 0 },
4969 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, 0 },
4970 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, 0 },
4971 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, 0 },
4972 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, 0 },
4973 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, 0 },
4974 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, 0 },
4975 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, 0 },
4976 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, 0 },
4977 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, 0 },
4978 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, 0 },
4979 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, 0 },
4980 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, 0 },
4981 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, 0 },
4982 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, 0 },
4983 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, 0 },
4984 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, 0 },
4985 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, 0 },
4986 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, 0 },
4987 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, 0 },
4988 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, 0 },
4989 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, 0 },
4990 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, 0 },
4991 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, 0 },
4992 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, 0 },
4993 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, 0 },
4994 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, 0 },
4995 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, 0 },
4996 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, 0 },
4997 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, 0 },
4998 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, 0 },
4999 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, 0 },
5000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, 0 },
5001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, 0 },
5002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, 0 },
5003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, 0 },
5004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, 0 },
5005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, 0 },
5006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, 0 },
5007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, 0 },
5008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, 0 },
5009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, 0 },
5010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, 0 },
5011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, 0 },
5012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, 0 },
5013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, 0 },
5014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, 0 },
5015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, 0 },
5016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, 0 },
5017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, 0 },
5018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, 0 },
5019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, 0 },
5020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, 0 },
5021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, 0 },
5022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, 0 },
5023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, 0 },
5024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, 0 },
5025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, 0 },
5026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, 0 },
5027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, 0 },
5028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, 0 },
5029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, 0 },
5030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, 0 },
5031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, 0 },
5032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, 0 },
5033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, 0 },
5034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, 0 },
5035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, 0 },
5036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, 0 },
5037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, 0 },
5038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, 0 },
5039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, 0 },
5040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, 0 },
5041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, 0 },
5042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, 0 },
5043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, 0 },
5044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, 0 },
5045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, 0 },
5046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, 0 },
5047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, 0 },
5048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, 0 },
5049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, 0 },
5050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, 0 },
5051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, 0 },
5052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, 0 },
5053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, 0 },
5054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, 0 },
5055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, 0 },
5056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, 0 },
5057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, 0 },
5058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, 0 },
5059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, 0 },
5060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, 0 },
5061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, 0 },
5062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, 0 },
5063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, 0 },
5064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, 0 },
5065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, 0 },
5066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, 0 },
5067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, 0 },
5068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, 0 },
5069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, 0 },
5070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, 0 },
5071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, 0 },
5072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, 0 },
5073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, 0 },
5074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, 0 },
5075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, 0 },
5076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, 0 },
5077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, 0 },
5078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, 0 },
5079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, 0 },
5080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, 0 },
5081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, 0 },
5082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, 0 },
5083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, 0 },
5084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, 0 },
5085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, 0 },
5086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, 0 },
5087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, 0 },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, 0 },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, 0 },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, 0 },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, 0 },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, 0 },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, 0 },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, 0 },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, 0 },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, 0 },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, 0 },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, 0 },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, 0 },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, 0 },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, 0 },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, 0 },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, 0 },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, 0 },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, 0 },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, 0 },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, 0 },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, 0 },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, 0 },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, 0 },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, 0 },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, 0 },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, 0 },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, 0 },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, 0 },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, 0 },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, 0 },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, 0 },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, 0 },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, 0 },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, 0 },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, 0 },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, 0 },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, 0 },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, 0 },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, 0 },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, 0 },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, 0 },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, 0 },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, 0 },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, 0 },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, 0 },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, 0 },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, 0 },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, 0 },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, 0 },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, 0 },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, 0 },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, 0 },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, 0 },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, 0 },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, 0 },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, 0 },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, 0 },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, 0 },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, 0 },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, 0 },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, 0 },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, 0 },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, 0 },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, 0 },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, 0 },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, 0 },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, 0 },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, 0 },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, 0 },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, 0 },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, 0 },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, 0 },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, 0 },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, 0 },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, 0 },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, 0 },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, 0 },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, 0 },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, 0 },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, 0 },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, 0 },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, 0 },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, 0 },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, 0 },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, 0 },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, 0 },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, 0 },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, 0 },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, 0 },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, 0 },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, 0 },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, 0 },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, 0 },
5181 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5182 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5183 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5184 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5185 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5186 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5187 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5188 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5189 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5190 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5191 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5192 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5193 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5194 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5195 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5196 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5198 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5199 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5200 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5201 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5202 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 },
5203 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5204 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5205 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
5206 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
5207 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5208 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
5209 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
5210 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5211 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5212 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5213 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5214 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5215 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, 0 },
5216 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5217 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5218 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5219 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5220 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5221 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 },
5222 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5223 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5224 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5225 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5226 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5227 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5228 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5229 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5230 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5231 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5233 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5234 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5235 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
5236 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5237 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5238 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
5239 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5240 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5241 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
5242 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5243 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5244 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
5245 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5246 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5247 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
5248 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5249 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5250 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
5251 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5252 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5253 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
5254 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5255 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5256 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
5257 {0 /* Terminate */, { 0, 0 }, 0 },
5260 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5261 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5262 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5263 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5264 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5265 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5266 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5267 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5268 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5269 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5270 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5271 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5272 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5273 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5274 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5275 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5276 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5277 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5278 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5279 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5280 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5281 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5282 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5283 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5284 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5285 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5286 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5287 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5288 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5289 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5290 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5291 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5292 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5293 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5294 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5295 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5296 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5297 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5298 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5299 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5300 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5301 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5302 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5303 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5304 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5305 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5306 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5307 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5308 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5309 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5310 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5311 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5312 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5313 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5314 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5315 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5316 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5317 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5318 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5319 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5320 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5321 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5322 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5323 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5324 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5325 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5326 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5327 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5328 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5329 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5330 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5331 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5332 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5333 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5334 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5335 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5336 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5337 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5338 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5339 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5340 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5341 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5342 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5343 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
5344 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
5345 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
5346 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
5347 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5348 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5349 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5350 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
5351 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
5352 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
5353 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
5354 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
5355 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
5356 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
5357 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
5358 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
5359 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
5360 {0 /* Terminate */, { 0, 0 }, 0 },
5362 #undef GLINFO_LOCATION
5364 #define GLINFO_LOCATION (*gl_info)
5365 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5367 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5369 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5370 WINED3DTEXOPCAPS_ADDSIGNED |
5371 WINED3DTEXOPCAPS_ADDSIGNED2X |
5372 WINED3DTEXOPCAPS_MODULATE |
5373 WINED3DTEXOPCAPS_MODULATE2X |
5374 WINED3DTEXOPCAPS_MODULATE4X |
5375 WINED3DTEXOPCAPS_SELECTARG1 |
5376 WINED3DTEXOPCAPS_SELECTARG2 |
5377 WINED3DTEXOPCAPS_DISABLE;
5379 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5380 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5381 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5382 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5383 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5384 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5385 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5386 WINED3DTEXOPCAPS_LERP |
5387 WINED3DTEXOPCAPS_SUBTRACT;
5389 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5390 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5391 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5392 WINED3DTEXOPCAPS_MULTIPLYADD |
5393 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5394 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5395 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5397 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5398 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5400 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5401 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5404 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5405 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5406 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5410 TRACE("Checking support for fixup:\n");
5411 dump_color_fixup_desc(fixup);
5414 /* We only support identity conversions. */
5415 if (is_identity_fixup(fixup))
5421 TRACE("[FAILED]\n");
5425 const struct fragment_pipeline ffp_fragment_pipeline = {
5427 ffp_fragment_get_caps,
5430 ffp_color_fixup_supported,
5431 ffp_fragmentstate_template,
5432 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5435 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5438 for(i = 0; funcs[i]; i++);
5442 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5443 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5444 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5447 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5448 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5449 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5450 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5453 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5454 const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5455 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5457 unsigned int i, type, handlers;
5458 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5459 const struct StateEntryTemplate *cur;
5460 BOOL set[STATE_HIGHEST + 1];
5462 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5464 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5465 StateTable[i].representative = 0;
5466 StateTable[i].apply = state_undefined;
5469 for(type = 0; type < 3; type++) {
5470 /* This switch decides the order in which the states are applied */
5472 case 0: cur = misc; break;
5473 case 1: cur = fragment->states; break;
5474 case 2: cur = vertex; break;
5475 default: cur = NULL; /* Stupid compiler */
5479 /* GL extension filtering should not prevent multiple handlers being applied from different
5482 memset(set, 0, sizeof(set));
5484 for(i = 0; cur[i].state; i++) {
5485 APPLYSTATEFUNC *funcs_array;
5487 /* Only use the first matching state with the available extension from one template.
5489 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5490 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5492 * if GL_XYZ_fancy is supported, ignore the 2nd line
5494 if(set[cur[i].state]) continue;
5495 /* Skip state lines depending on unsupported extensions */
5496 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5497 set[cur[i].state] = TRUE;
5498 /* In some cases having an extension means that nothing has to be
5499 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5500 * supported, the texture coordinate fixup can be ignored. If the
5501 * apply function is used, mark the state set(done above) to prevent
5502 * applying later lines, but do not record anything in the state
5505 if(!cur[i].content.apply) continue;
5507 handlers = num_handlers(multistate_funcs[cur[i].state]);
5508 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5511 StateTable[cur[i].state].apply = cur[i].content.apply;
5514 StateTable[cur[i].state].apply = multistate_apply_2;
5515 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5517 sizeof(**dev_multistate_funcs) * 2);
5518 if (!dev_multistate_funcs[cur[i].state]) {
5522 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5523 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5526 StateTable[cur[i].state].apply = multistate_apply_3;
5527 funcs_array = HeapReAlloc(GetProcessHeap(),
5529 dev_multistate_funcs[cur[i].state],
5530 sizeof(**dev_multistate_funcs) * 3);
5535 dev_multistate_funcs[cur[i].state] = funcs_array;
5536 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5539 ERR("Unexpected amount of state handlers for state %u: %u\n",
5540 cur[i].state, handlers + 1);
5543 if(StateTable[cur[i].state].representative &&
5544 StateTable[cur[i].state].representative != cur[i].content.representative) {
5545 FIXME("State %u has different representatives in different pipeline parts\n",
5548 StateTable[cur[i].state].representative = cur[i].content.representative;
5555 for (i = 0; i <= STATE_HIGHEST; ++i) {
5556 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5559 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5561 return E_OUTOFMEMORY;
5563 #undef GLINFO_LOCATION