2 * Copyright (c) 1998-2004 Lionel ULMER
3 * Copyright (c) 2002-2004 Christian Costa
5 * This file contains the MESA implementation of all the D3D devices that
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
39 #include "wine/debug.h"
40 #include "wine/library.h"
42 #include "mesa_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
54 X11DRV_GET_FONT, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL = {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps;
74 GL_EXTENSIONS_LIST GL_extensions;
76 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
77 D3DPRIMITIVETYPE d3dptPrimitiveType,
78 DWORD d3dvtVertexType,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
85 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
87 /* retrieve the X display to use on a given DC */
88 inline static Display *get_display( HDC hdc )
91 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
93 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94 sizeof(display), (LPSTR)&display )) display = NULL;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
105 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
106 DWORD opt_bitmap = 0x00000000;
108 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
109 ((d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE))) {
110 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
111 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
112 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
114 /* Disable multi-texturing for level 1 to disable all others */
115 glDisable(GL_TEXTURE_2D);
117 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
118 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
119 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
121 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
122 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
123 glEnable(GL_TEXTURE_2D);
124 if (gl_d3d_dev->unlock_tex == 0) {
125 glGenTextures(1, &gl_d3d_dev->unlock_tex);
126 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
133 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
136 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
137 glMatrixMode(GL_TEXTURE);
141 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
142 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
143 d3ddevice_set_ortho(d3d_dev);
146 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
147 glEnable(GL_SCISSOR_TEST);
148 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
149 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap |= DEPTH_RANGE_BIT;
153 if ((d3d_dev->active_viewport.dwX != 0) ||
154 (d3d_dev->active_viewport.dwY != 0) ||
155 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
156 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
157 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
158 opt_bitmap |= VIEWPORT_BIT;
160 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
161 pRect->right - pRect->left, pRect->bottom - pRect->top);
162 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
163 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
165 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
166 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
167 glAlphaFunc(GL_NOTEQUAL, 0.0);
169 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
171 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
172 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
173 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
174 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
175 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
180 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
181 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
183 /* And restore all the various states modified by this code */
184 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
185 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
186 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
187 glEnable(GL_ALPHA_TEST);
188 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
189 glDisable(GL_ALPHA_TEST);
191 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
192 glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
194 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
195 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
196 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
197 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
198 glDisable(GL_SCISSOR_TEST);
199 if (opt_bitmap & DEPTH_RANGE_BIT) {
200 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
202 if (opt_bitmap & VIEWPORT_BIT) {
203 glViewport(d3d_dev->active_viewport.dwX,
204 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
205 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
207 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
208 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
211 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
212 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
213 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
215 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
216 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
217 bind if ever the game changes the texture just after.
219 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
220 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
223 /* And re-enabled if needed texture level 1 */
224 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
225 (d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
226 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
227 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
228 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
230 glEnable(GL_TEXTURE_2D);
234 /* retrieve the X drawable to use on a given DC */
235 inline static Drawable get_drawable( HDC hdc )
238 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
240 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
241 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
246 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
248 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
249 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
251 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
253 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
254 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
256 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
257 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
258 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
265 /*******************************************************************************
266 * OpenGL static functions
268 static void set_context(IDirect3DDeviceImpl* This)
270 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
272 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
274 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
275 ERR("Error in setting current context (context %p drawable %ld)!\n",
276 glThis->gl_context, glThis->drawable);
281 static void fill_opengl_caps(D3DDEVICEDESC *d1)
283 d1->dwSize = sizeof(*d1);
284 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
285 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
286 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
287 d1->dcmColorModel = D3DCOLOR_RGB;
288 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
289 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
290 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
291 d1->bClipping = TRUE;
292 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
293 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
294 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
295 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
296 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
297 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
298 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
299 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
300 d1->dwMaxBufferSize = 0;
301 d1->dwMaxVertexCount = 65536;
302 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
303 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
304 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
305 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
306 d1->dwMinStippleWidth = 1;
307 d1->dwMinStippleHeight = 1;
308 d1->dwMaxStippleWidth = 32;
309 d1->dwMaxStippleHeight = 32;
310 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
311 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
312 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
313 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
314 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
315 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
316 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
317 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
318 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
319 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
320 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
321 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
322 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
325 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
327 *d = opengl_device_caps;
330 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
332 D3DDEVICEDESC dref, d1, d2;
335 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
336 Let's put the string in a sufficiently sized array in writable memory. */
337 char device_name[50];
338 strcpy(device_name,"direct3d");
340 fill_opengl_caps(&dref);
343 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
344 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
345 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
348 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
349 if (ret_value != D3DENUMRET_OK)
354 char interface_name[] = "WINE Direct3DX using OpenGL";
355 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
358 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
359 if (ret_value != D3DENUMRET_OK)
363 return D3DENUMRET_OK;
366 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
368 D3DDEVICEDESC7 ddesc;
369 char interface_name[] = "WINE Direct3D7 using OpenGL";
370 char device_name[] = "Wine D3D7 device";
372 fill_opengl_caps_7(&ddesc);
374 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
376 return cb(interface_name, device_name, &ddesc, context);
380 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
383 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
385 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
386 if (!--(This->ref)) {
388 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
390 /* Release texture associated with the device */
391 for (i = 0; i < MAX_TEXTURES; i++) {
392 if (This->current_texture[i] != NULL)
393 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
394 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
397 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
398 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
399 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
400 surf->aux_ctx = NULL;
401 surf->aux_data = NULL;
402 surf->aux_flip = NULL;
406 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
407 IDirectDrawSurfaceImpl *surf2;
408 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
409 for (; surf2 != NULL; surf2 = surf2->next_attached) {
410 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
411 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
412 /* Override the Lock / Unlock function for all these surfaces */
413 surf2->lock_update = surf2->lock_update_prev;
414 surf2->unlock_update = surf2->unlock_update_prev;
415 /* And install also the blt / bltfast overrides */
416 surf2->aux_blt = NULL;
417 surf2->aux_bltfast = NULL;
419 surf2->d3ddevice = NULL;
423 /* And warn the D3D object that this device is no longer active... */
424 This->d3d->d3d_removed_device(This->d3d, This);
426 HeapFree(GetProcessHeap(), 0, This->world_mat);
427 HeapFree(GetProcessHeap(), 0, This->view_mat);
428 HeapFree(GetProcessHeap(), 0, This->proj_mat);
430 if (glThis->surface_ptr)
431 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
433 DeleteCriticalSection(&(This->crit));
436 if (glThis->unlock_tex)
437 glDeleteTextures(1, &(glThis->unlock_tex));
438 glXDestroyContext(glThis->display, glThis->gl_context);
440 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
442 HeapFree(GetProcessHeap(), 0, This);
449 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
450 LPD3DDEVICEDESC lpD3DHWDevDesc,
451 LPD3DDEVICEDESC lpD3DHELDevDesc)
453 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
457 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
459 fill_opengl_caps(&desc);
460 dwSize = lpD3DHWDevDesc->dwSize;
461 memset(lpD3DHWDevDesc, 0, dwSize);
462 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
464 dwSize = lpD3DHELDevDesc->dwSize;
465 memset(lpD3DHELDevDesc, 0, dwSize);
466 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
468 TRACE(" returning caps : (no dump function yet)\n");
473 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
474 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
478 LPDDPIXELFORMAT pformat;
480 /* Do the texture enumeration */
481 sdesc.dwSize = sizeof(DDSURFACEDESC);
482 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
483 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
484 pformat = &(sdesc.ddpfPixelFormat);
485 pformat->dwSize = sizeof(DDPIXELFORMAT);
486 pformat->dwFourCC = 0;
488 TRACE("Enumerating GL_RGBA unpacked (32)\n");
489 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
490 pformat->u1.dwRGBBitCount = 32;
491 pformat->u2.dwRBitMask = 0x00FF0000;
492 pformat->u3.dwGBitMask = 0x0000FF00;
493 pformat->u4.dwBBitMask = 0x000000FF;
494 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
495 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
496 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
498 TRACE("Enumerating GL_RGB unpacked (32)\n");
499 pformat->dwFlags = DDPF_RGB;
500 pformat->u1.dwRGBBitCount = 32;
501 pformat->u2.dwRBitMask = 0x00FF0000;
502 pformat->u3.dwGBitMask = 0x0000FF00;
503 pformat->u4.dwBBitMask = 0x000000FF;
504 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
505 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
506 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
508 TRACE("Enumerating GL_RGB unpacked (24)\n");
509 pformat->dwFlags = DDPF_RGB;
510 pformat->u1.dwRGBBitCount = 24;
511 pformat->u2.dwRBitMask = 0x00FF0000;
512 pformat->u3.dwGBitMask = 0x0000FF00;
513 pformat->u4.dwBBitMask = 0x000000FF;
514 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
515 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
516 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
518 /* Note : even if this is an 'emulated' texture format, it needs to be first
519 as some dumb applications seem to rely on that. */
520 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
521 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
522 pformat->u1.dwRGBBitCount = 16;
523 pformat->u2.dwRBitMask = 0x00007C00;
524 pformat->u3.dwGBitMask = 0x000003E0;
525 pformat->u4.dwBBitMask = 0x0000001F;
526 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
527 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
528 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
530 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
531 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
532 pformat->u1.dwRGBBitCount = 16;
533 pformat->u2.dwRBitMask = 0x00000F00;
534 pformat->u3.dwGBitMask = 0x000000F0;
535 pformat->u4.dwBBitMask = 0x0000000F;
536 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
537 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
538 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
540 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
541 pformat->dwFlags = DDPF_RGB;
542 pformat->u1.dwRGBBitCount = 16;
543 pformat->u2.dwRBitMask = 0x0000F800;
544 pformat->u3.dwGBitMask = 0x000007E0;
545 pformat->u4.dwBBitMask = 0x0000001F;
546 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
547 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
548 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
550 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
551 pformat->dwFlags = DDPF_RGB;
552 pformat->u1.dwRGBBitCount = 16;
553 pformat->u2.dwRBitMask = 0x00007C00;
554 pformat->u3.dwGBitMask = 0x000003E0;
555 pformat->u4.dwBBitMask = 0x0000001F;
556 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
557 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
558 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
561 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
562 find enumerated, others the last one. And both want to have the ARGB one.
564 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
566 /* See argument about the RGBA format for 'packed' texture formats */
567 TRACE("Enumerating GL_RGBA unpacked (32)\n");
568 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
569 pformat->u1.dwRGBBitCount = 32;
570 pformat->u2.dwRBitMask = 0xFF000000;
571 pformat->u3.dwGBitMask = 0x00FF0000;
572 pformat->u4.dwBBitMask = 0x0000FF00;
573 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
574 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
575 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
577 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
578 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
579 pformat->u1.dwRGBBitCount = 16;
580 pformat->u2.dwRBitMask = 0x0000F000;
581 pformat->u3.dwGBitMask = 0x00000F00;
582 pformat->u4.dwBBitMask = 0x000000F0;
583 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
584 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
585 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
587 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
588 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
589 pformat->u1.dwRGBBitCount = 16;
590 pformat->u2.dwRBitMask = 0x0000F800;
591 pformat->u3.dwGBitMask = 0x000007C0;
592 pformat->u4.dwBBitMask = 0x0000003E;
593 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
594 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
595 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
598 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
599 pformat->dwFlags = DDPF_RGB;
600 pformat->u1.dwRGBBitCount = 8;
601 pformat->u2.dwRBitMask = 0x000000E0;
602 pformat->u3.dwGBitMask = 0x0000001C;
603 pformat->u4.dwBBitMask = 0x00000003;
604 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
605 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
606 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
608 TRACE("Enumerating Paletted (8)\n");
609 pformat->dwFlags = DDPF_PALETTEINDEXED8;
610 pformat->u1.dwRGBBitCount = 8;
611 pformat->u2.dwRBitMask = 0x00000000;
612 pformat->u3.dwGBitMask = 0x00000000;
613 pformat->u4.dwBBitMask = 0x00000000;
614 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
615 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
616 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
618 if (GL_extensions.s3tc_compressed_texture) {
619 TRACE("Enumerating DXT1\n");
620 pformat->dwFlags = DDPF_FOURCC;
621 pformat->dwFourCC = MAKE_FOURCC('D','X','T','1');
622 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
623 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
625 TRACE("Enumerating DXT3\n");
626 pformat->dwFlags = DDPF_FOURCC;
627 pformat->dwFourCC = MAKE_FOURCC('D','X','T','3');
628 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
629 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
631 TRACE("Enumerating DXT5\n");
632 pformat->dwFlags = DDPF_FOURCC;
633 pformat->dwFourCC = MAKE_FOURCC('D','X','T','5');
634 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
635 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
638 TRACE("End of enumeration\n");
644 d3ddevice_find(IDirectDrawImpl *d3d,
645 LPD3DFINDDEVICESEARCH lpD3DDFS,
646 LPD3DFINDDEVICERESULT lplpD3DDevice)
650 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
651 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
652 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
653 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
655 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
656 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
657 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
658 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
659 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
660 TRACE(" no match for this GUID.\n");
661 return DDERR_INVALIDPARAMS;
665 /* Now return our own GUID */
666 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
667 fill_opengl_caps(&desc);
668 lplpD3DDevice->ddHwDesc = desc;
669 lplpD3DDevice->ddSwDesc = desc;
671 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
677 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
678 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
681 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
682 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
683 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
687 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
688 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
691 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
692 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
693 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
697 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
698 D3DRENDERSTATETYPE dwRenderStateType,
701 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
702 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
704 /* Call the render state functions */
705 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
706 set_render_state(This, dwRenderStateType, &This->state_block);
712 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
713 D3DRENDERSTATETYPE dwRenderStateType,
714 LPDWORD lpdwRenderState)
716 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
717 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
719 /* Call the render state functions */
720 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
722 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
728 GL_IDirect3DDeviceImpl_3_2T_GetLightState(LPDIRECT3DDEVICE3 iface,
729 D3DLIGHTSTATETYPE dwLightStateType,
730 LPDWORD lpdwLightState)
732 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
734 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwLightStateType, lpdwLightState);
736 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
737 TRACE("Unexpected Light State Type\n");
738 return DDERR_INVALIDPARAMS;
741 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
742 *lpdwLightState = This->material;
743 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
744 *lpdwLightState = D3DCOLOR_RGB;
746 D3DRENDERSTATETYPE rs;
747 switch (dwLightStateType) {
748 case D3DLIGHTSTATE_AMBIENT: /* 2 */
749 rs = D3DRENDERSTATE_AMBIENT;
751 case D3DLIGHTSTATE_FOGMODE: /* 4 */
752 rs = D3DRENDERSTATE_FOGVERTEXMODE;
754 case D3DLIGHTSTATE_FOGSTART: /* 5 */
755 rs = D3DRENDERSTATE_FOGSTART;
757 case D3DLIGHTSTATE_FOGEND: /* 6 */
758 rs = D3DRENDERSTATE_FOGEND;
760 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
761 rs = D3DRENDERSTATE_FOGDENSITY;
763 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
764 rs = D3DRENDERSTATE_COLORVERTEX;
767 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
768 return DDERR_INVALIDPARAMS;
771 IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
779 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
780 D3DLIGHTSTATETYPE dwLightStateType,
783 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
785 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
787 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
788 TRACE("Unexpected Light State Type\n");
789 return DDERR_INVALIDPARAMS;
792 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
793 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
796 TRACE(" activating material %p.\n", mat);
799 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
801 This->material = dwLightState;
802 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
803 switch (dwLightState) {
805 ERR("DDCOLOR_MONO should not happen!\n");
808 /* We are already in this mode */
809 TRACE("Setting color model to RGB (no-op).\n");
812 ERR("Unknown color model!\n");
813 return DDERR_INVALIDPARAMS;
816 D3DRENDERSTATETYPE rs;
817 switch (dwLightStateType) {
818 case D3DLIGHTSTATE_AMBIENT: /* 2 */
819 rs = D3DRENDERSTATE_AMBIENT;
821 case D3DLIGHTSTATE_FOGMODE: /* 4 */
822 rs = D3DRENDERSTATE_FOGVERTEXMODE;
824 case D3DLIGHTSTATE_FOGSTART: /* 5 */
825 rs = D3DRENDERSTATE_FOGSTART;
827 case D3DLIGHTSTATE_FOGEND: /* 6 */
828 rs = D3DRENDERSTATE_FOGEND;
830 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
831 rs = D3DRENDERSTATE_FOGDENSITY;
833 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
834 rs = D3DRENDERSTATE_COLORVERTEX;
837 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
838 return DDERR_INVALIDPARAMS;
841 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
848 static GLenum convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt)
851 case D3DPT_POINTLIST:
852 TRACE(" primitive type is POINTS\n");
856 TRACE(" primitive type is LINES\n");
859 case D3DPT_LINESTRIP:
860 TRACE(" primitive type is LINE_STRIP\n");
861 return GL_LINE_STRIP;
863 case D3DPT_TRIANGLELIST:
864 TRACE(" primitive type is TRIANGLES\n");
867 case D3DPT_TRIANGLESTRIP:
868 TRACE(" primitive type is TRIANGLE_STRIP\n");
869 return GL_TRIANGLE_STRIP;
871 case D3DPT_TRIANGLEFAN:
872 TRACE(" primitive type is TRIANGLE_FAN\n");
873 return GL_TRIANGLE_FAN;
876 FIXME("Unhandled primitive %08x\n", d3dpt);
881 /* This function calculate the Z coordinate from Zproj */
882 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
885 /* Assume that X = Y = 0 and W = 1 */
886 a = This->proj_mat->_33;
887 b = This->proj_mat->_34;
888 c = This->proj_mat->_43;
889 d = This->proj_mat->_44;
890 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
891 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
892 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
894 return (d*Zproj - c) / (a - b*Zproj);
897 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
900 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
902 for (i = 0; i < 3; i++) {
903 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
905 for (elt = 0; elt < 0x10000; elt++) {
906 /* We apply the fog transformation and cache the result */
907 DWORD fog_intensity = elt & 0xFF;
908 DWORD vertex_color = (elt >> 8) & 0xFF;
909 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
914 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
915 BOOLEAN vertex_transformed,
916 BOOLEAN vertex_lit) {
917 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
919 /* Puts GL in the correct lighting / transformation mode */
920 if ((vertex_transformed == FALSE) &&
921 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
922 /* Need to put the correct transformation again if we go from Transformed
923 vertices to non-transformed ones.
925 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
926 This->world_mat, This->view_mat, This->proj_mat);
927 glThis->transform_state = GL_TRANSFORM_NORMAL;
929 } else if ((vertex_transformed == TRUE) &&
930 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
931 /* Set our orthographic projection */
932 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
933 glThis->transform_state = GL_TRANSFORM_ORTHO;
934 d3ddevice_set_ortho(This);
938 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
939 if no fogging state change occurred */
940 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
941 if (vertex_transformed == TRUE) {
942 if (glThis->fogging != 0) {
946 /* Now check if our fog_table still corresponds to the current vertex color.
947 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
948 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
949 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
950 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
951 /* We need to rebuild our fog table.... */
952 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
955 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
956 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
957 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
958 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
959 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
961 if (vertex_lit == FALSE) {
962 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
963 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
965 /* Special case of 'pixel fog' */
966 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
967 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
969 if (glThis->fogging == 0) {
974 if (glThis->fogging != 0) {
981 if (glThis->fogging != 0) {
987 /* Handle the 'no-normal' case */
988 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
989 if (glThis->lighting == 0) {
990 glEnable(GL_LIGHTING);
991 glThis->lighting = 1;
994 if (glThis->lighting != 0) {
995 glDisable(GL_LIGHTING);
996 glThis->lighting = 0;
1000 /* Handle the code for pre-vertex material properties */
1001 if (vertex_transformed == FALSE) {
1002 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1003 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1004 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1005 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1006 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1007 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
1008 glEnable(GL_COLOR_MATERIAL);
1015 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1016 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1018 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1021 case D3DVT_VERTEX: {
1022 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1023 strided.position.dwStride = sizeof(D3DVERTEX);
1024 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1025 strided.normal.dwStride = sizeof(D3DVERTEX);
1026 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1027 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1028 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1031 case D3DVT_LVERTEX: {
1032 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1033 strided.position.dwStride = sizeof(D3DLVERTEX);
1034 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1035 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1036 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1037 strided.specular.dwStride = sizeof(D3DLVERTEX);
1038 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1039 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1040 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1043 case D3DVT_TLVERTEX: {
1044 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1045 strided.position.dwStride = sizeof(D3DTLVERTEX);
1046 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1047 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1048 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1049 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1050 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1051 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1052 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1056 FIXME("Unhandled vertex type %08x\n", d3dvt);
1062 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1063 D3DPRIMITIVETYPE d3dptPrimitiveType,
1064 D3DVERTEXTYPE d3dvtVertexType,
1066 DWORD dwVertexCount,
1069 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1071 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1072 if (TRACE_ON(ddraw)) {
1073 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1076 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1082 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1083 D3DPRIMITIVETYPE d3dptPrimitiveType,
1084 D3DVERTEXTYPE d3dvtVertexType,
1086 DWORD dwVertexCount,
1091 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1092 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1093 if (TRACE_ON(ddraw)) {
1094 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1097 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1103 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1104 LPD3DEXECUTEBUFFERDESC lpDesc,
1105 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1106 IUnknown* pUnkOuter)
1108 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1109 IDirect3DExecuteBufferImpl *ret;
1112 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1114 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1115 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1117 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1122 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1123 static BOOLEAN first = TRUE;
1124 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1128 if (first == TRUE) {
1129 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1133 TRACE("flushing ZBuffer back to GL\n");
1135 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1136 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1137 d3ddevice_set_ortho(d3d_dev);
1140 glMatrixMode(GL_MODELVIEW);
1143 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1144 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1145 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1147 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1150 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1151 case 16: type = GL_UNSIGNED_SHORT; break;
1152 case 32: type = GL_UNSIGNED_INT; break;
1153 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1156 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1157 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1158 glRasterPos2i(0, row + 1);
1159 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1160 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1164 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1165 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1166 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1167 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1170 /* These are the various handler used in the generic path */
1171 inline static void handle_xyz(D3DVALUE *coords) {
1172 glVertex3fv(coords);
1174 inline static void handle_xyzrhw(D3DVALUE *coords) {
1175 if ((coords[3] < 1e-8) && (coords[3] > -1e-8))
1176 glVertex3fv(coords);
1178 GLfloat w = 1.0 / coords[3];
1180 glVertex4f(coords[0] * w,
1186 inline static void handle_normal(D3DVALUE *coords) {
1187 glNormal3fv(coords);
1190 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1191 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1192 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1193 glColor4ub((*color >> 16) & 0xFF,
1194 (*color >> 8) & 0xFF,
1195 (*color >> 0) & 0xFF,
1196 (*color >> 24) & 0xFF);
1198 glColor3ub((*color >> 16) & 0xFF,
1199 (*color >> 8) & 0xFF,
1200 (*color >> 0) & 0xFF);
1204 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1205 glColor4ub((*color >> 16) & 0xFF,
1206 (*color >> 8) & 0xFF,
1207 (*color >> 0) & 0xFF,
1208 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1211 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1212 if ((lighted == FALSE) &&
1213 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1214 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1215 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1216 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1217 handle_diffuse_base(sb, color);
1219 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1220 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1221 handle_diffuse_base(sb, color);
1223 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1224 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1225 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1226 handle_diffuse_base(sb, color);
1228 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1229 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1230 handle_diffuse_base(sb, color);
1233 handle_diffuse_base(sb, color);
1237 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1238 if ((lighted == FALSE) &&
1239 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1240 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1241 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1242 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1243 handle_specular_base(sb, color);
1245 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1246 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1247 handle_specular_base(sb, color);
1249 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1250 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1251 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1252 handle_specular_base(sb, color);
1254 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1255 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1256 handle_specular_base(sb, color);
1259 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1262 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1263 if (lighted == TRUE) {
1264 DWORD color = *color_d;
1265 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1266 /* Special case where the specular value is used to do fogging */
1267 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1268 color &= 0xFF000000; /* Only keep the alpha component */
1269 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1270 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1271 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1273 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1274 /* Standard specular value in transformed mode. TODO */
1276 handle_diffuse_base(sb, &color);
1278 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1279 handle_diffuse(sb, color_d, FALSE);
1280 handle_specular(sb, color_s, FALSE);
1282 /* In that case, only put the diffuse color... */
1283 handle_diffuse_base(sb, color_d);
1288 inline static void handle_texture(D3DVALUE *coords) {
1289 glTexCoord2fv(coords);
1291 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1292 if (GL_extensions.glMultiTexCoord2fv) {
1293 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1295 if (tex_stage == 0) glTexCoord2fv(coords);
1299 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1300 D3DPRIMITIVETYPE d3dptPrimitiveType,
1301 DWORD d3dvtVertexType,
1302 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1303 DWORD dwVertexCount,
1308 BOOLEAN vertex_lighted = FALSE;
1309 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1310 int num_active_stages = 0;
1311 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1313 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1314 if (TRACE_ON(ddraw)) {
1315 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1318 /* This is to prevent 'thread contention' between a thread locking the device and another
1319 doing 3D display on it... */
1320 EnterCriticalSection(&(This->crit));
1323 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1324 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1326 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1328 if (This->current_zbuffer == NULL) {
1329 /* Search for an attached ZBuffer */
1330 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1331 LPDIRECTDRAWSURFACE7 zbuf;
1334 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1335 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1337 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1338 IDirectDrawSurface7_Release(zbuf);
1341 if (This->current_zbuffer != NULL) {
1342 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1343 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1347 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1348 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1349 vertex_lighted = TRUE;
1351 /* Compute the number of active texture stages and set the various texture parameters */
1352 num_active_stages = draw_primitive_handle_textures(This);
1354 /* And restore to handle '0' in the case we use glTexCoord calls */
1355 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1356 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1357 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1360 draw_primitive_handle_GL_state(This,
1361 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1364 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1365 for now to some 'special' cases where we can do a direct mapping between D3D
1368 Note: in the future all calls will go through vertex arrays but the arrays
1369 will be generated by this function.
1371 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1372 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1373 which, as we are little indian, gives a B, G, R, A storage in memory.
1375 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1376 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
1378 TRACE(" using GL vertex arrays for performance !\n");
1379 /* First, the vertices (we are sure we have some :-) */
1380 glEnableClientState(GL_VERTEX_ARRAY);
1381 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1382 /* Then the normals */
1383 if (d3dvtVertexType & D3DFVF_NORMAL) {
1384 glEnableClientState(GL_NORMAL_ARRAY);
1385 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1387 /* Then the diffuse colour */
1388 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1389 glEnableClientState(GL_COLOR_ARRAY);
1390 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1391 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1393 /* Then the various textures */
1394 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1395 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1396 if (tex_index >= num_tex_index) {
1397 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1398 tex_index = num_tex_index - 1;
1400 if (GL_extensions.glClientActiveTexture) {
1401 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1403 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1404 glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1405 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1407 if (dwIndices != NULL) {
1408 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1410 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1412 glDisableClientState(GL_VERTEX_ARRAY);
1413 if (d3dvtVertexType & D3DFVF_NORMAL) {
1414 glDisableClientState(GL_NORMAL_ARRAY);
1416 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1417 glDisableClientState(GL_COLOR_ARRAY);
1419 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1420 if (GL_extensions.glClientActiveTexture) {
1421 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1423 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1426 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1428 /* Some fast paths first before the generic case.... */
1429 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1432 for (index = 0; index < dwIndexCount; index++) {
1433 int i = (dwIndices == NULL) ? index : dwIndices[index];
1435 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1436 D3DVALUE *tex_coord =
1437 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1438 D3DVALUE *position =
1439 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1441 handle_normal(normal);
1442 handle_texture(tex_coord);
1443 handle_xyz(position);
1445 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1446 position[0], position[1], position[2],
1447 normal[0], normal[1], normal[2],
1448 tex_coord[0], tex_coord[1]);
1450 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1453 for (index = 0; index < dwIndexCount; index++) {
1454 int i = (dwIndices == NULL) ? index : dwIndices[index];
1456 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1458 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1459 D3DVALUE *tex_coord =
1460 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1461 D3DVALUE *position =
1462 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1464 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1465 handle_texture(tex_coord);
1466 handle_xyzrhw(position);
1468 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1469 position[0], position[1], position[2], position[3],
1470 (*color_d >> 16) & 0xFF,
1471 (*color_d >> 8) & 0xFF,
1472 (*color_d >> 0) & 0xFF,
1473 (*color_d >> 24) & 0xFF,
1474 (*color_s >> 16) & 0xFF,
1475 (*color_s >> 8) & 0xFF,
1476 (*color_s >> 0) & 0xFF,
1477 (*color_s >> 24) & 0xFF,
1478 tex_coord[0], tex_coord[1]);
1480 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1481 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1482 /* This is the 'slow path' but that should support all possible vertex formats out there...
1483 Note that people should write a fast path for all vertex formats out there...
1486 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1488 for (index = 0; index < dwIndexCount; index++) {
1489 int i = (dwIndices == NULL) ? index : dwIndices[index];
1492 if (d3dvtVertexType & D3DFVF_NORMAL) {
1494 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1495 handle_normal(normal);
1497 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1499 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1501 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1502 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1504 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1506 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1507 handle_specular(&(This->state_block), color_s, vertex_lighted);
1508 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1510 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1511 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1515 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1516 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1517 if (tex_index >= num_tex_index) {
1518 handle_textures((D3DVALUE *) no_index, tex_stage);
1520 D3DVALUE *tex_coord =
1521 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1522 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1523 handle_textures(tex_coord, tex_stage);
1527 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1528 D3DVALUE *position =
1529 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1530 handle_xyz(position);
1531 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1532 D3DVALUE *position =
1533 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1534 handle_xyzrhw(position);
1537 if (TRACE_ON(ddraw_geom)) {
1540 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1541 D3DVALUE *position =
1542 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1543 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1544 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1545 D3DVALUE *position =
1546 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1547 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1549 if (d3dvtVertexType & D3DFVF_NORMAL) {
1551 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1552 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1554 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1556 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1557 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1558 (*color_d >> 16) & 0xFF,
1559 (*color_d >> 8) & 0xFF,
1560 (*color_d >> 0) & 0xFF,
1561 (*color_d >> 24) & 0xFF);
1563 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1565 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1566 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1567 (*color_s >> 16) & 0xFF,
1568 (*color_s >> 8) & 0xFF,
1569 (*color_s >> 0) & 0xFF,
1570 (*color_s >> 24) & 0xFF);
1572 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1573 D3DVALUE *tex_coord =
1574 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1575 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1576 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1578 TRACE_(ddraw_geom)("\n");
1582 ERR(" matrix weighting not handled yet....\n");
1588 /* Whatever the case, disable the color material stuff */
1589 glDisable(GL_COLOR_MATERIAL);
1594 LeaveCriticalSection(&(This->crit));
1598 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1599 D3DPRIMITIVETYPE d3dptPrimitiveType,
1600 DWORD d3dvtVertexType,
1602 DWORD dwVertexCount,
1605 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1606 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1608 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1609 if (TRACE_ON(ddraw)) {
1610 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1613 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1614 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1620 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1621 D3DPRIMITIVETYPE d3dptPrimitiveType,
1622 DWORD d3dvtVertexType,
1624 DWORD dwVertexCount,
1629 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1630 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1632 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1633 if (TRACE_ON(ddraw)) {
1634 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1637 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1638 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1644 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1645 D3DPRIMITIVETYPE d3dptPrimitiveType,
1647 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1648 DWORD dwVertexCount,
1651 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1653 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1654 if (TRACE_ON(ddraw)) {
1655 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1657 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1663 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1664 D3DPRIMITIVETYPE d3dptPrimitiveType,
1666 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1667 DWORD dwVertexCount,
1672 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1674 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1675 if (TRACE_ON(ddraw)) {
1676 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1679 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1685 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1686 D3DPRIMITIVETYPE d3dptPrimitiveType,
1687 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1688 DWORD dwStartVertex,
1689 DWORD dwNumVertices,
1692 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1693 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1694 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1696 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1697 if (TRACE_ON(ddraw)) {
1698 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1701 if (vb_impl->processed == TRUE) {
1702 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1703 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1705 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1706 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1707 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1709 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1710 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1713 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1714 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1721 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1722 D3DPRIMITIVETYPE d3dptPrimitiveType,
1723 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1724 DWORD dwStartVertex,
1725 DWORD dwNumVertices,
1730 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1731 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1732 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1734 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1735 if (TRACE_ON(ddraw)) {
1736 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1739 if (vb_impl->processed == TRUE) {
1740 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1741 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1743 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1744 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1745 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1747 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1748 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1751 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1752 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1758 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1760 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1762 BOOLEAN is_complement = FALSE;
1763 BOOLEAN is_alpha_replicate = FALSE;
1764 BOOLEAN handled = TRUE;
1766 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1770 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1771 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1776 if (tex_op == D3DTOP_SELECTARG2) {
1780 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1781 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1786 if (tex_op == D3DTOP_SELECTARG2) {
1791 if (dwState & D3DTA_COMPLEMENT) {
1792 is_complement = TRUE;
1794 if (dwState & D3DTA_ALPHAREPLICATE) {
1795 is_alpha_replicate = TRUE;
1797 dwState &= D3DTA_SELECTMASK;
1798 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1799 dwState = D3DTA_DIFFUSE;
1803 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1804 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1805 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1806 case D3DTA_TFACTOR: {
1807 /* Get the constant value from the current rendering state */
1809 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1811 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1812 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1813 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1814 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1815 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1817 src = GL_CONSTANT_EXT;
1819 default: src = GL_TEXTURE; handled = FALSE; break;
1823 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1824 if (is_alpha_replicate) {
1825 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1827 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1830 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1831 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1838 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1840 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1843 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1844 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1849 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1851 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1852 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1856 unit = GL_TEXTURE0_WINE + dwStage;
1857 if (unit != glThis->current_active_tex_unit) {
1858 GL_extensions.glActiveTexture(unit);
1859 glThis->current_active_tex_unit = unit;
1862 switch (d3dTexStageStateType) {
1863 #define GEN_CASE(a) case a: type = #a; break
1864 GEN_CASE(D3DTSS_COLOROP);
1865 GEN_CASE(D3DTSS_COLORARG1);
1866 GEN_CASE(D3DTSS_COLORARG2);
1867 GEN_CASE(D3DTSS_ALPHAOP);
1868 GEN_CASE(D3DTSS_ALPHAARG1);
1869 GEN_CASE(D3DTSS_ALPHAARG2);
1870 GEN_CASE(D3DTSS_BUMPENVMAT00);
1871 GEN_CASE(D3DTSS_BUMPENVMAT01);
1872 GEN_CASE(D3DTSS_BUMPENVMAT10);
1873 GEN_CASE(D3DTSS_BUMPENVMAT11);
1874 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1875 GEN_CASE(D3DTSS_ADDRESS);
1876 GEN_CASE(D3DTSS_ADDRESSU);
1877 GEN_CASE(D3DTSS_ADDRESSV);
1878 GEN_CASE(D3DTSS_BORDERCOLOR);
1879 GEN_CASE(D3DTSS_MAGFILTER);
1880 GEN_CASE(D3DTSS_MINFILTER);
1881 GEN_CASE(D3DTSS_MIPFILTER);
1882 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1883 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1884 GEN_CASE(D3DTSS_MAXANISOTROPY);
1885 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1886 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1887 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1889 default: type = "UNKNOWN";
1892 /* Store the values in the state array */
1893 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1894 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1895 /* Some special cases when one state modifies more than one... */
1896 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1897 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1898 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1903 switch (d3dTexStageStateType) {
1904 case D3DTSS_MINFILTER:
1905 case D3DTSS_MIPFILTER:
1906 if (TRACE_ON(ddraw)) {
1907 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1908 switch ((D3DTEXTUREMINFILTER) dwState) {
1909 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1910 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1911 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1914 switch ((D3DTEXTUREMIPFILTER) dwState) {
1915 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1916 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1917 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1918 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1924 case D3DTSS_MAGFILTER:
1925 if (TRACE_ON(ddraw)) {
1926 switch ((D3DTEXTUREMAGFILTER) dwState) {
1927 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1928 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1929 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1934 case D3DTSS_ADDRESS:
1935 case D3DTSS_ADDRESSU:
1936 case D3DTSS_ADDRESSV: {
1937 switch ((D3DTEXTUREADDRESS) dwState) {
1938 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1939 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1940 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1941 case D3DTADDRESS_MIRROR:
1942 if (GL_extensions.mirrored_repeat == TRUE) {
1943 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1945 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1948 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1952 case D3DTSS_ALPHAOP:
1953 case D3DTSS_COLOROP: {
1955 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1960 #define GEN_CASE(a) case a: value = #a; break
1961 GEN_CASE(D3DTOP_DISABLE);
1962 GEN_CASE(D3DTOP_SELECTARG1);
1963 GEN_CASE(D3DTOP_SELECTARG2);
1964 GEN_CASE(D3DTOP_MODULATE);
1965 GEN_CASE(D3DTOP_MODULATE2X);
1966 GEN_CASE(D3DTOP_MODULATE4X);
1967 GEN_CASE(D3DTOP_ADD);
1968 GEN_CASE(D3DTOP_ADDSIGNED);
1969 GEN_CASE(D3DTOP_ADDSIGNED2X);
1970 GEN_CASE(D3DTOP_SUBTRACT);
1971 GEN_CASE(D3DTOP_ADDSMOOTH);
1972 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1973 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1974 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1975 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1976 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1977 GEN_CASE(D3DTOP_PREMODULATE);
1978 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1979 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1980 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1981 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1982 GEN_CASE(D3DTOP_BUMPENVMAP);
1983 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1984 GEN_CASE(D3DTOP_DOTPRODUCT3);
1985 GEN_CASE(D3DTOP_FORCE_DWORD);
1987 default: value = "UNKNOWN";
1990 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1991 glDisable(GL_TEXTURE_2D);
1992 TRACE(" disabling 2D texturing.\n");
1994 /* Re-enable texturing only if COLOROP was not already disabled... */
1995 if ((glThis->current_bound_texture[dwStage] != NULL) &&
1996 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1997 glEnable(GL_TEXTURE_2D);
1998 TRACE(" enabling 2D texturing.\n");
2001 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
2002 if ((dwState != D3DTOP_DISABLE) &&
2003 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
2004 if (glThis->current_tex_env != GL_COMBINE_EXT) {
2005 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
2006 glThis->current_tex_env = GL_COMBINE_EXT;
2010 /* Now set up the operand correctly */
2012 case D3DTOP_DISABLE:
2013 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2014 and it works, so ignore this op */
2015 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2018 case D3DTOP_SELECTARG1:
2019 case D3DTOP_SELECTARG2:
2020 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2023 case D3DTOP_MODULATE4X:
2024 scale = scale * 2; /* Drop through */
2025 case D3DTOP_MODULATE2X:
2026 scale = scale * 2; /* Drop through */
2027 case D3DTOP_MODULATE:
2028 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2032 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2035 case D3DTOP_ADDSIGNED2X:
2036 scale = scale * 2; /* Drop through */
2037 case D3DTOP_ADDSIGNED:
2038 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2041 /* For the four blending modes, use the Arg2 parameter */
2042 case D3DTOP_BLENDDIFFUSEALPHA:
2043 case D3DTOP_BLENDTEXTUREALPHA:
2044 case D3DTOP_BLENDFACTORALPHA:
2045 case D3DTOP_BLENDCURRENTALPHA: {
2046 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2049 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2050 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2051 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2052 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2055 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2056 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2057 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2058 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2059 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2068 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2069 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2070 /* Switch the arguments if needed... */
2071 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2072 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2073 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2075 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2076 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2079 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2080 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2082 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2083 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2089 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2090 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2092 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2094 TRACE(" Stage type is : %s => %s\n", type, value);
2096 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2100 case D3DTSS_COLORARG1:
2101 case D3DTSS_COLORARG2:
2102 case D3DTSS_ALPHAARG1:
2103 case D3DTSS_ALPHAARG2: {
2104 const char *value, *value_comp = "", *value_alpha = "";
2106 D3DTEXTUREOP tex_op;
2108 switch (dwState & D3DTA_SELECTMASK) {
2109 #define GEN_CASE(a) case a: value = #a; break
2110 GEN_CASE(D3DTA_DIFFUSE);
2111 GEN_CASE(D3DTA_CURRENT);
2112 GEN_CASE(D3DTA_TEXTURE);
2113 GEN_CASE(D3DTA_TFACTOR);
2114 GEN_CASE(D3DTA_SPECULAR);
2116 default: value = "UNKNOWN";
2118 if (dwState & D3DTA_COMPLEMENT) {
2119 value_comp = " | D3DTA_COMPLEMENT";
2121 if (dwState & D3DTA_ALPHAREPLICATE) {
2122 value_alpha = " | D3DTA_ALPHAREPLICATE";
2125 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2126 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2128 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2131 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2134 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2136 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2140 case D3DTSS_MIPMAPLODBIAS: {
2141 D3DVALUE value = *((D3DVALUE *) &dwState);
2142 BOOLEAN handled = TRUE;
2144 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2148 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2149 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2151 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2155 case D3DTSS_MAXMIPLEVEL:
2156 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2159 case D3DTSS_BORDERCOLOR:
2160 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2161 ((dwState >> 16) & 0xFF),
2162 ((dwState >> 8) & 0xFF),
2163 ((dwState >> 0) & 0xFF),
2164 ((dwState >> 24) & 0xFF));
2167 case D3DTSS_TEXCOORDINDEX: {
2168 BOOLEAN handled = TRUE;
2171 switch (dwState & 0xFFFF0000) {
2172 #define GEN_CASE(a) case a: value = #a; break
2173 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2174 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2175 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2176 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2178 default: value = "UNKNOWN";
2180 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2184 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2186 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2190 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2191 const char *projected = "", *value;
2192 BOOLEAN handled = TRUE;
2193 switch (dwState & 0xFF) {
2194 #define GEN_CASE(a) case a: value = #a; break
2195 GEN_CASE(D3DTTFF_DISABLE);
2196 GEN_CASE(D3DTTFF_COUNT1);
2197 GEN_CASE(D3DTTFF_COUNT2);
2198 GEN_CASE(D3DTTFF_COUNT3);
2199 GEN_CASE(D3DTTFF_COUNT4);
2201 default: value = "UNKNOWN";
2203 if (dwState & D3DTTFF_PROJECTED) {
2204 projected = " | D3DTTFF_PROJECTED";
2208 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2209 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2212 if (handled == TRUE) {
2213 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2215 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2220 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2230 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2232 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2234 BOOLEAN enable_colorkey = FALSE;
2236 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2237 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2240 /* If this stage is disabled, no need to go further... */
2241 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2244 /* First check if we need to bind any other texture for this stage */
2245 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2246 if (This->current_texture[stage] == NULL) {
2247 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2249 unit = GL_TEXTURE0_WINE + stage;
2250 if (unit != glThis->current_active_tex_unit) {
2251 GL_extensions.glActiveTexture(unit);
2252 glThis->current_active_tex_unit = unit;
2254 glBindTexture(GL_TEXTURE_2D, 0);
2255 glDisable(GL_TEXTURE_2D);
2257 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2259 unit = GL_TEXTURE0_WINE + stage;
2260 if (unit != glThis->current_active_tex_unit) {
2261 GL_extensions.glActiveTexture(unit);
2262 glThis->current_active_tex_unit = unit;
2265 if (glThis->current_bound_texture[stage] == NULL) {
2266 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2267 TRACE(" enabling 2D texturing and");
2268 glEnable(GL_TEXTURE_2D);
2271 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2272 glBindTexture(GL_TEXTURE_2D, tex_name);
2275 glThis->current_bound_texture[stage] = This->current_texture[stage];
2277 if (glThis->current_bound_texture[stage] == NULL) {
2278 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2280 TRACE(" using already bound texture id %d for stage %ld.\n",
2281 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2285 /* If no texure valid for this stage, go out of the loop */
2286 if (This->current_texture[stage] == NULL) break;
2288 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2289 This will also update the various texture parameters if needed.
2291 gltex_upload_texture(surf_ptr, This, stage);
2293 /* And finally check for color-keying (only on first stage) */
2294 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2296 enable_colorkey = TRUE;
2298 static BOOL warn = FALSE;
2299 if (warn == FALSE) {
2301 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2306 enable_colorkey = FALSE;
2311 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2312 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2313 (glThis->version == 1)) &&
2314 (enable_colorkey)) {
2315 TRACE(" colorkey activated.\n");
2317 if (glThis->alpha_test == FALSE) {
2318 glEnable(GL_ALPHA_TEST);
2319 glThis->alpha_test = TRUE;
2321 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2322 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2323 static BOOL warn = FALSE;
2324 if (warn == FALSE) {
2326 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2329 glThis->current_alpha_test_func = GL_NOTEQUAL;
2330 glThis->current_alpha_test_ref = 0.0;
2331 glAlphaFunc(GL_NOTEQUAL, 0.0);
2333 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2334 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2336 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2337 glDisable(GL_ALPHA_TEST);
2338 glThis->alpha_test = FALSE;
2340 /* Maybe we should restore here the application-given alpha test states ? */
2347 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2349 LPDIRECTDRAWSURFACE7 lpTexture2)
2351 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2353 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2355 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2356 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2357 if (lpTexture2 != NULL) {
2358 WARN(" setting a texture to a non-supported texture stage !\n");
2363 if (This->current_texture[dwStage] != NULL) {
2364 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2367 if (lpTexture2 == NULL) {
2368 This->current_texture[dwStage] = NULL;
2370 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2371 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2372 This->current_texture[dwStage] = tex_impl;
2379 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2380 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2383 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2385 fill_opengl_caps_7(lpD3DHELDevDesc);
2387 TRACE(" returning caps : no dump function yet.\n");
2393 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2394 LPD3DMATERIAL7 lpMat)
2396 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2397 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2399 if (TRACE_ON(ddraw)) {
2400 TRACE(" material is : \n");
2401 dump_D3DMATERIAL7(lpMat);
2404 This->current_material = *lpMat;
2407 glMaterialfv(GL_FRONT_AND_BACK,
2409 (float *) &(This->current_material.u.diffuse));
2410 glMaterialfv(GL_FRONT_AND_BACK,
2412 (float *) &(This->current_material.u1.ambient));
2413 glMaterialfv(GL_FRONT_AND_BACK,
2415 (float *) &(This->current_material.u2.specular));
2416 glMaterialfv(GL_FRONT_AND_BACK,
2418 (float *) &(This->current_material.u3.emissive));
2419 glMaterialf(GL_FRONT_AND_BACK,
2421 This->current_material.u4.power); /* Not sure about this... */
2429 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2431 LPD3DLIGHT7 lpLight)
2433 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2434 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2435 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2437 if (TRACE_ON(ddraw)) {
2438 TRACE(" setting light : \n");
2439 dump_D3DLIGHT7(lpLight);
2442 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2443 This->set_lights |= 0x00000001 << dwLightIndex;
2444 This->light_parameters[dwLightIndex] = *lpLight;
2446 /* Some checks to print out nice warnings :-) */
2447 switch (lpLight->dltType) {
2448 case D3DLIGHT_DIRECTIONAL:
2449 case D3DLIGHT_POINT:
2450 /* These are handled properly... */
2454 if ((lpLight->dvTheta != 0.0) ||
2455 (lpLight->dvTheta != lpLight->dvPhi)) {
2456 ERR("dvTheta not fully supported yet !\n");
2461 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2464 /* This will force the Light setting on next drawing of primitives */
2465 glThis->transform_state = GL_TRANSFORM_NONE;
2471 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2475 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2476 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2478 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2482 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2483 /* Set the default parameters.. */
2484 TRACE(" setting default light parameters...\n");
2485 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2487 glEnable(GL_LIGHT0 + dwLightIndex);
2488 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2489 /* This light gets active... Need to update its parameters to GL before the next drawing */
2490 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2492 This->active_lights |= 0x00000001 << dwLightIndex;
2493 glThis->transform_state = GL_TRANSFORM_NONE;
2496 glDisable(GL_LIGHT0 + dwLightIndex);
2497 This->active_lights &= ~(0x00000001 << dwLightIndex);
2505 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2507 ICOM_THIS(IDirect3DDeviceImpl,iface);
2508 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2510 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2512 if (dwIndex >= This->max_clipping_planes) {
2513 return DDERR_INVALIDPARAMS;
2516 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2518 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2520 /* This is to force the reset of the transformation matrices on the next drawing.
2521 * This is needed to use the correct matrices for the various clipping planes.
2523 glThis->transform_state = GL_TRANSFORM_NONE;
2529 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2530 LPD3DVIEWPORT7 lpData)
2532 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2533 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2535 if (TRACE_ON(ddraw)) {
2536 TRACE(" viewport is : \n");
2537 TRACE(" - dwX = %ld dwY = %ld\n",
2538 lpData->dwX, lpData->dwY);
2539 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2540 lpData->dwWidth, lpData->dwHeight);
2541 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2542 lpData->dvMinZ, lpData->dvMaxZ);
2546 /* Set the viewport */
2547 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2548 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2549 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2551 if ((lpData->dwX != This->active_viewport.dwX) ||
2552 (lpData->dwY != This->active_viewport.dwY) ||
2553 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2554 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2555 glViewport(lpData->dwX,
2556 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2557 lpData->dwWidth, lpData->dwHeight);
2562 This->active_viewport = *lpData;
2567 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2568 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2570 # define XCAST(fun) (void*)
2573 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2575 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2576 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2577 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2578 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2579 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2580 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2581 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2582 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2583 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2584 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2585 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2586 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2587 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2588 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2589 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2590 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2591 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2592 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2593 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2594 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2595 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2596 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2597 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2598 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2599 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2600 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2601 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2602 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2603 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2604 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2605 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2606 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2607 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2608 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2609 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2610 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2611 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2612 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2613 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2614 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2615 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2616 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2617 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2618 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2619 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2620 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2621 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2622 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2623 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2624 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2627 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2632 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2633 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2635 # define XCAST(fun) (void*)
2638 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2640 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2641 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2642 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2643 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2644 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2645 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2646 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2647 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2648 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2649 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2650 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2651 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2652 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2653 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2654 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2655 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2656 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2657 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2658 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2659 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2660 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2661 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2662 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2663 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2664 XCAST(GetLightState) GL_IDirect3DDeviceImpl_3_2T_GetLightState,
2665 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2666 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2667 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2668 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2669 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2670 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2671 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2672 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2673 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2674 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2675 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2676 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2677 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2678 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2679 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2680 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2681 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2682 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2685 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2690 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2691 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2693 # define XCAST(fun) (void*)
2696 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2698 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2699 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2700 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2701 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2702 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2703 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2704 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2705 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2706 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2707 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2708 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2709 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2710 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2711 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2712 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2713 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2714 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2715 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2716 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2717 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2718 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2719 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2720 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2721 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2722 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2723 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2724 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2725 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2726 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2727 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2728 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2729 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2730 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2731 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2734 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2739 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2740 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2742 # define XCAST(fun) (void*)
2745 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2747 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2748 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2749 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2750 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2751 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2752 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2753 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2754 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2755 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2756 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2757 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2758 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2759 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2760 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2761 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2762 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2763 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2764 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2765 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2766 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2767 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2768 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2769 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2772 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2776 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2777 WINE_GL_BUFFER_TYPE buffer_type,
2785 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2786 GLbitfield bitfield = 0;
2790 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2791 if (TRACE_ON(ddraw)) {
2794 TRACE(" rectangles : \n");
2795 for (i = 0; i < dwCount; i++) {
2796 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2805 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2806 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2810 /* Clears the screen */
2813 if (dwFlags & D3DCLEAR_TARGET) {
2814 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2815 /* TODO: optimize here the case where Clear changes all the screen... */
2816 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2818 glThis->state[buffer_type] = SURFACE_GL;
2821 if (dwFlags & D3DCLEAR_ZBUFFER) {
2822 bitfield |= GL_DEPTH_BUFFER_BIT;
2823 if (glThis->depth_mask == FALSE) {
2824 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2826 if (dvZ != glThis->prev_clear_Z) {
2828 glThis->prev_clear_Z = dvZ;
2830 TRACE(" depth value : %f\n", dvZ);
2832 if (dwFlags & D3DCLEAR_STENCIL) {
2833 bitfield |= GL_STENCIL_BUFFER_BIT;
2834 if (dwStencil != glThis->prev_clear_stencil) {
2835 glClearStencil(dwStencil);
2836 glThis->prev_clear_stencil = dwStencil;
2838 TRACE(" stencil value : %ld\n", dwStencil);
2840 if (dwFlags & D3DCLEAR_TARGET) {
2841 bitfield |= GL_COLOR_BUFFER_BIT;
2842 if (dwColor != glThis->prev_clear_color) {
2843 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2844 ((dwColor >> 8) & 0xFF) / 255.0,
2845 ((dwColor >> 0) & 0xFF) / 255.0,
2846 ((dwColor >> 24) & 0xFF) / 255.0);
2847 glThis->prev_clear_color = dwColor;
2849 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2852 glEnable(GL_SCISSOR_TEST);
2853 for (i = 0; i < dwCount; i++) {
2854 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2855 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2858 glDisable(GL_SCISSOR_TEST);
2860 if (dwFlags & D3DCLEAR_ZBUFFER) {
2861 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2869 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2877 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2881 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2882 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2884 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2885 WINE_GL_BUFFER_TYPE buffer_type;
2887 /* First check if we BLT to the backbuffer... */
2888 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2889 buffer_type = WINE_GL_BUFFER_BACK;
2890 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2891 buffer_type = WINE_GL_BUFFER_FRONT;
2893 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2894 return DDERR_INVALIDPARAMS;
2897 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2898 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2899 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2900 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2901 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2902 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2905 return DDERR_INVALIDPARAMS;
2907 *buffer_type_p = buffer_type;
2913 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2914 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2915 DWORD dwFlags, LPDDBLTFX lpbltfx)
2917 WINE_GL_BUFFER_TYPE buffer_type;
2921 rect.u1.x1 = rdst->left;
2922 rect.u2.y1 = rdst->top;
2923 rect.u3.x2 = rdst->right;
2924 rect.u4.y2 = rdst->bottom;
2928 rect.u3.x2 = This->surface_desc.dwWidth;
2929 rect.u4.y2 = This->surface_desc.dwHeight;
2932 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2934 if (dwFlags & DDBLT_COLORFILL) {
2935 /* This is easy to handle for the D3D Device... */
2939 /* The color as given in the Blt function is in the format of the frame-buffer...
2940 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2942 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2943 if (This->palette) {
2944 color = ((0xFF000000) |
2945 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2946 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2947 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2951 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2952 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2953 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2954 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2955 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2956 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2957 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2958 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2961 color = ((0xFF000000) |
2962 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2963 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2964 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2966 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2967 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2968 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2969 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2970 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2971 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2973 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2974 return DDERR_INVALIDPARAMS;
2977 ERR("Wrong surface type for BLT override !\n");
2978 return DDERR_INVALIDPARAMS;
2981 TRACE(" executing D3D Device override.\n");
2985 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2986 if (buffer_type == WINE_GL_BUFFER_FRONT)
2987 glDrawBuffer(GL_FRONT);
2989 glDrawBuffer(GL_BACK);
2991 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2993 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2994 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2995 glDrawBuffer(prev_draw);
3000 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
3001 /* Normal blit without any special case... */
3003 /* And which has a SRC surface */
3004 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3006 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
3007 (src_impl->d3ddevice == This->d3ddevice) &&
3008 ((dwFlags & DDBLT_KEYSRC) == 0)) {
3009 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3013 WINE_GL_BUFFER_TYPE src_buffer_type;
3014 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3020 src_rect.u1.x1 = rsrc->left;
3021 src_rect.u2.y1 = rsrc->top;
3022 src_rect.u3.x2 = rsrc->right;
3023 src_rect.u4.y2 = rsrc->bottom;
3027 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3028 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3031 width = src_rect.u3.x2 - src_rect.u1.x1;
3032 height = src_rect.u4.y2 - src_rect.u2.y1;
3034 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3035 (height != (rect.u4.y2 - rect.u2.y1))) {
3036 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3037 return DDERR_INVALIDPARAMS;
3040 /* First check if we BLT from the backbuffer... */
3041 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3042 src_buffer_type = WINE_GL_BUFFER_BACK;
3043 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3044 src_buffer_type = WINE_GL_BUFFER_FRONT;
3046 ERR("Unexpected case in direct buffer to buffer copy !\n");
3047 return DDERR_INVALIDPARAMS;
3050 TRACE(" using direct buffer to buffer copy.\n");
3054 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3056 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3057 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3058 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3060 return DDERR_INVALIDPARAMS;
3063 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3064 if (buffer_type == WINE_GL_BUFFER_FRONT)
3065 glDrawBuffer(GL_FRONT);
3067 glDrawBuffer(GL_BACK);
3069 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3070 glReadBuffer(GL_FRONT);
3072 glReadBuffer(GL_BACK);
3074 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3075 And directly re-draws this on the destination buffer. */
3076 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3079 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3080 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3082 get_height = UNLOCK_TEX_SIZE;
3084 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3087 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3088 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3090 get_width = UNLOCK_TEX_SIZE;
3092 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3093 0, UNLOCK_TEX_SIZE - get_height,
3094 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3095 get_width, get_height);
3098 glTexCoord2f(0.0, 0.0);
3099 glVertex3d(rect.u1.x1 + x,
3100 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3102 glTexCoord2f(1.0, 0.0);
3103 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3104 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3106 glTexCoord2f(1.0, 1.0);
3107 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3110 glTexCoord2f(0.0, 1.0);
3111 glVertex3d(rect.u1.x1 + x,
3118 upload_surface_to_tex_memory_release();
3119 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3121 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3122 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3123 glDrawBuffer(prev_draw);
3129 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3130 (this prevents calling glReadPixels) */
3134 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3138 double x_stretch, y_stretch;
3141 src_rect.u1.x1 = rsrc->left;
3142 src_rect.u2.y1 = rsrc->top;
3143 src_rect.u3.x2 = rsrc->right;
3144 src_rect.u4.y2 = rsrc->bottom;
3148 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3149 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3152 width = src_rect.u3.x2 - src_rect.u1.x1;
3153 height = src_rect.u4.y2 - src_rect.u2.y1;
3155 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3156 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3158 TRACE(" using memory to buffer Blt overide.\n");
3162 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3164 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3165 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3166 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3168 return DDERR_INVALIDPARAMS;
3171 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3172 if (buffer_type == WINE_GL_BUFFER_FRONT)
3173 glDrawBuffer(GL_FRONT);
3175 glDrawBuffer(GL_BACK);
3177 /* Now the serious stuff happens. This is basically the same code that for the memory
3178 flush to frame buffer ... with stretching and different rectangles added :-) */
3179 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3182 flush_rect.top = src_rect.u2.y1 + y;
3183 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3185 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3187 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3188 flush_rect.left = src_rect.u1.x1 + x;
3189 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3191 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3193 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3196 glTexCoord2f(0.0, 0.0);
3197 glVertex3d(rect.u1.x1 + (x * x_stretch),
3198 rect.u2.y1 + (y * y_stretch),
3200 glTexCoord2f(1.0, 0.0);
3201 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3202 rect.u2.y1 + (y * y_stretch),
3204 glTexCoord2f(1.0, 1.0);
3205 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3206 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3208 glTexCoord2f(0.0, 1.0);
3209 glVertex3d(rect.u1.x1 + (x * x_stretch),
3210 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3216 upload_surface_to_tex_memory_release();
3217 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3219 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3220 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3221 glDrawBuffer(prev_draw);
3229 return DDERR_INVALIDPARAMS;
3233 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3234 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3235 LPRECT rsrc, DWORD trans)
3239 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3240 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3241 WINE_GL_BUFFER_TYPE buffer_type;
3245 int width, height, x, y;
3247 /* Cannot support DSTCOLORKEY blitting... */
3248 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3251 WARN("rsrc is NULL - getting the whole surface !!\n");
3253 rsrc->left = rsrc->top = 0;
3254 rsrc->right = src_impl->surface_desc.dwWidth;
3255 rsrc->bottom = src_impl->surface_desc.dwHeight;
3263 rdst.right = dstx + (rsrc->right - rsrc->left);
3264 if (rdst.right > This->surface_desc.dwWidth) {
3265 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3266 rdst.right = This->surface_desc.dwWidth;
3268 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3269 if (rdst.bottom > This->surface_desc.dwHeight) {
3270 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3271 rdst.bottom = This->surface_desc.dwHeight;
3274 width = rsrc->right - rsrc->left;
3275 height = rsrc->bottom - rsrc->top;
3277 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3279 TRACE(" using BltFast memory to frame buffer overide.\n");
3283 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3285 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3286 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3287 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3288 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3290 return DDERR_INVALIDPARAMS;
3293 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3294 if (buffer_type == WINE_GL_BUFFER_FRONT)
3295 glDrawBuffer(GL_FRONT);
3297 glDrawBuffer(GL_BACK);
3299 /* Now the serious stuff happens. This is basically the same code that for the memory
3300 flush to frame buffer but with different rectangles for source and destination :-) */
3301 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3304 flush_rect.top = rsrc->top + y;
3305 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3307 (rsrc->top + y + UNLOCK_TEX_SIZE));
3309 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3310 flush_rect.left = rsrc->left + x;
3311 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3313 (rsrc->left + x + UNLOCK_TEX_SIZE));
3315 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3318 glTexCoord2f(0.0, 0.0);
3319 glVertex3d(rdst.left + x,
3322 glTexCoord2f(1.0, 0.0);
3323 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3326 glTexCoord2f(1.0, 1.0);
3327 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3328 rdst.top + (y + UNLOCK_TEX_SIZE),
3330 glTexCoord2f(0.0, 1.0);
3331 glVertex3d(rdst.left + x,
3332 rdst.top + (y + UNLOCK_TEX_SIZE),
3338 upload_surface_to_tex_memory_release();
3339 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3341 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3342 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3343 glDrawBuffer(prev_draw);
3351 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3353 GLfloat height, width;
3354 GLfloat trans_mat[16];
3356 TRACE("(%p)\n", This);
3358 width = This->surface->surface_desc.dwWidth;
3359 height = This->surface->surface_desc.dwHeight;
3361 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3362 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3364 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3365 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3367 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3368 * that the Z coordinate needs to be given to GL unchanged.
3370 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3372 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = 0.0;
3373 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3376 glMatrixMode(GL_MODELVIEW);
3378 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3379 Correctness Tips section).
3381 Basically, from what I understood, if the game does not filter the font texture,
3382 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3383 one and we will have strange artifacts (as the rounding and stuff may give different results
3384 for different pixels, ie sometimes take the left pixel, sometimes the right).
3386 glTranslatef(0.375, 0.375, 0);
3387 glMatrixMode(GL_PROJECTION);
3388 glLoadMatrixf(trans_mat);
3393 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3394 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3396 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3399 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3400 glMatrixMode(GL_MODELVIEW);
3401 glLoadMatrixf((float *) view_mat);
3403 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3404 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3407 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3408 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3411 plane[0] = This->clipping_planes[i].plane[0];
3412 plane[1] = This->clipping_planes[i].plane[1];
3413 plane[2] = This->clipping_planes[i].plane[2];
3414 plane[3] = This->clipping_planes[i].plane[3];
3416 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3420 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3424 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3425 if (runner & This->active_lights) {
3426 switch (This->light_parameters[i].dltType) {
3427 case D3DLIGHT_DIRECTIONAL: {
3429 float cut_off = 180.0;
3431 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3432 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3433 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3434 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3436 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3437 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3438 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3440 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3443 case D3DLIGHT_POINT: {
3445 float cut_off = 180.0;
3447 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3448 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3449 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3450 position[0] = This->light_parameters[i].dvPosition.u1.x;
3451 position[1] = This->light_parameters[i].dvPosition.u2.y;
3452 position[2] = This->light_parameters[i].dvPosition.u3.z;
3454 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3455 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3456 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3457 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3458 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3461 case D3DLIGHT_SPOT: {
3464 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3466 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3467 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3468 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3470 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3471 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3472 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3474 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3475 position[0] = This->light_parameters[i].dvPosition.u1.x;
3476 position[1] = This->light_parameters[i].dvPosition.u2.y;
3477 position[2] = This->light_parameters[i].dvPosition.u3.z;
3479 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3480 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3481 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3482 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3483 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3484 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3488 /* No warning here as it's already done at light setting */
3495 glMultMatrixf((float *) world_mat);
3497 if ((matrices & PROJMAT_CHANGED) != 0) {
3498 glMatrixMode(GL_PROJECTION);
3499 glLoadMatrixf((float *) proj_mat);
3505 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3507 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3508 DWORD tex_mat, tex_stage;
3510 TRACE("(%p,%08lx)\n", This, matrices);
3512 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3513 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3514 /* This will force an update of the transform state at the next drawing. */
3515 glThis->transform_state = GL_TRANSFORM_NONE;
3518 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3519 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3522 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3523 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3524 if (matrices & tex_mat) {
3525 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3526 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3528 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3529 if (glThis->current_active_tex_unit != unit) {
3530 GL_extensions.glActiveTexture(unit);
3531 glThis->current_active_tex_unit = unit;
3533 glMatrixMode(GL_TEXTURE);
3534 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3536 This->tex_mat_is_identity[tex_stage] = is_identity;
3538 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3539 if (glThis->current_active_tex_unit != unit) {
3540 GL_extensions.glActiveTexture(unit);
3541 glThis->current_active_tex_unit = unit;
3543 glMatrixMode(GL_TEXTURE);
3545 This->tex_mat_is_identity[tex_stage] = TRUE;
3554 /* TODO for both these functions :
3555 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3556 by other OpenGL code in D3D
3557 - handle the case where no 'Begin / EndScene' was done between two locks
3558 - handle the rectangles in the unlock too
3559 - handle pitch correctly...
3561 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3563 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3564 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3565 WINE_GL_BUFFER_TYPE buffer_type;
3568 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3569 buffer_type = WINE_GL_BUFFER_FRONT;
3570 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3571 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3572 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3574 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3575 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3576 buffer_type = WINE_GL_BUFFER_BACK;
3577 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3578 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3579 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3581 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3583 ERR("Wrong surface type for locking !\n");
3587 if (pRect == NULL) {
3590 loc_rect.bottom = This->surface_desc.dwHeight;
3591 loc_rect.right = This->surface_desc.dwWidth;
3595 /* Try to acquire the device critical section */
3596 EnterCriticalSection(&(d3d_dev->crit));
3598 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3599 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3600 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3602 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3604 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3605 /* Check if the new rectangle is in the previous one or not.
3606 If it is not, flush first the previous locks on screen.
3608 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3609 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3610 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3611 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3612 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3613 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3614 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3615 pRect->left, pRect->top, pRect->right, pRect->bottom,
3616 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3617 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3618 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3620 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3621 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3623 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3625 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3628 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3629 /* If the surface is already in memory, no need to do anything here... */
3630 GLenum buffer_format;
3631 GLenum buffer_color;
3635 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3636 pRect->left, pRect->top, pRect->right, pRect->bottom);
3638 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3639 may only write to the device... But when we will blit it back to the screen, we need
3640 also to blit correctly the parts the application did not overwrite... */
3642 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3643 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3644 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3645 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3646 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3647 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3648 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3649 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3650 buffer_color = GL_RGB;
3651 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3652 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3653 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3654 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3655 buffer_format = GL_UNSIGNED_BYTE;
3656 buffer_color = GL_RGB;
3657 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3658 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3659 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3660 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3661 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3662 buffer_color = GL_BGRA;
3664 ERR(" unsupported pixel format at device locking.\n");
3668 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3674 if (buffer_type == WINE_GL_BUFFER_FRONT)
3675 /* Application wants to lock the front buffer */
3676 glReadBuffer(GL_FRONT);
3678 /* Application wants to lock the back buffer */
3679 glReadBuffer(GL_BACK);
3681 dst = ((char *)This->surface_desc.lpSurface) +
3682 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3684 if (This->surface_desc.u1.lPitch != (GET_BPP(This->surface_desc) * This->surface_desc.dwWidth)) {
3685 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3686 * could not be bothered considering the rare cases where it may be useful :-)
3688 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3689 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3691 glReadPixels(pRect->left, y,
3692 pRect->right - pRect->left, 1,
3693 buffer_color, buffer_format, dst);
3694 dst += This->surface_desc.u1.lPitch;
3697 /* Faster path for surface copy. Note that I can use static variables here as I am
3698 * protected by the OpenGL critical section so this function won't be called by
3699 * two threads at the same time.
3701 static char *buffer = NULL;
3702 static int buffer_width = 0;
3703 char *dst2 = dst + ((pRect->bottom - pRect->top) - 1) * This->surface_desc.u1.lPitch;
3704 int current_width = (pRect->right - pRect->left) * GET_BPP(This->surface_desc);
3706 glReadPixels(pRect->left, ((int) This->surface_desc.dwHeight - (int) pRect->bottom),
3707 pRect->right - pRect->left, pRect->bottom - pRect->top,
3708 buffer_color, buffer_format, dst);
3710 if (current_width > buffer_width) {
3711 if (buffer != NULL) HeapFree(GetProcessHeap(), 0, buffer);
3712 buffer_width = current_width;
3713 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_width);
3715 for (y = 0; y < ((pRect->bottom - pRect->top) / 2); y++) {
3716 memcpy(buffer, dst, current_width);
3717 memcpy(dst, dst2, current_width);
3718 memcpy(dst2, buffer, current_width);
3719 dst += This->surface_desc.u1.lPitch;
3720 dst2 -= This->surface_desc.u1.lPitch;
3724 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3727 /* I keep this code here as it's very useful to debug :-) */
3729 static int flush_count = 0;
3733 if ((++flush_count % 50) == 0) {
3734 sprintf(buf, "lock_%06d.pnm", flush_count);
3735 f = fopen(buf, "wb");
3736 DDRAW_dump_surface_to_disk(This, f);
3745 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3747 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3752 /* Note : no need here to lock the 'device critical section' as we are already protected by
3753 the GL critical section. */
3755 if (pRect == NULL) {
3758 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3759 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3763 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3765 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3767 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3768 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3769 ERR(" unsupported pixel format at frame buffer flush.\n");
3773 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3777 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3779 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3780 /* First, upload the texture... */
3781 flush_rect.left = x;
3782 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3784 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3787 glTexCoord2f(0.0, 0.0);
3788 glVertex3d(x, y, 0.5);
3789 glTexCoord2f(1.0, 0.0);
3790 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3791 glTexCoord2f(1.0, 1.0);
3792 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3793 glTexCoord2f(0.0, 1.0);
3794 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3799 upload_surface_to_tex_memory_release();
3800 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3803 /* I keep this code here as it's very useful to debug :-) */
3805 static int flush_count = 0;
3809 if ((++flush_count % 50) == 0) {
3810 sprintf(buf, "flush_%06d.pnm", flush_count);
3811 f = fopen(buf, "wb");
3812 DDRAW_dump_surface_to_disk(surf, f);
3818 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3820 WINE_GL_BUFFER_TYPE buffer_type;
3821 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3822 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3824 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3825 buffer_type = WINE_GL_BUFFER_FRONT;
3826 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3827 buffer_type = WINE_GL_BUFFER_BACK;
3829 ERR("Wrong surface type for locking !\n");
3833 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3834 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3835 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3837 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3839 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3840 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3841 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3844 TRACE(" flushing front buffer immediatly on screen.\n");
3847 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3848 glDrawBuffer(GL_FRONT);
3849 /* Note: we do not use the application provided lock rectangle but our own stored at
3850 lock time. This is because in old D3D versions, the 'lock' parameter did not
3853 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
3854 glDrawBuffer(prev_draw);
3857 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3861 /* And 'frees' the device critical section */
3862 LeaveCriticalSection(&(d3d_dev->crit));
3866 apply_texture_state(IDirect3DDeviceImpl *This)
3870 /* Initialize texture stages states */
3871 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3872 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3873 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3874 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3875 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3882 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3884 IDirect3DDeviceImpl *object;
3885 IDirect3DDeviceGLImpl *gl_object;
3886 IDirectDrawSurfaceImpl *surf;
3891 XVisualInfo template;
3892 GLenum buffer = GL_FRONT;
3895 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3896 if (object == NULL) return DDERR_OUTOFMEMORY;
3898 gl_object = (IDirect3DDeviceGLImpl *) object;
3902 object->surface = surface;
3903 object->set_context = set_context;
3904 object->clear = d3ddevice_clear_back;
3905 object->set_matrices = d3ddevice_set_matrices;
3906 object->matrices_updated = d3ddevice_matrices_updated;
3907 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3909 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3911 InitializeCriticalSection(&(object->crit));
3913 TRACE(" device critical section : %p\n", &(object->crit));
3915 /* This is just a hack for some badly done games :-/ */
3917 gl_object->version = 1;
3918 TRACE(" using D3D1 special hacks.\n");
3920 gl_object->version = 7;
3922 device_context = GetDC(surface->ddraw_owner->window);
3923 gl_object->display = get_display(device_context);
3924 gl_object->drawable = get_drawable(device_context);
3925 ReleaseDC(surface->ddraw_owner->window,device_context);
3928 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3929 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3931 HeapFree(GetProcessHeap(), 0, object);
3932 ERR("No visual found !\n");
3934 return DDERR_INVALIDPARAMS;
3936 TRACE(" visual found\n");
3939 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3942 if (gl_object->gl_context == NULL) {
3943 HeapFree(GetProcessHeap(), 0, object);
3944 ERR("Error in context creation !\n");
3946 return DDERR_INVALIDPARAMS;
3948 TRACE(" context created (%p)\n", gl_object->gl_context);
3951 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3952 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3953 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3954 surf->aux_ctx = (LPVOID) object;
3955 surf->aux_data = (LPVOID) gl_object->drawable;
3956 surf->aux_flip = opengl_flip;
3961 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3963 TRACE(" no double buffering : drawing on the front buffer\n");
3967 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3968 IDirectDrawSurfaceImpl *surf2;
3969 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3970 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3971 TRACE(" checking surface %p :", surf2);
3972 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3973 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3974 /* Override the Lock / Unlock function for all these surfaces */
3975 surf2->lock_update_prev = surf2->lock_update;
3976 surf2->lock_update = d3ddevice_lock_update;
3977 surf2->unlock_update_prev = surf2->unlock_update;
3978 surf2->unlock_update = d3ddevice_unlock_update;
3979 /* And install also the blt / bltfast overrides */
3980 surf2->aux_blt = d3ddevice_blt;
3981 surf2->aux_bltfast = d3ddevice_bltfast;
3983 TRACE(" overiding direct surface access.\n");
3985 TRACE(" no overide.\n");
3987 surf2->d3ddevice = object;
3991 /* Set the various light parameters */
3992 for (light = 0; light < MAX_LIGHTS; light++) {
3993 /* Only set the fields that are not zero-created */
3994 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3995 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3996 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3997 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3998 object->light_parameters[light].dvDirection.u3.z = 1.0;
4001 /* Allocate memory for the matrices */
4002 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4003 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4004 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4005 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
4006 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
4007 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
4008 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
4009 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4010 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
4011 object->tex_mat_is_identity[tex_num] = TRUE;
4014 /* Initialisation */
4015 TRACE(" setting current context\n");
4016 object->set_context(object);
4017 TRACE(" current context set\n");
4019 /* allocate the clipping planes */
4020 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
4021 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
4023 glHint(GL_FOG_HINT,GL_NICEST);
4025 /* Initialize the various GL contexts to be in sync with what we store locally */
4028 glClearColor(0.0, 0.0, 0.0, 0.0);
4029 glDepthMask(GL_TRUE);
4030 gl_object->depth_mask = TRUE;
4031 glEnable(GL_DEPTH_TEST);
4032 gl_object->depth_test = TRUE;
4033 glDisable(GL_ALPHA_TEST);
4034 glDisable(GL_STENCIL_TEST);
4035 glDisable(GL_CULL_FACE);
4036 glDisable(GL_LIGHTING);
4037 glDisable(GL_BLEND);
4039 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4040 gl_object->current_tex_env = GL_REPLACE;
4041 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
4042 if (GL_extensions.glActiveTexture != NULL) {
4043 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
4045 gl_object->current_alpha_test_ref = 0.0;
4046 gl_object->current_alpha_test_func = GL_ALWAYS;
4047 glAlphaFunc(GL_ALWAYS, 0.0);
4049 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4050 glDrawBuffer(buffer);
4051 glReadBuffer(buffer);
4052 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4055 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4056 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4058 /* fill_device_capabilities(d3d->ddraw); */
4060 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4061 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4062 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4063 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4067 TRACE(" creating implementation at %p.\n", *obj);
4069 /* And finally warn D3D that this device is now present */
4070 object->d3d->d3d_added_device(object->d3d, object);
4072 /* FIXME: Should handle other versions than just 7 */
4073 InitDefaultStateBlock(&object->state_block, 7);
4074 /* Apply default render state and texture stage state values */
4075 apply_render_state(object, &object->state_block);
4076 apply_texture_state(object);
4078 /* And fill the fog table with the default fog value */
4079 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4084 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4086 pc->dwSize = sizeof(*pc);
4087 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4088 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4089 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4090 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4091 D3DPRASTERCAPS_ZFOG;
4092 if (GL_extensions.mipmap_lodbias == TRUE) {
4093 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4095 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4096 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4097 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4098 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4099 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4100 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4101 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4102 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4103 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4104 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4105 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4106 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4107 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4108 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4109 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4110 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4111 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4112 D3DPTFILTERCAPS_MIPFPOINT;
4113 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4114 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4115 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4116 if (GL_extensions.mirrored_repeat == TRUE) {
4117 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4119 pc->dwStippleWidth = 32;
4120 pc->dwStippleHeight = 32;
4123 static void fill_caps(void)
4125 GLint max_clip_planes;
4128 /* Fill first all the fields with default values which will be overriden later on with
4129 correct ones from the GL code
4131 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4132 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4133 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4134 /* D3D 7 capabilities */
4135 D3DDEVCAPS_DRAWPRIMITIVES2 /*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_DRAWPRIMITIVES2EX;
4136 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4137 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4138 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4139 opengl_device_caps.dwMinTextureWidth = 1;
4140 opengl_device_caps.dwMinTextureHeight = 1;
4141 opengl_device_caps.dwMaxTextureWidth = 1024;
4142 opengl_device_caps.dwMaxTextureHeight = 1024;
4143 opengl_device_caps.dwMaxTextureRepeat = 16;
4144 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4145 opengl_device_caps.dwMaxAnisotropy = 0;
4146 opengl_device_caps.dvGuardBandLeft = 0.0;
4147 opengl_device_caps.dvGuardBandRight = 0.0;
4148 opengl_device_caps.dvGuardBandTop = 0.0;
4149 opengl_device_caps.dvGuardBandBottom = 0.0;
4150 opengl_device_caps.dvExtentsAdjust = 0.0;
4151 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4152 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4153 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4154 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4155 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4156 if (GL_extensions.max_texture_units != 0) {
4157 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4158 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4159 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4161 opengl_device_caps.wMaxTextureBlendStages = 1;
4162 opengl_device_caps.wMaxSimultaneousTextures = 1;
4163 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4165 opengl_device_caps.dwMaxActiveLights = 16;
4166 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4167 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4168 opengl_device_caps.wMaxUserClipPlanes = 1;
4169 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4170 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4171 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4172 opengl_device_caps.dwReserved1 = 0;
4173 opengl_device_caps.dwReserved2 = 0;
4174 opengl_device_caps.dwReserved3 = 0;
4175 opengl_device_caps.dwReserved4 = 0;
4177 /* And now some GL overides :-) */
4178 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4179 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4180 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4181 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4183 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4184 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4186 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4187 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4188 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4190 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4191 TRACE(": Z bits = %d\n", depth_bits);
4192 switch (depth_bits) {
4193 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4194 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4196 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4201 d3ddevice_init_at_startup(void *gl_handle)
4203 XVisualInfo template;
4208 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4209 XWindowAttributes win_attr;
4210 GLXContext gl_context;
4212 const char *glExtensions;
4213 const char *glVersion;
4214 const char *glXExtensions = NULL;
4215 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4216 int major, minor, patch, num_parsed;
4218 TRACE("Initializing GL...\n");
4220 /* Get a default rendering context to have the 'caps' function query some info from GL */
4221 device_context = GetDC(0);
4222 display = get_display(device_context);
4223 ReleaseDC(0, device_context);
4226 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4227 visual = win_attr.visual;
4229 visual = DefaultVisual(display, DefaultScreen(display));
4231 template.visualid = XVisualIDFromVisual(visual);
4232 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4235 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4238 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4240 if (gl_context == NULL) {
4242 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4245 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4246 glXDestroyContext(display, gl_context);
4248 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4252 /* Then, query all extensions */
4253 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); /* Note: not used right now but will for PBuffers */
4254 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4255 glVersion = (const char *) glGetString(GL_VERSION);
4256 if (gl_handle != NULL) {
4257 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4260 /* Parse the GL version string */
4261 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4262 if (num_parsed == 1) {
4265 } else if (num_parsed == 2) {
4268 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4270 /* And starts to fill the extension context properly */
4271 memset(&GL_extensions, 0, sizeof(GL_extensions));
4272 TRACE("GL supports following extensions used by Wine :\n");
4274 /* Mirrored Repeat extension :
4275 - GL_ARB_texture_mirrored_repeat
4276 - GL_IBM_texture_mirrored_repeat
4279 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4280 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4282 ((major == 1) && (minor >= 4))) {
4283 TRACE(" - mirrored repeat\n");
4284 GL_extensions.mirrored_repeat = TRUE;
4287 /* Texture LOD Bias :
4288 - GL_EXT_texture_lod_bias
4290 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4291 TRACE(" - texture lod bias\n");
4292 GL_extensions.mipmap_lodbias = TRUE;
4295 /* For all subsequent extensions, we need glXGetProcAddress */
4296 if (pglXGetProcAddressARB != NULL) {
4297 /* Multi-texturing :
4298 - GL_ARB_multitexture
4301 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4303 ((major == 1) && (minor > 2)) ||
4304 ((major == 1) && (minor == 2) && (patch >= 1))) {
4305 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4306 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4307 /* We query the ARB version to be the most portable we can... */
4308 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4309 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4310 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4313 if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
4314 TRACE(" - S3TC compression supported\n");
4315 GL_extensions.s3tc_compressed_texture = TRUE;
4316 GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2D");
4317 GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2D");
4321 /* Fill the D3D capabilities according to what GL tells us... */
4324 /* And frees this now-useless context */
4325 glXMakeCurrent(display, None, NULL);
4326 glXDestroyContext(display, gl_context);