ReactOS  0.4.13-dev-479-gec9c8fd
state.c
Go to the documentation of this file.
1 /*
2  * Direct3D state management
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Henri Verbeet
10  * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11  * Copyright 2009-2011 Henri Verbeet 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 #include "config.h"
29 #include "wine/port.h"
30 
31 #include <stdio.h>
32 #ifdef HAVE_FLOAT_H
33 # include <float.h>
34 #endif
35 
36 #include "wined3d_private.h"
37 
39 
41 {
42  ULONG refcount = InterlockedIncrement(&state->refcount);
43 
44  TRACE("%p increasing refcount to %u.\n", state, refcount);
45 
46  return refcount;
47 }
48 
49 static void wined3d_blend_state_destroy_object(void *object)
50 {
51  heap_free(object);
52 }
53 
55 {
56  ULONG refcount = InterlockedDecrement(&state->refcount);
57  struct wined3d_device *device = state->device;
58 
59  TRACE("%p decreasing refcount to %u.\n", state, refcount);
60 
61  if (!refcount)
62  {
63  state->parent_ops->wined3d_object_destroyed(state->parent);
65  }
66 
67  return refcount;
68 }
69 
71 {
72  TRACE("state %p.\n", state);
73 
74  return state->parent;
75 }
76 
78  const struct wined3d_blend_state_desc *desc, void *parent,
79  const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state)
80 {
82 
83  TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n",
85 
86  if (!(object = heap_alloc_zero(sizeof(*object))))
87  return E_OUTOFMEMORY;
88 
89  object->refcount = 1;
90  object->desc = *desc;
91  object->parent = parent;
92  object->parent_ops = parent_ops;
93  object->device = device;
94 
95  TRACE("Created blend state %p.\n", object);
96  *state = object;
97 
98  return WINED3D_OK;
99 }
100 
102 {
104 
105  TRACE("%p increasing refcount to %u.\n", state, refcount);
106 
107  return refcount;
108 }
109 
111 {
112  heap_free(object);
113 }
114 
116 {
118  struct wined3d_device *device = state->device;
119 
120  TRACE("%p decreasing refcount to %u.\n", state, refcount);
121 
122  if (!refcount)
123  {
124  state->parent_ops->wined3d_object_destroyed(state->parent);
126  }
127 
128  return refcount;
129 }
130 
132 {
133  TRACE("rasterizer_state %p.\n", state);
134 
135  return state->parent;
136 }
137 
139  const struct wined3d_rasterizer_state_desc *desc, void *parent,
140  const struct wined3d_parent_ops *parent_ops, struct wined3d_rasterizer_state **state)
141 {
143 
144  TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n",
146 
147  if (!(object = heap_alloc_zero(sizeof(*object))))
148  return E_OUTOFMEMORY;
149 
150  object->refcount = 1;
151  object->desc = *desc;
152  object->parent = parent;
153  object->parent_ops = parent_ops;
154  object->device = device;
155 
156  TRACE("Created rasterizer state %p.\n", object);
157  *state = object;
158 
159  return WINED3D_OK;
160 }
161 
162 /* Context activation for state handler is done by the caller. */
163 
164 static void state_undefined(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
165 {
166  ERR("Undefined state %s (%#x).\n", debug_d3dstate(state_id), state_id);
167 }
168 
169 void state_nop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
170 {
171  TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state_id));
172 }
173 
174 static void state_fillmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
175 {
176  enum wined3d_fill_mode mode = state->render_states[WINED3D_RS_FILLMODE];
177  const struct wined3d_gl_info *gl_info = context->gl_info;
178 
179  switch (mode)
180  {
181  case WINED3D_FILL_POINT:
182  gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
183  checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
184  break;
186  gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
187  checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
188  break;
189  case WINED3D_FILL_SOLID:
190  gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
191  checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
192  break;
193  default:
194  FIXME("Unrecognized fill mode %#x.\n", mode);
195  }
196 }
197 
198 static void state_lighting(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
199 {
200  const struct wined3d_gl_info *gl_info = context->gl_info;
201 
202  /* Lighting is not enabled if transformed vertices are drawn, but lighting
203  * does not affect the stream sources, so it is not grouped for
204  * performance reasons. This state reads the decoded vertex declaration,
205  * so if it is dirty don't do anything. The vertex declaration applying
206  * function calls this function for updating. */
208  return;
209 
210  if (state->render_states[WINED3D_RS_LIGHTING]
211  && !context->stream_info.position_transformed)
212  {
213  gl_info->gl_ops.gl.p_glEnable(GL_LIGHTING);
214  checkGLcall("glEnable GL_LIGHTING");
215  }
216  else
217  {
218  gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
219  checkGLcall("glDisable GL_LIGHTING");
220  }
221 }
222 
223 static void state_zenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
224 {
225  enum wined3d_depth_buffer_type zenable = state->render_states[WINED3D_RS_ZENABLE];
226  const struct wined3d_gl_info *gl_info = context->gl_info;
227 
228  /* No z test without depth stencil buffers */
229  if (!state->fb->depth_stencil)
230  {
231  TRACE("No Z buffer - disabling depth test\n");
232  zenable = WINED3D_ZB_FALSE;
233  }
234 
235  switch (zenable)
236  {
237  case WINED3D_ZB_FALSE:
238  gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
239  checkGLcall("glDisable GL_DEPTH_TEST");
240  break;
241  case WINED3D_ZB_TRUE:
242  gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
243  checkGLcall("glEnable GL_DEPTH_TEST");
244  break;
245  case WINED3D_ZB_USEW:
246  gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
247  checkGLcall("glEnable GL_DEPTH_TEST");
248  FIXME("W buffer is not well handled\n");
249  break;
250  default:
251  FIXME("Unrecognized depth buffer type %#x.\n", zenable);
252  break;
253  }
254 
257 }
258 
259 static void state_cullmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
260 {
261  const struct wined3d_gl_info *gl_info = context->gl_info;
262 
263  /* glFrontFace() is set in context.c at context init and on an
264  * offscreen / onscreen rendering switch. */
265  switch (state->render_states[WINED3D_RS_CULLMODE])
266  {
267  case WINED3D_CULL_NONE:
268  gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
269  checkGLcall("glDisable GL_CULL_FACE");
270  break;
271  case WINED3D_CULL_FRONT:
272  gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
273  checkGLcall("glEnable GL_CULL_FACE");
274  gl_info->gl_ops.gl.p_glCullFace(GL_FRONT);
275  checkGLcall("glCullFace(GL_FRONT)");
276  break;
277  case WINED3D_CULL_BACK:
278  gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
279  checkGLcall("glEnable GL_CULL_FACE");
280  gl_info->gl_ops.gl.p_glCullFace(GL_BACK);
281  checkGLcall("glCullFace(GL_BACK)");
282  break;
283  default:
284  FIXME("Unrecognized cull mode %#x.\n",
285  state->render_states[WINED3D_RS_CULLMODE]);
286  }
287 }
288 
289 void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
290 {
291  const struct wined3d_gl_info *gl_info = context->gl_info;
292 
293  switch (state->render_states[WINED3D_RS_SHADEMODE])
294  {
295  case WINED3D_SHADE_FLAT:
296  gl_info->gl_ops.gl.p_glShadeModel(GL_FLAT);
297  checkGLcall("glShadeModel(GL_FLAT)");
298  break;
300  /* WINED3D_SHADE_PHONG in practice is the same as WINED3D_SHADE_GOURAUD
301  * in D3D. */
302  case WINED3D_SHADE_PHONG:
303  gl_info->gl_ops.gl.p_glShadeModel(GL_SMOOTH);
304  checkGLcall("glShadeModel(GL_SMOOTH)");
305  break;
306  default:
307  FIXME("Unrecognized shade mode %#x.\n",
308  state->render_states[WINED3D_RS_SHADEMODE]);
309  }
310 }
311 
312 static void state_ditherenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
313 {
314  const struct wined3d_gl_info *gl_info = context->gl_info;
315 
316  if (state->render_states[WINED3D_RS_DITHERENABLE])
317  {
318  gl_info->gl_ops.gl.p_glEnable(GL_DITHER);
319  checkGLcall("glEnable GL_DITHER");
320  }
321  else
322  {
323  gl_info->gl_ops.gl.p_glDisable(GL_DITHER);
324  checkGLcall("glDisable GL_DITHER");
325  }
326 }
327 
328 static void state_zwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
329 {
330  const struct wined3d_gl_info *gl_info = context->gl_info;
331 
332  if (state->render_states[WINED3D_RS_ZWRITEENABLE])
333  {
334  gl_info->gl_ops.gl.p_glDepthMask(1);
335  checkGLcall("glDepthMask(1)");
336  }
337  else
338  {
339  gl_info->gl_ops.gl.p_glDepthMask(0);
340  checkGLcall("glDepthMask(0)");
341  }
342 }
343 
345 {
346  switch (f)
347  {
348  case WINED3D_CMP_NEVER:
349  return GL_NEVER;
350  case WINED3D_CMP_LESS:
351  return GL_LESS;
352  case WINED3D_CMP_EQUAL:
353  return GL_EQUAL;
355  return GL_LEQUAL;
356  case WINED3D_CMP_GREATER:
357  return GL_GREATER;
359  return GL_NOTEQUAL;
361  return GL_GEQUAL;
362  case WINED3D_CMP_ALWAYS:
363  return GL_ALWAYS;
364  default:
365  if (!f)
366  WARN("Unrecognized compare function %#x.\n", f);
367  else
368  FIXME("Unrecognized compare function %#x.\n", f);
369  return GL_NONE;
370  }
371 }
372 
373 static void state_zfunc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
374 {
375  GLenum depth_func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ZFUNC]);
376  const struct wined3d_gl_info *gl_info = context->gl_info;
377 
378  if (!depth_func) return;
379 
380  gl_info->gl_ops.gl.p_glDepthFunc(depth_func);
381  checkGLcall("glDepthFunc");
382 }
383 
384 static void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
385 {
386  const struct wined3d_gl_info *gl_info = context->gl_info;
387  struct wined3d_color color;
388 
390  TRACE("Setting ambient to %s.\n", debug_color(&color));
391  gl_info->gl_ops.gl.p_glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &color.r);
392  checkGLcall("glLightModel for MODEL_AMBIENT");
393 }
394 
395 static void state_blendop_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
396 {
397  WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
398 }
399 
400 static GLenum gl_blend_op(const struct wined3d_gl_info *gl_info, enum wined3d_blend_op op)
401 {
402  switch (op)
403  {
405  return GL_FUNC_ADD;
411  return gl_info->supported[EXT_BLEND_MINMAX] ? GL_MIN : GL_FUNC_ADD;
413  return gl_info->supported[EXT_BLEND_MINMAX] ? GL_MAX : GL_FUNC_ADD;
414  default:
415  if (!op)
416  WARN("Unhandled blend op %#x.\n", op);
417  else
418  FIXME("Unhandled blend op %#x.\n", op);
419  return GL_FUNC_ADD;
420  }
421 }
422 
423 static void state_blendop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
424 {
425  const struct wined3d_gl_info *gl_info = context->gl_info;
426  GLenum blend_equation_alpha = GL_FUNC_ADD_EXT;
427  GLenum blend_equation = GL_FUNC_ADD_EXT;
428 
429  /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
430  if (state->render_states[WINED3D_RS_BLENDOPALPHA]
432  {
433  WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparate.\n");
434  return;
435  }
436 
437  blend_equation = gl_blend_op(gl_info, state->render_states[WINED3D_RS_BLENDOP]);
438  blend_equation_alpha = gl_blend_op(gl_info, state->render_states[WINED3D_RS_BLENDOPALPHA]);
439  TRACE("blend_equation %#x, blend_equation_alpha %#x.\n", blend_equation, blend_equation_alpha);
440 
441  if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
442  {
443  GL_EXTCALL(glBlendEquationSeparate(blend_equation, blend_equation_alpha));
444  checkGLcall("glBlendEquationSeparate");
445  }
446  else
447  {
448  GL_EXTCALL(glBlendEquation(blend_equation));
449  checkGLcall("glBlendEquation");
450  }
451 }
452 
454 {
455  switch (factor)
456  {
457  case WINED3D_BLEND_ZERO:
458  return GL_ZERO;
459  case WINED3D_BLEND_ONE:
460  return GL_ONE;
462  return GL_SRC_COLOR;
464  return GL_ONE_MINUS_SRC_COLOR;
466  return GL_SRC_ALPHA;
468  return GL_ONE_MINUS_SRC_ALPHA;
470  return GL_DST_COLOR;
472  return GL_ONE_MINUS_DST_COLOR;
473  /* To compensate for the lack of format switching with backbuffer
474  * offscreen rendering, and with onscreen rendering, we modify the
475  * alpha test parameters for (INV)DESTALPHA if the render target
476  * doesn't support alpha blending. A nonexistent alpha channel
477  * returns 1.0, so WINED3D_BLEND_DESTALPHA becomes GL_ONE, and
478  * WINED3D_BLEND_INVDESTALPHA becomes GL_ZERO. */
480  return dst_format->alpha_size ? GL_DST_ALPHA : GL_ONE;
482  return dst_format->alpha_size ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
484  return GL_SRC_ALPHA_SATURATE;
486  return GL_CONSTANT_COLOR_EXT;
490  return GL_SRC1_COLOR;
494  return GL_SRC1_ALPHA;
497  default:
498  if (!factor)
499  WARN("Unhandled blend factor %#x.\n", factor);
500  else
501  FIXME("Unhandled blend factor %#x.\n", factor);
502  return GL_NONE;
503  }
504 }
505 
506 static void gl_blend_from_d3d(GLenum *src_blend, GLenum *dst_blend,
507  enum wined3d_blend d3d_src_blend, enum wined3d_blend d3d_dst_blend,
508  const struct wined3d_format *rt_format)
509 {
510  /* WINED3D_BLEND_BOTHSRCALPHA and WINED3D_BLEND_BOTHINVSRCALPHA are legacy
511  * source blending values which are still valid up to d3d9. They should
512  * not occur as dest blend values. */
513  if (d3d_src_blend == WINED3D_BLEND_BOTHSRCALPHA)
514  {
515  *src_blend = GL_SRC_ALPHA;
516  *dst_blend = GL_ONE_MINUS_SRC_ALPHA;
517  }
518  else if (d3d_src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
519  {
520  *src_blend = GL_ONE_MINUS_SRC_ALPHA;
521  *dst_blend = GL_SRC_ALPHA;
522  }
523  else
524  {
525  *src_blend = gl_blend_factor(d3d_src_blend, rt_format);
526  *dst_blend = gl_blend_factor(d3d_dst_blend, rt_format);
527  }
528 }
529 
530 static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
531 {
532  const struct wined3d_gl_info *gl_info = context->gl_info;
533  const struct wined3d_format *rt_format;
534  GLenum src_blend, dst_blend;
535  unsigned int rt_fmt_flags;
536  BOOL enable_dual_blend;
537  BOOL enable_blend;
538 
539  enable_blend = state->fb->render_targets[0] && state->render_states[WINED3D_RS_ALPHABLENDENABLE];
540  enable_dual_blend = wined3d_dualblend_enabled(state, context->gl_info);
541 
542  if (enable_blend && !enable_dual_blend)
543  {
544  rt_fmt_flags = state->fb->render_targets[0]->format_flags;
545 
546  /* Disable blending in all cases even without pixelshaders.
547  * With blending on we could face a big performance penalty.
548  * The d3d9 visual test confirms the behavior. */
549  if (context->render_offscreen && !(rt_fmt_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
550  enable_blend = FALSE;
551  }
552 
553  /* Dual state blending changes the assignment of the output variables */
554  if (context->last_was_dual_blend != enable_dual_blend)
555  {
556  context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
557  context->last_was_dual_blend = enable_dual_blend;
558  }
559 
560  if (!enable_blend)
561  {
562  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
563  checkGLcall("glDisable(GL_BLEND)");
564  return;
565  }
566 
567  gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
568  checkGLcall("glEnable(GL_BLEND)");
569 
570  rt_format = state->fb->render_targets[0]->format;
571  gl_blend_from_d3d(&src_blend, &dst_blend,
572  state->render_states[WINED3D_RS_SRCBLEND],
573  state->render_states[WINED3D_RS_DESTBLEND], rt_format);
574 
575  /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
578 
579  if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
580  {
581  GLenum src_blend_alpha, dst_blend_alpha;
582 
583  /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
584  if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
585  {
586  WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparate.\n");
587  return;
588  }
589 
590  gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha,
591  state->render_states[WINED3D_RS_SRCBLENDALPHA],
592  state->render_states[WINED3D_RS_DESTBLENDALPHA], rt_format);
593 
594  GL_EXTCALL(glBlendFuncSeparate(src_blend, dst_blend, src_blend_alpha, dst_blend_alpha));
595  checkGLcall("glBlendFuncSeparate");
596  }
597  else
598  {
599  TRACE("glBlendFunc src=%x, dst=%x.\n", src_blend, dst_blend);
600  gl_info->gl_ops.gl.p_glBlendFunc(src_blend, dst_blend);
601  checkGLcall("glBlendFunc");
602  }
603 
604  /* Colorkey fixup for stage 0 alphaop depends on
605  * WINED3D_RS_ALPHABLENDENABLE state, so it may need updating. */
606  if (state->render_states[WINED3D_RS_COLORKEYENABLE])
608 }
609 
610 static void state_blendfactor_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
611 {
612  WARN("Unsupported in local OpenGL implementation: glBlendColor.\n");
613 }
614 
615 static void state_blendfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
616 {
617  const struct wined3d_gl_info *gl_info = context->gl_info;
618  struct wined3d_color color;
619 
620  TRACE("Setting blend factor to %#x.\n", state->render_states[WINED3D_RS_BLENDFACTOR]);
621 
624  checkGLcall("glBlendColor");
625 }
626 
627 static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
628 {
629  const struct wined3d_gl_info *gl_info = context->gl_info;
630  BOOL alpha_to_coverage = FALSE;
631 
632  if (!gl_info->supported[ARB_MULTISAMPLE])
633  return;
634 
635  if (state->blend_state)
636  {
637  struct wined3d_blend_state_desc *desc = &state->blend_state->desc;
638  alpha_to_coverage = desc->alpha_to_coverage;
639  }
640 
641  if (alpha_to_coverage)
642  gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
643  else
644  gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
645 
646  checkGLcall("blend state");
647 }
648 
649 void state_alpha_test(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
650 {
651  const struct wined3d_gl_info *gl_info = context->gl_info;
652  int glParm = 0;
653  float ref;
654  BOOL enable_ckey = FALSE;
655 
656  TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
657 
658  /* Find out if the texture on the first stage has a ckey set. The alpha
659  * state func reads the texture settings, even though alpha and texture
660  * are not grouped together. This is to avoid making a huge alpha +
661  * texture + texture stage + ckey block due to the hardly used
662  * WINED3D_RS_COLORKEYENABLE state(which is d3d <= 3 only). The texture
663  * function will call alpha in case it finds some texture + colorkeyenable
664  * combination which needs extra care. */
665  if (state->textures[0] && (state->textures[0]->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
666  enable_ckey = TRUE;
667 
668  if (enable_ckey || context->last_was_ckey)
670  context->last_was_ckey = enable_ckey;
671 
672  if (state->render_states[WINED3D_RS_ALPHATESTENABLE]
673  || (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey))
674  {
675  gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
676  checkGLcall("glEnable GL_ALPHA_TEST");
677  }
678  else
679  {
680  gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
681  checkGLcall("glDisable GL_ALPHA_TEST");
682  /* Alpha test is disabled, don't bother setting the params - it will happen on the next
683  * enable call
684  */
685  return;
686  }
687 
688  if (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey)
689  {
690  glParm = GL_NOTEQUAL;
691  ref = 0.0f;
692  }
693  else
694  {
695  ref = ((float)state->render_states[WINED3D_RS_ALPHAREF]) / 255.0f;
696  glParm = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
697  }
698  if (glParm)
699  {
700  gl_info->gl_ops.gl.p_glAlphaFunc(glParm, ref);
701  checkGLcall("glAlphaFunc");
702  }
703 }
704 
705 void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
706 {
707  unsigned int enable_mask;
708 
709  if (use_vs(state) && !context->d3d_info->vs_clipping)
710  {
711  static BOOL warned;
712 
713  /* The OpenGL spec says that clipping planes are disabled when using
714  * shaders. Direct3D planes aren't, so that is an issue. The MacOS ATI
715  * driver keeps clipping planes activated with shaders in some
716  * conditions I got sick of tracking down. The shader state handler
717  * disables all clip planes because of that - don't do anything here
718  * and keep them disabled. */
719  if (state->render_states[WINED3D_RS_CLIPPLANEENABLE] && !warned++)
720  FIXME("Clipping not supported with vertex shaders.\n");
721  return;
722  }
723 
724  /* glEnable(GL_CLIP_PLANEx) doesn't apply to (ARB backend) vertex shaders.
725  * The enabled / disabled planes are hardcoded into the shader. Update the
726  * shader to update the enabled clipplanes. In case of fixed function, we
727  * need to update the clipping field from ffp_vertex_settings. */
728  context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
729 
730  /* If enabling / disabling all
731  * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
732  */
733  enable_mask = state->render_states[WINED3D_RS_CLIPPING] ?
734  state->render_states[WINED3D_RS_CLIPPLANEENABLE] : 0;
736 }
737 
738 static void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
739 {
740  const struct wined3d_gl_info *gl_info = context->gl_info;
741  /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
742  * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
743  * specular color. This is wrong:
744  * Separate specular color means the specular colour is maintained separately, whereas
745  * single color means it is merged in. However in both cases they are being used to
746  * some extent.
747  * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
748  * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
749  * running 1.4 yet!
750  *
751  *
752  * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
753  * Instead, we need to setup the FinalCombiner properly.
754  *
755  * The default setup for the FinalCombiner is:
756  *
757  * <variable> <input> <mapping> <usage>
758  * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
759  * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
760  * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
761  * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
762  * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
763  * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
764  * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
765  *
766  * That's pretty much fine as it is, except for variable B, which needs to take
767  * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
768  * whether WINED3D_RS_SPECULARENABLE is enabled or not.
769  */
770 
771  TRACE("Setting specular enable state and materials\n");
772  if (state->render_states[WINED3D_RS_SPECULARENABLE])
773  {
774  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
775  checkGLcall("glMaterialfv");
776 
777  if (state->material.power > gl_info->limits.shininess)
778  {
779  /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
780  * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
781  * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the
782  * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp
783  * them, it should be safe to do so without major visual distortions.
784  */
785  WARN("Material power = %.8e, limit %.8e\n", state->material.power, gl_info->limits.shininess);
786  gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess);
787  }
788  else
789  {
790  gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, state->material.power);
791  }
792  checkGLcall("glMaterialf(GL_SHININESS)");
793 
794  if (gl_info->supported[EXT_SECONDARY_COLOR])
795  gl_info->gl_ops.gl.p_glEnable(GL_COLOR_SUM_EXT);
796  else
797  TRACE("Specular colors cannot be enabled in this version of opengl\n");
798  checkGLcall("glEnable(GL_COLOR_SUM)");
799 
800  if (gl_info->supported[NV_REGISTER_COMBINERS])
801  {
803  checkGLcall("glFinalCombinerInputNV()");
804  }
805  } else {
806  static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
807 
808  /* for the case of enabled lighting: */
809  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
810  checkGLcall("glMaterialfv");
811 
812  /* for the case of disabled lighting: */
813  if (gl_info->supported[EXT_SECONDARY_COLOR])
814  gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
815  else
816  TRACE("Specular colors cannot be disabled in this version of opengl\n");
817  checkGLcall("glDisable(GL_COLOR_SUM)");
818 
819  if (gl_info->supported[NV_REGISTER_COMBINERS])
820  {
822  checkGLcall("glFinalCombinerInputNV()");
823  }
824  }
825 
826  TRACE("diffuse %s\n", debug_color(&state->material.diffuse));
827  TRACE("ambient %s\n", debug_color(&state->material.ambient));
828  TRACE("specular %s\n", debug_color(&state->material.specular));
829  TRACE("emissive %s\n", debug_color(&state->material.emissive));
830 
831  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
832  checkGLcall("glMaterialfv(GL_AMBIENT)");
833  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
834  checkGLcall("glMaterialfv(GL_DIFFUSE)");
835  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
836  checkGLcall("glMaterialfv(GL_EMISSION)");
837 }
838 
839 static void state_texfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
840 {
841  const struct wined3d_gl_info *gl_info = context->gl_info;
842  struct wined3d_color color;
843  unsigned int i;
844 
845  /* Note the texture color applies to all textures whereas
846  * GL_TEXTURE_ENV_COLOR applies to active only. */
848 
849  /* And now the default texture color as well */
850  for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
851  {
852  /* Note the WINED3D_RS value applies to all textures, but GL has one
853  * per texture, so apply it now ready to be used! */
854  context_active_texture(context, gl_info, i);
855 
856  gl_info->gl_ops.gl.p_glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
857  checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
858  }
859 }
860 
862  GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
863 {
864  const struct wined3d_gl_info *gl_info = context->gl_info;
865 
866  gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
867  checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
868  GL_EXTCALL(glActiveStencilFaceEXT(face));
869  checkGLcall("glActiveStencilFaceEXT(...)");
870  gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
871  checkGLcall("glStencilFunc(...)");
872  gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
873  checkGLcall("glStencilOp(...)");
874 }
875 
877 {
878  switch (op)
879  {
881  return GL_KEEP;
883  return GL_ZERO;
885  return GL_REPLACE;
887  return GL_INCR;
889  return GL_DECR;
891  return GL_INVERT;
893  return GL_INCR_WRAP;
895  return GL_DECR_WRAP;
896  default:
897  if (!op)
898  WARN("Unrecognized stencil op %#x.\n", op);
899  else
900  FIXME("Unrecognized stencil op %#x.\n", op);
901  return GL_KEEP;
902  }
903 }
904 
905 static void state_stencil(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
906 {
907  const struct wined3d_gl_info *gl_info = context->gl_info;
908  DWORD onesided_enable;
909  DWORD twosided_enable;
910  GLint func;
911  GLint func_back;
912  GLint ref;
913  GLuint mask;
914  GLint stencilFail;
915  GLint stencilFail_back;
916  GLint stencilPass;
917  GLint stencilPass_back;
918  GLint depthFail;
919  GLint depthFail_back;
920 
921  /* No stencil test without a stencil buffer. */
922  if (!state->fb->depth_stencil)
923  {
924  gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
925  checkGLcall("glDisable GL_STENCIL_TEST");
926  return;
927  }
928 
929  onesided_enable = state->render_states[WINED3D_RS_STENCILENABLE];
930  twosided_enable = state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE];
931  if (!(func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_STENCILFUNC])))
932  func = GL_ALWAYS;
933  if (!(func_back = wined3d_gl_compare_func(state->render_states[WINED3D_RS_BACK_STENCILFUNC])))
934  func_back = GL_ALWAYS;
935  ref = state->render_states[WINED3D_RS_STENCILREF];
936  mask = state->render_states[WINED3D_RS_STENCILMASK];
937  stencilFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILFAIL]);
938  depthFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILZFAIL]);
939  stencilPass = gl_stencil_op(state->render_states[WINED3D_RS_STENCILPASS]);
940  stencilFail_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILFAIL]);
941  depthFail_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILZFAIL]);
942  stencilPass_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILPASS]);
943 
944  TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
945  "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
946  "GL_BACK: func: %x, fail %x, zfail %x, zpass %x)\n",
947  onesided_enable, twosided_enable, ref, mask,
948  func, stencilFail, depthFail, stencilPass,
949  func_back, stencilFail_back, depthFail_back, stencilPass_back);
950 
951  if (twosided_enable && onesided_enable)
952  {
953  gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
954  checkGLcall("glEnable GL_STENCIL_TEST");
955 
956  if (gl_info->supported[WINED3D_GL_VERSION_2_0])
957  {
958  GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
959  GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
960  GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func_back, ref, mask));
961  GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail_back, depthFail_back, stencilPass_back));
962  checkGLcall("setting two sided stencil state");
963  }
964  else if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
965  {
966  /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
967  * which has an effect on the code below too. If we apply the front face
968  * afterwards, we are sure that the active stencil face is set to front,
969  * and other stencil functions which do not use two sided stencil do not have
970  * to set it back
971  */
973  func_back, ref, mask, stencilFail_back, depthFail_back, stencilPass_back);
975  func, ref, mask, stencilFail, depthFail, stencilPass);
976  }
977  else if (gl_info->supported[ATI_SEPARATE_STENCIL])
978  {
979  GL_EXTCALL(glStencilFuncSeparateATI(func, func_back, ref, mask));
980  checkGLcall("glStencilFuncSeparateATI(...)");
981  GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
982  checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
983  GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_back, depthFail_back, stencilPass_back));
984  checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
985  }
986  else
987  {
988  FIXME("Separate (two sided) stencil not supported on this version of OpenGL. Caps weren't honored?\n");
989  }
990  }
991  else if(onesided_enable)
992  {
993  if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
994  {
995  gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
996  checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
997  }
998 
999  /* This code disables the ATI extension as well, since the standard stencil functions are equal
1000  * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
1001  */
1002  gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
1003  checkGLcall("glEnable GL_STENCIL_TEST");
1004  gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
1005  checkGLcall("glStencilFunc(...)");
1006  gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
1007  checkGLcall("glStencilOp(...)");
1008  }
1009  else
1010  {
1011  gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
1012  checkGLcall("glDisable GL_STENCIL_TEST");
1013  }
1014 }
1015 
1016 static void state_stencilwrite2s_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1017 {
1018  DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
1019  const struct wined3d_gl_info *gl_info = context->gl_info;
1020 
1021  GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
1022  checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
1023  gl_info->gl_ops.gl.p_glStencilMask(mask);
1024  checkGLcall("glStencilMask");
1025  GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
1026  checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
1027  gl_info->gl_ops.gl.p_glStencilMask(mask);
1028 }
1029 
1030 static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1031 {
1032  DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
1033  const struct wined3d_gl_info *gl_info = context->gl_info;
1034 
1035  gl_info->gl_ops.gl.p_glStencilMask(mask);
1036  checkGLcall("glStencilMask");
1037 }
1038 
1039 static void state_fog_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1040 {
1041  const struct wined3d_gl_info *gl_info = context->gl_info;
1042 
1043  TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
1044 
1045  if (!state->render_states[WINED3D_RS_FOGENABLE])
1046  return;
1047 
1048  /* Table fog on: Never use fog coords, and use per-fragment fog */
1049  if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
1050  {
1051  gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_NICEST);
1052  if (context->fog_coord)
1053  {
1055  checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1056  context->fog_coord = FALSE;
1057  }
1058 
1059  /* Range fog is only used with per-vertex fog in d3d */
1060  if (gl_info->supported[NV_FOG_DISTANCE])
1061  {
1063  checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1064  }
1065  return;
1066  }
1067 
1068  /* Otherwise use per-vertex fog in any case */
1069  gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_FASTEST);
1070 
1071  if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->last_was_rhw)
1072  {
1073  /* No fog at all, or transformed vertices: Use fog coord */
1074  if (!context->fog_coord)
1075  {
1077  checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1078  context->fog_coord = TRUE;
1079  }
1080  }
1081  else
1082  {
1083  /* Otherwise, use the fragment depth */
1084  if (context->fog_coord)
1085  {
1087  checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1088  context->fog_coord = FALSE;
1089  }
1090 
1091  if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
1092  {
1093  if (gl_info->supported[NV_FOG_DISTANCE])
1094  {
1095  gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1096  checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1097  }
1098  else
1099  {
1100  WARN("Range fog enabled, but not supported by this GL implementation.\n");
1101  }
1102  }
1103  else if (gl_info->supported[NV_FOG_DISTANCE])
1104  {
1106  checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1107  }
1108  }
1109 }
1110 
1111 void state_fogstartend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1112 {
1113  const struct wined3d_gl_info *gl_info = context->gl_info;
1114  float fogstart, fogend;
1115 
1116  get_fog_start_end(context, state, &fogstart, &fogend);
1117 
1118  gl_info->gl_ops.gl.p_glFogf(GL_FOG_START, fogstart);
1119  checkGLcall("glFogf(GL_FOG_START, fogstart)");
1120  TRACE("Fog Start == %f\n", fogstart);
1121 
1122  gl_info->gl_ops.gl.p_glFogf(GL_FOG_END, fogend);
1123  checkGLcall("glFogf(GL_FOG_END, fogend)");
1124  TRACE("Fog End == %f\n", fogend);
1125 }
1126 
1127 void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1128 {
1129  const struct wined3d_gl_info *gl_info = context->gl_info;
1130  enum fogsource new_source;
1131  DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
1132  DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
1133 
1134  TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
1135 
1136  if (!state->render_states[WINED3D_RS_FOGENABLE])
1137  {
1138  /* No fog? Disable it, and we're done :-) */
1139  glDisableWINE(GL_FOG);
1140  checkGLcall("glDisable GL_FOG");
1141  return;
1142  }
1143 
1144  /* Fog Rules:
1145  *
1146  * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
1147  * It can use the Z value of the vertex, or the alpha component of the specular color.
1148  * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
1149  * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
1150  * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
1151  *
1152  * FOGTABLEMODE != NONE:
1153  * The Z value is used, with the equation specified, no matter what vertex type.
1154  *
1155  * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1156  * Per vertex fog is calculated using the specified fog equation and the parameters
1157  *
1158  * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1159  * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1160  * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1161  *
1162  *
1163  * Rules for vertex fog with shaders:
1164  *
1165  * When mixing fixed function functionality with the programmable pipeline, D3D expects
1166  * the fog computation to happen during transformation while openGL expects it to happen
1167  * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1168  * the pixel shader while openGL always expects the pixel shader to handle the blending.
1169  * To solve this problem, WineD3D does:
1170  * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1171  * shader,
1172  * and 2) disables the fog computation (in either the fixed function or programmable
1173  * rasterizer) if using a vertex program.
1174  *
1175  * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1176  * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1177  * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1178  * the specular color, a vertex shader counts as pretransformed geometry in this case.
1179  * There are some GL differences between specular fog coords and vertex shaders though.
1180  *
1181  * With table fog the vertex shader fog coordinate is ignored.
1182  *
1183  * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1184  * without shaders).
1185  */
1186 
1187  /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1188  * the system will apply only pixel(=table) fog effects."
1189  */
1190  if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
1191  {
1192  if (use_vs(state))
1193  {
1194  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1195  checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1196  new_source = FOGSOURCE_VS;
1197  }
1198  else
1199  {
1200  switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
1201  {
1202  /* If processed vertices are used, fall through to the NONE case */
1203  case WINED3D_FOG_EXP:
1204  if (!context->last_was_rhw)
1205  {
1206  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
1207  checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1208  new_source = FOGSOURCE_FFP;
1209  break;
1210  }
1211  /* drop through */
1212 
1213  case WINED3D_FOG_EXP2:
1214  if (!context->last_was_rhw)
1215  {
1216  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
1217  checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1218  new_source = FOGSOURCE_FFP;
1219  break;
1220  }
1221  /* drop through */
1222 
1223  case WINED3D_FOG_LINEAR:
1224  if (!context->last_was_rhw)
1225  {
1226  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1227  checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1228  new_source = FOGSOURCE_FFP;
1229  break;
1230  }
1231  /* drop through */
1232 
1233  case WINED3D_FOG_NONE:
1234  /* Both are none? According to msdn the alpha channel of
1235  * the specular colour contains a fog factor. Set it in
1236  * draw_primitive_immediate_mode(). Same happens with
1237  * vertex fog on transformed vertices. */
1238  new_source = FOGSOURCE_COORD;
1239  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1240  checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1241  break;
1242 
1243  default:
1244  FIXME("Unexpected WINED3D_RS_FOGVERTEXMODE %#x.\n",
1245  state->render_states[WINED3D_RS_FOGVERTEXMODE]);
1246  new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1247  }
1248  }
1249  } else {
1250  new_source = FOGSOURCE_FFP;
1251 
1252  switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
1253  {
1254  case WINED3D_FOG_EXP:
1255  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
1256  checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1257  break;
1258 
1259  case WINED3D_FOG_EXP2:
1260  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
1261  checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1262  break;
1263 
1264  case WINED3D_FOG_LINEAR:
1265  gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1266  checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1267  break;
1268 
1269  case WINED3D_FOG_NONE: /* Won't happen */
1270  default:
1271  FIXME("Unexpected WINED3D_RS_FOGTABLEMODE %#x.\n",
1272  state->render_states[WINED3D_RS_FOGTABLEMODE]);
1273  }
1274  }
1275 
1276  glEnableWINE(GL_FOG);
1277  checkGLcall("glEnable GL_FOG");
1278  if (new_source != context->fog_source || fogstart == fogend)
1279  {
1280  context->fog_source = new_source;
1282  }
1283 }
1284 
1285 void state_fogcolor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1286 {
1287  const struct wined3d_gl_info *gl_info = context->gl_info;
1288  struct wined3d_color color;
1289 
1291  gl_info->gl_ops.gl.p_glFogfv(GL_FOG_COLOR, &color.r);
1292  checkGLcall("glFog GL_FOG_COLOR");
1293 }
1294 
1295 void state_fogdensity(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1296 {
1297  const struct wined3d_gl_info *gl_info = context->gl_info;
1298  union {
1299  DWORD d;
1300  float f;
1301  } tmpvalue;
1302 
1303  tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY];
1304  gl_info->gl_ops.gl.p_glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1305  checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1306 }
1307 
1308 static void state_colormat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1309 {
1310  const struct wined3d_gl_info *gl_info = context->gl_info;
1311  GLenum Parm = 0;
1312 
1313  /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1314  * The vertex declaration will call this function if the fixed function pipeline is used.
1315  */
1316 
1318  return;
1319  }
1320 
1321  context->num_untracked_materials = 0;
1322  if ((context->stream_info.use_map & (1u << WINED3D_FFP_DIFFUSE))
1323  && state->render_states[WINED3D_RS_COLORVERTEX])
1324  {
1325  TRACE("diff %d, amb %d, emis %d, spec %d\n",
1326  state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE],
1327  state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE],
1328  state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE],
1329  state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE]);
1330 
1332  {
1334  Parm = GL_AMBIENT_AND_DIFFUSE;
1335  else
1336  Parm = GL_DIFFUSE;
1338  {
1339  context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1340  context->num_untracked_materials++;
1341  }
1343  {
1344  context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1345  context->num_untracked_materials++;
1346  }
1347  }
1348  else if (state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1349  {
1350  Parm = GL_AMBIENT;
1352  {
1353  context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1354  context->num_untracked_materials++;
1355  }
1357  {
1358  context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1359  context->num_untracked_materials++;
1360  }
1361  }
1362  else if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1363  {
1364  Parm = GL_EMISSION;
1366  {
1367  context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1368  context->num_untracked_materials++;
1369  }
1370  }
1371  else if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1372  {
1373  Parm = GL_SPECULAR;
1374  }
1375  }
1376 
1377  /* Nothing changed, return. */
1378  if (Parm == context->tracking_parm) return;
1379 
1380  if (!Parm)
1381  {
1382  gl_info->gl_ops.gl.p_glDisable(GL_COLOR_MATERIAL);
1383  checkGLcall("glDisable GL_COLOR_MATERIAL");
1384  }
1385  else
1386  {
1387  gl_info->gl_ops.gl.p_glColorMaterial(GL_FRONT_AND_BACK, Parm);
1388  checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1389  gl_info->gl_ops.gl.p_glEnable(GL_COLOR_MATERIAL);
1390  checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1391  }
1392 
1393  /* Apparently calls to glMaterialfv are ignored for properties we're
1394  * tracking with glColorMaterial, so apply those here. */
1395  switch (context->tracking_parm)
1396  {
1398  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
1399  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
1400  checkGLcall("glMaterialfv");
1401  break;
1402 
1403  case GL_DIFFUSE:
1404  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
1405  checkGLcall("glMaterialfv");
1406  break;
1407 
1408  case GL_AMBIENT:
1409  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
1410  checkGLcall("glMaterialfv");
1411  break;
1412 
1413  case GL_EMISSION:
1414  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
1415  checkGLcall("glMaterialfv");
1416  break;
1417 
1418  case GL_SPECULAR:
1419  /* Only change material color if specular is enabled, otherwise it is set to black */
1420  if (state->render_states[WINED3D_RS_SPECULARENABLE])
1421  {
1422  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
1423  checkGLcall("glMaterialfv");
1424  }
1425  else
1426  {
1427  static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1428  gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1429  checkGLcall("glMaterialfv");
1430  }
1431  break;
1432  }
1433 
1434  context->tracking_parm = Parm;
1435 }
1436 
1437 static void state_linepattern(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1438 {
1439  const struct wined3d_gl_info *gl_info = context->gl_info;
1440  union
1441  {
1442  DWORD d;
1443  struct wined3d_line_pattern lp;
1444  } tmppattern;
1445  tmppattern.d = state->render_states[WINED3D_RS_LINEPATTERN];
1446 
1447  TRACE("Line pattern: repeat %d bits %x.\n", tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
1448 
1449  if (tmppattern.lp.repeat_factor)
1450  {
1451  gl_info->gl_ops.gl.p_glLineStipple(tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
1452  checkGLcall("glLineStipple(repeat, linepattern)");
1453  gl_info->gl_ops.gl.p_glEnable(GL_LINE_STIPPLE);
1454  checkGLcall("glEnable(GL_LINE_STIPPLE);");
1455  }
1456  else
1457  {
1458  gl_info->gl_ops.gl.p_glDisable(GL_LINE_STIPPLE);
1459  checkGLcall("glDisable(GL_LINE_STIPPLE);");
1460  }
1461 }
1462 
1463 static void state_linepattern_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1464 {
1465  static unsigned int once;
1466 
1467  if (!once++)
1468  FIXME("Setting line patterns is not supported in OpenGL core contexts.\n");
1469 }
1470 
1471 static void state_normalize(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1472 {
1473  const struct wined3d_gl_info *gl_info = context->gl_info;
1474 
1476  return;
1477 
1478  /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1479  * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1480  * by zero and is not properly defined in opengl, so avoid it
1481  */
1482  if (state->render_states[WINED3D_RS_NORMALIZENORMALS]
1483  && (context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL)))
1484  {
1485  gl_info->gl_ops.gl.p_glEnable(GL_NORMALIZE);
1486  checkGLcall("glEnable(GL_NORMALIZE);");
1487  }
1488  else
1489  {
1490  gl_info->gl_ops.gl.p_glDisable(GL_NORMALIZE);
1491  checkGLcall("glDisable(GL_NORMALIZE);");
1492  }
1493 }
1494 
1495 static void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1496 {
1497  float min, max;
1498 
1500 
1501  if (min != 1.0f)
1502  FIXME("WINED3D_RS_POINTSIZE_MIN value %.8e not supported on this OpenGL implementation.\n", min);
1503  if (max != 64.0f)
1504  FIXME("WINED3D_RS_POINTSIZE_MAX value %.8e not supported on this OpenGL implementation.\n", max);
1505 }
1506 
1507 static void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1508 {
1509  const struct wined3d_gl_info *gl_info = context->gl_info;
1510  float min, max;
1511 
1513 
1514  GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min);
1515  checkGLcall("glPointParameterfEXT(...)");
1516  GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max);
1517  checkGLcall("glPointParameterfEXT(...)");
1518 }
1519 
1520 static void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1521 {
1522  const struct wined3d_gl_info *gl_info = context->gl_info;
1523  float min, max;
1524 
1526 
1527  GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min);
1528  checkGLcall("glPointParameterfARB(...)");
1529  GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max);
1530  checkGLcall("glPointParameterfARB(...)");
1531 }
1532 
1533 static void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1534 {
1535  const struct wined3d_gl_info *gl_info = context->gl_info;
1536  float att[3];
1537  float pointsize;
1538 
1539  get_pointsize(context, state, &pointsize, att);
1540 
1541  if (gl_info->supported[ARB_POINT_PARAMETERS])
1542  {
1543  GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1544  checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1545  }
1546  else if (gl_info->supported[EXT_POINT_PARAMETERS])
1547  {
1548  GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1549  checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1550  }
1551  else if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
1552  {
1553  WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1554  }
1555 
1556  gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN));
1557  checkGLcall("glPointSize(...);");
1558 }
1559 
1560 static void state_debug_monitor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1561 {
1562  WARN("token: %#x.\n", state->render_states[WINED3D_RS_DEBUGMONITORTOKEN]);
1563 }
1564 
1565 static void state_colorwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1566 {
1567  DWORD mask0 = state->render_states[WINED3D_RS_COLORWRITEENABLE];
1568  const struct wined3d_gl_info *gl_info = context->gl_info;
1569 
1570  TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1571  mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1572  mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1573  mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1574  mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1575  gl_info->gl_ops.gl.p_glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1579  checkGLcall("glColorMask(...)");
1580 
1581  /* FIXME: WINED3D_RS_COLORWRITEENABLE1 .. WINED3D_RS_COLORWRITEENABLE7 not implemented. */
1582 }
1583 
1584 static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask)
1585 {
1586  GL_EXTCALL(glColorMaski(index,
1591  checkGLcall("glColorMaski");
1592 }
1593 
1594 static void state_colorwrite_i(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1595 {
1596  const struct wined3d_gl_info *gl_info = context->gl_info;
1597  int index;
1598 
1599  if (state_id == WINED3D_RS_COLORWRITEENABLE) index = 0;
1600  else if (state_id <= WINED3D_RS_COLORWRITEENABLE3) index = state_id - WINED3D_RS_COLORWRITEENABLE1 + 1;
1601  else if (state_id <= WINED3D_RS_COLORWRITEENABLE7) index = state_id - WINED3D_RS_COLORWRITEENABLE4 + 4;
1602  else return;
1603 
1604  if (index >= gl_info->limits.buffers)
1605  WARN("Ignoring color write value for index %d, because gpu only supports %d render targets\n", index, gl_info->limits.buffers);
1606 
1607  set_color_mask(context->gl_info, index, state->render_states[state_id]);
1608 }
1609 
1610 static void state_localviewer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1611 {
1612  const struct wined3d_gl_info *gl_info = context->gl_info;
1613 
1614  if (state->render_states[WINED3D_RS_LOCALVIEWER])
1615  {
1616  gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1617  checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1618  }
1619  else
1620  {
1621  gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1622  checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1623  }
1624 }
1625 
1626 static void state_lastpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1627 {
1628  if (state->render_states[WINED3D_RS_LASTPIXEL])
1629  {
1630  TRACE("Last Pixel Drawing Enabled\n");
1631  }
1632  else
1633  {
1634  static BOOL warned;
1635  if (!warned) {
1636  FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1637  warned = TRUE;
1638  } else {
1639  TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1640  }
1641  }
1642 }
1643 
1644 void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1645 {
1646  static BOOL warned;
1647 
1648  /* TODO: NV_POINT_SPRITE */
1649  if (!warned && state->render_states[WINED3D_RS_POINTSPRITEENABLE])
1650  {
1651  /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1652  FIXME("Point sprites not supported\n");
1653  warned = TRUE;
1654  }
1655 }
1656 
1657 void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1658 {
1659  const struct wined3d_gl_info *gl_info = context->gl_info;
1660 
1661  if (state->render_states[WINED3D_RS_POINTSPRITEENABLE])
1662  {
1663  gl_info->gl_ops.gl.p_glEnable(GL_POINT_SPRITE_ARB);
1664  checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1665  }
1666  else
1667  {
1668  gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
1669  checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1670  }
1671 }
1672 
1673 static void state_wrap(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1674 {
1675  static unsigned int once;
1676 
1677  if ((state->render_states[WINED3D_RS_WRAP0]
1678  || state->render_states[WINED3D_RS_WRAP1]
1679  || state->render_states[WINED3D_RS_WRAP2]
1680  || state->render_states[WINED3D_RS_WRAP3]
1681  || state->render_states[WINED3D_RS_WRAP4]
1682  || state->render_states[WINED3D_RS_WRAP5]
1683  || state->render_states[WINED3D_RS_WRAP6]
1684  || state->render_states[WINED3D_RS_WRAP7]
1685  || state->render_states[WINED3D_RS_WRAP8]
1686  || state->render_states[WINED3D_RS_WRAP9]
1687  || state->render_states[WINED3D_RS_WRAP10]
1688  || state->render_states[WINED3D_RS_WRAP11]
1689  || state->render_states[WINED3D_RS_WRAP12]
1690  || state->render_states[WINED3D_RS_WRAP13]
1691  || state->render_states[WINED3D_RS_WRAP14]
1692  || state->render_states[WINED3D_RS_WRAP15])
1693  && !once++)
1694  FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n");
1695 }
1696 
1697 static void state_msaa_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1698 {
1699  if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
1700  WARN("Multisample antialiasing not supported by GL.\n");
1701 }
1702 
1703 static void state_msaa(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1704 {
1705  const struct wined3d_gl_info *gl_info = context->gl_info;
1706 
1707  if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
1708  {
1709  gl_info->gl_ops.gl.p_glEnable(GL_MULTISAMPLE_ARB);
1710  checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1711  }
1712  else
1713  {
1714  gl_info->gl_ops.gl.p_glDisable(GL_MULTISAMPLE_ARB);
1715  checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1716  }
1717 }
1718 
1719 static void state_line_antialias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1720 {
1721  const struct wined3d_gl_info *gl_info = context->gl_info;
1722 
1723  if (state->render_states[WINED3D_RS_EDGEANTIALIAS]
1724  || state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE])
1725  {
1726  gl_info->gl_ops.gl.p_glEnable(GL_LINE_SMOOTH);
1727  checkGLcall("glEnable(GL_LINE_SMOOTH)");
1728  }
1729  else
1730  {
1731  gl_info->gl_ops.gl.p_glDisable(GL_LINE_SMOOTH);
1732  checkGLcall("glDisable(GL_LINE_SMOOTH)");
1733  }
1734 }
1735 
1736 static void state_scissor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1737 {
1738  const struct wined3d_gl_info *gl_info = context->gl_info;
1739 
1740  if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
1741  {
1742  gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
1743  checkGLcall("glEnable(GL_SCISSOR_TEST)");
1744  }
1745  else
1746  {
1747  gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
1748  checkGLcall("glDisable(GL_SCISSOR_TEST)");
1749  }
1750 }
1751 
1752 /* The Direct3D depth bias is specified in normalized depth coordinates. In
1753  * OpenGL the bias is specified in units of "the smallest value that is
1754  * guaranteed to produce a resolvable offset for a given implementation". To
1755  * convert from D3D to GL we need to divide the D3D depth bias by that value.
1756  * We try to detect the value from GL with test draws. On most drivers (r300g,
1757  * 600g, Nvidia, i965 on Mesa) the value is 2^23 for fixed point depth buffers,
1758  * for r200 and i965 on OSX it is 2^24, for r500 on OSX it is 2^22. For floating
1759  * point buffers it is 2^22, 2^23 or 2^24 depending on the GPU. The value does
1760  * not depend on the depth buffer precision on any driver.
1761  *
1762  * Two games that are picky regarding depth bias are Mass Effect 2 (flickering
1763  * decals) and F.E.A.R and F.E.A.R. 2 (semi-transparent guns).
1764  *
1765  * Note that SLOPESCALEDEPTHBIAS is a scaling factor for the depth slope, and
1766  * doesn't need to be scaled to account for GL vs D3D differences. */
1767 static void state_depthbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1768 {
1769  const struct wined3d_gl_info *gl_info = context->gl_info;
1770 
1771  if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS]
1772  || state->render_states[WINED3D_RS_DEPTHBIAS])
1773  {
1774  const struct wined3d_rendertarget_view *depth = state->fb->depth_stencil;
1775  float factor, units, scale;
1776 
1777  union
1778  {
1779  DWORD d;
1780  float f;
1781  } scale_bias, const_bias, bias_clamp;
1782 
1783  scale_bias.d = state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS];
1784  const_bias.d = state->render_states[WINED3D_RS_DEPTHBIAS];
1785  bias_clamp.d = state->render_states[WINED3D_RS_DEPTHBIASCLAMP];
1786 
1787  if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
1788  {
1789  factor = units = -(float)const_bias.d;
1790  }
1791  else
1792  {
1793  if (depth)
1794  {
1795  scale = depth->format->depth_bias_scale;
1796 
1797  TRACE("Depth format %s, using depthbias scale of %.8e.\n",
1798  debug_d3dformat(depth->format->id), scale);
1799  }
1800  else
1801  {
1802  /* The context manager will reapply this state on a depth stencil change */
1803  TRACE("No depth stencil, using depth bias scale of 0.0.\n");
1804  scale = 0.0f;
1805  }
1806 
1807  factor = scale_bias.f;
1808  units = const_bias.f * scale;
1809  }
1810 
1811  gl_info->gl_ops.gl.p_glEnable(GL_POLYGON_OFFSET_FILL);
1812  if (gl_info->supported[EXT_POLYGON_OFFSET_CLAMP])
1813  {
1814  GL_EXTCALL(glPolygonOffsetClampEXT(factor, units, bias_clamp.f));
1815  checkGLcall("glPolygonOffsetClampEXT(...)");
1816  }
1817  else
1818  {
1819  if (bias_clamp.f)
1820  WARN("EXT_polygon_offset_clamp extension missing, no support for depth bias clamping.\n");
1821 
1822  gl_info->gl_ops.gl.p_glPolygonOffset(factor, units);
1823  }
1824  }
1825  else
1826  {
1827  gl_info->gl_ops.gl.p_glDisable(GL_POLYGON_OFFSET_FILL);
1828  }
1829 
1830  checkGLcall("depth bias");
1831 }
1832 
1833 static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1834 {
1835  if (state->render_states[WINED3D_RS_ZVISIBLE])
1836  FIXME("WINED3D_RS_ZVISIBLE not implemented.\n");
1837 }
1838 
1839 static void state_stippledalpha(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1840 {
1841  if (state->render_states[WINED3D_RS_STIPPLEDALPHA])
1842  FIXME("Stippled Alpha not supported yet.\n");
1843 }
1844 
1845 static void state_antialias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1846 {
1847  if (state->render_states[WINED3D_RS_ANTIALIAS])
1848  FIXME("Antialias not supported yet.\n");
1849 }
1850 
1851 static void state_multisampmask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1852 {
1853  if (state->render_states[WINED3D_RS_MULTISAMPLEMASK] != 0xffffffff)
1854  FIXME("WINED3D_RS_MULTISAMPLEMASK %#x not yet implemented.\n",
1855  state->render_states[WINED3D_RS_MULTISAMPLEMASK]);
1856 }
1857 
1858 static void state_patchedgestyle(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1859 {
1861  FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n",
1862  state->render_states[WINED3D_RS_PATCHEDGESTYLE]);
1863 }
1864 
1865 static void state_patchsegments(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1866 {
1867  union {
1868  DWORD d;
1869  float f;
1870  } tmpvalue;
1871  tmpvalue.f = 1.0f;
1872 
1873  if (state->render_states[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d)
1874  {
1875  static BOOL displayed = FALSE;
1876 
1877  tmpvalue.d = state->render_states[WINED3D_RS_PATCHSEGMENTS];
1878  if(!displayed)
1879  FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1880 
1881  displayed = TRUE;
1882  }
1883 }
1884 
1885 static void state_positiondegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1886 {
1887  if (state->render_states[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC)
1888  FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n",
1889  state->render_states[WINED3D_RS_POSITIONDEGREE]);
1890 }
1891 
1892 static void state_normaldegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1893 {
1894  if (state->render_states[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR)
1895  FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n",
1896  state->render_states[WINED3D_RS_NORMALDEGREE]);
1897 }
1898 
1899 static void state_tessellation(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1900 {
1901  if (state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION])
1902  FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n",
1904 }
1905 
1906 static void state_nvdb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1907 {
1908  union {
1909  DWORD d;
1910  float f;
1911  } zmin, zmax;
1912 
1913  const struct wined3d_gl_info *gl_info = context->gl_info;
1914 
1915  if (state->render_states[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB)
1916  {
1917  zmin.d = state->render_states[WINED3D_RS_ADAPTIVETESS_Z];
1918  zmax.d = state->render_states[WINED3D_RS_ADAPTIVETESS_W];
1919 
1920  /* If zmin is larger than zmax INVALID_VALUE error is generated.
1921  * In d3d9 test is not performed in this case*/
1922  if (zmin.f <= zmax.f)
1923  {
1924  gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_BOUNDS_TEST_EXT);
1925  checkGLcall("glEnable(GL_DEPTH_BOUNDS_TEST_EXT)");
1926  GL_EXTCALL(glDepthBoundsEXT(zmin.f, zmax.f));
1927  checkGLcall("glDepthBoundsEXT(...)");
1928  }
1929  else
1930  {
1931  gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1932  checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
1933  }
1934  }
1935  else
1936  {
1937  gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1938  checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
1939  }
1940 
1942 }
1943 
1944 static void state_wrapu(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1945 {
1946  if (state->render_states[WINED3D_RS_WRAPU])
1947  FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n");
1948 }
1949 
1950 static void state_wrapv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1951 {
1952  if (state->render_states[WINED3D_RS_WRAPV])
1953  FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n");
1954 }
1955 
1956 static void state_monoenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1957 {
1958  if (state->render_states[WINED3D_RS_MONOENABLE])
1959  FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n");
1960 }
1961 
1962 static void state_rop2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1963 {
1964  if (state->render_states[WINED3D_RS_ROP2])
1965  FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n");
1966 }
1967 
1968 static void state_planemask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1969 {
1970  if (state->render_states[WINED3D_RS_PLANEMASK])
1971  FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n");
1972 }
1973 
1974 static void state_subpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1975 {
1976  if (state->render_states[WINED3D_RS_SUBPIXEL])
1977  FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n");
1978 }
1979 
1980 static void state_subpixelx(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1981 {
1982  if (state->render_states[WINED3D_RS_SUBPIXELX])
1983  FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n");
1984 }
1985 
1986 static void state_stippleenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1987 {
1988  if (state->render_states[WINED3D_RS_STIPPLEENABLE])
1989  FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n");
1990 }
1991 
1992 static void state_mipmaplodbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1993 {
1994  if (state->render_states[WINED3D_RS_MIPMAPLODBIAS])
1995  FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n");
1996 }
1997 
1998 static void state_anisotropy(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1999 {
2000  if (state->render_states[WINED3D_RS_ANISOTROPY])
2001  FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n");
2002 }
2003 
2004 static void state_flushbatch(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2005 {
2006  if (state->render_states[WINED3D_RS_FLUSHBATCH])
2007  FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n");
2008 }
2009 
2010 static void state_translucentsi(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2011 {
2012  if (state->render_states[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT])
2013  FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
2014 }
2015 
2016 static void state_extents(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2017 {
2018  if (state->render_states[WINED3D_RS_EXTENTS])
2019  FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n");
2020 }
2021 
2022 static void state_ckeyblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2023 {
2024  if (state->render_states[WINED3D_RS_COLORKEYBLENDENABLE])
2025  FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n");
2026 }
2027 
2028 static void state_swvp(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2029 {
2030  static int once;
2031  if (state->render_states[WINED3D_RS_SOFTWAREVERTEXPROCESSING])
2032  {
2033  if (!once++)
2034  FIXME("Software vertex processing not implemented.\n");
2035  }
2036 }
2037 
2039  /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
2040  * input should be used for all input components. The WINED3DTA_COMPLEMENT
2041  * flag specifies the complement of the input should be used. */
2042  BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
2043  BOOL complement = arg & WINED3DTA_COMPLEMENT;
2044 
2045  /* Calculate the operand */
2046  if (complement) {
2047  if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
2048  else *operand = GL_ONE_MINUS_SRC_COLOR;
2049  } else {
2050  if (from_alpha) *operand = GL_SRC_ALPHA;
2051  else *operand = GL_SRC_COLOR;
2052  }
2053 
2054  /* Calculate the source */
2055  switch (arg & WINED3DTA_SELECTMASK) {
2056  case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
2058  case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
2059  case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
2060  case WINED3DTA_SPECULAR:
2061  /*
2062  * According to the GL_ARB_texture_env_combine specs, SPECULAR is
2063  * 'Secondary color' and isn't supported until base GL supports it
2064  * There is no concept of temp registers as far as I can tell
2065  */
2066  FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
2067  *source = GL_TEXTURE;
2068  break;
2069  default:
2070  FIXME("Unrecognized texture arg %#x\n", arg);
2071  *source = GL_TEXTURE;
2072  break;
2073  }
2074 }
2075 
2076 /* Setup the texture operations texture stage states */
2077 static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
2078  BOOL isAlpha, int Stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
2079 {
2080  GLenum src1, src2, src3;
2081  GLenum opr1, opr2, opr3;
2082  GLenum comb_target;
2083  GLenum src0_target, src1_target, src2_target;
2084  GLenum opr0_target, opr1_target, opr2_target;
2085  GLenum scal_target;
2086  GLenum opr=0, invopr, src3_target, opr3_target;
2087  BOOL Handled = FALSE;
2088 
2089  TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
2090 
2091  /* Operations usually involve two args, src0 and src1 and are operations
2092  * of the form (a1 <operation> a2). However, some of the more complex
2093  * operations take 3 parameters. Instead of the (sensible) addition of a3,
2094  * Microsoft added in a third parameter called a0. Therefore these are
2095  * operations of the form a0 <operation> a1 <operation> a2. I.e., the new
2096  * parameter goes to the front.
2097  *
2098  * However, below we treat the new (a0) parameter as src2/opr2, so in the
2099  * actual functions below, expect their syntax to differ slightly to those
2100  * listed in the manuals. I.e., replace arg1 with arg3, arg2 with arg1 and
2101  * arg3 with arg2. This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP. */
2102 
2103  if (isAlpha)
2104  {
2105  comb_target = GL_COMBINE_ALPHA;
2106  src0_target = GL_SOURCE0_ALPHA;
2107  src1_target = GL_SOURCE1_ALPHA;
2108  src2_target = GL_SOURCE2_ALPHA;
2109  opr0_target = GL_OPERAND0_ALPHA;
2110  opr1_target = GL_OPERAND1_ALPHA;
2111  opr2_target = GL_OPERAND2_ALPHA;
2112  scal_target = GL_ALPHA_SCALE;
2113  }
2114  else
2115  {
2116  comb_target = GL_COMBINE_RGB;
2117  src0_target = GL_SOURCE0_RGB;
2118  src1_target = GL_SOURCE1_RGB;
2119  src2_target = GL_SOURCE2_RGB;
2120  opr0_target = GL_OPERAND0_RGB;
2121  opr1_target = GL_OPERAND1_RGB;
2122  opr2_target = GL_OPERAND2_RGB;
2123  scal_target = GL_RGB_SCALE;
2124  }
2125 
2126  /* If a texture stage references an invalid texture unit the stage just
2127  * passes through the result from the previous stage */
2128  if (is_invalid_op(state, Stage, op, arg1, arg2, arg3))
2129  {
2132  }
2133 
2134  if (isAlpha && !state->textures[Stage] && arg1 == WINED3DTA_TEXTURE)
2135  {
2136  get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
2137  } else {
2138  get_src_and_opr(arg1, isAlpha, &src1, &opr1);
2139  }
2140  get_src_and_opr(arg2, isAlpha, &src2, &opr2);
2141  get_src_and_opr(arg3, isAlpha, &src3, &opr3);
2142 
2143  TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
2144 
2145  Handled = TRUE; /* Assume will be handled */
2146 
2147  /* Other texture operations require special extensions: */
2148  if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
2149  {
2150  if (isAlpha) {
2151  opr = GL_SRC_ALPHA;
2152  invopr = GL_ONE_MINUS_SRC_ALPHA;
2153  src3_target = GL_SOURCE3_ALPHA_NV;
2154  opr3_target = GL_OPERAND3_ALPHA_NV;
2155  } else {
2156  opr = GL_SRC_COLOR;
2157  invopr = GL_ONE_MINUS_SRC_COLOR;
2158  src3_target = GL_SOURCE3_RGB_NV;
2159  opr3_target = GL_OPERAND3_RGB_NV;
2160  }
2161  switch (op)
2162  {
2163  case WINED3D_TOP_DISABLE: /* Only for alpha */
2164  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2165  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2166  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2167  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2168  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2169  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2170  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2171  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2172  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2173  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2174  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2175  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2176  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2177  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2178  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2179  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2180  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2181  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2182  break;
2183 
2184  case WINED3D_TOP_SELECT_ARG1: /* = a1 * 1 + 0 * 0 */
2185  case WINED3D_TOP_SELECT_ARG2: /* = a2 * 1 + 0 * 0 */
2186  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2187  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2188  if (op == WINED3D_TOP_SELECT_ARG1)
2189  {
2190  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2191  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2192  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2193  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2194  }
2195  else
2196  {
2197  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2198  checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2199  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2200  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2201  }
2202  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2203  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2204  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2205  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2206  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2207  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2208  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2209  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2210  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2211  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2212  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2213  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2214  break;
2215 
2216  case WINED3D_TOP_MODULATE:
2217  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2218  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2219  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2220  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2221  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2222  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2223  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2224  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2225  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2226  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2227  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2228  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2229  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2230  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2231  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2232  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2233  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2234  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2235  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2236  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2237  break;
2239  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2240  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2241  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2242  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2243  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2244  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2245  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2246  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2247  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2248  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2249  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2250  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2251  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2252  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2253  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2254  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2255  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2256  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2257  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2258  checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2259  break;
2261  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2262  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2263  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2264  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2265  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2266  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2267  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2268  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2269  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2270  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2271  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2272  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2273  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2274  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2275  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2276  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2277  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2278  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2279  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2280  checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2281  break;
2282 
2283  case WINED3D_TOP_ADD:
2284  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2285  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2286  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2287  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2288  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2289  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2290  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2291  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2292  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2293  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2294  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2295  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2296  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2297  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2298  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2299  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2300  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2301  checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2302  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2303  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2304  break;
2305 
2307  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2308  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2309  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2310  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2311  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2312  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2313  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2314  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2315  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2316  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2317  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2318  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2319  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2320  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2321  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2322  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2323  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2324  checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2325  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2326  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2327  break;
2328 
2330  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2331  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2332  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2333  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2334  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2335  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2336  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2337  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2338  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2339  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2340  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2341  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2342  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2343  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2344  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2345  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2346  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2347  checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2348  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2349  checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2350  break;
2351 
2353  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2354  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2355  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2356  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2357  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2358  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2359  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2360  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2361  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2362  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2363  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2364  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2365  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2366  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2367  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2368  checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2369  switch (opr1) {
2370  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2371  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2372  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2373  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2374  }
2375  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2376  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2377  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2378  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2379  break;
2380 
2382  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2383  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2384  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2385  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2386  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2387  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2388  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR);
2389  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR");
2390  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2391  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2392  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2393  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2394  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2395  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2396  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR);
2397  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR");
2398  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2399  checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2400  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2401  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2402  break;
2404  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2405  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2406  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2407  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2408  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2409  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2410  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2411  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2412  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2413  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2414  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2415  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2416  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2417  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2418  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2419  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2420  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2421  checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2422  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2423  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2424  break;
2426  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2427  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2428  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2429  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2430  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2431  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2432  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_CONSTANT);
2433  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_CONSTANT");
2434  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2435  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2436  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2437  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2438  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2439  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2440  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_CONSTANT);
2441  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_CONSTANT");
2442  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2443  checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2444  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2445  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2446  break;
2448  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2449  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2450  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2451  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2452  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2453  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2454  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2455  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2456  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2457  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2458  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2459  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2460  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2461  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2462  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2463  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2464  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2465  checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2466  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2467  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2468  break;
2470  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2471  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2472  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2473  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2474  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2475  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2476  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2477  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2478  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2479  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2480  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2481  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2482  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2483  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2484  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2485  checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2486  switch (opr) {
2487  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2489  }
2490  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2491  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2492  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2493  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2494  break;
2496  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2497  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2498  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2499  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2500  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2501  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2502  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2503  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2504  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2505  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2506  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2507  checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2508  switch (opr1) {
2509  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2511  }
2512  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2513  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2514  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2515  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2516  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2517  checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2518  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2519  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2520  break;
2522  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2523  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2524  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2525  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2526  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2527  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2528  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2529  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2530  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2531  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2532  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2533  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2534  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2535  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2536  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2537  checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2538  switch (opr1) {
2539  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2540  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2541  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2542  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2543  }
2544  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2545  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2546  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2547  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2548  break;
2550  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2551  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2552  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2553  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2554  switch (opr1) {
2555  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2556  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2557  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2558  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2559  }
2560  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2561  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2562  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2563  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2564  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2565  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2566  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2567  checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2568  switch (opr1) {
2569  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2571  }
2572  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2573  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2574  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2575  checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2576  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2577  checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2578  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2579  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2580  break;
2582  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2583  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2584  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2585  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2586  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2587  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2588  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2589  checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2590  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2591  checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2592  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2593  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2594  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2595  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2596  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2597  checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2598  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2599  checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2600  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2601  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2602  break;
2603 
2606  FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2607  Handled = FALSE;
2608  break;
2609 
2610  default:
2611  Handled = FALSE;
2612  }
2613  if (Handled)
2614  {
2615  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2616  checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2617 
2618  return;
2619  }
2620  } /* GL_NV_texture_env_combine4 */
2621 
2622  Handled = TRUE; /* Again, assume handled */
2623  switch (op) {
2624  case WINED3D_TOP_DISABLE: /* Only for alpha */
2625  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2626  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2627  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2628  checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2629  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2630  checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2631  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2632  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2633  break;
2635  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2636  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2637  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2638  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2639  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2640  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2641  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2642  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2643  break;
2645  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2646  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2647  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2648  checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2649  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2650  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2651  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2652  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2653  break;
2654  case WINED3D_TOP_MODULATE:
2655  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2656  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2657  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2658  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2659  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2660  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2661  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2662  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2663  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2664  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2665  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2666  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2667  break;
2669  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2670  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2671  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2672  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2673  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2674  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2675  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2676  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2677  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2678  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2679  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2680  checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2681  break;
2683  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2684  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2685  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2686  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2687  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2688  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2689  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2690  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2691  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2692  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2693  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2694  checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2695  break;
2696  case WINED3D_TOP_ADD:
2697  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2698  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2699  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2700  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2701  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2702  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2703  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2704  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2705  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2706  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2707  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2708  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2709  break;
2711  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2712  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2713  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2714  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2715  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2716  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2717  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2718  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2719  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2720  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2721  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2722  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2723  break;
2725  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2726  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2727  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2728  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2729  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2730  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2731  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2732  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2733  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2734  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2735  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2736  checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2737  break;
2738  case WINED3D_TOP_SUBTRACT:
2739  if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE])
2740  {
2741  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2742  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_SUBTRACT");
2743  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2744  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2745  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2746  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2747  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2748  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2749  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2750  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2751  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2752  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2753  } else {
2754  FIXME("This version of opengl does not support GL_SUBTRACT\n");
2755  }
2756  break;
2757 
2759  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2760  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2761  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2762  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2763  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2764  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2765  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2766  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2767  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2768  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2769  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR);
2770  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2771  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2772  checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2773  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2774  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2775  break;
2777  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2778  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2779  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2780  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2781  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2782  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2783  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2784  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2785  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2786  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2787  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2788  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2789  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2790  checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2791  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2792  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2793  break;
2795  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2796  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2797  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2798  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2799  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2800  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2801  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2802  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2803  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2804  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2805  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_CONSTANT);
2806  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2807  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2808  checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2809  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2810  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2811  break;
2813  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2814  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2815  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2816  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2817  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2818  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2819  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2820  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2821  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2822  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2823  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PREVIOUS);
2824  checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2825  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2826  checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2827  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2828  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2829  break;
2831  if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
2832  {
2833  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2834  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2835  }
2836  else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3])
2837  {
2838  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2839  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2840  } else {
2841  FIXME("This version of opengl does not support GL_DOT3\n");
2842  }
2843  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2844  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2845  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2846  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2847  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2848  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2849  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2850  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2851  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2852  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2853  break;
2854  case WINED3D_TOP_LERP:
2855  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2856  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2857  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2858  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2859  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2860  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2861  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2862  checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2863  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2864  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2865  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2866  checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2867  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2868  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2869  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2870  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2871  break;
2873  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2874  {
2875  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2876  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2877  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2878  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2879  switch (opr1) {
2880  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2881  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2882  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2883  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2884  }
2885  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2886  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2887  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2888  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2889  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2890  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2891  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2892  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2893  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2894  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2895  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2896  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2897  } else
2898  Handled = FALSE;
2899  break;
2901  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2902  {
2903  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2904  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2905  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2906  checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2907  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2908  checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2909  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2910  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2911  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2912  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2913  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2914  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2915  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2916  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2917  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2918  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2919  } else
2920  Handled = FALSE;
2921  break;
2923  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2924  {
2925  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2926  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2927  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2928  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2929  switch (opr1) {
2930  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2932  case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2934  }
2935  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2936  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2937  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2938  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2939  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2940  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2941  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2942  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2943  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2944  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2945  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2946  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2947  } else
2948  Handled = FALSE;
2949  break;
2951  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2952  {
2953  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2954  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2955  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2956  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2957  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2958  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2959  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2960  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2961  switch (opr1) {
2962  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2964  case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2966  }
2967  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2968  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2969  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2970  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2971  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2972  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2973  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2974  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2975  } else
2976  Handled = FALSE;
2977  break;
2979  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2980  {
2981  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2982  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2983  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2984  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2985  switch (opr1) {
2986  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2987  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2988  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2989  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2990  }
2991  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2992  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2993  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2994  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2995  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2996  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2997  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2998  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2999  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3000  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3001  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3002  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
3003  } else
3004  Handled = FALSE;
3005  break;
3007  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
3008  {
3009  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
3010  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
3011  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
3012  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
3013  switch (opr1) {
3014  case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
3015  case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
3016  case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
3017  case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
3018  }
3019  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
3020  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
3021  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
3022  checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
3023  switch (opr1) {
3024  case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
3026  case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
3028  }
3029  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
3030  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
3031  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3032  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3033  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3034  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3035  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3036  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
3037  } else
3038  Handled = FALSE;
3039  break;
3041  if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
3042  {
3043  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
3044  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
3045  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
3046  checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
3047  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
3048  checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
3049  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
3050  checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
3051  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
3052  checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
3053  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3054  checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3055  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3056  checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3057  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3058  checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
3059  } else
3060  Handled = FALSE;
3061  break;
3064  if (gl_info->supported[NV_TEXTURE_SHADER2])
3065  {
3066  /* Technically texture shader support without register combiners is possible, but not expected to occur
3067  * on real world cards, so for now a fixme should be enough
3068  */
3069  FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
3070  }
3071  Handled = FALSE;
3072  break;
3073 
3074  default:
3075  Handled = FALSE;
3076  }
3077 
3078  if (Handled) {
3079  BOOL combineOK = TRUE;
3080  if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
3081  {
3082  DWORD op2;
3083 
3084  if (isAlpha)
3085  op2 = state->texture_states[Stage][WINED3D_TSS_COLOR_OP];
3086  else
3087  op2 = state->texture_states[Stage][WINED3D_TSS_ALPHA_OP];
3088 
3089  /* Note: If COMBINE4 in effect can't go back to combine! */
3090  switch (op2)
3091  {
3099  /* Ignore those implemented in both cases */
3100  switch (op)
3101  {
3104  combineOK = FALSE;
3105  Handled = FALSE;
3106  break;
3107  default:
3108  FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
3109  return;
3110  }
3111  }
3112  }
3113 
3114  if (combineOK)
3115  {
3116  gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3117  checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE");
3118 
3119  return;
3120  }
3121  }
3122 
3123  /* After all the extensions, if still unhandled, report fixme */
3124  FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
3125 }
3126 
3127 
3128 static void tex_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3129 {
3130  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3131  BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
3132  DWORD mapped_stage = context->tex_unit_map[stage];
3133  const struct wined3d_gl_info *gl_info = context->gl_info;
3134 
3135  TRACE("Setting color op for stage %d\n", stage);
3136 
3137  /* Using a pixel shader? Don't care for anything here, the shader applying does it */
3138  if (use_ps(state)) return;
3139 
3140  if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
3141 
3142  if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3143  {
3144  if (tex_used && mapped_stage >= gl_info->limits.textures)
3145  {
3146  FIXME("Attempt to enable unsupported stage!\n");
3147  return;
3148  }
3149  context_active_texture(context, gl_info, mapped_stage);
3150  }
3151 
3152  if (stage >= context->lowest_disabled_stage)
3153  {
3154  TRACE("Stage disabled\n");
3155  if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3156  {
3157  /* Disable everything here */
3158  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3159  checkGLcall("glDisable(GL_TEXTURE_2D)");
3160  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3161  checkGLcall("glDisable(GL_TEXTURE_3D)");
3162  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3163  {
3164  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3165  checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3166  }
3167  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3168  {
3169  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3170  checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3171  }
3172  }
3173  /* All done */
3174  return;
3175  }
3176 
3177  /* The sampler will also activate the correct texture dimensions, so no
3178  * need to do it here if the sampler for this stage is dirty. */
3179  if (!isStateDirty(context, STATE_SAMPLER(stage)) && tex_used)
3180  texture_activate_dimensions(state->textures[stage], gl_info);
3181 
3182  set_tex_op(gl_info, state, FALSE, stage,
3183  state->texture_states[stage][WINED3D_TSS_COLOR_OP],
3184  state->texture_states[stage][WINED3D_TSS_COLOR_ARG1],
3185  state->texture_states[stage][WINED3D_TSS_COLOR_ARG2],
3186  state->texture_states[stage][WINED3D_TSS_COLOR_ARG0]);
3187 }
3188 
3189 void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3190 {
3191  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3192  BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
3193  DWORD mapped_stage = context->tex_unit_map[stage];
3194  const struct wined3d_gl_info *gl_info = context->gl_info;
3195  DWORD op, arg1, arg2, arg0;
3196 
3197  TRACE("Setting alpha op for stage %d\n", stage);
3198  /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
3199  if (mapped_stage != WINED3D_UNMAPPED_STAGE)
3200  {
3201  if (tex_used && mapped_stage >= gl_info->limits.textures)
3202  {
3203  FIXME("Attempt to enable unsupported stage!\n");
3204  return;
3205  }
3206  context_active_texture(context, gl_info, mapped_stage);
3207  }
3208 
3209  op = state->texture_states[stage][WINED3D_TSS_ALPHA_OP];
3210  arg1 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG1];
3211  arg2 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG2];
3212  arg0 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG0];
3213 
3214  if (state->render_states[WINED3D_RS_COLORKEYENABLE] && !stage && state->textures[0])
3215  {
3216  struct wined3d_texture *texture = state->textures[0];
3217  GLenum texture_dimensions = texture->target;
3218 
3219  if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3220  {
3221  if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size)
3222  {
3223  /* Color keying needs to pass alpha values from the texture through to have the alpha test work
3224  * properly. On the other hand applications can still use texture combiners apparently. This code
3225  * takes care that apps cannot remove the texture's alpha channel entirely.
3226  *
3227  * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
3228  * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
3229  * and alpha component of diffuse color to draw things like translucent text and perform other
3230  * blending effects.
3231  *
3232  * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
3233  * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
3234  * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
3235  * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
3236  * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
3237  * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
3238  * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
3239  * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
3240  * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
3241  * alpha.
3242  *
3243  * What to do with multitexturing? So far no app has been found that uses color keying with
3244  * multitexturing */
3245  if (op == WINED3D_TOP_DISABLE)
3246  {
3249  }
3251  {
3252  if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3253  {
3256  }
3257  else arg1 = WINED3DTA_TEXTURE;
3258  }
3260  {
3261  if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3262  {
3265  }
3266  else arg2 = WINED3DTA_TEXTURE;
3267  }
3268  }
3269  }
3270  }
3271 
3272  /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3273  * this if block here, and the other code(color keying, texture unit selection) are the same
3274  */
3275  TRACE("Setting alpha op for stage %d\n", stage);
3276  if (gl_info->supported[NV_REGISTER_COMBINERS])
3277  {
3278  set_tex_op_nvrc(gl_info, state, TRUE, stage, op, arg1, arg2, arg0,
3279  mapped_stage, state->texture_states[stage][WINED3D_TSS_RESULT_ARG]);
3280  }
3281  else
3282  {
3283  set_tex_op(gl_info, state, TRUE, stage, op, arg1, arg2, arg0);
3284  }
3285 }
3286 
3287 static void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3288 {
3289  const struct wined3d_gl_info *gl_info = context->gl_info;
3290  unsigned int tex = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3291  unsigned int mapped_stage = context->tex_unit_map[tex];
3292  struct wined3d_matrix mat;
3293 
3294  /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3296  {
3297  TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3298  return;
3299  }
3300 
3301  if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3302  if (mapped_stage >= gl_info->limits.textures) return;
3303 
3304  context_active_texture(context, gl_info, mapped_stage);
3305  gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
3306  checkGLcall("glMatrixMode(GL_TEXTURE)");
3307 
3308  get_texture_matrix(context, state, mapped_stage, &mat);
3309 
3310  gl_info->gl_ops.gl.p_glLoadMatrixf(&mat._11);
3311  checkGLcall("glLoadMatrixf");
3312 }
3313 
3314 static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3315 {
3316  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3317  static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
3318  static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
3319  static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
3320  static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3321  const struct wined3d_gl_info *gl_info = context->gl_info;
3322  DWORD mapped_stage = context->tex_unit_map[stage];
3323 
3324  if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3325  {
3326  TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3327  return;
3328  }
3329 
3330  if (mapped_stage >= min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_FRAGMENT_SAMPLERS))
3331  {
3332  WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3333  return;
3334  }
3335  context_active_texture(context, gl_info, mapped_stage);
3336 
3337  /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3338  *
3339  * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3340  * eg. SetTextureStageState( 0, WINED3D_TSS_TEXCOORDINDEX, WINED3D_TSS_TCI_CAMERASPACEPOSITION | 1 );
3341  * means use the vertex position (camera-space) as the input texture coordinates
3342  * for this texture stage, and the wrap mode set in the WINED3D_RS_WRAP1 render
3343  * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3344  * to the TEXCOORDINDEX value
3345  */
3346  switch (state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000)
3347  {
3349  /* Use the specified texture coordinates contained within the
3350  * vertex format. This value resolves to zero. */
3351  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
3352  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
3353  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
3354  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
3355  checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3356  break;
3357 
3359  /* CameraSpacePosition means use the vertex position, transformed to camera space,
3360  * as the input texture coordinates for this stage's texture transformation. This
3361  * equates roughly to EYE_LINEAR */
3362 
3363  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3364  gl_info->gl_ops.gl.p_glPushMatrix();
3365  gl_info->gl_ops.gl.p_glLoadIdentity();
3366  gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3367  gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3368  gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3369  gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3370  gl_info->gl_ops.gl.p_glPopMatrix();
3371  checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3372 
3373  gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3374  gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3375  gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3376  checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3377 
3378  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
3379  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
3380  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3381  checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3382 
3383  break;
3384 
3386  /* Note that NV_TEXGEN_REFLECTION support is implied when
3387  * ARB_TEXTURE_CUBE_MAP is supported */
3388  if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3389  {
3390  FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3391  break;
3392  }
3393 
3394  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3395  gl_info->gl_ops.gl.p_glPushMatrix();
3396  gl_info->gl_ops.gl.p_glLoadIdentity();
3397  gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3398  gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3399  gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3400  gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3401  gl_info->gl_ops.gl.p_glPopMatrix();
3402  checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3403 
3404  gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3405  gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3406  gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3407  checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3408 
3409  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
3410  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
3411  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3412  checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3413 
3414  break;
3415 
3417  /* Note that NV_TEXGEN_REFLECTION support is implied when
3418  * ARB_TEXTURE_CUBE_MAP is supported */
3419  if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3420  {
3421  FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3422  break;
3423  }
3424 
3425  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3426  gl_info->gl_ops.gl.p_glPushMatrix();
3427  gl_info->gl_ops.gl.p_glLoadIdentity();
3428  gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3429  gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3430  gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3431  gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3432  gl_info->gl_ops.gl.p_glPopMatrix();
3433  checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3434 
3435  gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3436  gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3437  gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3438  checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3439 
3440  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
3441  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
3442  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3443  checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3444 
3445  break;
3446 
3448  gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3449  gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3450  checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3451 
3452  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
3453  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
3454  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
3455  checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3456 
3457  break;
3458 
3459  default:
3460  FIXME("Unhandled WINED3D_TSS_TEXCOORD_INDEX %#x.\n",
3461  state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX]);
3462  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
3463  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
3464  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
3465  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
3466  checkGLcall("Disable texgen.");
3467 
3468  break;
3469  }
3470 
3471  /* Update the texture matrix. */
3474 
3475  if (!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded)
3476  {
3477  /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3478  * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3479  * and do all the things linked to it
3480  * TODO: Tidy that up to reload only the arrays of the changed unit
3481  */
3482  GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
3483 
3485  context_load_tex_coords(context, &context->stream_info, &curVBO, state);
3486  }
3487 }
3488 
3489 static void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3490 {
3491  const DWORD sampler = state_id - STATE_SAMPLER(0);
3492  const struct wined3d_texture *texture = state->textures[sampler];
3493 
3494  TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
3495 
3496  if (!texture)
3497  return;
3498 
3499  /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3500  * wined3d_texture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3501  * scaling is reapplied or removed, the texture matrix has to be reapplied.
3502  */
3503  if (sampler < MAX_TEXTURES)
3504  {
3505  const BOOL tex_is_pow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT);
3506 
3507  if (tex_is_pow2 || (context->lastWasPow2Texture & (1u << sampler)))
3508  {
3509  if (tex_is_pow2)
3510  context->lastWasPow2Texture |= 1u << sampler;
3511  else
3512  context->lastWasPow2Texture &= ~(1u << sampler);
3513 
3515  }
3516  }
3517 }
3518 
3521 {
3523  {
3524  FIXME("Unrecognized or unsupported texture address mode %#x.\n", t);
3525  return WINED3D_TADDRESS_WRAP;
3526  }
3527 
3528  /* Cubemaps are always set to clamp, regardless of the sampler state. */
3529  if (texture->target == GL_TEXTURE_CUBE_MAP_ARB || ((texture->flags & WINED3D_TEXTURE_COND_NP2)
3530  && t == WINED3D_TADDRESS_WRAP))
3531  return WINED3D_TADDRESS_CLAMP;
3532 
3533  return t;
3534 }
3535 
3537  const struct wined3d_context *context, const DWORD *sampler_states, const struct wined3d_texture *texture)
3538 {
3539  union
3540  {
3541  float f;
3542  DWORD d;
3543  } lod_bias;
3544 
3545  desc->address_u = wined3d_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_U]);
3546  desc->address_v = wined3d_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_V]);
3547  desc->address_w = wined3d_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_W]);
3548  wined3d_color_from_d3dcolor((struct wined3d_color *)desc->border_color,
3549  sampler_states[WINED3D_SAMP_BORDER_COLOR]);
3550  if (sampler_states[WINED3D_SAMP_MAG_FILTER] > WINED3D_TEXF_ANISOTROPIC)
3551  FIXME("Unrecognized or unsupported WINED3D_SAMP_MAG_FILTER %#x.\n",
3552  sampler_states[WINED3D_SAMP_MAG_FILTER]);
3553  desc->mag_filter = min(max(sampler_states[WINED3D_SAMP_MAG_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
3554  if (sampler_states[WINED3D_SAMP_MIN_FILTER] > WINED3D_TEXF_ANISOTROPIC)
3555  FIXME("Unrecognized or unsupported WINED3D_SAMP_MIN_FILTER %#x.\n",
3556  sampler_states[WINED3D_SAMP_MIN_FILTER]);
3557  desc->min_filter = min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
3558  if (sampler_states[WINED3D_SAMP_MIP_FILTER] > WINED3D_TEXF_ANISOTROPIC)
3559  FIXME("Unrecognized or unsupported WINED3D_SAMP_MIP_FILTER %#x.\n",
3560  sampler_states[WINED3D_SAMP_MIP_FILTER]);
3561  desc->mip_filter = min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR);
3562  lod_bias.d = sampler_states[WINED3D_SAMP_MIPMAP_LOD_BIAS];
3563  desc->lod_bias = lod_bias.f;
3564  desc->min_lod = -1000.0f;
3565  desc->max_lod = 1000.0f;
3566  desc->mip_base_level = sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL];
3567  desc->max_anisotropy = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY];
3568  if ((sampler_states[WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_ANISOTROPIC
3570  && sampler_states[WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_ANISOTROPIC)
3571  || (texture->flags & WINED3D_TEXTURE_COND_NP2))
3572  desc->max_anisotropy = 1;
3573  desc->compare = texture->resource.format_flags & WINED3DFMT_FLAG_SHADOW;
3574  desc->comparison_func = WINED3D_CMP_LESSEQUAL;
3575  desc->srgb_decode = sampler_states[WINED3D_SAMP_SRGB_TEXTURE];
3576 
3577  if (!(texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING))
3578  {
3579  desc->mag_filter = WINED3D_TEXF_POINT;
3580  desc->min_filter = WINED3D_TEXF_POINT;
3581  desc->mip_filter = WINED3D_TEXF_NONE;
3582  }
3583 
3584  if (texture->flags & WINED3D_TEXTURE_COND_NP2)
3585  {
3586  desc->mip_filter = WINED3D_TEXF_NONE;
3587  if (context->gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
3588  desc->min_filter = WINED3D_TEXF_POINT;
3589  }
3590 }
3591 
3592 /* Enabling and disabling texture dimensions is done by texture stage state /
3593  * pixel shader setup, this function only has to bind textures and set the per
3594  * texture states. */
3595 static void sampler(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3596 {
3597  DWORD sampler_idx = state_id - STATE_SAMPLER(0);
3598  DWORD mapped_stage = context->tex_unit_map[sampler_idx];
3599  const struct wined3d_gl_info *gl_info = context->gl_info;
3600 
3601  TRACE("Sampler %u.\n", sampler_idx);
3602 
3603  if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3604  {
3605  TRACE("No sampler mapped to stage %u. Returning.\n", sampler_idx);
3606  return;
3607  }
3608 
3609  if (mapped_stage >= gl_info->limits.graphics_samplers)
3610  return;
3611  context_active_texture(context, gl_info, mapped_stage);
3612 
3613  if (state->textures[sampler_idx])
3614  {
3615  BOOL srgb = state->sampler_states[sampler_idx][WINED3D_SAMP_SRGB_TEXTURE];
3616  const DWORD *sampler_states = state->sampler_states[sampler_idx];
3617  struct wined3d_texture *texture = state->textures[sampler_idx];
3618  struct wined3d_device *device = context->device;
3619  struct wined3d_sampler_desc desc;
3620  struct wined3d_sampler *sampler;
3621  struct wine_rb_entry *entry;
3622 
3624 
3626 
3627  if ((entry = wine_rb_get(&device->samplers, &desc)))
3628  {
3630  }
3631  else
3632  {
3634  {
3635  ERR("Failed to create sampler.\n");
3636  return;
3637  }
3638  if (wine_rb_put(&device->samplers, &desc, &sampler->entry) == -1)
3639  {
3640  ERR("Failed to insert sampler.\n");
3642  return;
3643  }
3644  }
3645 
3646  wined3d_sampler_bind(sampler, mapped_stage, texture, context);
3647 
3648  /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3649  if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
3650  context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
3651  }
3652  else
3653  {
3655  if (gl_info->supported[ARB_SAMPLER_OBJECTS])
3656  {
3657  GL_EXTCALL(glBindSampler(mapped_stage, 0));
3658  checkGLcall("glBindSampler");
3659  }
3660  }
3661 }
3662 
3663 void apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3664 {
3665  unsigned int i;
3666 
3667  if (use_ps(state))
3668  {
3669  if (!context->last_was_pshader)
3670  {
3671  /* Former draw without a pixel shader, some samplers may be
3672  * disabled because of WINED3D_TSS_COLOR_OP = WINED3DTOP_DISABLE
3673  * make sure to enable them. */
3674  for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
3675  {
3678  }
3679  context->last_was_pshader = TRUE;
3680  }
3681  else
3682  {
3683  /* Otherwise all samplers were activated by the code above in
3684  * earlier draws, or by sampler() if a different texture was
3685  * bound. I don't have to do anything. */
3686  }
3687  }
3688  else
3689  {
3690  /* Disabled the pixel shader - color ops weren't applied while it was
3691  * enabled, so re-apply them. */
3692  for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
3693  {
3696  }
3697  context->last_was_pshader = FALSE;
3698  }
3699 
3700  context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
3701 }
3702 
3703 static void state_compute_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3704 {
3705  context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3706 }
3707 
3708 static void state_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3709 {
3710  enum wined3d_shader_type shader_type = state_id - STATE_SHADER(0);
3711  context->shader_update_mask |= 1u << shader_type;
3712 }
3713 
3714 static void shader_bumpenv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3715 {
3716  context->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
3717 }
3718 
3719 static void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3720 {
3721  const struct wined3d_gl_info *gl_info = context->gl_info;
3722  struct wined3d_matrix mat;
3723 
3724  /* This function is called by transform_view below if the view matrix was changed too
3725  *
3726  * Deliberately no check if the vertex declaration is dirty because the vdecl state
3727  * does not always update the world matrix, only on a switch between transformed
3728  * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3729  * draw, but that should be rather rare and cheaper in total.
3730  */
3731  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3732  checkGLcall("glMatrixMode");
3733 
3735 
3736  gl_info->gl_ops.gl.p_glLoadMatrixf((GLfloat *)&mat);
3737  checkGLcall("glLoadMatrixf");
3738 }
3739 
3740 void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3741 {
3742  const struct wined3d_gl_info *gl_info = context->gl_info;
3743  UINT index = state_id - STATE_CLIPPLANE(0);
3744  GLdouble plane[4];
3745 
3746  if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)) || index >= gl_info->limits.user_clip_distances)
3747  return;
3748 
3749  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3750  gl_info->gl_ops.gl.p_glPushMatrix();
3751 
3752  /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3753  if (!use_vs(state))
3754  gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
3755  else
3756  /* With vertex shaders, clip planes are not transformed in Direct3D,
3757  * while in OpenGL they are still transformed by the model view matrix. */
3758  gl_info->gl_ops.gl.p_glLoadIdentity();
3759 
3760  plane[0] = state->clip_planes[index].x;
3761  plane[1] = state->clip_planes[index].y;
3762  plane[2] = state->clip_planes[index].z;
3763  plane[3] = state->clip_planes[index].w;
3764 
3765  TRACE("Clipplane [%.8e, %.8e, %.8e, %.8e]\n",
3766  plane[0], plane[1], plane[2], plane[3]);
3767  gl_info->gl_ops.gl.p_glClipPlane(GL_CLIP_PLANE0 + index, plane);
3768  checkGLcall("glClipPlane");
3769 
3770  gl_info->gl_ops.gl.p_glPopMatrix();
3771 }
3772 
3773 static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3774 {
3775  unsigned int matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
3776 
3777  WARN("Unsupported world matrix %u set.\n", matrix);
3778 }
3779 
3780 static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3781 {
3783  static unsigned int once;
3784 
3785  if (f == WINED3D_VBF_DISABLE)
3786  return;
3787 
3788  if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
3789  else WARN("Vertex blend flags %#x not supported.\n", f);
3790 }
3791 
3792 static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3793 {
3794  const struct wined3d_gl_info *gl_info = context->gl_info;
3795  const struct wined3d_light_info *light = NULL;
3796  unsigned int k;
3797 
3798  /* If we are changing the View matrix, reset the light and clipping planes to the new view
3799  * NOTE: We have to reset the positions even if the light/plane is not currently
3800  * enabled, since the call to enable it will not reset the position.
3801  * NOTE2: Apparently texture transforms do NOT need reapplying
3802  */
3803 
3804  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3805  checkGLcall("glMatrixMode(GL_MODELVIEW)");
3806  gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
3807  checkGLcall("glLoadMatrixf(...)");
3808 
3809  /* Reset lights. TODO: Call light apply func */
3810  for (k = 0; k < gl_info->limits.lights; ++k)
3811  {
3812  if (!(light = state->lights[k]))
3813  continue;
3814  if (light->OriginalParms.type == WINED3D_LIGHT_DIRECTIONAL)
3815  gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, &light->direction.x);
3816  else
3817  gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, &light->position.x);
3818  checkGLcall("glLightfv posn");
3819  gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, &light->direction.x);
3820  checkGLcall("glLightfv dirn");
3821  }
3822 
3823  /* Reset Clipping Planes */
3824  for (k = 0; k < gl_info->limits.user_clip_distances; ++k)
3825  {
3828  }
3829 
3830  if (context->last_was_rhw)
3831  {
3832  gl_info->gl_ops.gl.p_glLoadIdentity();
3833  checkGLcall("glLoadIdentity()");
3834  /* No need to update the world matrix, the identity is fine */
3835  return;
3836  }
3837 
3838  /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3839  * No need to do it here if the state is scheduled for update. */
3842 }
3843 
3844 static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3845 {
3846  const struct wined3d_gl_info *gl_info = context->gl_info;
3847  struct wined3d_matrix projection;
3848 
3849  gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
3850  checkGLcall("glMatrixMode(GL_PROJECTION)");
3851 
3852  get_projection_matrix(context, state, &projection);
3853  gl_info->gl_ops.gl.p_glLoadMatrixf(&projection._11);
3854  checkGLcall("glLoadMatrixf");
3855 }
3856 
3857 static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3858 {
3860  return;
3862 }
3863 
3864 static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3865 {
3867  return;
3869 }
3870 
3871 static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state,