VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/state.c@ 16477

Last change on this file since 16477 was 16477, checked in by vboxsync, 16 years ago

LGPL disclaimer by filemuncher

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette