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