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 static void handle_texture(DWORD size, const D3DVALUE *coords) {
1301 case 1: glTexCoord1fv(coords); break;
1302 case 2: glTexCoord2fv(coords); break;
1303 case 3: glTexCoord3fv(coords); break;
1304 case 4: glTexCoord4fv(coords); break;
1308 inline static void handle_textures(DWORD size, const D3DVALUE *coords, int tex_stage) {
1309 if (GL_extensions.max_texture_units > 0) {
1310 GL_extensions.glMultiTexCoord[size - 1](GL_TEXTURE0_WINE + tex_stage, coords);
1312 if (tex_stage == 0) handle_texture(size, coords);
1316 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1317 D3DPRIMITIVETYPE d3dptPrimitiveType,
1318 DWORD d3dvtVertexType,
1319 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1320 DWORD dwVertexCount,
1325 BOOLEAN vertex_lighted = FALSE;
1326 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1327 int num_active_stages = 0;
1328 int num_tex_index = GET_TEXCOUNT_FROM_FVF(d3dvtVertexType);
1330 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1331 if (TRACE_ON(ddraw)) {
1332 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1335 /* This is to prevent 'thread contention' between a thread locking the device and another
1336 doing 3D display on it... */
1337 EnterCriticalSection(&(This->crit));
1340 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1341 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1343 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1345 if (This->current_zbuffer == NULL) {
1346 /* Search for an attached ZBuffer */
1347 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1348 LPDIRECTDRAWSURFACE7 zbuf;
1351 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1352 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1354 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1355 IDirectDrawSurface7_Release(zbuf);
1358 if (This->current_zbuffer != NULL) {
1359 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1360 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1364 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1365 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1366 vertex_lighted = TRUE;
1368 /* Compute the number of active texture stages and set the various texture parameters */
1369 num_active_stages = draw_primitive_handle_textures(This);
1371 /* And restore to handle '0' in the case we use glTexCoord calls */
1372 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1373 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1374 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1377 draw_primitive_handle_GL_state(This,
1378 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1381 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1382 for now to some 'special' cases where we can do a direct mapping between D3D
1385 Note: in the future all calls will go through vertex arrays but the arrays
1386 will be generated by this function.
1388 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1389 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1390 which, as we are little indian, gives a B, G, R, A storage in memory.
1392 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1393 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
1395 TRACE(" using GL vertex arrays for performance !\n");
1396 /* First, the vertices (we are sure we have some :-) */
1397 glEnableClientState(GL_VERTEX_ARRAY);
1398 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1399 /* Then the normals */
1400 if (d3dvtVertexType & D3DFVF_NORMAL) {
1401 glEnableClientState(GL_NORMAL_ARRAY);
1402 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1404 /* Then the diffuse colour */
1405 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1406 glEnableClientState(GL_COLOR_ARRAY);
1407 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1408 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1410 /* Then the various textures */
1411 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1412 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1413 if (tex_index >= num_tex_index) {
1414 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1415 tex_index = num_tex_index - 1;
1417 if (GL_extensions.glClientActiveTexture) {
1418 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1420 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1421 glTexCoordPointer(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1422 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1424 if (dwIndices != NULL) {
1425 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1427 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1429 glDisableClientState(GL_VERTEX_ARRAY);
1430 if (d3dvtVertexType & D3DFVF_NORMAL) {
1431 glDisableClientState(GL_NORMAL_ARRAY);
1433 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1434 glDisableClientState(GL_COLOR_ARRAY);
1436 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1437 if (GL_extensions.glClientActiveTexture) {
1438 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1440 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1443 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1445 /* Some fast paths first before the generic case.... */
1446 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1449 for (index = 0; index < dwIndexCount; index++) {
1450 int i = (dwIndices == NULL) ? index : dwIndices[index];
1452 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1453 D3DVALUE *tex_coord =
1454 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1455 D3DVALUE *position =
1456 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1458 handle_normal(normal);
1459 handle_texture(2, tex_coord);
1460 handle_xyz(position);
1462 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1463 position[0], position[1], position[2],
1464 normal[0], normal[1], normal[2],
1465 tex_coord[0], tex_coord[1]);
1467 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1470 for (index = 0; index < dwIndexCount; index++) {
1471 int i = (dwIndices == NULL) ? index : dwIndices[index];
1473 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1475 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1476 D3DVALUE *tex_coord =
1477 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1478 D3DVALUE *position =
1479 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1481 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1482 handle_texture(2, tex_coord);
1483 handle_xyzrhw(position);
1485 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1486 position[0], position[1], position[2], position[3],
1487 (*color_d >> 16) & 0xFF,
1488 (*color_d >> 8) & 0xFF,
1489 (*color_d >> 0) & 0xFF,
1490 (*color_d >> 24) & 0xFF,
1491 (*color_s >> 16) & 0xFF,
1492 (*color_s >> 8) & 0xFF,
1493 (*color_s >> 0) & 0xFF,
1494 (*color_s >> 24) & 0xFF,
1495 tex_coord[0], tex_coord[1]);
1497 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1498 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1499 /* This is the 'slow path' but that should support all possible vertex formats out there...
1500 Note that people should write a fast path for all vertex formats out there...
1503 /* static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 }; */
1505 for (index = 0; index < dwIndexCount; index++) {
1506 int i = (dwIndices == NULL) ? index : dwIndices[index];
1509 if (d3dvtVertexType & D3DFVF_NORMAL) {
1511 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1512 handle_normal(normal);
1514 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1516 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1518 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1519 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1521 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1523 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1524 handle_specular(&(This->state_block), color_s, vertex_lighted);
1525 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1527 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1528 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1532 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1533 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1534 D3DVALUE *tex_coord;
1536 if (tex_index >= num_tex_index) {
1537 /* This will have to be checked on Windows. RealMYST uses this feature and I would find it more
1538 * logical to re-use the index of the previous stage than a default index of '0'.
1541 /* handle_textures((const D3DVALUE *) no_index, tex_stage); */
1542 tex_index = num_tex_index - 1;
1544 tex_coord = (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1545 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1546 handle_textures(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), tex_coord, tex_stage);
1549 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1550 D3DVALUE *position =
1551 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1552 handle_xyz(position);
1553 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1554 D3DVALUE *position =
1555 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1556 handle_xyzrhw(position);
1559 if (TRACE_ON(ddraw_geom)) {
1560 unsigned int tex_index;
1562 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1563 D3DVALUE *position =
1564 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1565 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1566 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1567 D3DVALUE *position =
1568 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1569 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1571 if (d3dvtVertexType & D3DFVF_NORMAL) {
1573 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1574 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1576 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1578 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1579 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1580 (*color_d >> 16) & 0xFF,
1581 (*color_d >> 8) & 0xFF,
1582 (*color_d >> 0) & 0xFF,
1583 (*color_d >> 24) & 0xFF);
1585 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1587 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1588 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1589 (*color_s >> 16) & 0xFF,
1590 (*color_s >> 8) & 0xFF,
1591 (*color_s >> 0) & 0xFF,
1592 (*color_s >> 24) & 0xFF);
1594 for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); tex_index++) {
1595 D3DVALUE *tex_coord =
1596 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1597 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1598 switch (GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)) {
1599 case 1: TRACE_(ddraw_geom)(" / %f", tex_coord[0]); break;
1600 case 2: TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]); break;
1601 case 3: TRACE_(ddraw_geom)(" / %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2]); break;
1602 case 4: TRACE_(ddraw_geom)(" / %f %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2], tex_coord[3]); break;
1603 default: TRACE_(ddraw_geom)("Invalid texture size (%ld) !!!", GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)); break;
1606 TRACE_(ddraw_geom)("\n");
1610 ERR(" matrix weighting not handled yet....\n");
1616 /* Whatever the case, disable the color material stuff */
1617 glDisable(GL_COLOR_MATERIAL);
1622 LeaveCriticalSection(&(This->crit));
1626 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1627 D3DPRIMITIVETYPE d3dptPrimitiveType,
1628 DWORD d3dvtVertexType,
1630 DWORD dwVertexCount,
1633 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1634 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1636 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1637 if (TRACE_ON(ddraw)) {
1638 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1641 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1642 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1648 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1649 D3DPRIMITIVETYPE d3dptPrimitiveType,
1650 DWORD d3dvtVertexType,
1652 DWORD dwVertexCount,
1657 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1658 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1660 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1661 if (TRACE_ON(ddraw)) {
1662 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1665 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1666 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1672 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1673 D3DPRIMITIVETYPE d3dptPrimitiveType,
1675 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1676 DWORD dwVertexCount,
1679 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1681 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1682 if (TRACE_ON(ddraw)) {
1683 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1685 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1691 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1692 D3DPRIMITIVETYPE d3dptPrimitiveType,
1694 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1695 DWORD dwVertexCount,
1700 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1702 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1703 if (TRACE_ON(ddraw)) {
1704 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1707 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1713 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1714 D3DPRIMITIVETYPE d3dptPrimitiveType,
1715 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1716 DWORD dwStartVertex,
1717 DWORD dwNumVertices,
1720 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1721 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1722 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1724 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1725 if (TRACE_ON(ddraw)) {
1726 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1729 if (vb_impl->processed) {
1730 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1731 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1733 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1734 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1735 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1737 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1738 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1741 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1742 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1749 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1750 D3DPRIMITIVETYPE d3dptPrimitiveType,
1751 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1752 DWORD dwStartVertex,
1753 DWORD dwNumVertices,
1758 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1759 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1760 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1762 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1763 if (TRACE_ON(ddraw)) {
1764 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1767 if (vb_impl->processed) {
1768 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1769 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1771 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1772 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1773 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1775 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1776 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1779 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1780 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1786 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1788 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1790 BOOLEAN is_complement = FALSE;
1791 BOOLEAN is_alpha_replicate = FALSE;
1792 BOOLEAN handled = TRUE;
1794 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1798 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1799 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1804 if (tex_op == D3DTOP_SELECTARG2) {
1808 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1809 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1814 if (tex_op == D3DTOP_SELECTARG2) {
1819 if (dwState & D3DTA_COMPLEMENT) {
1820 is_complement = TRUE;
1822 if (dwState & D3DTA_ALPHAREPLICATE) {
1823 is_alpha_replicate = TRUE;
1825 dwState &= D3DTA_SELECTMASK;
1826 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1827 dwState = D3DTA_DIFFUSE;
1831 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1832 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1833 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1834 case D3DTA_TFACTOR: {
1835 /* Get the constant value from the current rendering state */
1837 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1839 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1840 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1841 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1842 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1843 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1845 src = GL_CONSTANT_EXT;
1847 default: src = GL_TEXTURE; handled = FALSE; break;
1851 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1852 if (is_alpha_replicate) {
1853 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1855 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1858 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1859 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1866 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1868 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1871 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1872 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1877 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1879 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1880 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1884 unit = GL_TEXTURE0_WINE + dwStage;
1885 if (unit != glThis->current_active_tex_unit) {
1886 GL_extensions.glActiveTexture(unit);
1887 glThis->current_active_tex_unit = unit;
1890 switch (d3dTexStageStateType) {
1891 #define GEN_CASE(a) case a: type = #a; break
1892 GEN_CASE(D3DTSS_COLOROP);
1893 GEN_CASE(D3DTSS_COLORARG1);
1894 GEN_CASE(D3DTSS_COLORARG2);
1895 GEN_CASE(D3DTSS_ALPHAOP);
1896 GEN_CASE(D3DTSS_ALPHAARG1);
1897 GEN_CASE(D3DTSS_ALPHAARG2);
1898 GEN_CASE(D3DTSS_BUMPENVMAT00);
1899 GEN_CASE(D3DTSS_BUMPENVMAT01);
1900 GEN_CASE(D3DTSS_BUMPENVMAT10);
1901 GEN_CASE(D3DTSS_BUMPENVMAT11);
1902 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1903 GEN_CASE(D3DTSS_ADDRESS);
1904 GEN_CASE(D3DTSS_ADDRESSU);
1905 GEN_CASE(D3DTSS_ADDRESSV);
1906 GEN_CASE(D3DTSS_BORDERCOLOR);
1907 GEN_CASE(D3DTSS_MAGFILTER);
1908 GEN_CASE(D3DTSS_MINFILTER);
1909 GEN_CASE(D3DTSS_MIPFILTER);
1910 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1911 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1912 GEN_CASE(D3DTSS_MAXANISOTROPY);
1913 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1914 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1915 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1917 default: type = "UNKNOWN";
1920 /* Store the values in the state array */
1921 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1922 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1923 /* Some special cases when one state modifies more than one... */
1924 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1925 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1926 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1931 switch (d3dTexStageStateType) {
1932 case D3DTSS_MINFILTER:
1933 case D3DTSS_MIPFILTER:
1934 if (TRACE_ON(ddraw)) {
1935 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1936 switch ((D3DTEXTUREMINFILTER) dwState) {
1937 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1938 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1939 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1942 switch ((D3DTEXTUREMIPFILTER) dwState) {
1943 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1944 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1945 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1946 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1952 case D3DTSS_MAGFILTER:
1953 if (TRACE_ON(ddraw)) {
1954 switch ((D3DTEXTUREMAGFILTER) dwState) {
1955 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1956 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1957 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1962 case D3DTSS_ADDRESS:
1963 case D3DTSS_ADDRESSU:
1964 case D3DTSS_ADDRESSV: {
1965 switch ((D3DTEXTUREADDRESS) dwState) {
1966 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1967 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1968 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1969 case D3DTADDRESS_MIRROR:
1970 if (GL_extensions.mirrored_repeat) {
1971 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1973 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1976 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1980 case D3DTSS_ALPHAOP:
1981 case D3DTSS_COLOROP: {
1983 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1988 #define GEN_CASE(a) case a: value = #a; break
1989 GEN_CASE(D3DTOP_DISABLE);
1990 GEN_CASE(D3DTOP_SELECTARG1);
1991 GEN_CASE(D3DTOP_SELECTARG2);
1992 GEN_CASE(D3DTOP_MODULATE);
1993 GEN_CASE(D3DTOP_MODULATE2X);
1994 GEN_CASE(D3DTOP_MODULATE4X);
1995 GEN_CASE(D3DTOP_ADD);
1996 GEN_CASE(D3DTOP_ADDSIGNED);
1997 GEN_CASE(D3DTOP_ADDSIGNED2X);
1998 GEN_CASE(D3DTOP_SUBTRACT);
1999 GEN_CASE(D3DTOP_ADDSMOOTH);
2000 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
2001 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
2002 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
2003 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
2004 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
2005 GEN_CASE(D3DTOP_PREMODULATE);
2006 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
2007 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
2008 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
2009 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
2010 GEN_CASE(D3DTOP_BUMPENVMAP);
2011 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
2012 GEN_CASE(D3DTOP_DOTPRODUCT3);
2013 GEN_CASE(D3DTOP_FORCE_DWORD);
2015 default: value = "UNKNOWN";
2018 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
2019 glDisable(GL_TEXTURE_2D);
2020 TRACE(" disabling 2D texturing.\n");
2022 /* Re-enable texturing only if COLOROP was not already disabled... */
2023 if ((glThis->current_bound_texture[dwStage] != NULL) &&
2024 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
2025 glEnable(GL_TEXTURE_2D);
2026 TRACE(" enabling 2D texturing.\n");
2029 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
2030 if ((dwState != D3DTOP_DISABLE) &&
2031 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
2032 if (glThis->current_tex_env != GL_COMBINE_EXT) {
2033 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
2034 glThis->current_tex_env = GL_COMBINE_EXT;
2038 /* Now set up the operand correctly */
2040 case D3DTOP_DISABLE:
2041 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2042 and it works, so ignore this op */
2043 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2046 case D3DTOP_SELECTARG1:
2047 case D3DTOP_SELECTARG2:
2048 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2051 case D3DTOP_MODULATE4X:
2052 scale = scale * 2; /* Drop through */
2053 case D3DTOP_MODULATE2X:
2054 scale = scale * 2; /* Drop through */
2055 case D3DTOP_MODULATE:
2056 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2060 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2063 case D3DTOP_ADDSIGNED2X:
2064 scale = scale * 2; /* Drop through */
2065 case D3DTOP_ADDSIGNED:
2066 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2069 /* For the four blending modes, use the Arg2 parameter */
2070 case D3DTOP_BLENDDIFFUSEALPHA:
2071 case D3DTOP_BLENDTEXTUREALPHA:
2072 case D3DTOP_BLENDFACTORALPHA:
2073 case D3DTOP_BLENDCURRENTALPHA: {
2074 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2077 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2078 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2079 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2080 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2083 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2084 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2085 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2086 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2087 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2096 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2097 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2098 /* Switch the arguments if needed... */
2099 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2100 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2101 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2103 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2104 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2107 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2108 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2110 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2111 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2117 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2118 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2120 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2122 TRACE(" Stage type is : %s => %s\n", type, value);
2124 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2128 case D3DTSS_COLORARG1:
2129 case D3DTSS_COLORARG2:
2130 case D3DTSS_ALPHAARG1:
2131 case D3DTSS_ALPHAARG2: {
2132 const char *value, *value_comp = "", *value_alpha = "";
2134 D3DTEXTUREOP tex_op;
2136 switch (dwState & D3DTA_SELECTMASK) {
2137 #define GEN_CASE(a) case a: value = #a; break
2138 GEN_CASE(D3DTA_DIFFUSE);
2139 GEN_CASE(D3DTA_CURRENT);
2140 GEN_CASE(D3DTA_TEXTURE);
2141 GEN_CASE(D3DTA_TFACTOR);
2142 GEN_CASE(D3DTA_SPECULAR);
2144 default: value = "UNKNOWN";
2146 if (dwState & D3DTA_COMPLEMENT) {
2147 value_comp = " | D3DTA_COMPLEMENT";
2149 if (dwState & D3DTA_ALPHAREPLICATE) {
2150 value_alpha = " | D3DTA_ALPHAREPLICATE";
2153 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2154 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2156 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2159 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2162 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2164 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2168 case D3DTSS_MIPMAPLODBIAS: {
2169 D3DVALUE value = *((D3DVALUE *) &dwState);
2170 BOOLEAN handled = TRUE;
2172 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2176 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2177 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2179 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2183 case D3DTSS_MAXMIPLEVEL:
2184 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2187 case D3DTSS_BORDERCOLOR:
2188 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2189 ((dwState >> 16) & 0xFF),
2190 ((dwState >> 8) & 0xFF),
2191 ((dwState >> 0) & 0xFF),
2192 ((dwState >> 24) & 0xFF));
2195 case D3DTSS_TEXCOORDINDEX: {
2196 BOOLEAN handled = TRUE;
2199 switch (dwState & 0xFFFF0000) {
2200 #define GEN_CASE(a) case a: value = #a; break
2201 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2202 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2203 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2204 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2206 default: value = "UNKNOWN";
2208 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2212 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2214 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2218 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2219 const char *projected = "", *value;
2220 BOOLEAN handled = TRUE;
2221 switch (dwState & 0xFF) {
2222 #define GEN_CASE(a) case a: value = #a; break
2223 GEN_CASE(D3DTTFF_DISABLE);
2224 GEN_CASE(D3DTTFF_COUNT1);
2225 GEN_CASE(D3DTTFF_COUNT2);
2226 GEN_CASE(D3DTTFF_COUNT3);
2227 GEN_CASE(D3DTTFF_COUNT4);
2229 default: value = "UNKNOWN";
2231 if (dwState & D3DTTFF_PROJECTED) {
2232 projected = " | D3DTTFF_PROJECTED";
2236 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2237 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2241 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2243 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2248 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2258 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2260 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2262 BOOLEAN enable_colorkey = FALSE;
2264 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2265 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2268 /* If this stage is disabled, no need to go further... */
2269 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2272 /* First check if we need to bind any other texture for this stage */
2273 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2274 if (This->current_texture[stage] == NULL) {
2275 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2277 unit = GL_TEXTURE0_WINE + stage;
2278 if (unit != glThis->current_active_tex_unit) {
2279 GL_extensions.glActiveTexture(unit);
2280 glThis->current_active_tex_unit = unit;
2282 glBindTexture(GL_TEXTURE_2D, 0);
2283 glDisable(GL_TEXTURE_2D);
2285 GLenum tex_name = gltex_get_tex_name(surf_ptr);
2287 unit = GL_TEXTURE0_WINE + stage;
2288 if (unit != glThis->current_active_tex_unit) {
2289 GL_extensions.glActiveTexture(unit);
2290 glThis->current_active_tex_unit = unit;
2293 if (glThis->current_bound_texture[stage] == NULL) {
2294 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2295 TRACE(" enabling 2D texturing and");
2296 glEnable(GL_TEXTURE_2D);
2299 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2300 glBindTexture(GL_TEXTURE_2D, tex_name);
2303 glThis->current_bound_texture[stage] = This->current_texture[stage];
2305 if (glThis->current_bound_texture[stage] == NULL) {
2306 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2308 TRACE(" using already bound texture id %d for stage %ld.\n",
2309 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2313 /* If no texure valid for this stage, go out of the loop */
2314 if (This->current_texture[stage] == NULL) break;
2316 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2317 This will also update the various texture parameters if needed.
2319 gltex_upload_texture(surf_ptr, This, stage);
2321 /* And finally check for color-keying (only on first stage) */
2322 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2324 enable_colorkey = TRUE;
2326 static BOOL warn = FALSE;
2327 if (warn == FALSE) {
2329 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2334 enable_colorkey = FALSE;
2339 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2340 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2341 (glThis->parent.version == 1)) &&
2342 (enable_colorkey)) {
2343 TRACE(" colorkey activated.\n");
2345 if (glThis->alpha_test == FALSE) {
2346 glEnable(GL_ALPHA_TEST);
2347 glThis->alpha_test = TRUE;
2349 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2350 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1]) {
2351 static BOOL warn = FALSE;
2352 if (warn == FALSE) {
2354 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2357 glThis->current_alpha_test_func = GL_NOTEQUAL;
2358 glThis->current_alpha_test_ref = 0.0;
2359 glAlphaFunc(GL_NOTEQUAL, 0.0);
2361 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2362 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2364 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2365 glDisable(GL_ALPHA_TEST);
2366 glThis->alpha_test = FALSE;
2368 /* Maybe we should restore here the application-given alpha test states ? */
2375 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2377 LPDIRECTDRAWSURFACE7 lpTexture2)
2379 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2381 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2383 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2384 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2385 if (lpTexture2 != NULL) {
2386 WARN(" setting a texture to a non-supported texture stage !\n");
2391 if (This->current_texture[dwStage] != NULL) {
2392 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2395 if (lpTexture2 == NULL) {
2396 This->current_texture[dwStage] = NULL;
2398 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2399 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2400 This->current_texture[dwStage] = tex_impl;
2407 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2408 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2410 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2411 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2413 fill_opengl_caps_7(lpD3DHELDevDesc);
2415 TRACE(" returning caps : no dump function yet.\n");
2421 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2422 LPD3DMATERIAL7 lpMat)
2424 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2425 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2427 if (TRACE_ON(ddraw)) {
2428 TRACE(" material is : \n");
2429 dump_D3DMATERIAL7(lpMat);
2432 This->current_material = *lpMat;
2435 glMaterialfv(GL_FRONT_AND_BACK,
2437 (float *) &(This->current_material.u.diffuse));
2438 glMaterialfv(GL_FRONT_AND_BACK,
2440 (float *) &(This->current_material.u1.ambient));
2441 glMaterialfv(GL_FRONT_AND_BACK,
2443 (float *) &(This->current_material.u2.specular));
2444 glMaterialfv(GL_FRONT_AND_BACK,
2446 (float *) &(This->current_material.u3.emissive));
2447 glMaterialf(GL_FRONT_AND_BACK,
2449 This->current_material.u4.power); /* Not sure about this... */
2455 static LPD3DLIGHT7 get_light(IDirect3DDeviceImpl *This, DWORD dwLightIndex)
2457 if (dwLightIndex >= This->num_set_lights)
2459 /* Extend, or allocate the light parameters array. */
2460 DWORD newlightnum = dwLightIndex + 1;
2461 LPD3DLIGHT7 newarrayptr = NULL;
2463 if (This->light_parameters)
2464 newarrayptr = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2465 This->light_parameters, newlightnum * sizeof(D3DLIGHT7));
2467 newarrayptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2468 newlightnum * sizeof(D3DLIGHT7));
2473 This->light_parameters = newarrayptr;
2474 This->num_set_lights = newlightnum;
2477 return &This->light_parameters[dwLightIndex];
2481 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2483 LPD3DLIGHT7 lpLight)
2485 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2486 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2487 LPD3DLIGHT7 lpdestlight = get_light( This, dwLightIndex );
2489 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2491 if (TRACE_ON(ddraw)) {
2492 TRACE(" setting light : \n");
2493 dump_D3DLIGHT7(lpLight);
2496 /* DirectX7 documentation states that this function can return
2497 DDERR_OUTOFMEMORY, so we do just that in case of an allocation
2498 error (which is the only reason why get_light() can fail). */
2500 return DDERR_OUTOFMEMORY;
2502 *lpdestlight = *lpLight;
2504 /* Some checks to print out nice warnings :-) */
2505 switch (lpLight->dltType) {
2506 case D3DLIGHT_DIRECTIONAL:
2507 case D3DLIGHT_POINT:
2508 /* These are handled properly... */
2512 if ((lpLight->dvTheta != 0.0) ||
2513 (lpLight->dvTheta != lpLight->dvPhi)) {
2514 ERR("dvTheta not fully supported yet !\n");
2519 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2522 /* This will force the Light setting on next drawing of primitives */
2523 glThis->transform_state = GL_TRANSFORM_NONE;
2529 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2533 int lightslot = -1, i;
2534 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2535 LPD3DLIGHT7 lpdestlight = get_light(This, dwLightIndex);
2537 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2539 /* The DirectX doc isn't as explicit as for SetLight as whether we can
2540 return this from this function, but it doesn't state otherwise. */
2542 return DDERR_OUTOFMEMORY;
2544 /* If this light hasn't been set, initialise it with default values. */
2545 if (lpdestlight->dltType == 0)
2547 TRACE("setting default light parameters\n");
2549 /* We always use HEAP_ZERO_MEMORY when allocating the light_parameters
2550 array, so we only have to setup anything that shoud not be zero. */
2551 lpdestlight->dltType = D3DLIGHT_DIRECTIONAL;
2552 lpdestlight->dcvDiffuse.u1.r = 1.f;
2553 lpdestlight->dcvDiffuse.u2.g = 1.f;
2554 lpdestlight->dcvDiffuse.u3.b = 1.f;
2555 lpdestlight->dvDirection.u3.z = 1.f;
2558 /* Look for this light in the active lights array. */
2559 for (i = 0; i < This->max_active_lights; i++)
2560 if (This->active_lights[i] == dwLightIndex)
2566 /* If we didn't find it, let's find the first available slot, if any. */
2567 if (lightslot == -1)
2568 for (i = 0; i < This->max_active_lights; i++)
2569 if (This->active_lights[i] == ~0)
2577 if (lightslot == -1)
2579 /* This means that the app is trying to enable more lights than
2580 the maximum possible indicated in the caps.
2582 Windows actually let you do this, and disable one of the
2583 previously enabled lights to let you enable this one.
2585 It's not documented and I'm not sure how windows pick which light
2586 to disable to make room for this one. */
2587 FIXME("Enabling more light than the maximum is not supported yet.");
2591 glEnable(GL_LIGHT0 + lightslot);
2594 if (This->active_lights[lightslot] == ~0)
2596 /* This light gets active... Need to update its parameters to GL before the next drawing */
2597 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2599 This->active_lights[lightslot] = dwLightIndex;
2600 glThis->transform_state = GL_TRANSFORM_NONE;
2603 glDisable(GL_LIGHT0 + lightslot);
2604 This->active_lights[lightslot] = ~0;
2612 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2614 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2615 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2617 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2619 if (dwIndex >= This->max_clipping_planes) {
2620 return DDERR_INVALIDPARAMS;
2623 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2625 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2627 /* This is to force the reset of the transformation matrices on the next drawing.
2628 * This is needed to use the correct matrices for the various clipping planes.
2630 glThis->transform_state = GL_TRANSFORM_NONE;
2636 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2637 LPD3DVIEWPORT7 lpData)
2639 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2640 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2642 if (TRACE_ON(ddraw)) {
2643 TRACE(" viewport is : \n");
2644 TRACE(" - dwX = %ld dwY = %ld\n",
2645 lpData->dwX, lpData->dwY);
2646 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2647 lpData->dwWidth, lpData->dwHeight);
2648 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2649 lpData->dvMinZ, lpData->dvMaxZ);
2653 /* Set the viewport */
2654 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2655 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2656 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2658 if ((lpData->dwX != This->active_viewport.dwX) ||
2659 (lpData->dwY != This->active_viewport.dwY) ||
2660 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2661 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2662 glViewport(lpData->dwX,
2663 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2664 lpData->dwWidth, lpData->dwHeight);
2669 This->active_viewport = *lpData;
2674 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2675 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2677 # define XCAST(fun) (void*)
2680 static const IDirect3DDevice7Vtbl VTABLE_IDirect3DDevice7 =
2682 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2683 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2684 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2685 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2686 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2687 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2688 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2689 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2690 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2691 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2692 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2693 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2694 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2695 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2696 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2697 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2698 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2699 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2700 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2701 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2702 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2703 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2704 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2705 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2706 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2707 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2708 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2709 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2710 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2711 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2712 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2713 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2714 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2715 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2716 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2717 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2718 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2719 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2720 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2721 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2722 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2723 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2724 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2725 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2726 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2727 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2728 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2729 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2730 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2733 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2738 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2739 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2741 # define XCAST(fun) (void*)
2744 static const IDirect3DDevice3Vtbl VTABLE_IDirect3DDevice3 =
2746 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2747 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2748 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2749 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2750 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2751 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2752 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2753 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2754 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2755 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2756 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2757 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2758 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2759 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2760 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2761 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2762 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2763 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2764 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2765 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2766 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2767 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2768 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2769 XCAST(GetLightState) GL_IDirect3DDeviceImpl_3_2T_GetLightState,
2770 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2771 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2772 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2773 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2774 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2775 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2776 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2777 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2778 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2779 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2780 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2781 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2782 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2783 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2784 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2785 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2786 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2787 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2790 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2795 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2796 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2798 # define XCAST(fun) (void*)
2801 static const IDirect3DDevice2Vtbl VTABLE_IDirect3DDevice2 =
2803 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2804 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2805 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2806 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2807 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2808 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2809 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2810 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2811 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2812 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2813 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2814 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2815 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2816 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2817 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2818 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2819 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2820 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2821 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2822 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2823 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2824 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2825 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2826 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2827 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2828 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2829 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2830 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2831 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2832 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2833 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2834 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2835 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2838 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2843 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2844 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2846 # define XCAST(fun) (void*)
2849 static const IDirect3DDeviceVtbl VTABLE_IDirect3DDevice =
2851 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2852 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2853 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2854 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2855 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2856 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2857 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2858 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2859 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2860 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2861 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2862 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2863 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2864 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2865 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2866 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2867 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2868 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2869 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2870 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2871 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2872 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2875 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2879 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2880 WINE_GL_BUFFER_TYPE buffer_type,
2888 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2889 GLbitfield bitfield = 0;
2893 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2894 if (TRACE_ON(ddraw)) {
2897 TRACE(" rectangles : \n");
2898 for (i = 0; i < dwCount; i++) {
2899 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2908 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2909 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2913 /* Clears the screen */
2916 if (dwFlags & D3DCLEAR_TARGET) {
2917 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2918 /* TODO: optimize here the case where Clear changes all the screen... */
2919 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2921 glThis->state[buffer_type] = SURFACE_GL;
2924 if (dwFlags & D3DCLEAR_ZBUFFER) {
2925 bitfield |= GL_DEPTH_BUFFER_BIT;
2926 if (glThis->depth_mask == FALSE) {
2927 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2929 if (dvZ != glThis->prev_clear_Z) {
2931 glThis->prev_clear_Z = dvZ;
2933 TRACE(" depth value : %f\n", dvZ);
2935 if (dwFlags & D3DCLEAR_STENCIL) {
2936 bitfield |= GL_STENCIL_BUFFER_BIT;
2937 if (dwStencil != glThis->prev_clear_stencil) {
2938 glClearStencil(dwStencil);
2939 glThis->prev_clear_stencil = dwStencil;
2941 TRACE(" stencil value : %ld\n", dwStencil);
2943 if (dwFlags & D3DCLEAR_TARGET) {
2944 bitfield |= GL_COLOR_BUFFER_BIT;
2945 if (dwColor != glThis->prev_clear_color) {
2946 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2947 ((dwColor >> 8) & 0xFF) / 255.0,
2948 ((dwColor >> 0) & 0xFF) / 255.0,
2949 ((dwColor >> 24) & 0xFF) / 255.0);
2950 glThis->prev_clear_color = dwColor;
2952 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2955 glEnable(GL_SCISSOR_TEST);
2956 for (i = 0; i < dwCount; i++) {
2957 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2958 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2961 glDisable(GL_SCISSOR_TEST);
2963 if (dwFlags & D3DCLEAR_ZBUFFER) {
2964 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2972 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2980 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2984 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2985 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2987 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2988 WINE_GL_BUFFER_TYPE buffer_type;
2990 /* First check if we BLT to the backbuffer... */
2991 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2992 buffer_type = WINE_GL_BUFFER_BACK;
2993 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2994 buffer_type = WINE_GL_BUFFER_FRONT;
2996 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2997 return DDERR_INVALIDPARAMS;
3000 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
3001 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
3002 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
3003 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
3004 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3005 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
3008 return DDERR_INVALIDPARAMS;
3010 *buffer_type_p = buffer_type;
3016 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
3017 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
3018 DWORD dwFlags, LPDDBLTFX lpbltfx)
3020 WINE_GL_BUFFER_TYPE buffer_type;
3024 rect.u1.x1 = rdst->left;
3025 rect.u2.y1 = rdst->top;
3026 rect.u3.x2 = rdst->right;
3027 rect.u4.y2 = rdst->bottom;
3031 rect.u3.x2 = This->surface_desc.dwWidth;
3032 rect.u4.y2 = This->surface_desc.dwHeight;
3035 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
3037 if (dwFlags & DDBLT_COLORFILL) {
3038 /* This is easy to handle for the D3D Device... */
3042 /* The color as given in the Blt function is in the format of the frame-buffer...
3043 * 'clear' expect it in ARGB format => we need to do some conversion :-)
3045 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
3046 if (This->palette) {
3047 color = ((0xFF000000) |
3048 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
3049 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
3050 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
3054 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
3055 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3056 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3057 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3058 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3059 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3060 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3061 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
3064 color = ((0xFF000000) |
3065 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
3066 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
3067 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
3069 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
3070 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
3071 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3072 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3073 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3074 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
3076 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
3077 return DDERR_INVALIDPARAMS;
3080 ERR("Wrong surface type for BLT override !\n");
3081 return DDERR_INVALIDPARAMS;
3084 TRACE(" executing D3D Device override.\n");
3088 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3089 if (buffer_type == WINE_GL_BUFFER_FRONT)
3090 glDrawBuffer(GL_FRONT);
3092 glDrawBuffer(GL_BACK);
3094 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
3096 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3097 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3098 glDrawBuffer(prev_draw);
3103 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
3104 /* Normal blit without any special case... */
3106 /* And which has a SRC surface */
3107 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3109 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
3110 (src_impl->d3ddevice == This->d3ddevice) &&
3111 ((dwFlags & DDBLT_KEYSRC) == 0)) {
3112 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3116 WINE_GL_BUFFER_TYPE src_buffer_type;
3117 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3123 src_rect.u1.x1 = rsrc->left;
3124 src_rect.u2.y1 = rsrc->top;
3125 src_rect.u3.x2 = rsrc->right;
3126 src_rect.u4.y2 = rsrc->bottom;
3130 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3131 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3134 width = src_rect.u3.x2 - src_rect.u1.x1;
3135 height = src_rect.u4.y2 - src_rect.u2.y1;
3137 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3138 (height != (rect.u4.y2 - rect.u2.y1))) {
3139 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3140 return DDERR_INVALIDPARAMS;
3143 /* First check if we BLT from the backbuffer... */
3144 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3145 src_buffer_type = WINE_GL_BUFFER_BACK;
3146 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3147 src_buffer_type = WINE_GL_BUFFER_FRONT;
3149 ERR("Unexpected case in direct buffer to buffer copy !\n");
3150 return DDERR_INVALIDPARAMS;
3153 TRACE(" using direct buffer to buffer copy.\n");
3157 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3159 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3160 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3161 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3163 return DDERR_INVALIDPARAMS;
3166 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3167 if (buffer_type == WINE_GL_BUFFER_FRONT)
3168 glDrawBuffer(GL_FRONT);
3170 glDrawBuffer(GL_BACK);
3172 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3173 glReadBuffer(GL_FRONT);
3175 glReadBuffer(GL_BACK);
3177 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3178 And directly re-draws this on the destination buffer. */
3179 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3182 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3183 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3185 get_height = UNLOCK_TEX_SIZE;
3187 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3190 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3191 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3193 get_width = UNLOCK_TEX_SIZE;
3195 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3196 0, UNLOCK_TEX_SIZE - get_height,
3197 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3198 get_width, get_height);
3201 glTexCoord2f(0.0, 0.0);
3202 glVertex3d(rect.u1.x1 + x,
3203 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3205 glTexCoord2f(1.0, 0.0);
3206 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3207 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3209 glTexCoord2f(1.0, 1.0);
3210 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3213 glTexCoord2f(0.0, 1.0);
3214 glVertex3d(rect.u1.x1 + x,
3221 upload_surface_to_tex_memory_release();
3222 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3224 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3225 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3226 glDrawBuffer(prev_draw);
3232 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3233 (this prevents calling glReadPixels) */
3237 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3241 double x_stretch, y_stretch;
3244 src_rect.u1.x1 = rsrc->left;
3245 src_rect.u2.y1 = rsrc->top;
3246 src_rect.u3.x2 = rsrc->right;
3247 src_rect.u4.y2 = rsrc->bottom;
3251 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3252 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3255 width = src_rect.u3.x2 - src_rect.u1.x1;
3256 height = src_rect.u4.y2 - src_rect.u2.y1;
3258 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3259 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3261 TRACE(" using memory to buffer Blt override.\n");
3265 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3267 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3268 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3269 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3271 return DDERR_INVALIDPARAMS;
3274 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3275 if (buffer_type == WINE_GL_BUFFER_FRONT)
3276 glDrawBuffer(GL_FRONT);
3278 glDrawBuffer(GL_BACK);
3280 /* Now the serious stuff happens. This is basically the same code as for the memory
3281 flush to frame buffer ... with stretching and different rectangles added :-) */
3282 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3285 flush_rect.top = src_rect.u2.y1 + y;
3286 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3288 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3290 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3291 flush_rect.left = src_rect.u1.x1 + x;
3292 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3294 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3296 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3299 glTexCoord2f(0.0, 0.0);
3300 glVertex3d(rect.u1.x1 + (x * x_stretch),
3301 rect.u2.y1 + (y * y_stretch),
3303 glTexCoord2f(1.0, 0.0);
3304 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3305 rect.u2.y1 + (y * y_stretch),
3307 glTexCoord2f(1.0, 1.0);
3308 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3309 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3311 glTexCoord2f(0.0, 1.0);
3312 glVertex3d(rect.u1.x1 + (x * x_stretch),
3313 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3319 upload_surface_to_tex_memory_release();
3320 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3322 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3323 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3324 glDrawBuffer(prev_draw);
3332 return DDERR_INVALIDPARAMS;
3336 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3337 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3338 LPRECT rsrc, DWORD trans)
3342 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3343 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3344 WINE_GL_BUFFER_TYPE buffer_type;
3348 int width, height, x, y;
3350 /* Cannot support DSTCOLORKEY blitting... */
3351 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3354 WARN("rsrc is NULL - getting the whole surface !!\n");
3356 rsrc->left = rsrc->top = 0;
3357 rsrc->right = src_impl->surface_desc.dwWidth;
3358 rsrc->bottom = src_impl->surface_desc.dwHeight;
3366 rdst.right = dstx + (rsrc->right - rsrc->left);
3367 if (rdst.right > This->surface_desc.dwWidth) {
3368 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3369 rdst.right = This->surface_desc.dwWidth;
3371 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3372 if (rdst.bottom > This->surface_desc.dwHeight) {
3373 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3374 rdst.bottom = This->surface_desc.dwHeight;
3377 width = rsrc->right - rsrc->left;
3378 height = rsrc->bottom - rsrc->top;
3380 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3382 TRACE(" using BltFast memory to frame buffer override.\n");
3386 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3388 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3389 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3390 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3391 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3393 return DDERR_INVALIDPARAMS;
3396 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3397 if (buffer_type == WINE_GL_BUFFER_FRONT)
3398 glDrawBuffer(GL_FRONT);
3400 glDrawBuffer(GL_BACK);
3402 /* Now the serious stuff happens. This is basically the same code that for the memory
3403 flush to frame buffer but with different rectangles for source and destination :-) */
3404 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3407 flush_rect.top = rsrc->top + y;
3408 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3410 (rsrc->top + y + UNLOCK_TEX_SIZE));
3412 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3413 flush_rect.left = rsrc->left + x;
3414 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3416 (rsrc->left + x + UNLOCK_TEX_SIZE));
3418 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3421 glTexCoord2f(0.0, 0.0);
3422 glVertex3d(rdst.left + x,
3425 glTexCoord2f(1.0, 0.0);
3426 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3429 glTexCoord2f(1.0, 1.0);
3430 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3431 rdst.top + (y + UNLOCK_TEX_SIZE),
3433 glTexCoord2f(0.0, 1.0);
3434 glVertex3d(rdst.left + x,
3435 rdst.top + (y + UNLOCK_TEX_SIZE),
3441 upload_surface_to_tex_memory_release();
3442 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3444 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3445 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3446 glDrawBuffer(prev_draw);
3454 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3456 GLfloat height, width;
3457 GLfloat trans_mat[16];
3459 TRACE("(%p)\n", This);
3461 width = This->surface->surface_desc.dwWidth;
3462 height = This->surface->surface_desc.dwHeight;
3464 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3465 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3467 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3468 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3470 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3471 * that the Z coordinate needs to be given to GL unchanged.
3473 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3475 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = 0.0;
3476 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3479 glMatrixMode(GL_MODELVIEW);
3481 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3482 Correctness Tips section).
3484 Basically, from what I understood, if the game does not filter the font texture,
3485 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3486 one and we will have strange artifacts (as the rounding and stuff may give different results
3487 for different pixels, ie sometimes take the left pixel, sometimes the right).
3489 glTranslatef(0.375, 0.375, 0);
3490 glMatrixMode(GL_PROJECTION);
3491 glLoadMatrixf(trans_mat);
3496 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3497 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3499 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3502 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3503 glMatrixMode(GL_MODELVIEW);
3504 glLoadMatrixf((float *) view_mat);
3506 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3507 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3510 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3511 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3514 plane[0] = This->clipping_planes[i].plane[0];
3515 plane[1] = This->clipping_planes[i].plane[1];
3516 plane[2] = This->clipping_planes[i].plane[2];
3517 plane[3] = This->clipping_planes[i].plane[3];
3519 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3523 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3526 for (i = 0; i < This->max_active_lights; i++ )
3528 DWORD dwLightIndex = This->active_lights[i];
3529 if (dwLightIndex != ~0)
3531 LPD3DLIGHT7 pLight = &This->light_parameters[dwLightIndex];
3532 switch (pLight->dltType)
3534 case D3DLIGHT_DIRECTIONAL: {
3536 float cut_off = 180.0;
3538 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3539 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3540 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3541 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3543 direction[0] = pLight->dvDirection.u1.x;
3544 direction[1] = pLight->dvDirection.u2.y;
3545 direction[2] = pLight->dvDirection.u3.z;
3547 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3550 case D3DLIGHT_POINT: {
3552 float cut_off = 180.0;
3554 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3555 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3556 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3557 position[0] = pLight->dvPosition.u1.x;
3558 position[1] = pLight->dvPosition.u2.y;
3559 position[2] = pLight->dvPosition.u3.z;
3561 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3562 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3563 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3564 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
3565 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3568 case D3DLIGHT_SPOT: {
3571 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3573 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3574 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3575 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3577 direction[0] = pLight->dvDirection.u1.x;
3578 direction[1] = pLight->dvDirection.u2.y;
3579 direction[2] = pLight->dvDirection.u3.z;
3581 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3582 position[0] = pLight->dvPosition.u1.x;
3583 position[1] = pLight->dvPosition.u2.y;
3584 position[2] = pLight->dvPosition.u3.z;
3586 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3587 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3588 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3589 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
3590 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3591 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &pLight->dvFalloff);
3595 /* No warning here as it's already done at light setting */
3602 glMultMatrixf((float *) world_mat);
3604 if ((matrices & PROJMAT_CHANGED) != 0) {
3605 glMatrixMode(GL_PROJECTION);
3606 glLoadMatrixf((float *) proj_mat);
3612 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3614 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3615 DWORD tex_mat, tex_stage;
3617 TRACE("(%p,%08lx)\n", This, matrices);
3619 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3620 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3621 /* This will force an update of the transform state at the next drawing. */
3622 glThis->transform_state = GL_TRANSFORM_NONE;
3625 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3626 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3629 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3630 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3631 if (matrices & tex_mat) {
3632 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3633 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3635 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3636 if (glThis->current_active_tex_unit != unit) {
3637 GL_extensions.glActiveTexture(unit);
3638 glThis->current_active_tex_unit = unit;
3640 glMatrixMode(GL_TEXTURE);
3641 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3643 This->tex_mat_is_identity[tex_stage] = is_identity;
3645 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3646 if (glThis->current_active_tex_unit != unit) {
3647 GL_extensions.glActiveTexture(unit);
3648 glThis->current_active_tex_unit = unit;
3650 glMatrixMode(GL_TEXTURE);
3652 This->tex_mat_is_identity[tex_stage] = TRUE;
3661 /* TODO for both these functions :
3662 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3663 by other OpenGL code in D3D
3664 - handle the case where no 'Begin / EndScene' was done between two locks
3665 - handle the rectangles in the unlock too
3666 - handle pitch correctly...
3668 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3670 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3671 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3672 WINE_GL_BUFFER_TYPE buffer_type;
3675 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3676 buffer_type = WINE_GL_BUFFER_FRONT;
3677 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3678 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3679 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3681 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3682 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3683 buffer_type = WINE_GL_BUFFER_BACK;
3684 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3685 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3686 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3688 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3690 ERR("Wrong surface type for locking !\n");
3694 if (pRect == NULL) {
3697 loc_rect.bottom = This->surface_desc.dwHeight;
3698 loc_rect.right = This->surface_desc.dwWidth;
3702 /* Try to acquire the device critical section */
3703 EnterCriticalSection(&(d3d_dev->crit));
3705 if (gl_d3d_dev->lock_rect_valid[buffer_type]) {
3706 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3707 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3709 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3711 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3712 /* Check if the new rectangle is in the previous one or not.
3713 If it is not, flush first the previous locks on screen.
3715 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3716 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3717 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3718 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3719 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3720 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3721 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3722 pRect->left, pRect->top, pRect->right, pRect->bottom,
3723 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3724 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3725 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3727 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3728 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3730 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3732 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3735 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3736 /* If the surface is already in memory, no need to do anything here... */
3737 GLenum buffer_format;
3738 GLenum buffer_color;
3742 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3743 pRect->left, pRect->top, pRect->right, pRect->bottom);
3745 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3746 may only write to the device... But when we will blit it back to the screen, we need
3747 also to blit correctly the parts the application did not overwrite... */
3749 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3750 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3751 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3752 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3753 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3754 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3755 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3756 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3757 buffer_color = GL_RGB;
3758 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3759 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3760 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3761 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3762 buffer_format = GL_UNSIGNED_BYTE;
3763 buffer_color = GL_RGB;
3764 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3765 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3766 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3767 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3768 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3769 buffer_color = GL_BGRA;
3771 ERR(" unsupported pixel format at device locking.\n");
3775 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3781 if (buffer_type == WINE_GL_BUFFER_FRONT)
3782 /* Application wants to lock the front buffer */
3783 glReadBuffer(GL_FRONT);
3785 /* Application wants to lock the back buffer */
3786 glReadBuffer(GL_BACK);
3788 dst = ((char *)This->surface_desc.lpSurface) +
3789 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3791 if (This->surface_desc.u1.lPitch != (GET_BPP(This->surface_desc) * This->surface_desc.dwWidth)) {
3792 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3793 * could not be bothered considering the rare cases where it may be useful :-)
3795 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3796 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3798 glReadPixels(pRect->left, y,
3799 pRect->right - pRect->left, 1,
3800 buffer_color, buffer_format, dst);
3801 dst += This->surface_desc.u1.lPitch;
3804 /* Faster path for surface copy. Note that I can use static variables here as I am
3805 * protected by the OpenGL critical section so this function won't be called by
3806 * two threads at the same time.
3808 static char *buffer = NULL;
3809 static int buffer_width = 0;
3810 char *dst2 = dst + ((pRect->bottom - pRect->top) - 1) * This->surface_desc.u1.lPitch;
3811 int current_width = (pRect->right - pRect->left) * GET_BPP(This->surface_desc);
3813 glReadPixels(pRect->left, ((int) This->surface_desc.dwHeight - (int) pRect->bottom),
3814 pRect->right - pRect->left, pRect->bottom - pRect->top,
3815 buffer_color, buffer_format, dst);
3817 if (current_width > buffer_width) {
3818 if (buffer != NULL) HeapFree(GetProcessHeap(), 0, buffer);
3819 buffer_width = current_width;
3820 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_width);
3822 for (y = 0; y < ((pRect->bottom - pRect->top) / 2); y++) {
3823 memcpy(buffer, dst, current_width);
3824 memcpy(dst, dst2, current_width);
3825 memcpy(dst2, buffer, current_width);
3826 dst += This->surface_desc.u1.lPitch;
3827 dst2 -= This->surface_desc.u1.lPitch;
3831 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3834 /* I keep this code here as it's very useful to debug :-) */
3836 static int flush_count = 0;
3840 if ((++flush_count % 50) == 0) {
3841 sprintf(buf, "lock_%06d.pnm", flush_count);
3842 f = fopen(buf, "wb");
3843 DDRAW_dump_surface_to_disk(This, f);
3852 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3854 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3859 /* Note : no need here to lock the 'device critical section' as we are already protected by
3860 the GL critical section. */
3862 if (pRect == NULL) {
3865 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3866 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3870 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3872 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3874 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3875 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3876 ERR(" unsupported pixel format at frame buffer flush.\n");
3880 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3884 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3886 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3887 /* First, upload the texture... */
3888 flush_rect.left = x;
3889 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3891 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3894 glTexCoord2f(0.0, 0.0);
3895 glVertex3d(x, y, 0.5);
3896 glTexCoord2f(1.0, 0.0);
3897 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3898 glTexCoord2f(1.0, 1.0);
3899 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3900 glTexCoord2f(0.0, 1.0);
3901 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3906 upload_surface_to_tex_memory_release();
3907 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3910 /* I keep this code here as it's very useful to debug :-) */
3912 static int flush_count = 0;
3916 if ((++flush_count % 50) == 0) {
3917 sprintf(buf, "flush_%06d.pnm", flush_count);
3918 f = fopen(buf, "wb");
3919 DDRAW_dump_surface_to_disk(surf, f);
3925 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3927 WINE_GL_BUFFER_TYPE buffer_type;
3928 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3929 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3931 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3932 buffer_type = WINE_GL_BUFFER_FRONT;
3933 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3934 buffer_type = WINE_GL_BUFFER_BACK;
3936 ERR("Wrong surface type for locking !\n");
3940 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3941 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3942 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3944 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3946 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3947 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3948 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3951 TRACE(" flushing front buffer immediately on screen.\n");
3954 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3955 glDrawBuffer(GL_FRONT);
3956 /* Note: we do not use the application provided lock rectangle but our own stored at
3957 lock time. This is because in old D3D versions, the 'lock' parameter did not
3960 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]);
3961 glDrawBuffer(prev_draw);
3964 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3968 /* And 'frees' the device critical section */
3969 LeaveCriticalSection(&(d3d_dev->crit));
3973 apply_texture_state(IDirect3DDeviceImpl *This)
3977 /* Initialize texture stages states */
3978 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3979 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3980 if (This->state_block.set_flags.texture_stage_state[stage][state]) {
3981 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3982 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3989 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, int version)
3991 IDirect3DDeviceImpl *object;
3992 IDirect3DDeviceGLImpl *gl_object;
3993 IDirectDrawSurfaceImpl *surf;
3998 XVisualInfo template;
3999 GLenum buffer = GL_FRONT;
4002 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
4003 if (object == NULL) return DDERR_OUTOFMEMORY;
4005 gl_object = (IDirect3DDeviceGLImpl *) object;
4009 object->surface = surface;
4010 object->set_context = set_context;
4011 object->clear = d3ddevice_clear_back;
4012 object->set_matrices = d3ddevice_set_matrices;
4013 object->matrices_updated = d3ddevice_matrices_updated;
4014 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
4015 object->version = version;
4017 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
4019 InitializeCriticalSection(&(object->crit));
4021 TRACE(" device critical section : %p\n", &(object->crit));
4023 device_context = GetDC(surface->ddraw_owner->window);
4024 gl_object->display = get_display(device_context);
4025 gl_object->drawable = get_drawable(device_context);
4026 ReleaseDC(surface->ddraw_owner->window,device_context);
4029 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
4030 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
4032 HeapFree(GetProcessHeap(), 0, object);
4033 ERR("No visual found !\n");
4035 return DDERR_INVALIDPARAMS;
4037 TRACE(" visual found\n");
4040 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
4043 if (gl_object->gl_context == NULL) {
4044 HeapFree(GetProcessHeap(), 0, object);
4045 ERR("Error in context creation !\n");
4047 return DDERR_INVALIDPARAMS;
4049 TRACE(" context created (%p)\n", gl_object->gl_context);
4052 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
4053 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4054 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
4055 surf->aux_ctx = (LPVOID) object;
4056 surf->aux_data = (LPVOID) gl_object->drawable;
4057 surf->aux_flip = opengl_flip;
4062 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
4064 TRACE(" no double buffering : drawing on the front buffer\n");
4068 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4069 IDirectDrawSurfaceImpl *surf2;
4070 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
4071 for (; surf2 != NULL; surf2 = surf2->next_attached) {
4072 TRACE(" checking surface %p :", surf2);
4073 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
4074 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
4075 /* Override the Lock / Unlock function for all these surfaces */
4076 surf2->lock_update_prev = surf2->lock_update;
4077 surf2->lock_update = d3ddevice_lock_update;
4078 surf2->unlock_update_prev = surf2->unlock_update;
4079 surf2->unlock_update = d3ddevice_unlock_update;
4080 /* And install also the blt / bltfast overrides */
4081 surf2->aux_blt = d3ddevice_blt;
4082 surf2->aux_bltfast = d3ddevice_bltfast;
4084 TRACE(" overriding direct surface access.\n");
4086 TRACE(" no override.\n");
4088 surf2->d3ddevice = object;
4092 /* Set the various light parameters */
4093 object->num_set_lights = 0;
4094 object->max_active_lights = opengl_device_caps.dwMaxActiveLights;
4095 object->light_parameters = NULL;
4096 object->active_lights = HeapAlloc(GetProcessHeap(), 0,
4097 object->max_active_lights * sizeof(BOOLEAN));
4098 /* Fill the active light array with ~0, which is used to indicate an
4099 invalid light index. We don't use 0, because it's a valid light index. */
4100 for (light=0; light < object->max_active_lights; light++)
4101 object->active_lights[light] = ~0;
4104 /* Allocate memory for the matrices */
4105 object->world_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4106 object->view_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4107 object->proj_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4108 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
4109 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
4110 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
4111 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
4112 object->tex_mat[tex_num] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4113 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
4114 object->tex_mat_is_identity[tex_num] = TRUE;
4117 /* Initialisation */
4118 TRACE(" setting current context\n");
4119 object->set_context(object);
4120 TRACE(" current context set\n");
4122 /* allocate the clipping planes */
4123 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
4124 object->clipping_planes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
4126 glHint(GL_FOG_HINT,GL_NICEST);
4128 /* Initialize the various GL contexts to be in sync with what we store locally */
4131 glClearColor(0.0, 0.0, 0.0, 0.0);
4132 glDepthMask(GL_TRUE);
4133 gl_object->depth_mask = TRUE;
4134 glEnable(GL_DEPTH_TEST);
4135 gl_object->depth_test = TRUE;
4136 glDisable(GL_ALPHA_TEST);
4137 glDisable(GL_STENCIL_TEST);
4138 glDisable(GL_CULL_FACE);
4139 glDisable(GL_LIGHTING);
4140 glDisable(GL_BLEND);
4142 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4143 gl_object->current_tex_env = GL_REPLACE;
4144 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
4145 if (GL_extensions.glActiveTexture != NULL) {
4146 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
4148 gl_object->current_alpha_test_ref = 0.0;
4149 gl_object->current_alpha_test_func = GL_ALWAYS;
4150 glAlphaFunc(GL_ALWAYS, 0.0);
4152 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4153 glDrawBuffer(buffer);
4154 glReadBuffer(buffer);
4155 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4158 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4159 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4161 /* fill_device_capabilities(d3d->ddraw); */
4163 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4164 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4165 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4166 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4170 TRACE(" creating implementation at %p.\n", *obj);
4172 /* And finally warn D3D that this device is now present */
4173 object->d3d->d3d_added_device(object->d3d, object);
4175 InitDefaultStateBlock(&object->state_block, object->version);
4176 /* Apply default render state and texture stage state values */
4177 apply_render_state(object, &object->state_block);
4178 apply_texture_state(object);
4180 /* And fill the fog table with the default fog value */
4181 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4186 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4188 pc->dwSize = sizeof(*pc);
4189 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4190 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4191 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4192 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4193 D3DPRASTERCAPS_ZFOG;
4194 if (GL_extensions.mipmap_lodbias) {
4195 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4197 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4198 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4199 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4200 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4201 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4202 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4203 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4204 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4205 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4206 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4207 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4208 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4209 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4210 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4211 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4212 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4213 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4214 D3DPTFILTERCAPS_MIPFPOINT;
4215 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4216 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4217 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4218 if (GL_extensions.mirrored_repeat) {
4219 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4221 pc->dwStippleWidth = 32;
4222 pc->dwStippleHeight = 32;
4225 static void fill_caps(void)
4227 GLint max_clip_planes;
4230 /* Fill first all the fields with default values which will be overriden later on with
4231 correct ones from the GL code
4233 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4234 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4235 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4236 /* D3D 7 capabilities */
4237 D3DDEVCAPS_DRAWPRIMITIVES2 /*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_DRAWPRIMITIVES2EX;
4238 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4239 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4240 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4241 opengl_device_caps.dwMinTextureWidth = 1;
4242 opengl_device_caps.dwMinTextureHeight = 1;
4243 opengl_device_caps.dwMaxTextureWidth = 1024;
4244 opengl_device_caps.dwMaxTextureHeight = 1024;
4245 opengl_device_caps.dwMaxTextureRepeat = 16;
4246 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4247 opengl_device_caps.dwMaxAnisotropy = 0;
4248 opengl_device_caps.dvGuardBandLeft = 0.0;
4249 opengl_device_caps.dvGuardBandRight = 0.0;
4250 opengl_device_caps.dvGuardBandTop = 0.0;
4251 opengl_device_caps.dvGuardBandBottom = 0.0;
4252 opengl_device_caps.dvExtentsAdjust = 0.0;
4253 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4254 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4255 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4256 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4257 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4258 if (GL_extensions.max_texture_units != 0) {
4259 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4260 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4261 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4263 opengl_device_caps.wMaxTextureBlendStages = 1;
4264 opengl_device_caps.wMaxSimultaneousTextures = 1;
4265 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4267 opengl_device_caps.dwMaxActiveLights = 16;
4268 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4269 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4270 opengl_device_caps.wMaxUserClipPlanes = 1;
4271 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4272 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4273 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4274 opengl_device_caps.dwReserved1 = 0;
4275 opengl_device_caps.dwReserved2 = 0;
4276 opengl_device_caps.dwReserved3 = 0;
4277 opengl_device_caps.dwReserved4 = 0;
4279 /* And now some GL overrides :-) */
4280 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4281 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4282 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4283 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4285 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4286 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4288 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4289 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4290 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4292 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4293 TRACE(": Z bits = %d\n", depth_bits);
4294 switch (depth_bits) {
4295 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4296 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4298 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4303 d3ddevice_init_at_startup(void *gl_handle)
4305 XVisualInfo template;
4310 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4311 XWindowAttributes win_attr;
4312 GLXContext gl_context;
4314 const char *glExtensions;
4315 const char *glVersion;
4316 const char *glXExtensions = NULL;
4317 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4318 int major, minor, patch, num_parsed;
4320 TRACE("Initializing GL...\n");
4324 WARN("x11drv not loaded - D3D support disabled!\n");
4328 /* Get a default rendering context to have the 'caps' function query some info from GL */
4329 device_context = GetDC(0);
4330 display = get_display(device_context);
4331 ReleaseDC(0, device_context);
4334 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4335 visual = win_attr.visual;
4337 visual = DefaultVisual(display, DefaultScreen(display));
4339 template.visualid = XVisualIDFromVisual(visual);
4340 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4343 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4346 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4348 if (gl_context == NULL) {
4350 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4353 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4354 glXDestroyContext(display, gl_context);
4356 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4360 /* Then, query all extensions */
4361 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); /* Note: not used right now but will for PBuffers */
4362 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4363 glVersion = (const char *) glGetString(GL_VERSION);
4364 if (gl_handle != NULL) {
4365 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4368 /* Parse the GL version string */
4369 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4370 if (num_parsed == 1) {
4373 } else if (num_parsed == 2) {
4376 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4378 /* And starts to fill the extension context properly */
4379 memset(&GL_extensions, 0, sizeof(GL_extensions));
4380 TRACE("GL supports following extensions used by Wine :\n");
4382 /* Mirrored Repeat extension :
4383 - GL_ARB_texture_mirrored_repeat
4384 - GL_IBM_texture_mirrored_repeat
4387 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4388 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4390 ((major == 1) && (minor >= 4))) {
4391 TRACE(" - mirrored repeat\n");
4392 GL_extensions.mirrored_repeat = TRUE;
4395 /* Texture LOD Bias :
4396 - GL_EXT_texture_lod_bias
4398 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4399 TRACE(" - texture lod bias\n");
4400 GL_extensions.mipmap_lodbias = TRUE;
4403 /* For all subsequent extensions, we need glXGetProcAddress */
4404 if (pglXGetProcAddressARB != NULL) {
4405 /* Multi-texturing :
4406 - GL_ARB_multitexture
4409 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4411 ((major == 1) && (minor > 2)) ||
4412 ((major == 1) && (minor == 2) && (patch >= 1))) {
4413 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4414 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4415 /* We query the ARB version to be the most portable we can... */
4416 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4417 GL_extensions.glMultiTexCoord[0] = pglXGetProcAddressARB("glMultiTexCoord1fvARB");
4418 GL_extensions.glMultiTexCoord[1] = pglXGetProcAddressARB("glMultiTexCoord2fvARB");
4419 GL_extensions.glMultiTexCoord[2] = pglXGetProcAddressARB("glMultiTexCoord3fvARB");
4420 GL_extensions.glMultiTexCoord[3] = pglXGetProcAddressARB("glMultiTexCoord4fvARB");
4421 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4423 GL_extensions.max_texture_units = 0;
4426 if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
4427 TRACE(" - S3TC compression supported\n");
4428 GL_extensions.s3tc_compressed_texture = TRUE;
4429 GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2DARB");
4430 GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2DARB");
4434 /* Fill the D3D capabilities according to what GL tells us... */
4437 /* And frees this now-useless context */
4438 glXMakeCurrent(display, None, NULL);
4439 glXDestroyContext(display, gl_context);