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
42 #include "wine/debug.h"
43 #include "wine/library.h"
45 #include "d3d_private.h"
46 #include "opengl_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
49 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
51 /* x11drv GDI escapes */
52 #define X11DRV_ESCAPE 6789
53 enum x11drv_escape_codes
55 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
56 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
57 X11DRV_GET_FONT, /* get current X font for a DC */
60 /* They are non-static as they are used by Direct3D in the creation function */
61 const GUID IID_D3DDEVICE_OpenGL = {
65 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
68 const float id_mat[16] = {
75 /* This is filled at DLL loading time */
76 static D3DDEVICEDESC7 opengl_device_caps;
77 GL_EXTENSIONS_LIST GL_extensions;
79 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
80 D3DPRIMITIVETYPE d3dptPrimitiveType,
81 DWORD d3dvtVertexType,
82 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
88 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
90 /* retrieve the X display to use on a given DC */
91 inline static Display *get_display( HDC hdc )
94 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
96 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
97 sizeof(display), (LPSTR)&display )) display = NULL;
102 #define UNLOCK_TEX_SIZE 256
104 #define DEPTH_RANGE_BIT (0x00000001 << 0)
105 #define VIEWPORT_BIT (0x00000001 << 1)
107 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
108 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
109 DWORD opt_bitmap = 0x00000000;
111 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
112 ((d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE))) {
113 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
114 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
115 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
117 /* Disable multi-texturing for level 1 to disable all others */
118 glDisable(GL_TEXTURE_2D);
120 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
121 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
122 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
124 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
125 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
126 glEnable(GL_TEXTURE_2D);
127 if (gl_d3d_dev->unlock_tex == 0) {
128 glGenTextures(1, &gl_d3d_dev->unlock_tex);
129 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
136 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
139 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
140 glMatrixMode(GL_TEXTURE);
144 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
145 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
146 d3ddevice_set_ortho(d3d_dev);
149 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
150 glEnable(GL_SCISSOR_TEST);
151 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
152 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
153 glDepthRange(0.0, 1.0);
154 opt_bitmap |= DEPTH_RANGE_BIT;
156 if ((d3d_dev->active_viewport.dwX != 0) ||
157 (d3d_dev->active_viewport.dwY != 0) ||
158 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
159 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
160 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
161 opt_bitmap |= VIEWPORT_BIT;
163 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
164 pRect->right - pRect->left, pRect->bottom - pRect->top);
165 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
166 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
168 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
169 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
170 glAlphaFunc(GL_NOTEQUAL, 0.0);
172 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
174 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
175 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
176 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
177 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
178 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
183 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
184 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
186 /* And restore all the various states modified by this code */
187 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
188 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
189 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
190 glEnable(GL_ALPHA_TEST);
191 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
192 glDisable(GL_ALPHA_TEST);
194 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
195 glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
197 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
198 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
199 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
200 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
201 glDisable(GL_SCISSOR_TEST);
202 if (opt_bitmap & DEPTH_RANGE_BIT) {
203 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
205 if (opt_bitmap & VIEWPORT_BIT) {
206 glViewport(d3d_dev->active_viewport.dwX,
207 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
208 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
210 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
211 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
214 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
215 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
216 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
218 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
219 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
220 bind if ever the game changes the texture just after.
222 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
223 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
224 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
226 /* And re-enabled if needed texture level 1 */
227 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
228 (d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
229 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
230 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
231 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
233 glEnable(GL_TEXTURE_2D);
237 /* retrieve the X drawable to use on a given DC */
238 inline static Drawable get_drawable( HDC hdc )
241 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
243 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
244 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
249 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
251 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
252 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
254 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
256 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
257 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]);
259 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
260 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
261 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
268 /*******************************************************************************
269 * OpenGL static functions
271 static void set_context(IDirect3DDeviceImpl* This)
273 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
275 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
277 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
278 ERR("Error in setting current context (context %p drawable %ld)!\n",
279 glThis->gl_context, glThis->drawable);
284 static void fill_opengl_caps(D3DDEVICEDESC *d1)
286 d1->dwSize = sizeof(*d1);
287 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
288 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
289 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
290 d1->dcmColorModel = D3DCOLOR_RGB;
291 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
292 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
293 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
294 d1->bClipping = TRUE;
295 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
296 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
297 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
298 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
299 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
300 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
301 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
302 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
303 d1->dwMaxBufferSize = 0;
304 d1->dwMaxVertexCount = 65536;
305 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
306 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
307 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
308 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
309 d1->dwMinStippleWidth = 1;
310 d1->dwMinStippleHeight = 1;
311 d1->dwMaxStippleWidth = 32;
312 d1->dwMaxStippleHeight = 32;
313 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
314 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
315 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
316 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
317 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
318 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
319 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
320 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
321 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
322 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
323 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
324 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
325 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
328 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
330 *d = opengl_device_caps;
333 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
335 D3DDEVICEDESC dref, d1, d2;
338 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
339 Let's put the string in a sufficiently sized array in writable memory. */
340 char device_name[50];
341 strcpy(device_name,"direct3d");
343 fill_opengl_caps(&dref);
346 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
347 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
348 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
351 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
352 if (ret_value != D3DENUMRET_OK)
357 char interface_name[] = "WINE Direct3DX using OpenGL";
358 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
361 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
362 if (ret_value != D3DENUMRET_OK)
366 return D3DENUMRET_OK;
369 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
371 D3DDEVICEDESC7 ddesc;
372 char interface_name[] = "WINE Direct3D7 using OpenGL";
373 char device_name[] = "Wine D3D7 device";
375 fill_opengl_caps_7(&ddesc);
377 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
379 return cb(interface_name, device_name, &ddesc, context);
383 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
386 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
387 ULONG ref = InterlockedDecrement(&This->ref);
389 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
393 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
395 /* Release texture associated with the device */
396 for (i = 0; i < MAX_TEXTURES; i++) {
397 if (This->current_texture[i] != NULL)
398 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
399 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
402 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
403 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
404 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
405 surf->aux_ctx = NULL;
406 surf->aux_data = NULL;
407 surf->aux_flip = NULL;
411 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
412 IDirectDrawSurfaceImpl *surf2;
413 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
414 for (; surf2 != NULL; surf2 = surf2->next_attached) {
415 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
416 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
417 /* Override the Lock / Unlock function for all these surfaces */
418 surf2->lock_update = surf2->lock_update_prev;
419 surf2->unlock_update = surf2->unlock_update_prev;
420 /* And install also the blt / bltfast overrides */
421 surf2->aux_blt = NULL;
422 surf2->aux_bltfast = NULL;
424 surf2->d3ddevice = NULL;
428 /* And warn the D3D object that this device is no longer active... */
429 This->d3d->d3d_removed_device(This->d3d, This);
431 /* Free light arrays */
432 if (This->light_parameters)
433 HeapFree(GetProcessHeap(), 0, This->light_parameters);
434 HeapFree(GetProcessHeap(), 0, This->active_lights);
436 HeapFree(GetProcessHeap(), 0, This->world_mat);
437 HeapFree(GetProcessHeap(), 0, This->view_mat);
438 HeapFree(GetProcessHeap(), 0, This->proj_mat);
440 if (glThis->surface_ptr)
441 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
443 DeleteCriticalSection(&(This->crit));
446 if (glThis->unlock_tex)
447 glDeleteTextures(1, &(glThis->unlock_tex));
448 glXDestroyContext(glThis->display, glThis->gl_context);
450 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
452 HeapFree(GetProcessHeap(), 0, This);
459 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
460 LPD3DDEVICEDESC lpD3DHWDevDesc,
461 LPD3DDEVICEDESC lpD3DHELDevDesc)
463 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
467 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
469 fill_opengl_caps(&desc);
470 dwSize = lpD3DHWDevDesc->dwSize;
471 memset(lpD3DHWDevDesc, 0, dwSize);
472 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
474 dwSize = lpD3DHELDevDesc->dwSize;
475 memset(lpD3DHELDevDesc, 0, dwSize);
476 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
478 TRACE(" returning caps : (no dump function yet)\n");
483 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
484 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
485 LPVOID context, int version)
488 LPDDPIXELFORMAT pformat;
490 /* Do the texture enumeration */
491 sdesc.dwSize = sizeof(DDSURFACEDESC);
492 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
493 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
494 pformat = &(sdesc.ddpfPixelFormat);
495 pformat->dwSize = sizeof(DDPIXELFORMAT);
496 pformat->dwFourCC = 0;
498 TRACE("Enumerating GL_RGBA unpacked (32)\n");
499 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
500 pformat->u1.dwRGBBitCount = 32;
501 pformat->u2.dwRBitMask = 0x00FF0000;
502 pformat->u3.dwGBitMask = 0x0000FF00;
503 pformat->u4.dwBBitMask = 0x000000FF;
504 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
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 (32)\n");
509 pformat->dwFlags = DDPF_RGB;
510 pformat->u1.dwRGBBitCount = 32;
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 TRACE("Enumerating GL_RGB unpacked (24)\n");
519 pformat->dwFlags = DDPF_RGB;
520 pformat->u1.dwRGBBitCount = 24;
521 pformat->u2.dwRBitMask = 0x00FF0000;
522 pformat->u3.dwGBitMask = 0x0000FF00;
523 pformat->u4.dwBBitMask = 0x000000FF;
524 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
525 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
526 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
528 /* Note : even if this is an 'emulated' texture format, it needs to be first
529 as some dumb applications seem to rely on that. */
530 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
531 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
532 pformat->u1.dwRGBBitCount = 16;
533 pformat->u2.dwRBitMask = 0x00007C00;
534 pformat->u3.dwGBitMask = 0x000003E0;
535 pformat->u4.dwBBitMask = 0x0000001F;
536 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
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_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
541 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
542 pformat->u1.dwRGBBitCount = 16;
543 pformat->u2.dwRBitMask = 0x00000F00;
544 pformat->u3.dwGBitMask = 0x000000F0;
545 pformat->u4.dwBBitMask = 0x0000000F;
546 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
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_6_5 (16)\n");
551 pformat->dwFlags = DDPF_RGB;
552 pformat->u1.dwRGBBitCount = 16;
553 pformat->u2.dwRBitMask = 0x0000F800;
554 pformat->u3.dwGBitMask = 0x000007E0;
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;
560 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
561 pformat->dwFlags = DDPF_RGB;
562 pformat->u1.dwRGBBitCount = 16;
563 pformat->u2.dwRBitMask = 0x00007C00;
564 pformat->u3.dwGBitMask = 0x000003E0;
565 pformat->u4.dwBBitMask = 0x0000001F;
566 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
567 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
568 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
571 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
572 find enumerated, others the last one. And both want to have the ARGB one.
574 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
576 /* See argument about the RGBA format for 'packed' texture formats */
577 TRACE("Enumerating GL_RGBA unpacked (32)\n");
578 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
579 pformat->u1.dwRGBBitCount = 32;
580 pformat->u2.dwRBitMask = 0xFF000000;
581 pformat->u3.dwGBitMask = 0x00FF0000;
582 pformat->u4.dwBBitMask = 0x0000FF00;
583 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
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_4_4_4_4 (16)\n");
588 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
589 pformat->u1.dwRGBBitCount = 16;
590 pformat->u2.dwRBitMask = 0x0000F000;
591 pformat->u3.dwGBitMask = 0x00000F00;
592 pformat->u4.dwBBitMask = 0x000000F0;
593 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
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;
597 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
598 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
599 pformat->u1.dwRGBBitCount = 16;
600 pformat->u2.dwRBitMask = 0x0000F800;
601 pformat->u3.dwGBitMask = 0x000007C0;
602 pformat->u4.dwBBitMask = 0x0000003E;
603 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
604 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
605 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
608 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
609 pformat->dwFlags = DDPF_RGB;
610 pformat->u1.dwRGBBitCount = 8;
611 pformat->u2.dwRBitMask = 0x000000E0;
612 pformat->u3.dwGBitMask = 0x0000001C;
613 pformat->u4.dwBBitMask = 0x00000003;
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 TRACE("Enumerating Paletted (8)\n");
619 pformat->dwFlags = DDPF_PALETTEINDEXED8;
620 pformat->u1.dwRGBBitCount = 8;
621 pformat->u2.dwRBitMask = 0x00000000;
622 pformat->u3.dwGBitMask = 0x00000000;
623 pformat->u4.dwBBitMask = 0x00000000;
624 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
625 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
626 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
628 /* DXT textures only exist for devices created from IDirect3D3 and above */
629 if ((version >= 3) && GL_extensions.s3tc_compressed_texture) {
630 TRACE("Enumerating DXT1\n");
631 pformat->dwFlags = DDPF_FOURCC;
632 pformat->dwFourCC = MAKE_FOURCC('D','X','T','1');
633 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
634 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
636 TRACE("Enumerating DXT3\n");
637 pformat->dwFlags = DDPF_FOURCC;
638 pformat->dwFourCC = MAKE_FOURCC('D','X','T','3');
639 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
640 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
642 TRACE("Enumerating DXT5\n");
643 pformat->dwFlags = DDPF_FOURCC;
644 pformat->dwFourCC = MAKE_FOURCC('D','X','T','5');
645 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
646 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
649 TRACE("End of enumeration\n");
655 d3ddevice_find(IDirectDrawImpl *d3d,
656 LPD3DFINDDEVICESEARCH lpD3DDFS,
657 LPD3DFINDDEVICERESULT lplpD3DDevice)
661 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
662 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
663 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
664 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
666 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
667 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
668 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
669 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
670 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
671 TRACE(" no match for this GUID.\n");
672 return DDERR_INVALIDPARAMS;
676 /* Now return our own GUID */
677 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
678 fill_opengl_caps(&desc);
679 lplpD3DDevice->ddHwDesc = desc;
680 lplpD3DDevice->ddSwDesc = desc;
682 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
688 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
689 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
692 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
693 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
694 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg, This->version);
698 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
699 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
702 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
703 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
704 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg, This->version);
708 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
709 D3DRENDERSTATETYPE dwRenderStateType,
712 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
713 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
715 /* Call the render state functions */
716 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
717 set_render_state(This, dwRenderStateType, &This->state_block);
723 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
724 D3DRENDERSTATETYPE dwRenderStateType,
725 LPDWORD lpdwRenderState)
727 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
728 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
730 /* Call the render state functions */
731 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
733 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
739 GL_IDirect3DDeviceImpl_3_2T_GetLightState(LPDIRECT3DDEVICE3 iface,
740 D3DLIGHTSTATETYPE dwLightStateType,
741 LPDWORD lpdwLightState)
743 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
745 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwLightStateType, lpdwLightState);
747 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
748 TRACE("Unexpected Light State Type\n");
749 return DDERR_INVALIDPARAMS;
752 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
753 *lpdwLightState = This->material;
754 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
755 *lpdwLightState = D3DCOLOR_RGB;
757 D3DRENDERSTATETYPE rs;
758 switch (dwLightStateType) {
759 case D3DLIGHTSTATE_AMBIENT: /* 2 */
760 rs = D3DRENDERSTATE_AMBIENT;
762 case D3DLIGHTSTATE_FOGMODE: /* 4 */
763 rs = D3DRENDERSTATE_FOGVERTEXMODE;
765 case D3DLIGHTSTATE_FOGSTART: /* 5 */
766 rs = D3DRENDERSTATE_FOGSTART;
768 case D3DLIGHTSTATE_FOGEND: /* 6 */
769 rs = D3DRENDERSTATE_FOGEND;
771 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
772 rs = D3DRENDERSTATE_FOGDENSITY;
774 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
775 rs = D3DRENDERSTATE_COLORVERTEX;
778 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
779 return DDERR_INVALIDPARAMS;
782 IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
790 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
791 D3DLIGHTSTATETYPE dwLightStateType,
794 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
796 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
798 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
799 TRACE("Unexpected Light State Type\n");
800 return DDERR_INVALIDPARAMS;
803 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
804 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
807 TRACE(" activating material %p.\n", mat);
810 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
812 This->material = dwLightState;
813 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
814 switch (dwLightState) {
816 ERR("DDCOLOR_MONO should not happen!\n");
819 /* We are already in this mode */
820 TRACE("Setting color model to RGB (no-op).\n");
823 ERR("Unknown color model!\n");
824 return DDERR_INVALIDPARAMS;
827 D3DRENDERSTATETYPE rs;
828 switch (dwLightStateType) {
829 case D3DLIGHTSTATE_AMBIENT: /* 2 */
830 rs = D3DRENDERSTATE_AMBIENT;
832 case D3DLIGHTSTATE_FOGMODE: /* 4 */
833 rs = D3DRENDERSTATE_FOGVERTEXMODE;
835 case D3DLIGHTSTATE_FOGSTART: /* 5 */
836 rs = D3DRENDERSTATE_FOGSTART;
838 case D3DLIGHTSTATE_FOGEND: /* 6 */
839 rs = D3DRENDERSTATE_FOGEND;
841 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
842 rs = D3DRENDERSTATE_FOGDENSITY;
844 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
845 rs = D3DRENDERSTATE_COLORVERTEX;
848 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
849 return DDERR_INVALIDPARAMS;
852 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
859 static GLenum convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt)
862 case D3DPT_POINTLIST:
863 TRACE(" primitive type is POINTS\n");
867 TRACE(" primitive type is LINES\n");
870 case D3DPT_LINESTRIP:
871 TRACE(" primitive type is LINE_STRIP\n");
872 return GL_LINE_STRIP;
874 case D3DPT_TRIANGLELIST:
875 TRACE(" primitive type is TRIANGLES\n");
878 case D3DPT_TRIANGLESTRIP:
879 TRACE(" primitive type is TRIANGLE_STRIP\n");
880 return GL_TRIANGLE_STRIP;
882 case D3DPT_TRIANGLEFAN:
883 TRACE(" primitive type is TRIANGLE_FAN\n");
884 return GL_TRIANGLE_FAN;
887 FIXME("Unhandled primitive %08x\n", d3dpt);
892 /* This function calculate the Z coordinate from Zproj */
893 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
896 /* Assume that X = Y = 0 and W = 1 */
897 a = This->proj_mat->_33;
898 b = This->proj_mat->_34;
899 c = This->proj_mat->_43;
900 d = This->proj_mat->_44;
901 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
902 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
903 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
905 return (d*Zproj - c) / (a - b*Zproj);
908 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
911 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
913 for (i = 0; i < 3; i++) {
914 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
916 for (elt = 0; elt < 0x10000; elt++) {
917 /* We apply the fog transformation and cache the result */
918 DWORD fog_intensity = elt & 0xFF;
919 DWORD vertex_color = (elt >> 8) & 0xFF;
920 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
925 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
926 BOOLEAN vertex_transformed,
927 BOOLEAN vertex_lit) {
928 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
930 /* Puts GL in the correct lighting / transformation mode */
931 if ((vertex_transformed == FALSE) &&
932 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
933 /* Need to put the correct transformation again if we go from Transformed
934 vertices to non-transformed ones.
936 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
937 This->world_mat, This->view_mat, This->proj_mat);
938 glThis->transform_state = GL_TRANSFORM_NORMAL;
940 } else if (vertex_transformed &&
941 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
942 /* Set our orthographic projection */
943 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
944 glThis->transform_state = GL_TRANSFORM_ORTHO;
945 d3ddevice_set_ortho(This);
949 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
950 if no fogging state change occurred */
951 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1]) {
952 if (vertex_transformed) {
953 if (glThis->fogging != 0) {
957 /* Now check if our fog_table still corresponds to the current vertex color.
958 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
959 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
960 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
961 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
962 /* We need to rebuild our fog table.... */
963 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
966 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
967 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
968 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
969 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
970 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
972 if (vertex_lit == FALSE) {
973 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
974 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
976 /* Special case of 'pixel fog' */
977 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
978 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
980 if (glThis->fogging == 0) {
985 if (glThis->fogging != 0) {
992 if (glThis->fogging != 0) {
998 /* Handle the 'no-normal' case */
999 if ((vertex_lit == FALSE) && This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1]) {
1000 if (glThis->lighting == 0) {
1001 glEnable(GL_LIGHTING);
1002 glThis->lighting = 1;
1005 if (glThis->lighting != 0) {
1006 glDisable(GL_LIGHTING);
1007 glThis->lighting = 0;
1011 /* Handle the code for pre-vertex material properties */
1012 if (vertex_transformed == FALSE) {
1013 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1014 This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
1015 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1016 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1017 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1018 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
1019 glEnable(GL_COLOR_MATERIAL);
1026 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1027 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1029 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1032 case D3DVT_VERTEX: {
1033 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1034 strided.position.dwStride = sizeof(D3DVERTEX);
1035 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1036 strided.normal.dwStride = sizeof(D3DVERTEX);
1037 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1038 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1039 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1042 case D3DVT_LVERTEX: {
1043 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1044 strided.position.dwStride = sizeof(D3DLVERTEX);
1045 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1046 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1047 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1048 strided.specular.dwStride = sizeof(D3DLVERTEX);
1049 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1050 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1051 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1054 case D3DVT_TLVERTEX: {
1055 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1056 strided.position.dwStride = sizeof(D3DTLVERTEX);
1057 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1058 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1059 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1060 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1061 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1062 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1063 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1067 FIXME("Unhandled vertex type %08x\n", d3dvt);
1073 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1074 D3DPRIMITIVETYPE d3dptPrimitiveType,
1075 D3DVERTEXTYPE d3dvtVertexType,
1077 DWORD dwVertexCount,
1080 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1082 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1083 if (TRACE_ON(ddraw)) {
1084 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1087 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1093 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1094 D3DPRIMITIVETYPE d3dptPrimitiveType,
1095 D3DVERTEXTYPE d3dvtVertexType,
1097 DWORD dwVertexCount,
1102 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1103 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1104 if (TRACE_ON(ddraw)) {
1105 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1108 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1114 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1115 LPD3DEXECUTEBUFFERDESC lpDesc,
1116 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1117 IUnknown* pUnkOuter)
1119 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1120 IDirect3DExecuteBufferImpl *ret;
1123 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1125 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1126 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1128 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1133 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1134 static BOOLEAN first = TRUE;
1135 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1140 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1144 TRACE("flushing ZBuffer back to GL\n");
1146 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1147 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1148 d3ddevice_set_ortho(d3d_dev);
1151 glMatrixMode(GL_MODELVIEW);
1154 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1155 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1156 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1158 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1161 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1162 case 16: type = GL_UNSIGNED_SHORT; break;
1163 case 32: type = GL_UNSIGNED_INT; break;
1164 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1167 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1168 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1169 glRasterPos2i(0, row + 1);
1170 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1171 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1175 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1176 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1177 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1178 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1181 /* These are the various handler used in the generic path */
1182 inline static void handle_xyz(D3DVALUE *coords) {
1183 glVertex3fv(coords);
1185 inline static void handle_xyzrhw(D3DVALUE *coords) {
1186 if ((coords[3] < 1e-8) && (coords[3] > -1e-8))
1187 glVertex3fv(coords);
1189 GLfloat w = 1.0 / coords[3];
1191 glVertex4f(coords[0] * w,
1197 inline static void handle_normal(D3DVALUE *coords) {
1198 glNormal3fv(coords);
1201 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1202 if (sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] ||
1203 sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1]) {
1204 glColor4ub((*color >> 16) & 0xFF,
1205 (*color >> 8) & 0xFF,
1206 (*color >> 0) & 0xFF,
1207 (*color >> 24) & 0xFF);
1209 glColor3ub((*color >> 16) & 0xFF,
1210 (*color >> 8) & 0xFF,
1211 (*color >> 0) & 0xFF);
1215 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1216 glColor4ub((*color >> 16) & 0xFF,
1217 (*color >> 8) & 0xFF,
1218 (*color >> 0) & 0xFF,
1219 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1222 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1223 if ((lighted == FALSE) &&
1224 sb->render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1225 sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
1226 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1227 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1228 handle_diffuse_base(sb, color);
1230 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1231 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1232 handle_diffuse_base(sb, color);
1234 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1235 sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
1236 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1237 handle_diffuse_base(sb, color);
1239 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1240 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1241 handle_diffuse_base(sb, color);
1244 handle_diffuse_base(sb, color);
1248 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1249 if ((lighted == FALSE) &&
1250 sb->render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1251 sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
1252 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1253 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1254 handle_specular_base(sb, color);
1256 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1257 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1258 handle_specular_base(sb, color);
1260 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1261 sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
1262 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1263 handle_specular_base(sb, color);
1265 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1266 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1267 handle_specular_base(sb, color);
1270 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1273 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1275 DWORD color = *color_d;
1276 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1]) {
1277 /* Special case where the specular value is used to do fogging */
1278 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1279 color &= 0xFF000000; /* Only keep the alpha component */
1280 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1281 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1282 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1284 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
1285 /* Standard specular value in transformed mode. TODO */
1287 handle_diffuse_base(sb, &color);
1289 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1]) {
1290 handle_diffuse(sb, color_d, FALSE);
1291 handle_specular(sb, color_s, FALSE);
1293 /* In that case, only put the diffuse color... */
1294 handle_diffuse_base(sb, color_d);
1299 inline static void handle_texture(D3DVALUE *coords) {
1300 glTexCoord2fv(coords);
1302 inline static void handle_textures(const D3DVALUE *coords, int tex_stage) {
1303 if (GL_extensions.glMultiTexCoord2fv) {
1304 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1306 if (tex_stage == 0) glTexCoord2fv(coords);
1310 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1311 D3DPRIMITIVETYPE d3dptPrimitiveType,
1312 DWORD d3dvtVertexType,
1313 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1314 DWORD dwVertexCount,
1319 BOOLEAN vertex_lighted = FALSE;
1320 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1321 int num_active_stages = 0;
1322 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1324 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1325 if (TRACE_ON(ddraw)) {
1326 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1329 /* This is to prevent 'thread contention' between a thread locking the device and another
1330 doing 3D display on it... */
1331 EnterCriticalSection(&(This->crit));
1334 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1335 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1337 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1339 if (This->current_zbuffer == NULL) {
1340 /* Search for an attached ZBuffer */
1341 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1342 LPDIRECTDRAWSURFACE7 zbuf;
1345 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1346 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1348 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1349 IDirectDrawSurface7_Release(zbuf);
1352 if (This->current_zbuffer != NULL) {
1353 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1354 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1358 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1359 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1360 vertex_lighted = TRUE;
1362 /* Compute the number of active texture stages and set the various texture parameters */
1363 num_active_stages = draw_primitive_handle_textures(This);
1365 /* And restore to handle '0' in the case we use glTexCoord calls */
1366 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1367 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1368 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1371 draw_primitive_handle_GL_state(This,
1372 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1375 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1376 for now to some 'special' cases where we can do a direct mapping between D3D
1379 Note: in the future all calls will go through vertex arrays but the arrays
1380 will be generated by this function.
1382 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1383 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1384 which, as we are little indian, gives a B, G, R, A storage in memory.
1386 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1387 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
1389 TRACE(" using GL vertex arrays for performance !\n");
1390 /* First, the vertices (we are sure we have some :-) */
1391 glEnableClientState(GL_VERTEX_ARRAY);
1392 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1393 /* Then the normals */
1394 if (d3dvtVertexType & D3DFVF_NORMAL) {
1395 glEnableClientState(GL_NORMAL_ARRAY);
1396 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1398 /* Then the diffuse colour */
1399 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1400 glEnableClientState(GL_COLOR_ARRAY);
1401 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1402 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1404 /* Then the various textures */
1405 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1406 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1407 if (tex_index >= num_tex_index) {
1408 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1409 tex_index = num_tex_index - 1;
1411 if (GL_extensions.glClientActiveTexture) {
1412 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1414 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1415 glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1416 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1418 if (dwIndices != NULL) {
1419 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1421 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1423 glDisableClientState(GL_VERTEX_ARRAY);
1424 if (d3dvtVertexType & D3DFVF_NORMAL) {
1425 glDisableClientState(GL_NORMAL_ARRAY);
1427 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1428 glDisableClientState(GL_COLOR_ARRAY);
1430 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1431 if (GL_extensions.glClientActiveTexture) {
1432 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1434 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1437 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1439 /* Some fast paths first before the generic case.... */
1440 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1443 for (index = 0; index < dwIndexCount; index++) {
1444 int i = (dwIndices == NULL) ? index : dwIndices[index];
1446 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1447 D3DVALUE *tex_coord =
1448 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1449 D3DVALUE *position =
1450 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1452 handle_normal(normal);
1453 handle_texture(tex_coord);
1454 handle_xyz(position);
1456 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1457 position[0], position[1], position[2],
1458 normal[0], normal[1], normal[2],
1459 tex_coord[0], tex_coord[1]);
1461 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1464 for (index = 0; index < dwIndexCount; index++) {
1465 int i = (dwIndices == NULL) ? index : dwIndices[index];
1467 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1469 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1470 D3DVALUE *tex_coord =
1471 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1472 D3DVALUE *position =
1473 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1475 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1476 handle_texture(tex_coord);
1477 handle_xyzrhw(position);
1479 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1480 position[0], position[1], position[2], position[3],
1481 (*color_d >> 16) & 0xFF,
1482 (*color_d >> 8) & 0xFF,
1483 (*color_d >> 0) & 0xFF,
1484 (*color_d >> 24) & 0xFF,
1485 (*color_s >> 16) & 0xFF,
1486 (*color_s >> 8) & 0xFF,
1487 (*color_s >> 0) & 0xFF,
1488 (*color_s >> 24) & 0xFF,
1489 tex_coord[0], tex_coord[1]);
1491 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1492 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1493 /* This is the 'slow path' but that should support all possible vertex formats out there...
1494 Note that people should write a fast path for all vertex formats out there...
1497 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1499 for (index = 0; index < dwIndexCount; index++) {
1500 int i = (dwIndices == NULL) ? index : dwIndices[index];
1503 if (d3dvtVertexType & D3DFVF_NORMAL) {
1505 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1506 handle_normal(normal);
1508 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1510 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1512 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1513 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1515 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1517 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1518 handle_specular(&(This->state_block), color_s, vertex_lighted);
1519 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1521 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1522 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1526 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1527 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1528 if (tex_index >= num_tex_index) {
1529 handle_textures((const D3DVALUE *) no_index, tex_stage);
1531 D3DVALUE *tex_coord =
1532 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1533 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1534 handle_textures(tex_coord, tex_stage);
1538 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1539 D3DVALUE *position =
1540 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1541 handle_xyz(position);
1542 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1543 D3DVALUE *position =
1544 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1545 handle_xyzrhw(position);
1548 if (TRACE_ON(ddraw_geom)) {
1549 unsigned int tex_index;
1551 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1552 D3DVALUE *position =
1553 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1554 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1555 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1556 D3DVALUE *position =
1557 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1558 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1560 if (d3dvtVertexType & D3DFVF_NORMAL) {
1562 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1563 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1565 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1567 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1568 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1569 (*color_d >> 16) & 0xFF,
1570 (*color_d >> 8) & 0xFF,
1571 (*color_d >> 0) & 0xFF,
1572 (*color_d >> 24) & 0xFF);
1574 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1576 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1577 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1578 (*color_s >> 16) & 0xFF,
1579 (*color_s >> 8) & 0xFF,
1580 (*color_s >> 0) & 0xFF,
1581 (*color_s >> 24) & 0xFF);
1583 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1584 D3DVALUE *tex_coord =
1585 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1586 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1587 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1589 TRACE_(ddraw_geom)("\n");
1593 ERR(" matrix weighting not handled yet....\n");
1599 /* Whatever the case, disable the color material stuff */
1600 glDisable(GL_COLOR_MATERIAL);
1605 LeaveCriticalSection(&(This->crit));
1609 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1610 D3DPRIMITIVETYPE d3dptPrimitiveType,
1611 DWORD d3dvtVertexType,
1613 DWORD dwVertexCount,
1616 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1617 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1619 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1620 if (TRACE_ON(ddraw)) {
1621 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1624 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1625 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1631 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1632 D3DPRIMITIVETYPE d3dptPrimitiveType,
1633 DWORD d3dvtVertexType,
1635 DWORD dwVertexCount,
1640 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1641 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1643 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1644 if (TRACE_ON(ddraw)) {
1645 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1648 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1649 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1655 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1656 D3DPRIMITIVETYPE d3dptPrimitiveType,
1658 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1659 DWORD dwVertexCount,
1662 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1664 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1665 if (TRACE_ON(ddraw)) {
1666 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1668 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1674 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1675 D3DPRIMITIVETYPE d3dptPrimitiveType,
1677 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1678 DWORD dwVertexCount,
1683 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1685 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1686 if (TRACE_ON(ddraw)) {
1687 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1690 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1696 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1697 D3DPRIMITIVETYPE d3dptPrimitiveType,
1698 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1699 DWORD dwStartVertex,
1700 DWORD dwNumVertices,
1703 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1704 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1705 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1707 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1708 if (TRACE_ON(ddraw)) {
1709 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1712 if (vb_impl->processed) {
1713 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1714 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1716 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1717 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1718 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1720 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1721 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1724 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1725 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1732 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1733 D3DPRIMITIVETYPE d3dptPrimitiveType,
1734 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1735 DWORD dwStartVertex,
1736 DWORD dwNumVertices,
1741 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1742 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1743 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1745 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1746 if (TRACE_ON(ddraw)) {
1747 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1750 if (vb_impl->processed) {
1751 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1752 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1754 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1755 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1756 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1758 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1759 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1762 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1763 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1769 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1771 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1773 BOOLEAN is_complement = FALSE;
1774 BOOLEAN is_alpha_replicate = FALSE;
1775 BOOLEAN handled = TRUE;
1777 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1781 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1782 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1787 if (tex_op == D3DTOP_SELECTARG2) {
1791 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1792 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1797 if (tex_op == D3DTOP_SELECTARG2) {
1802 if (dwState & D3DTA_COMPLEMENT) {
1803 is_complement = TRUE;
1805 if (dwState & D3DTA_ALPHAREPLICATE) {
1806 is_alpha_replicate = TRUE;
1808 dwState &= D3DTA_SELECTMASK;
1809 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1810 dwState = D3DTA_DIFFUSE;
1814 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1815 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1816 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1817 case D3DTA_TFACTOR: {
1818 /* Get the constant value from the current rendering state */
1820 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1822 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1823 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1824 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1825 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1826 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1828 src = GL_CONSTANT_EXT;
1830 default: src = GL_TEXTURE; handled = FALSE; break;
1834 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1835 if (is_alpha_replicate) {
1836 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1838 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1841 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1842 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1849 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1851 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1854 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1855 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1860 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1862 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1863 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1867 unit = GL_TEXTURE0_WINE + dwStage;
1868 if (unit != glThis->current_active_tex_unit) {
1869 GL_extensions.glActiveTexture(unit);
1870 glThis->current_active_tex_unit = unit;
1873 switch (d3dTexStageStateType) {
1874 #define GEN_CASE(a) case a: type = #a; break
1875 GEN_CASE(D3DTSS_COLOROP);
1876 GEN_CASE(D3DTSS_COLORARG1);
1877 GEN_CASE(D3DTSS_COLORARG2);
1878 GEN_CASE(D3DTSS_ALPHAOP);
1879 GEN_CASE(D3DTSS_ALPHAARG1);
1880 GEN_CASE(D3DTSS_ALPHAARG2);
1881 GEN_CASE(D3DTSS_BUMPENVMAT00);
1882 GEN_CASE(D3DTSS_BUMPENVMAT01);
1883 GEN_CASE(D3DTSS_BUMPENVMAT10);
1884 GEN_CASE(D3DTSS_BUMPENVMAT11);
1885 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1886 GEN_CASE(D3DTSS_ADDRESS);
1887 GEN_CASE(D3DTSS_ADDRESSU);
1888 GEN_CASE(D3DTSS_ADDRESSV);
1889 GEN_CASE(D3DTSS_BORDERCOLOR);
1890 GEN_CASE(D3DTSS_MAGFILTER);
1891 GEN_CASE(D3DTSS_MINFILTER);
1892 GEN_CASE(D3DTSS_MIPFILTER);
1893 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1894 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1895 GEN_CASE(D3DTSS_MAXANISOTROPY);
1896 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1897 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1898 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1900 default: type = "UNKNOWN";
1903 /* Store the values in the state array */
1904 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1905 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1906 /* Some special cases when one state modifies more than one... */
1907 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1908 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1909 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1914 switch (d3dTexStageStateType) {
1915 case D3DTSS_MINFILTER:
1916 case D3DTSS_MIPFILTER:
1917 if (TRACE_ON(ddraw)) {
1918 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1919 switch ((D3DTEXTUREMINFILTER) dwState) {
1920 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1921 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1922 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1925 switch ((D3DTEXTUREMIPFILTER) dwState) {
1926 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1927 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1928 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1929 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1935 case D3DTSS_MAGFILTER:
1936 if (TRACE_ON(ddraw)) {
1937 switch ((D3DTEXTUREMAGFILTER) dwState) {
1938 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1939 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1940 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1945 case D3DTSS_ADDRESS:
1946 case D3DTSS_ADDRESSU:
1947 case D3DTSS_ADDRESSV: {
1948 switch ((D3DTEXTUREADDRESS) dwState) {
1949 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1950 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1951 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1952 case D3DTADDRESS_MIRROR:
1953 if (GL_extensions.mirrored_repeat) {
1954 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1956 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1959 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1963 case D3DTSS_ALPHAOP:
1964 case D3DTSS_COLOROP: {
1966 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1971 #define GEN_CASE(a) case a: value = #a; break
1972 GEN_CASE(D3DTOP_DISABLE);
1973 GEN_CASE(D3DTOP_SELECTARG1);
1974 GEN_CASE(D3DTOP_SELECTARG2);
1975 GEN_CASE(D3DTOP_MODULATE);
1976 GEN_CASE(D3DTOP_MODULATE2X);
1977 GEN_CASE(D3DTOP_MODULATE4X);
1978 GEN_CASE(D3DTOP_ADD);
1979 GEN_CASE(D3DTOP_ADDSIGNED);
1980 GEN_CASE(D3DTOP_ADDSIGNED2X);
1981 GEN_CASE(D3DTOP_SUBTRACT);
1982 GEN_CASE(D3DTOP_ADDSMOOTH);
1983 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1984 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1985 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1986 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1987 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1988 GEN_CASE(D3DTOP_PREMODULATE);
1989 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1990 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1991 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1992 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1993 GEN_CASE(D3DTOP_BUMPENVMAP);
1994 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1995 GEN_CASE(D3DTOP_DOTPRODUCT3);
1996 GEN_CASE(D3DTOP_FORCE_DWORD);
1998 default: value = "UNKNOWN";
2001 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
2002 glDisable(GL_TEXTURE_2D);
2003 TRACE(" disabling 2D texturing.\n");
2005 /* Re-enable texturing only if COLOROP was not already disabled... */
2006 if ((glThis->current_bound_texture[dwStage] != NULL) &&
2007 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
2008 glEnable(GL_TEXTURE_2D);
2009 TRACE(" enabling 2D texturing.\n");
2012 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
2013 if ((dwState != D3DTOP_DISABLE) &&
2014 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
2015 if (glThis->current_tex_env != GL_COMBINE_EXT) {
2016 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
2017 glThis->current_tex_env = GL_COMBINE_EXT;
2021 /* Now set up the operand correctly */
2023 case D3DTOP_DISABLE:
2024 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2025 and it works, so ignore this op */
2026 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2029 case D3DTOP_SELECTARG1:
2030 case D3DTOP_SELECTARG2:
2031 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2034 case D3DTOP_MODULATE4X:
2035 scale = scale * 2; /* Drop through */
2036 case D3DTOP_MODULATE2X:
2037 scale = scale * 2; /* Drop through */
2038 case D3DTOP_MODULATE:
2039 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2043 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2046 case D3DTOP_ADDSIGNED2X:
2047 scale = scale * 2; /* Drop through */
2048 case D3DTOP_ADDSIGNED:
2049 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2052 /* For the four blending modes, use the Arg2 parameter */
2053 case D3DTOP_BLENDDIFFUSEALPHA:
2054 case D3DTOP_BLENDTEXTUREALPHA:
2055 case D3DTOP_BLENDFACTORALPHA:
2056 case D3DTOP_BLENDCURRENTALPHA: {
2057 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2060 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2061 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2062 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2063 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2066 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2067 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2068 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2069 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2070 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2079 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2080 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2081 /* Switch the arguments if needed... */
2082 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2083 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2084 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2086 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2087 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2090 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2091 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2093 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2094 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2100 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2101 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2103 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2105 TRACE(" Stage type is : %s => %s\n", type, value);
2107 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2111 case D3DTSS_COLORARG1:
2112 case D3DTSS_COLORARG2:
2113 case D3DTSS_ALPHAARG1:
2114 case D3DTSS_ALPHAARG2: {
2115 const char *value, *value_comp = "", *value_alpha = "";
2117 D3DTEXTUREOP tex_op;
2119 switch (dwState & D3DTA_SELECTMASK) {
2120 #define GEN_CASE(a) case a: value = #a; break
2121 GEN_CASE(D3DTA_DIFFUSE);
2122 GEN_CASE(D3DTA_CURRENT);
2123 GEN_CASE(D3DTA_TEXTURE);
2124 GEN_CASE(D3DTA_TFACTOR);
2125 GEN_CASE(D3DTA_SPECULAR);
2127 default: value = "UNKNOWN";
2129 if (dwState & D3DTA_COMPLEMENT) {
2130 value_comp = " | D3DTA_COMPLEMENT";
2132 if (dwState & D3DTA_ALPHAREPLICATE) {
2133 value_alpha = " | D3DTA_ALPHAREPLICATE";
2136 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2137 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2139 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2142 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2145 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2147 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2151 case D3DTSS_MIPMAPLODBIAS: {
2152 D3DVALUE value = *((D3DVALUE *) &dwState);
2153 BOOLEAN handled = TRUE;
2155 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2159 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2160 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2162 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2166 case D3DTSS_MAXMIPLEVEL:
2167 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2170 case D3DTSS_BORDERCOLOR:
2171 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2172 ((dwState >> 16) & 0xFF),
2173 ((dwState >> 8) & 0xFF),
2174 ((dwState >> 0) & 0xFF),
2175 ((dwState >> 24) & 0xFF));
2178 case D3DTSS_TEXCOORDINDEX: {
2179 BOOLEAN handled = TRUE;
2182 switch (dwState & 0xFFFF0000) {
2183 #define GEN_CASE(a) case a: value = #a; break
2184 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2185 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2186 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2187 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2189 default: value = "UNKNOWN";
2191 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2195 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2197 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2201 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2202 const char *projected = "", *value;
2203 BOOLEAN handled = TRUE;
2204 switch (dwState & 0xFF) {
2205 #define GEN_CASE(a) case a: value = #a; break
2206 GEN_CASE(D3DTTFF_DISABLE);
2207 GEN_CASE(D3DTTFF_COUNT1);
2208 GEN_CASE(D3DTTFF_COUNT2);
2209 GEN_CASE(D3DTTFF_COUNT3);
2210 GEN_CASE(D3DTTFF_COUNT4);
2212 default: value = "UNKNOWN";
2214 if (dwState & D3DTTFF_PROJECTED) {
2215 projected = " | D3DTTFF_PROJECTED";
2219 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2220 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2224 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2226 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2231 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2241 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2243 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2245 BOOLEAN enable_colorkey = FALSE;
2247 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2248 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2251 /* If this stage is disabled, no need to go further... */
2252 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2255 /* First check if we need to bind any other texture for this stage */
2256 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2257 if (This->current_texture[stage] == NULL) {
2258 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2260 unit = GL_TEXTURE0_WINE + stage;
2261 if (unit != glThis->current_active_tex_unit) {
2262 GL_extensions.glActiveTexture(unit);
2263 glThis->current_active_tex_unit = unit;
2265 glBindTexture(GL_TEXTURE_2D, 0);
2266 glDisable(GL_TEXTURE_2D);
2268 GLenum tex_name = gltex_get_tex_name(surf_ptr);
2270 unit = GL_TEXTURE0_WINE + stage;
2271 if (unit != glThis->current_active_tex_unit) {
2272 GL_extensions.glActiveTexture(unit);
2273 glThis->current_active_tex_unit = unit;
2276 if (glThis->current_bound_texture[stage] == NULL) {
2277 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2278 TRACE(" enabling 2D texturing and");
2279 glEnable(GL_TEXTURE_2D);
2282 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2283 glBindTexture(GL_TEXTURE_2D, tex_name);
2286 glThis->current_bound_texture[stage] = This->current_texture[stage];
2288 if (glThis->current_bound_texture[stage] == NULL) {
2289 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2291 TRACE(" using already bound texture id %d for stage %ld.\n",
2292 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2296 /* If no texure valid for this stage, go out of the loop */
2297 if (This->current_texture[stage] == NULL) break;
2299 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2300 This will also update the various texture parameters if needed.
2302 gltex_upload_texture(surf_ptr, This, stage);
2304 /* And finally check for color-keying (only on first stage) */
2305 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2307 enable_colorkey = TRUE;
2309 static BOOL warn = FALSE;
2310 if (warn == FALSE) {
2312 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2317 enable_colorkey = FALSE;
2322 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2323 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2324 (glThis->parent.version == 1)) &&
2325 (enable_colorkey)) {
2326 TRACE(" colorkey activated.\n");
2328 if (glThis->alpha_test == FALSE) {
2329 glEnable(GL_ALPHA_TEST);
2330 glThis->alpha_test = TRUE;
2332 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2333 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1]) {
2334 static BOOL warn = FALSE;
2335 if (warn == FALSE) {
2337 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2340 glThis->current_alpha_test_func = GL_NOTEQUAL;
2341 glThis->current_alpha_test_ref = 0.0;
2342 glAlphaFunc(GL_NOTEQUAL, 0.0);
2344 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2345 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2347 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2348 glDisable(GL_ALPHA_TEST);
2349 glThis->alpha_test = FALSE;
2351 /* Maybe we should restore here the application-given alpha test states ? */
2358 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2360 LPDIRECTDRAWSURFACE7 lpTexture2)
2362 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2364 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2366 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2367 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2368 if (lpTexture2 != NULL) {
2369 WARN(" setting a texture to a non-supported texture stage !\n");
2374 if (This->current_texture[dwStage] != NULL) {
2375 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2378 if (lpTexture2 == NULL) {
2379 This->current_texture[dwStage] = NULL;
2381 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2382 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2383 This->current_texture[dwStage] = tex_impl;
2390 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2391 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2393 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2394 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2396 fill_opengl_caps_7(lpD3DHELDevDesc);
2398 TRACE(" returning caps : no dump function yet.\n");
2404 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2405 LPD3DMATERIAL7 lpMat)
2407 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2408 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2410 if (TRACE_ON(ddraw)) {
2411 TRACE(" material is : \n");
2412 dump_D3DMATERIAL7(lpMat);
2415 This->current_material = *lpMat;
2418 glMaterialfv(GL_FRONT_AND_BACK,
2420 (float *) &(This->current_material.u.diffuse));
2421 glMaterialfv(GL_FRONT_AND_BACK,
2423 (float *) &(This->current_material.u1.ambient));
2424 glMaterialfv(GL_FRONT_AND_BACK,
2426 (float *) &(This->current_material.u2.specular));
2427 glMaterialfv(GL_FRONT_AND_BACK,
2429 (float *) &(This->current_material.u3.emissive));
2430 glMaterialf(GL_FRONT_AND_BACK,
2432 This->current_material.u4.power); /* Not sure about this... */
2438 static LPD3DLIGHT7 get_light(IDirect3DDeviceImpl *This, DWORD dwLightIndex)
2440 if (dwLightIndex >= This->num_set_lights)
2442 /* Extend, or allocate the light parameters array. */
2443 DWORD newlightnum = dwLightIndex + 1;
2444 LPD3DLIGHT7 newarrayptr = NULL;
2446 if (This->light_parameters)
2447 newarrayptr = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2448 This->light_parameters, newlightnum * sizeof(D3DLIGHT7));
2450 newarrayptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2451 newlightnum * sizeof(D3DLIGHT7));
2456 This->light_parameters = newarrayptr;
2457 This->num_set_lights = newlightnum;
2460 return &This->light_parameters[dwLightIndex];
2464 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2466 LPD3DLIGHT7 lpLight)
2468 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2469 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2470 LPD3DLIGHT7 lpdestlight = get_light( This, dwLightIndex );
2472 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2474 if (TRACE_ON(ddraw)) {
2475 TRACE(" setting light : \n");
2476 dump_D3DLIGHT7(lpLight);
2479 /* DirectX7 documentation states that this function can return
2480 DDERR_OUTOFMEMORY, so we do just that in case of an allocation
2481 error (which is the only reason why get_light() can fail). */
2483 return DDERR_OUTOFMEMORY;
2485 *lpdestlight = *lpLight;
2487 /* Some checks to print out nice warnings :-) */
2488 switch (lpLight->dltType) {
2489 case D3DLIGHT_DIRECTIONAL:
2490 case D3DLIGHT_POINT:
2491 /* These are handled properly... */
2495 if ((lpLight->dvTheta != 0.0) ||
2496 (lpLight->dvTheta != lpLight->dvPhi)) {
2497 ERR("dvTheta not fully supported yet !\n");
2502 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2505 /* This will force the Light setting on next drawing of primitives */
2506 glThis->transform_state = GL_TRANSFORM_NONE;
2512 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2516 int lightslot = -1, i;
2517 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2518 LPD3DLIGHT7 lpdestlight = get_light(This, dwLightIndex);
2520 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2522 /* The DirectX doc isn't as explicit as for SetLight as whether we can
2523 return this from this function, but it doesn't state otherwise. */
2525 return DDERR_OUTOFMEMORY;
2527 /* If this light hasn't been set, initialise it with default values. */
2528 if (lpdestlight->dltType == 0)
2530 TRACE("setting default light parameters\n");
2532 /* We always use HEAP_ZERO_MEMORY when allocating the light_parameters
2533 array, so we only have to setup anything that shoud not be zero. */
2534 lpdestlight->dltType = D3DLIGHT_DIRECTIONAL;
2535 lpdestlight->dcvDiffuse.u1.r = 1.f;
2536 lpdestlight->dcvDiffuse.u2.g = 1.f;
2537 lpdestlight->dcvDiffuse.u3.b = 1.f;
2538 lpdestlight->dvDirection.u3.z = 1.f;
2541 /* Look for this light in the active lights array. */
2542 for (i = 0; i < This->max_active_lights; i++)
2543 if (This->active_lights[i] == dwLightIndex)
2549 /* If we didn't find it, let's find the first available slot, if any. */
2550 if (lightslot == -1)
2551 for (i = 0; i < This->max_active_lights; i++)
2552 if (This->active_lights[i] == ~0)
2560 if (lightslot == -1)
2562 /* This means that the app is trying to enable more lights than
2563 the maximum possible indicated in the caps.
2565 Windows actually let you do this, and disable one of the
2566 previously enabled lights to let you enable this one.
2568 It's not documented and I'm not sure how windows pick which light
2569 to disable to make room for this one. */
2570 FIXME("Enabling more light than the maximum is not supported yet.");
2574 glEnable(GL_LIGHT0 + lightslot);
2577 if (This->active_lights[lightslot] == ~0)
2579 /* This light gets active... Need to update its parameters to GL before the next drawing */
2580 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2582 This->active_lights[lightslot] = dwLightIndex;
2583 glThis->transform_state = GL_TRANSFORM_NONE;
2586 glDisable(GL_LIGHT0 + lightslot);
2587 This->active_lights[lightslot] = ~0;
2595 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2597 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2598 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2600 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2602 if (dwIndex >= This->max_clipping_planes) {
2603 return DDERR_INVALIDPARAMS;
2606 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2608 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2610 /* This is to force the reset of the transformation matrices on the next drawing.
2611 * This is needed to use the correct matrices for the various clipping planes.
2613 glThis->transform_state = GL_TRANSFORM_NONE;
2619 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2620 LPD3DVIEWPORT7 lpData)
2622 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2623 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2625 if (TRACE_ON(ddraw)) {
2626 TRACE(" viewport is : \n");
2627 TRACE(" - dwX = %ld dwY = %ld\n",
2628 lpData->dwX, lpData->dwY);
2629 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2630 lpData->dwWidth, lpData->dwHeight);
2631 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2632 lpData->dvMinZ, lpData->dvMaxZ);
2636 /* Set the viewport */
2637 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2638 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2639 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2641 if ((lpData->dwX != This->active_viewport.dwX) ||
2642 (lpData->dwY != This->active_viewport.dwY) ||
2643 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2644 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2645 glViewport(lpData->dwX,
2646 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2647 lpData->dwWidth, lpData->dwHeight);
2652 This->active_viewport = *lpData;
2657 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2658 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2660 # define XCAST(fun) (void*)
2663 static const IDirect3DDevice7Vtbl VTABLE_IDirect3DDevice7 =
2665 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2666 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2667 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2668 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2669 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2670 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2671 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2672 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2673 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2674 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2675 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2676 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2677 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2678 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2679 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2680 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2681 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2682 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2683 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2684 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2685 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2686 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2687 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2688 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2689 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2690 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2691 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2692 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2693 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2694 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2695 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2696 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2697 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2698 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2699 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2700 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2701 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2702 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2703 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2704 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2705 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2706 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2707 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2708 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2709 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2710 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2711 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2712 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2713 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2716 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2721 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2722 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2724 # define XCAST(fun) (void*)
2727 static const IDirect3DDevice3Vtbl VTABLE_IDirect3DDevice3 =
2729 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2730 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2731 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2732 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2733 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2734 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2735 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2736 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2737 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2738 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2739 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2740 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2741 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2742 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2743 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2744 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2745 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2746 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2747 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2748 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2749 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2750 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2751 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2752 XCAST(GetLightState) GL_IDirect3DDeviceImpl_3_2T_GetLightState,
2753 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2754 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2755 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2756 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2757 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2758 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2759 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2760 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2761 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2762 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2763 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2764 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2765 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2766 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2767 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2768 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2769 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2770 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2773 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2778 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2779 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2781 # define XCAST(fun) (void*)
2784 static const IDirect3DDevice2Vtbl VTABLE_IDirect3DDevice2 =
2786 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2787 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2788 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2789 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2790 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2791 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2792 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2793 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2794 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2795 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2796 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2797 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2798 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2799 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2800 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2801 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2802 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2803 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2804 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2805 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2806 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2807 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2808 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2809 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2810 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2811 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2812 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2813 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2814 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2815 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2816 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2817 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2818 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2821 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2826 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2827 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2829 # define XCAST(fun) (void*)
2832 static const IDirect3DDeviceVtbl VTABLE_IDirect3DDevice =
2834 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2835 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2836 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2837 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2838 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2839 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2840 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2841 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2842 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2843 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2844 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2845 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2846 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2847 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2848 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2849 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2850 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2851 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2852 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2853 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2854 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2855 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2858 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2862 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2863 WINE_GL_BUFFER_TYPE buffer_type,
2871 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2872 GLbitfield bitfield = 0;
2876 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2877 if (TRACE_ON(ddraw)) {
2880 TRACE(" rectangles : \n");
2881 for (i = 0; i < dwCount; i++) {
2882 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2891 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2892 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2896 /* Clears the screen */
2899 if (dwFlags & D3DCLEAR_TARGET) {
2900 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2901 /* TODO: optimize here the case where Clear changes all the screen... */
2902 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2904 glThis->state[buffer_type] = SURFACE_GL;
2907 if (dwFlags & D3DCLEAR_ZBUFFER) {
2908 bitfield |= GL_DEPTH_BUFFER_BIT;
2909 if (glThis->depth_mask == FALSE) {
2910 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2912 if (dvZ != glThis->prev_clear_Z) {
2914 glThis->prev_clear_Z = dvZ;
2916 TRACE(" depth value : %f\n", dvZ);
2918 if (dwFlags & D3DCLEAR_STENCIL) {
2919 bitfield |= GL_STENCIL_BUFFER_BIT;
2920 if (dwStencil != glThis->prev_clear_stencil) {
2921 glClearStencil(dwStencil);
2922 glThis->prev_clear_stencil = dwStencil;
2924 TRACE(" stencil value : %ld\n", dwStencil);
2926 if (dwFlags & D3DCLEAR_TARGET) {
2927 bitfield |= GL_COLOR_BUFFER_BIT;
2928 if (dwColor != glThis->prev_clear_color) {
2929 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2930 ((dwColor >> 8) & 0xFF) / 255.0,
2931 ((dwColor >> 0) & 0xFF) / 255.0,
2932 ((dwColor >> 24) & 0xFF) / 255.0);
2933 glThis->prev_clear_color = dwColor;
2935 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2938 glEnable(GL_SCISSOR_TEST);
2939 for (i = 0; i < dwCount; i++) {
2940 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2941 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2944 glDisable(GL_SCISSOR_TEST);
2946 if (dwFlags & D3DCLEAR_ZBUFFER) {
2947 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2955 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2963 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2967 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2968 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2970 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2971 WINE_GL_BUFFER_TYPE buffer_type;
2973 /* First check if we BLT to the backbuffer... */
2974 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2975 buffer_type = WINE_GL_BUFFER_BACK;
2976 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2977 buffer_type = WINE_GL_BUFFER_FRONT;
2979 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2980 return DDERR_INVALIDPARAMS;
2983 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2984 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2985 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2986 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2987 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2988 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2991 return DDERR_INVALIDPARAMS;
2993 *buffer_type_p = buffer_type;
2999 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
3000 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
3001 DWORD dwFlags, LPDDBLTFX lpbltfx)
3003 WINE_GL_BUFFER_TYPE buffer_type;
3007 rect.u1.x1 = rdst->left;
3008 rect.u2.y1 = rdst->top;
3009 rect.u3.x2 = rdst->right;
3010 rect.u4.y2 = rdst->bottom;
3014 rect.u3.x2 = This->surface_desc.dwWidth;
3015 rect.u4.y2 = This->surface_desc.dwHeight;
3018 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
3020 if (dwFlags & DDBLT_COLORFILL) {
3021 /* This is easy to handle for the D3D Device... */
3025 /* The color as given in the Blt function is in the format of the frame-buffer...
3026 * 'clear' expect it in ARGB format => we need to do some conversion :-)
3028 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
3029 if (This->palette) {
3030 color = ((0xFF000000) |
3031 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
3032 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
3033 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
3037 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
3038 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3039 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3040 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3041 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3042 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3043 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3044 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
3047 color = ((0xFF000000) |
3048 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
3049 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
3050 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
3052 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
3053 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
3054 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3055 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3056 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3057 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
3059 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
3060 return DDERR_INVALIDPARAMS;
3063 ERR("Wrong surface type for BLT override !\n");
3064 return DDERR_INVALIDPARAMS;
3067 TRACE(" executing D3D Device override.\n");
3071 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3072 if (buffer_type == WINE_GL_BUFFER_FRONT)
3073 glDrawBuffer(GL_FRONT);
3075 glDrawBuffer(GL_BACK);
3077 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
3079 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3080 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3081 glDrawBuffer(prev_draw);
3086 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
3087 /* Normal blit without any special case... */
3089 /* And which has a SRC surface */
3090 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3092 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
3093 (src_impl->d3ddevice == This->d3ddevice) &&
3094 ((dwFlags & DDBLT_KEYSRC) == 0)) {
3095 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3099 WINE_GL_BUFFER_TYPE src_buffer_type;
3100 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3106 src_rect.u1.x1 = rsrc->left;
3107 src_rect.u2.y1 = rsrc->top;
3108 src_rect.u3.x2 = rsrc->right;
3109 src_rect.u4.y2 = rsrc->bottom;
3113 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3114 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3117 width = src_rect.u3.x2 - src_rect.u1.x1;
3118 height = src_rect.u4.y2 - src_rect.u2.y1;
3120 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3121 (height != (rect.u4.y2 - rect.u2.y1))) {
3122 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3123 return DDERR_INVALIDPARAMS;
3126 /* First check if we BLT from the backbuffer... */
3127 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3128 src_buffer_type = WINE_GL_BUFFER_BACK;
3129 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3130 src_buffer_type = WINE_GL_BUFFER_FRONT;
3132 ERR("Unexpected case in direct buffer to buffer copy !\n");
3133 return DDERR_INVALIDPARAMS;
3136 TRACE(" using direct buffer to buffer copy.\n");
3140 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3142 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3143 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3144 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3146 return DDERR_INVALIDPARAMS;
3149 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3150 if (buffer_type == WINE_GL_BUFFER_FRONT)
3151 glDrawBuffer(GL_FRONT);
3153 glDrawBuffer(GL_BACK);
3155 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3156 glReadBuffer(GL_FRONT);
3158 glReadBuffer(GL_BACK);
3160 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3161 And directly re-draws this on the destination buffer. */
3162 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3165 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3166 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3168 get_height = UNLOCK_TEX_SIZE;
3170 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3173 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3174 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3176 get_width = UNLOCK_TEX_SIZE;
3178 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3179 0, UNLOCK_TEX_SIZE - get_height,
3180 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3181 get_width, get_height);
3184 glTexCoord2f(0.0, 0.0);
3185 glVertex3d(rect.u1.x1 + x,
3186 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3188 glTexCoord2f(1.0, 0.0);
3189 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3190 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3192 glTexCoord2f(1.0, 1.0);
3193 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3196 glTexCoord2f(0.0, 1.0);
3197 glVertex3d(rect.u1.x1 + x,
3204 upload_surface_to_tex_memory_release();
3205 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3207 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3208 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3209 glDrawBuffer(prev_draw);
3215 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3216 (this prevents calling glReadPixels) */
3220 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3224 double x_stretch, y_stretch;
3227 src_rect.u1.x1 = rsrc->left;
3228 src_rect.u2.y1 = rsrc->top;
3229 src_rect.u3.x2 = rsrc->right;
3230 src_rect.u4.y2 = rsrc->bottom;
3234 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3235 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3238 width = src_rect.u3.x2 - src_rect.u1.x1;
3239 height = src_rect.u4.y2 - src_rect.u2.y1;
3241 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3242 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3244 TRACE(" using memory to buffer Blt override.\n");
3248 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3250 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3251 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3252 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3254 return DDERR_INVALIDPARAMS;
3257 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3258 if (buffer_type == WINE_GL_BUFFER_FRONT)
3259 glDrawBuffer(GL_FRONT);
3261 glDrawBuffer(GL_BACK);
3263 /* Now the serious stuff happens. This is basically the same code as for the memory
3264 flush to frame buffer ... with stretching and different rectangles added :-) */
3265 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3268 flush_rect.top = src_rect.u2.y1 + y;
3269 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3271 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3273 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3274 flush_rect.left = src_rect.u1.x1 + x;
3275 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3277 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3279 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3282 glTexCoord2f(0.0, 0.0);
3283 glVertex3d(rect.u1.x1 + (x * x_stretch),
3284 rect.u2.y1 + (y * y_stretch),
3286 glTexCoord2f(1.0, 0.0);
3287 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3288 rect.u2.y1 + (y * y_stretch),
3290 glTexCoord2f(1.0, 1.0);
3291 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3292 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3294 glTexCoord2f(0.0, 1.0);
3295 glVertex3d(rect.u1.x1 + (x * x_stretch),
3296 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3302 upload_surface_to_tex_memory_release();
3303 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3305 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3306 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3307 glDrawBuffer(prev_draw);
3315 return DDERR_INVALIDPARAMS;
3319 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3320 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3321 LPRECT rsrc, DWORD trans)
3325 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3326 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3327 WINE_GL_BUFFER_TYPE buffer_type;
3331 int width, height, x, y;
3333 /* Cannot support DSTCOLORKEY blitting... */
3334 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3337 WARN("rsrc is NULL - getting the whole surface !!\n");
3339 rsrc->left = rsrc->top = 0;
3340 rsrc->right = src_impl->surface_desc.dwWidth;
3341 rsrc->bottom = src_impl->surface_desc.dwHeight;
3349 rdst.right = dstx + (rsrc->right - rsrc->left);
3350 if (rdst.right > This->surface_desc.dwWidth) {
3351 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3352 rdst.right = This->surface_desc.dwWidth;
3354 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3355 if (rdst.bottom > This->surface_desc.dwHeight) {
3356 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3357 rdst.bottom = This->surface_desc.dwHeight;
3360 width = rsrc->right - rsrc->left;
3361 height = rsrc->bottom - rsrc->top;
3363 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3365 TRACE(" using BltFast memory to frame buffer override.\n");
3369 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3371 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3372 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3373 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3374 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3376 return DDERR_INVALIDPARAMS;
3379 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3380 if (buffer_type == WINE_GL_BUFFER_FRONT)
3381 glDrawBuffer(GL_FRONT);
3383 glDrawBuffer(GL_BACK);
3385 /* Now the serious stuff happens. This is basically the same code that for the memory
3386 flush to frame buffer but with different rectangles for source and destination :-) */
3387 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3390 flush_rect.top = rsrc->top + y;
3391 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3393 (rsrc->top + y + UNLOCK_TEX_SIZE));
3395 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3396 flush_rect.left = rsrc->left + x;
3397 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3399 (rsrc->left + x + UNLOCK_TEX_SIZE));
3401 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3404 glTexCoord2f(0.0, 0.0);
3405 glVertex3d(rdst.left + x,
3408 glTexCoord2f(1.0, 0.0);
3409 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3412 glTexCoord2f(1.0, 1.0);
3413 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3414 rdst.top + (y + UNLOCK_TEX_SIZE),
3416 glTexCoord2f(0.0, 1.0);
3417 glVertex3d(rdst.left + x,
3418 rdst.top + (y + UNLOCK_TEX_SIZE),
3424 upload_surface_to_tex_memory_release();
3425 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3427 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3428 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3429 glDrawBuffer(prev_draw);
3437 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3439 GLfloat height, width;
3440 GLfloat trans_mat[16];
3442 TRACE("(%p)\n", This);
3444 width = This->surface->surface_desc.dwWidth;
3445 height = This->surface->surface_desc.dwHeight;
3447 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3448 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3450 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3451 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3453 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3454 * that the Z coordinate needs to be given to GL unchanged.
3456 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3458 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = 0.0;
3459 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3462 glMatrixMode(GL_MODELVIEW);
3464 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3465 Correctness Tips section).
3467 Basically, from what I understood, if the game does not filter the font texture,
3468 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3469 one and we will have strange artifacts (as the rounding and stuff may give different results
3470 for different pixels, ie sometimes take the left pixel, sometimes the right).
3472 glTranslatef(0.375, 0.375, 0);
3473 glMatrixMode(GL_PROJECTION);
3474 glLoadMatrixf(trans_mat);
3479 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3480 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3482 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3485 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3486 glMatrixMode(GL_MODELVIEW);
3487 glLoadMatrixf((float *) view_mat);
3489 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3490 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3493 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3494 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3497 plane[0] = This->clipping_planes[i].plane[0];
3498 plane[1] = This->clipping_planes[i].plane[1];
3499 plane[2] = This->clipping_planes[i].plane[2];
3500 plane[3] = This->clipping_planes[i].plane[3];
3502 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3506 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3509 for (i = 0; i < This->max_active_lights; i++ )
3511 DWORD dwLightIndex = This->active_lights[i];
3512 if (dwLightIndex != ~0)
3514 LPD3DLIGHT7 pLight = &This->light_parameters[dwLightIndex];
3515 switch (pLight->dltType)
3517 case D3DLIGHT_DIRECTIONAL: {
3519 float cut_off = 180.0;
3521 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3522 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3523 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3524 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3526 direction[0] = pLight->dvDirection.u1.x;
3527 direction[1] = pLight->dvDirection.u2.y;
3528 direction[2] = pLight->dvDirection.u3.z;
3530 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3533 case D3DLIGHT_POINT: {
3535 float cut_off = 180.0;
3537 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3538 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3539 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3540 position[0] = pLight->dvPosition.u1.x;
3541 position[1] = pLight->dvPosition.u2.y;
3542 position[2] = pLight->dvPosition.u3.z;
3544 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3545 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3546 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3547 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
3548 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3551 case D3DLIGHT_SPOT: {
3554 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3556 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3557 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3558 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3560 direction[0] = pLight->dvDirection.u1.x;
3561 direction[1] = pLight->dvDirection.u2.y;
3562 direction[2] = pLight->dvDirection.u3.z;
3564 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3565 position[0] = pLight->dvPosition.u1.x;
3566 position[1] = pLight->dvPosition.u2.y;
3567 position[2] = pLight->dvPosition.u3.z;
3569 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3570 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3571 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3572 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
3573 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3574 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &pLight->dvFalloff);
3578 /* No warning here as it's already done at light setting */
3585 glMultMatrixf((float *) world_mat);
3587 if ((matrices & PROJMAT_CHANGED) != 0) {
3588 glMatrixMode(GL_PROJECTION);
3589 glLoadMatrixf((float *) proj_mat);
3595 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3597 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3598 DWORD tex_mat, tex_stage;
3600 TRACE("(%p,%08lx)\n", This, matrices);
3602 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3603 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3604 /* This will force an update of the transform state at the next drawing. */
3605 glThis->transform_state = GL_TRANSFORM_NONE;
3608 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3609 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3612 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3613 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3614 if (matrices & tex_mat) {
3615 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3616 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3618 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3619 if (glThis->current_active_tex_unit != unit) {
3620 GL_extensions.glActiveTexture(unit);
3621 glThis->current_active_tex_unit = unit;
3623 glMatrixMode(GL_TEXTURE);
3624 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3626 This->tex_mat_is_identity[tex_stage] = is_identity;
3628 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3629 if (glThis->current_active_tex_unit != unit) {
3630 GL_extensions.glActiveTexture(unit);
3631 glThis->current_active_tex_unit = unit;
3633 glMatrixMode(GL_TEXTURE);
3635 This->tex_mat_is_identity[tex_stage] = TRUE;
3644 /* TODO for both these functions :
3645 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3646 by other OpenGL code in D3D
3647 - handle the case where no 'Begin / EndScene' was done between two locks
3648 - handle the rectangles in the unlock too
3649 - handle pitch correctly...
3651 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3653 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3654 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3655 WINE_GL_BUFFER_TYPE buffer_type;
3658 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3659 buffer_type = WINE_GL_BUFFER_FRONT;
3660 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3661 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3662 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3664 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3665 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3666 buffer_type = WINE_GL_BUFFER_BACK;
3667 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3668 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3669 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3671 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3673 ERR("Wrong surface type for locking !\n");
3677 if (pRect == NULL) {
3680 loc_rect.bottom = This->surface_desc.dwHeight;
3681 loc_rect.right = This->surface_desc.dwWidth;
3685 /* Try to acquire the device critical section */
3686 EnterCriticalSection(&(d3d_dev->crit));
3688 if (gl_d3d_dev->lock_rect_valid[buffer_type]) {
3689 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3690 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3692 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3694 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3695 /* Check if the new rectangle is in the previous one or not.
3696 If it is not, flush first the previous locks on screen.
3698 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3699 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3700 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3701 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3702 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3703 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3704 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3705 pRect->left, pRect->top, pRect->right, pRect->bottom,
3706 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3707 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3708 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3710 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3711 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3713 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3715 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3718 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3719 /* If the surface is already in memory, no need to do anything here... */
3720 GLenum buffer_format;
3721 GLenum buffer_color;
3725 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3726 pRect->left, pRect->top, pRect->right, pRect->bottom);
3728 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3729 may only write to the device... But when we will blit it back to the screen, we need
3730 also to blit correctly the parts the application did not overwrite... */
3732 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3733 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3734 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3735 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3736 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3737 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3738 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3739 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3740 buffer_color = GL_RGB;
3741 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3742 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3743 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3744 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3745 buffer_format = GL_UNSIGNED_BYTE;
3746 buffer_color = GL_RGB;
3747 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3748 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3749 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3750 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3751 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3752 buffer_color = GL_BGRA;
3754 ERR(" unsupported pixel format at device locking.\n");
3758 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3764 if (buffer_type == WINE_GL_BUFFER_FRONT)
3765 /* Application wants to lock the front buffer */
3766 glReadBuffer(GL_FRONT);
3768 /* Application wants to lock the back buffer */
3769 glReadBuffer(GL_BACK);
3771 dst = ((char *)This->surface_desc.lpSurface) +
3772 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3774 if (This->surface_desc.u1.lPitch != (GET_BPP(This->surface_desc) * This->surface_desc.dwWidth)) {
3775 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3776 * could not be bothered considering the rare cases where it may be useful :-)
3778 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3779 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3781 glReadPixels(pRect->left, y,
3782 pRect->right - pRect->left, 1,
3783 buffer_color, buffer_format, dst);
3784 dst += This->surface_desc.u1.lPitch;
3787 /* Faster path for surface copy. Note that I can use static variables here as I am
3788 * protected by the OpenGL critical section so this function won't be called by
3789 * two threads at the same time.
3791 static char *buffer = NULL;
3792 static int buffer_width = 0;
3793 char *dst2 = dst + ((pRect->bottom - pRect->top) - 1) * This->surface_desc.u1.lPitch;
3794 int current_width = (pRect->right - pRect->left) * GET_BPP(This->surface_desc);
3796 glReadPixels(pRect->left, ((int) This->surface_desc.dwHeight - (int) pRect->bottom),
3797 pRect->right - pRect->left, pRect->bottom - pRect->top,
3798 buffer_color, buffer_format, dst);
3800 if (current_width > buffer_width) {
3801 if (buffer != NULL) HeapFree(GetProcessHeap(), 0, buffer);
3802 buffer_width = current_width;
3803 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_width);
3805 for (y = 0; y < ((pRect->bottom - pRect->top) / 2); y++) {
3806 memcpy(buffer, dst, current_width);
3807 memcpy(dst, dst2, current_width);
3808 memcpy(dst2, buffer, current_width);
3809 dst += This->surface_desc.u1.lPitch;
3810 dst2 -= This->surface_desc.u1.lPitch;
3814 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3817 /* I keep this code here as it's very useful to debug :-) */
3819 static int flush_count = 0;
3823 if ((++flush_count % 50) == 0) {
3824 sprintf(buf, "lock_%06d.pnm", flush_count);
3825 f = fopen(buf, "wb");
3826 DDRAW_dump_surface_to_disk(This, f);
3835 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3837 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3842 /* Note : no need here to lock the 'device critical section' as we are already protected by
3843 the GL critical section. */
3845 if (pRect == NULL) {
3848 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3849 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3853 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3855 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3857 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3858 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3859 ERR(" unsupported pixel format at frame buffer flush.\n");
3863 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3867 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3869 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3870 /* First, upload the texture... */
3871 flush_rect.left = x;
3872 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3874 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3877 glTexCoord2f(0.0, 0.0);
3878 glVertex3d(x, y, 0.5);
3879 glTexCoord2f(1.0, 0.0);
3880 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3881 glTexCoord2f(1.0, 1.0);
3882 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3883 glTexCoord2f(0.0, 1.0);
3884 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3889 upload_surface_to_tex_memory_release();
3890 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3893 /* I keep this code here as it's very useful to debug :-) */
3895 static int flush_count = 0;
3899 if ((++flush_count % 50) == 0) {
3900 sprintf(buf, "flush_%06d.pnm", flush_count);
3901 f = fopen(buf, "wb");
3902 DDRAW_dump_surface_to_disk(surf, f);
3908 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3910 WINE_GL_BUFFER_TYPE buffer_type;
3911 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3912 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3914 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3915 buffer_type = WINE_GL_BUFFER_FRONT;
3916 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3917 buffer_type = WINE_GL_BUFFER_BACK;
3919 ERR("Wrong surface type for locking !\n");
3923 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3924 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3925 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3927 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3929 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3930 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3931 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3934 TRACE(" flushing front buffer immediately on screen.\n");
3937 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3938 glDrawBuffer(GL_FRONT);
3939 /* Note: we do not use the application provided lock rectangle but our own stored at
3940 lock time. This is because in old D3D versions, the 'lock' parameter did not
3943 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]);
3944 glDrawBuffer(prev_draw);
3947 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3951 /* And 'frees' the device critical section */
3952 LeaveCriticalSection(&(d3d_dev->crit));
3956 apply_texture_state(IDirect3DDeviceImpl *This)
3960 /* Initialize texture stages states */
3961 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3962 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3963 if (This->state_block.set_flags.texture_stage_state[stage][state]) {
3964 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3965 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3972 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, int version)
3974 IDirect3DDeviceImpl *object;
3975 IDirect3DDeviceGLImpl *gl_object;
3976 IDirectDrawSurfaceImpl *surf;
3981 XVisualInfo template;
3982 GLenum buffer = GL_FRONT;
3985 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3986 if (object == NULL) return DDERR_OUTOFMEMORY;
3988 gl_object = (IDirect3DDeviceGLImpl *) object;
3992 object->surface = surface;
3993 object->set_context = set_context;
3994 object->clear = d3ddevice_clear_back;
3995 object->set_matrices = d3ddevice_set_matrices;
3996 object->matrices_updated = d3ddevice_matrices_updated;
3997 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3998 object->version = version;
4000 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
4002 InitializeCriticalSection(&(object->crit));
4004 TRACE(" device critical section : %p\n", &(object->crit));
4006 device_context = GetDC(surface->ddraw_owner->window);
4007 gl_object->display = get_display(device_context);
4008 gl_object->drawable = get_drawable(device_context);
4009 ReleaseDC(surface->ddraw_owner->window,device_context);
4012 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
4013 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
4015 HeapFree(GetProcessHeap(), 0, object);
4016 ERR("No visual found !\n");
4018 return DDERR_INVALIDPARAMS;
4020 TRACE(" visual found\n");
4023 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
4026 if (gl_object->gl_context == NULL) {
4027 HeapFree(GetProcessHeap(), 0, object);
4028 ERR("Error in context creation !\n");
4030 return DDERR_INVALIDPARAMS;
4032 TRACE(" context created (%p)\n", gl_object->gl_context);
4035 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
4036 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4037 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
4038 surf->aux_ctx = (LPVOID) object;
4039 surf->aux_data = (LPVOID) gl_object->drawable;
4040 surf->aux_flip = opengl_flip;
4045 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
4047 TRACE(" no double buffering : drawing on the front buffer\n");
4051 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4052 IDirectDrawSurfaceImpl *surf2;
4053 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
4054 for (; surf2 != NULL; surf2 = surf2->next_attached) {
4055 TRACE(" checking surface %p :", surf2);
4056 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
4057 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
4058 /* Override the Lock / Unlock function for all these surfaces */
4059 surf2->lock_update_prev = surf2->lock_update;
4060 surf2->lock_update = d3ddevice_lock_update;
4061 surf2->unlock_update_prev = surf2->unlock_update;
4062 surf2->unlock_update = d3ddevice_unlock_update;
4063 /* And install also the blt / bltfast overrides */
4064 surf2->aux_blt = d3ddevice_blt;
4065 surf2->aux_bltfast = d3ddevice_bltfast;
4067 TRACE(" overriding direct surface access.\n");
4069 TRACE(" no override.\n");
4071 surf2->d3ddevice = object;
4075 /* Set the various light parameters */
4076 object->num_set_lights = 0;
4077 object->max_active_lights = opengl_device_caps.dwMaxActiveLights;
4078 object->light_parameters = NULL;
4079 object->active_lights = HeapAlloc(GetProcessHeap(), 0,
4080 object->max_active_lights * sizeof(BOOLEAN));
4081 /* Fill the active light array with ~0, which is used to indicate an
4082 invalid light index. We don't use 0, because it's a valid light index. */
4083 for (light=0; light < object->max_active_lights; light++)
4084 object->active_lights[light] = ~0;
4087 /* Allocate memory for the matrices */
4088 object->world_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4089 object->view_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4090 object->proj_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4091 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
4092 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
4093 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
4094 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
4095 object->tex_mat[tex_num] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4096 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
4097 object->tex_mat_is_identity[tex_num] = TRUE;
4100 /* Initialisation */
4101 TRACE(" setting current context\n");
4102 object->set_context(object);
4103 TRACE(" current context set\n");
4105 /* allocate the clipping planes */
4106 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
4107 object->clipping_planes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
4109 glHint(GL_FOG_HINT,GL_NICEST);
4111 /* Initialize the various GL contexts to be in sync with what we store locally */
4114 glClearColor(0.0, 0.0, 0.0, 0.0);
4115 glDepthMask(GL_TRUE);
4116 gl_object->depth_mask = TRUE;
4117 glEnable(GL_DEPTH_TEST);
4118 gl_object->depth_test = TRUE;
4119 glDisable(GL_ALPHA_TEST);
4120 glDisable(GL_STENCIL_TEST);
4121 glDisable(GL_CULL_FACE);
4122 glDisable(GL_LIGHTING);
4123 glDisable(GL_BLEND);
4125 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4126 gl_object->current_tex_env = GL_REPLACE;
4127 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
4128 if (GL_extensions.glActiveTexture != NULL) {
4129 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
4131 gl_object->current_alpha_test_ref = 0.0;
4132 gl_object->current_alpha_test_func = GL_ALWAYS;
4133 glAlphaFunc(GL_ALWAYS, 0.0);
4135 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4136 glDrawBuffer(buffer);
4137 glReadBuffer(buffer);
4138 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4141 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4142 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4144 /* fill_device_capabilities(d3d->ddraw); */
4146 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4147 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4148 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4149 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4153 TRACE(" creating implementation at %p.\n", *obj);
4155 /* And finally warn D3D that this device is now present */
4156 object->d3d->d3d_added_device(object->d3d, object);
4158 InitDefaultStateBlock(&object->state_block, object->version);
4159 /* Apply default render state and texture stage state values */
4160 apply_render_state(object, &object->state_block);
4161 apply_texture_state(object);
4163 /* And fill the fog table with the default fog value */
4164 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4169 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4171 pc->dwSize = sizeof(*pc);
4172 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4173 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4174 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4175 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4176 D3DPRASTERCAPS_ZFOG;
4177 if (GL_extensions.mipmap_lodbias) {
4178 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4180 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4181 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4182 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4183 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4184 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4185 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4186 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4187 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4188 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4189 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4190 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4191 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4192 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4193 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4194 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4195 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4196 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4197 D3DPTFILTERCAPS_MIPFPOINT;
4198 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4199 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4200 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4201 if (GL_extensions.mirrored_repeat) {
4202 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4204 pc->dwStippleWidth = 32;
4205 pc->dwStippleHeight = 32;
4208 static void fill_caps(void)
4210 GLint max_clip_planes;
4213 /* Fill first all the fields with default values which will be overriden later on with
4214 correct ones from the GL code
4216 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4217 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4218 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4219 /* D3D 7 capabilities */
4220 D3DDEVCAPS_DRAWPRIMITIVES2 /*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_DRAWPRIMITIVES2EX;
4221 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4222 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4223 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4224 opengl_device_caps.dwMinTextureWidth = 1;
4225 opengl_device_caps.dwMinTextureHeight = 1;
4226 opengl_device_caps.dwMaxTextureWidth = 1024;
4227 opengl_device_caps.dwMaxTextureHeight = 1024;
4228 opengl_device_caps.dwMaxTextureRepeat = 16;
4229 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4230 opengl_device_caps.dwMaxAnisotropy = 0;
4231 opengl_device_caps.dvGuardBandLeft = 0.0;
4232 opengl_device_caps.dvGuardBandRight = 0.0;
4233 opengl_device_caps.dvGuardBandTop = 0.0;
4234 opengl_device_caps.dvGuardBandBottom = 0.0;
4235 opengl_device_caps.dvExtentsAdjust = 0.0;
4236 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4237 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4238 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4239 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4240 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4241 if (GL_extensions.max_texture_units != 0) {
4242 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4243 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4244 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4246 opengl_device_caps.wMaxTextureBlendStages = 1;
4247 opengl_device_caps.wMaxSimultaneousTextures = 1;
4248 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4250 opengl_device_caps.dwMaxActiveLights = 16;
4251 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4252 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4253 opengl_device_caps.wMaxUserClipPlanes = 1;
4254 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4255 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4256 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4257 opengl_device_caps.dwReserved1 = 0;
4258 opengl_device_caps.dwReserved2 = 0;
4259 opengl_device_caps.dwReserved3 = 0;
4260 opengl_device_caps.dwReserved4 = 0;
4262 /* And now some GL overrides :-) */
4263 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4264 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4265 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4266 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4268 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4269 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4271 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4272 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4273 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4275 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4276 TRACE(": Z bits = %d\n", depth_bits);
4277 switch (depth_bits) {
4278 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4279 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4281 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4286 d3ddevice_init_at_startup(void *gl_handle)
4288 XVisualInfo template;
4293 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4294 XWindowAttributes win_attr;
4295 GLXContext gl_context;
4297 const char *glExtensions;
4298 const char *glVersion;
4299 const char *glXExtensions = NULL;
4300 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4301 int major, minor, patch, num_parsed;
4303 TRACE("Initializing GL...\n");
4307 WARN("x11drv not loaded - D3D support disabled!\n");
4311 /* Get a default rendering context to have the 'caps' function query some info from GL */
4312 device_context = GetDC(0);
4313 display = get_display(device_context);
4314 ReleaseDC(0, device_context);
4317 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4318 visual = win_attr.visual;
4320 visual = DefaultVisual(display, DefaultScreen(display));
4322 template.visualid = XVisualIDFromVisual(visual);
4323 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4326 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4329 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4331 if (gl_context == NULL) {
4333 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4336 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4337 glXDestroyContext(display, gl_context);
4339 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4343 /* Then, query all extensions */
4344 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); /* Note: not used right now but will for PBuffers */
4345 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4346 glVersion = (const char *) glGetString(GL_VERSION);
4347 if (gl_handle != NULL) {
4348 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4351 /* Parse the GL version string */
4352 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4353 if (num_parsed == 1) {
4356 } else if (num_parsed == 2) {
4359 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4361 /* And starts to fill the extension context properly */
4362 memset(&GL_extensions, 0, sizeof(GL_extensions));
4363 TRACE("GL supports following extensions used by Wine :\n");
4365 /* Mirrored Repeat extension :
4366 - GL_ARB_texture_mirrored_repeat
4367 - GL_IBM_texture_mirrored_repeat
4370 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4371 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4373 ((major == 1) && (minor >= 4))) {
4374 TRACE(" - mirrored repeat\n");
4375 GL_extensions.mirrored_repeat = TRUE;
4378 /* Texture LOD Bias :
4379 - GL_EXT_texture_lod_bias
4381 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4382 TRACE(" - texture lod bias\n");
4383 GL_extensions.mipmap_lodbias = TRUE;
4386 /* For all subsequent extensions, we need glXGetProcAddress */
4387 if (pglXGetProcAddressARB != NULL) {
4388 /* Multi-texturing :
4389 - GL_ARB_multitexture
4392 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4394 ((major == 1) && (minor > 2)) ||
4395 ((major == 1) && (minor == 2) && (patch >= 1))) {
4396 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4397 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4398 /* We query the ARB version to be the most portable we can... */
4399 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4400 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4401 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4404 if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
4405 TRACE(" - S3TC compression supported\n");
4406 GL_extensions.s3tc_compressed_texture = TRUE;
4407 GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2D");
4408 GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2D");
4412 /* Fill the D3D capabilities according to what GL tells us... */
4415 /* And frees this now-useless context */
4416 glXMakeCurrent(display, None, NULL);
4417 glXDestroyContext(display, gl_context);