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