2 * Compatibility functions for older GL implementations
4 * Copyright 2008 Stefan Dösinger for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wined3d_private.h"
24 #include "wined3d_gl.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(gl_compat
);
27 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf
);
29 /* Start GL_ARB_multitexture emulation */
30 static void WINE_GLAPI
wine_glMultiTexCoord1fARB(GLenum target
, GLfloat s
)
32 if (target
!= GL_TEXTURE0
)
34 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
37 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord1f(s
);
40 static void WINE_GLAPI
wine_glMultiTexCoord1fvARB(GLenum target
, const GLfloat
*v
)
42 if (target
!= GL_TEXTURE0
)
44 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
47 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord1fv(v
);
50 static void WINE_GLAPI
wine_glMultiTexCoord2fARB(GLenum target
, GLfloat s
, GLfloat t
)
52 if (target
!= GL_TEXTURE0
)
54 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
57 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord2f(s
, t
);
60 static void WINE_GLAPI
wine_glMultiTexCoord2fvARB(GLenum target
, const GLfloat
*v
)
62 if (target
!= GL_TEXTURE0
)
64 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
67 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord2fv(v
);
70 static void WINE_GLAPI
wine_glMultiTexCoord3fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
)
72 if (target
!= GL_TEXTURE0
)
74 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
77 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord3f(s
, t
, r
);
80 static void WINE_GLAPI
wine_glMultiTexCoord3fvARB(GLenum target
, const GLfloat
*v
)
82 if (target
!= GL_TEXTURE0
)
84 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
87 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord3fv(v
);
90 static void WINE_GLAPI
wine_glMultiTexCoord4fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
92 if (target
!= GL_TEXTURE0
)
94 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
97 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord4f(s
, t
, r
, q
);
100 static void WINE_GLAPI
wine_glMultiTexCoord4fvARB(GLenum target
, const GLfloat
*v
)
102 if (target
!= GL_TEXTURE0
)
104 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
107 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord4fv(v
);
110 static void WINE_GLAPI
wine_glMultiTexCoord2svARB(GLenum target
, const GLshort
*v
)
112 if (target
!= GL_TEXTURE0
)
114 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
117 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord2sv(v
);
120 static void WINE_GLAPI
wine_glMultiTexCoord4svARB(GLenum target
, const GLshort
*v
)
122 if (target
!= GL_TEXTURE0
)
124 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported.\n");
127 wined3d_context_gl_get_current()->gl_info
->gl_ops
.gl
.p_glTexCoord4sv(v
);
130 static void WINE_GLAPI
wine_glActiveTexture(GLenum texture
)
132 if(texture
!= GL_TEXTURE0
) {
133 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
138 static void WINE_GLAPI
wine_glClientActiveTextureARB(GLenum texture
) {
139 if(texture
!= GL_TEXTURE0
) {
140 ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
145 static void (WINE_GLAPI
*old_multitex_glGetIntegerv
) (GLenum pname
, GLint
* params
) = NULL
;
146 static void WINE_GLAPI
wine_glGetIntegerv(GLenum pname
, GLint
* params
) {
148 case GL_ACTIVE_TEXTURE
: *params
= 0; break;
149 case GL_MAX_TEXTURE_UNITS_ARB
: *params
= 1; break;
150 default: old_multitex_glGetIntegerv(pname
, params
);
154 static void (WINE_GLAPI
*old_multitex_glGetFloatv
) (GLenum pname
, GLfloat
* params
) = NULL
;
155 static void WINE_GLAPI
wine_glGetFloatv(GLenum pname
, GLfloat
* params
) {
156 if (pname
== GL_ACTIVE_TEXTURE
) *params
= 0.0f
;
157 else old_multitex_glGetFloatv(pname
, params
);
160 static void (WINE_GLAPI
*old_multitex_glGetDoublev
) (GLenum pname
, GLdouble
* params
) = NULL
;
161 static void WINE_GLAPI
wine_glGetDoublev(GLenum pname
, GLdouble
* params
) {
162 if(pname
== GL_ACTIVE_TEXTURE
) *params
= 0.0;
163 else old_multitex_glGetDoublev(pname
, params
);
166 /* Start GL_EXT_fogcoord emulation */
167 static void (WINE_GLAPI
*old_fogcoord_glEnable
)(GLenum cap
);
168 static void WINE_GLAPI
wine_glEnable(GLenum cap
)
172 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
174 ctx
->fog_enabled
= 1;
175 if (ctx
->gl_fog_source
!= GL_FRAGMENT_DEPTH_EXT
)
178 old_fogcoord_glEnable(cap
);
181 static void (WINE_GLAPI
*old_fogcoord_glDisable
)(GLenum cap
);
182 static void WINE_GLAPI
wine_glDisable(GLenum cap
)
186 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
188 ctx
->fog_enabled
= 0;
189 if (ctx
->gl_fog_source
!= GL_FRAGMENT_DEPTH_EXT
)
192 old_fogcoord_glDisable(cap
);
195 static void (WINE_GLAPI
*old_fogcoord_glFogi
)(GLenum pname
, GLint param
);
196 static void WINE_GLAPI
wine_glFogi(GLenum pname
, GLint param
)
198 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
200 if (pname
== GL_FOG_COORDINATE_SOURCE_EXT
)
202 ctx
->gl_fog_source
= param
;
203 if (param
== GL_FRAGMENT_DEPTH_EXT
)
205 if (ctx
->fog_enabled
)
206 old_fogcoord_glEnable(GL_FOG
);
210 WARN_(d3d_perf
)("Fog coordinates activated, but not supported. Using slow emulation.\n");
211 old_fogcoord_glDisable(GL_FOG
);
216 if (pname
== GL_FOG_START
)
217 ctx
->fog_start
= (float)param
;
218 else if (pname
== GL_FOG_END
)
219 ctx
->fog_end
= (float)param
;
220 old_fogcoord_glFogi(pname
, param
);
224 static void (WINE_GLAPI
*old_fogcoord_glFogiv
)(GLenum pname
, const GLint
*param
);
225 static void WINE_GLAPI
wine_glFogiv(GLenum pname
, const GLint
*param
)
227 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
229 if (pname
== GL_FOG_COORDINATE_SOURCE_EXT
)
231 ctx
->gl_fog_source
= *param
;
232 if (*param
== GL_FRAGMENT_DEPTH_EXT
)
234 if (ctx
->fog_enabled
)
235 old_fogcoord_glEnable(GL_FOG
);
239 WARN_(d3d_perf
)("Fog coordinates activated, but not supported. Using slow emulation.\n");
240 old_fogcoord_glDisable(GL_FOG
);
245 if (pname
== GL_FOG_START
)
246 ctx
->fog_start
= (float)*param
;
247 else if (pname
== GL_FOG_END
)
248 ctx
->fog_end
= (float)*param
;
249 old_fogcoord_glFogiv(pname
, param
);
253 static void (WINE_GLAPI
*old_fogcoord_glFogf
)(GLenum pname
, GLfloat param
);
254 static void WINE_GLAPI
wine_glFogf(GLenum pname
, GLfloat param
)
256 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
258 if (pname
== GL_FOG_COORDINATE_SOURCE_EXT
)
260 ctx
->gl_fog_source
= (GLint
)param
;
261 if (param
== GL_FRAGMENT_DEPTH_EXT
)
263 if (ctx
->fog_enabled
)
264 old_fogcoord_glEnable(GL_FOG
);
268 WARN_(d3d_perf
)("Fog coordinates activated, but not supported. Using slow emulation.\n");
269 old_fogcoord_glDisable(GL_FOG
);
274 if (pname
== GL_FOG_START
)
275 ctx
->fog_start
= param
;
276 else if (pname
== GL_FOG_END
)
277 ctx
->fog_end
= param
;
278 old_fogcoord_glFogf(pname
, param
);
282 static void (WINE_GLAPI
*old_fogcoord_glFogfv
)(GLenum pname
, const GLfloat
*param
);
283 static void WINE_GLAPI
wine_glFogfv(GLenum pname
, const GLfloat
*param
)
285 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
287 if (pname
== GL_FOG_COORDINATE_SOURCE_EXT
)
289 ctx
->gl_fog_source
= (GLint
)*param
;
290 if (*param
== GL_FRAGMENT_DEPTH_EXT
)
292 if (ctx
->fog_enabled
)
293 old_fogcoord_glEnable(GL_FOG
);
297 WARN_(d3d_perf
)("Fog coordinates activated, but not supported. Using slow emulation.\n");
298 old_fogcoord_glDisable(GL_FOG
);
303 if (pname
== GL_FOG_COLOR
)
305 ctx
->fog_colour
[0] = param
[0];
306 ctx
->fog_colour
[1] = param
[1];
307 ctx
->fog_colour
[2] = param
[2];
308 ctx
->fog_colour
[3] = param
[3];
310 else if (pname
== GL_FOG_START
)
312 ctx
->fog_start
= *param
;
314 else if (pname
== GL_FOG_END
)
316 ctx
->fog_end
= *param
;
318 old_fogcoord_glFogfv(pname
, param
);
322 static void (WINE_GLAPI
*old_fogcoord_glVertex4f
)(GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
);
323 static void (WINE_GLAPI
*old_fogcoord_glColor4f
)(GLfloat r
, GLfloat g
, GLfloat b
, GLfloat a
);
325 static void WINE_GLAPI
wine_glVertex4f(GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
327 const struct wined3d_context_gl
*ctx_gl
= wined3d_context_gl_get_current();
329 /* This can be called from draw_test_quad() and at that point there is no
330 * wined3d_context current. */
333 old_fogcoord_glVertex4f(x
, y
, z
, w
);
337 if (ctx_gl
->gl_fog_source
== GL_FOG_COORDINATE_EXT
&& ctx_gl
->fog_enabled
)
339 GLfloat c
[4] = {ctx_gl
->colour
[0], ctx_gl
->colour
[1], ctx_gl
->colour
[2], ctx_gl
->colour
[3]};
342 i
= (ctx_gl
->fog_end
- ctx_gl
->fog_coord_value
) / (ctx_gl
->fog_end
- ctx_gl
->fog_start
);
343 c
[0] = i
* c
[0] + (1.0f
- i
) * ctx_gl
->fog_colour
[0];
344 c
[1] = i
* c
[1] + (1.0f
- i
) * ctx_gl
->fog_colour
[1];
345 c
[2] = i
* c
[2] + (1.0f
- i
) * ctx_gl
->fog_colour
[2];
347 old_fogcoord_glColor4f(c
[0], c
[1], c
[2], c
[3]);
348 old_fogcoord_glVertex4f(x
, y
, z
, w
);
352 old_fogcoord_glVertex4f(x
, y
, z
, w
);
356 static void WINE_GLAPI
wine_glVertex4fv(const GLfloat
*pos
) {
357 wine_glVertex4f(pos
[0], pos
[1], pos
[2], pos
[3]);
360 static void WINE_GLAPI
wine_glVertex3f(GLfloat x
, GLfloat y
, GLfloat z
) {
361 wine_glVertex4f(x
, y
, z
, 1.0f
);
364 static void WINE_GLAPI
wine_glVertex3fv(const GLfloat
*pos
) {
365 wine_glVertex4f(pos
[0], pos
[1], pos
[2], 1.0f
);
368 static void WINE_GLAPI
wine_glColor4f(GLfloat r
, GLfloat g
, GLfloat b
, GLfloat a
)
370 struct wined3d_context_gl
*ctx_gl
= wined3d_context_gl_get_current();
372 /* This can be called from draw_test_quad() and at that point there is no
373 * wined3d_context current. */
376 old_fogcoord_glColor4f(r
, g
, b
, a
);
380 ctx_gl
->colour
[0] = r
;
381 ctx_gl
->colour
[1] = g
;
382 ctx_gl
->colour
[2] = b
;
383 ctx_gl
->colour
[3] = a
;
384 old_fogcoord_glColor4f(r
, g
, b
, a
);
387 static void WINE_GLAPI
wine_glColor4fv(const GLfloat
*c
) {
388 wine_glColor4f(c
[0], c
[1], c
[2], c
[3]);
391 static void WINE_GLAPI
wine_glColor3f(GLfloat r
, GLfloat g
, GLfloat b
) {
392 wine_glColor4f(r
, g
, b
, 1.0f
);
395 static void WINE_GLAPI
wine_glColor3fv(const GLfloat
*c
) {
396 wine_glColor4f(c
[0], c
[1], c
[2], 1.0f
);
399 static void WINE_GLAPI
wine_glColor4ub(GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
) {
400 wine_glColor4f(r
/ 255.0f
, g
/ 255.0f
, b
/ 255.0f
, a
/ 255.0f
);
403 /* In D3D the fog coord is a UBYTE, so there's no problem with using the
404 * single precision function. */
405 static void WINE_GLAPI
wine_glFogCoordfEXT(GLfloat f
)
407 struct wined3d_context_gl
*ctx
= wined3d_context_gl_get_current();
409 ctx
->fog_coord_value
= f
;
411 static void WINE_GLAPI
wine_glFogCoorddEXT(GLdouble f
) {
412 wine_glFogCoordfEXT((GLfloat
) f
);
414 static void WINE_GLAPI
wine_glFogCoordfvEXT(const GLfloat
*f
) {
415 wine_glFogCoordfEXT(*f
);
417 static void WINE_GLAPI
wine_glFogCoorddvEXT(const GLdouble
*f
) {
418 wine_glFogCoordfEXT((GLfloat
) *f
);
421 /* End GL_EXT_fog_coord emulation */
423 void install_gl_compat_wrapper(struct wined3d_gl_info
*gl_info
, enum wined3d_gl_extension ext
)
427 case ARB_MULTITEXTURE
:
428 if (gl_info
->supported
[ARB_MULTITEXTURE
])
430 if (gl_info
->gl_ops
.ext
.p_glActiveTexture
== wine_glActiveTexture
)
432 FIXME("ARB_multitexture emulation hooks already applied.\n");
435 TRACE("Applying GL_ARB_multitexture emulation hooks.\n");
436 gl_info
->gl_ops
.ext
.p_glActiveTexture
= wine_glActiveTexture
;
437 gl_info
->gl_ops
.ext
.p_glClientActiveTextureARB
= wine_glClientActiveTextureARB
;
438 gl_info
->gl_ops
.ext
.p_glMultiTexCoord1fARB
= wine_glMultiTexCoord1fARB
;
439 gl_info
->gl_ops
.ext
.p_glMultiTexCoord1fvARB
= wine_glMultiTexCoord1fvARB
;
440 gl_info
->gl_ops
.ext
.p_glMultiTexCoord2fARB
= wine_glMultiTexCoord2fARB
;
441 gl_info
->gl_ops
.ext
.p_glMultiTexCoord2fvARB
= wine_glMultiTexCoord2fvARB
;
442 gl_info
->gl_ops
.ext
.p_glMultiTexCoord3fARB
= wine_glMultiTexCoord3fARB
;
443 gl_info
->gl_ops
.ext
.p_glMultiTexCoord3fvARB
= wine_glMultiTexCoord3fvARB
;
444 gl_info
->gl_ops
.ext
.p_glMultiTexCoord4fARB
= wine_glMultiTexCoord4fARB
;
445 gl_info
->gl_ops
.ext
.p_glMultiTexCoord4fvARB
= wine_glMultiTexCoord4fvARB
;
446 gl_info
->gl_ops
.ext
.p_glMultiTexCoord2svARB
= wine_glMultiTexCoord2svARB
;
447 gl_info
->gl_ops
.ext
.p_glMultiTexCoord4svARB
= wine_glMultiTexCoord4svARB
;
448 old_multitex_glGetIntegerv
= gl_info
->gl_ops
.gl
.p_glGetIntegerv
;
449 gl_info
->gl_ops
.gl
.p_glGetIntegerv
= wine_glGetIntegerv
;
450 old_multitex_glGetFloatv
= gl_info
->gl_ops
.gl
.p_glGetFloatv
;
451 gl_info
->gl_ops
.gl
.p_glGetFloatv
= wine_glGetFloatv
;
452 old_multitex_glGetDoublev
= gl_info
->gl_ops
.gl
.p_glGetDoublev
;
453 gl_info
->gl_ops
.gl
.p_glGetDoublev
= wine_glGetDoublev
;
454 gl_info
->supported
[ARB_MULTITEXTURE
] = TRUE
;
458 /* This emulation isn't perfect. There are a number of potential problems, but they should
459 * not matter in practise:
461 * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
462 * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
463 * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
464 * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
466 * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
467 * ignore the vertex color, thus effectively disabling our fog. However, in D3D this type of fog is
468 * a per-vertex fog too, so the apps shouldn't do that.
470 * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
471 * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
472 * calculations could affect the already blended in fog color. There's nothing we can do against that,
473 * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
476 if (gl_info
->supported
[EXT_FOG_COORD
])
478 if (gl_info
->gl_ops
.gl
.p_glFogi
== wine_glFogi
)
480 FIXME("EXT_fog_coord emulation hooks already applied.\n");
483 TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
485 /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
486 * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
487 * dependent loading for this extension if we ever hit this situation
489 if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
])
491 FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
492 FIXME("The fog coord emulation will most likely fail\n");
494 else if (gl_info
->supported
[ARB_FRAGMENT_SHADER
])
496 FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
497 FIXME("The fog coord emulation will most likely fail\n");
500 old_fogcoord_glFogi
= gl_info
->gl_ops
.gl
.p_glFogi
;
501 gl_info
->gl_ops
.gl
.p_glFogi
= wine_glFogi
;
502 old_fogcoord_glFogiv
= gl_info
->gl_ops
.gl
.p_glFogiv
;
503 gl_info
->gl_ops
.gl
.p_glFogiv
= wine_glFogiv
;
504 old_fogcoord_glFogf
= gl_info
->gl_ops
.gl
.p_glFogf
;
505 gl_info
->gl_ops
.gl
.p_glFogf
= wine_glFogf
;
506 old_fogcoord_glFogfv
= gl_info
->gl_ops
.gl
.p_glFogfv
;
507 gl_info
->gl_ops
.gl
.p_glFogfv
= wine_glFogfv
;
508 old_fogcoord_glEnable
= gl_info
->p_glEnableWINE
;
509 gl_info
->p_glEnableWINE
= wine_glEnable
;
510 old_fogcoord_glDisable
= gl_info
->p_glDisableWINE
;
511 gl_info
->p_glDisableWINE
= wine_glDisable
;
513 old_fogcoord_glVertex4f
= gl_info
->gl_ops
.gl
.p_glVertex4f
;
514 gl_info
->gl_ops
.gl
.p_glVertex4f
= wine_glVertex4f
;
515 gl_info
->gl_ops
.gl
.p_glVertex4fv
= wine_glVertex4fv
;
516 gl_info
->gl_ops
.gl
.p_glVertex3f
= wine_glVertex3f
;
517 gl_info
->gl_ops
.gl
.p_glVertex3fv
= wine_glVertex3fv
;
519 old_fogcoord_glColor4f
= gl_info
->gl_ops
.gl
.p_glColor4f
;
520 gl_info
->gl_ops
.gl
.p_glColor4f
= wine_glColor4f
;
521 gl_info
->gl_ops
.gl
.p_glColor4fv
= wine_glColor4fv
;
522 gl_info
->gl_ops
.gl
.p_glColor3f
= wine_glColor3f
;
523 gl_info
->gl_ops
.gl
.p_glColor3fv
= wine_glColor3fv
;
524 gl_info
->gl_ops
.gl
.p_glColor4ub
= wine_glColor4ub
;
526 gl_info
->gl_ops
.ext
.p_glFogCoordfEXT
= wine_glFogCoordfEXT
;
527 gl_info
->gl_ops
.ext
.p_glFogCoordfvEXT
= wine_glFogCoordfvEXT
;
528 gl_info
->gl_ops
.ext
.p_glFogCoorddEXT
= wine_glFogCoorddEXT
;
529 gl_info
->gl_ops
.ext
.p_glFogCoorddvEXT
= wine_glFogCoorddvEXT
;
530 gl_info
->supported
[EXT_FOG_COORD
] = TRUE
;
534 FIXME("Extension %u emulation not supported.\n", ext
);