2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/port.h"
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "wine/debug.h"
39 #include "wine/library.h"
41 #include "mesa_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
45 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
54 X11DRV_GET_FONT, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL = {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps;
74 GL_EXTENSIONS_LIST GL_extensions;
76 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
77 D3DPRIMITIVETYPE d3dptPrimitiveType,
78 DWORD d3dvtVertexType,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
85 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
87 /* retrieve the X display to use on a given DC */
88 inline static Display *get_display( HDC hdc )
91 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
93 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94 sizeof(display), (LPSTR)&display )) display = NULL;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
105 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
106 DWORD opt_bitmap = 0x00000000;
108 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
109 ((d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE))) {
110 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
111 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
112 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
114 /* Disable multi-texturing for level 1 to disable all others */
115 glDisable(GL_TEXTURE_2D);
117 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
118 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
119 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
121 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
122 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
123 glEnable(GL_TEXTURE_2D);
124 if (gl_d3d_dev->unlock_tex == 0) {
125 glGenTextures(1, &gl_d3d_dev->unlock_tex);
126 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
133 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
136 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
137 glMatrixMode(GL_TEXTURE);
141 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
142 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
143 d3ddevice_set_ortho(d3d_dev);
146 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
147 glEnable(GL_SCISSOR_TEST);
148 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
149 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap |= DEPTH_RANGE_BIT;
153 if ((d3d_dev->active_viewport.dwX != 0) ||
154 (d3d_dev->active_viewport.dwY != 0) ||
155 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
156 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
157 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
158 opt_bitmap |= VIEWPORT_BIT;
160 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
161 pRect->right - pRect->left, pRect->bottom - pRect->top);
162 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
163 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
165 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
166 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
167 glAlphaFunc(GL_NOTEQUAL, 0.0);
169 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
171 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
172 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
173 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
174 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
175 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
180 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
181 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
183 /* And restore all the various states modified by this code */
184 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
185 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
186 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
187 glEnable(GL_ALPHA_TEST);
188 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
189 glDisable(GL_ALPHA_TEST);
191 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
192 glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
194 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
195 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
196 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
197 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
198 glDisable(GL_SCISSOR_TEST);
199 if (opt_bitmap & DEPTH_RANGE_BIT) {
200 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
202 if (opt_bitmap & VIEWPORT_BIT) {
203 glViewport(d3d_dev->active_viewport.dwX,
204 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
205 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
207 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
208 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
211 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
212 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
213 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
215 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
216 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
217 bind if ever the game changes the texture just after.
219 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
220 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
223 /* And re-enabled if needed texture level 1 */
224 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
225 (d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
226 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
227 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
228 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
230 glEnable(GL_TEXTURE_2D);
234 /* retrieve the X drawable to use on a given DC */
235 inline static Drawable get_drawable( HDC hdc )
238 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
240 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
241 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
246 /* This is unnecessarely complicated :-) */
247 #define MEASUREMENT_WINDOW 5
248 #define NUMBER_OF_WINDOWS 10
250 static LONGLONG perf_freq;
251 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
252 static LONGLONG prev_time = 0;
253 static unsigned int current_window;
254 static unsigned int measurements_in_window;
255 static unsigned int valid_windows;
257 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
259 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
260 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
262 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
264 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
265 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]);
267 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
268 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
269 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
272 if (TRACE_ON(ddraw_fps)) {
273 LONGLONG current_time;
274 LONGLONG frame_duration;
275 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
277 if (prev_time != 0) {
278 LONGLONG total_time = 0;
281 frame_duration = current_time - prev_time;
282 prev_time = current_time;
284 perf_storage[current_window] += frame_duration;
285 measurements_in_window++;
287 if (measurements_in_window >= MEASUREMENT_WINDOW) {
291 if (valid_windows < NUMBER_OF_WINDOWS) {
293 tot_meas = valid_windows * MEASUREMENT_WINDOW;
294 for (i = 0; i < valid_windows; i++) {
295 total_time += perf_storage[i];
299 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
300 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
301 total_time += perf_storage[i];
305 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
307 if (current_window >= NUMBER_OF_WINDOWS) {
310 perf_storage[current_window] = 0;
311 measurements_in_window = 0;
314 prev_time = current_time;
315 memset(perf_storage, 0, sizeof(perf_storage));
318 measurements_in_window = 0;
319 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
327 /*******************************************************************************
328 * OpenGL static functions
330 static void set_context(IDirect3DDeviceImpl* This)
332 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
334 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
336 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
337 ERR("Error in setting current context (context %p drawable %ld)!\n",
338 glThis->gl_context, glThis->drawable);
343 static void fill_opengl_caps(D3DDEVICEDESC *d1)
345 d1->dwSize = sizeof(*d1);
346 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
347 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
348 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
349 d1->dcmColorModel = D3DCOLOR_RGB;
350 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
351 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
352 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
353 d1->bClipping = TRUE;
354 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
355 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
356 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
357 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
358 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
359 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
360 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
361 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
362 d1->dwMaxBufferSize = 0;
363 d1->dwMaxVertexCount = 65536;
364 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
365 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
366 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
367 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
368 d1->dwMinStippleWidth = 1;
369 d1->dwMinStippleHeight = 1;
370 d1->dwMaxStippleWidth = 32;
371 d1->dwMaxStippleHeight = 32;
372 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
373 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
374 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
375 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
376 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
377 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
378 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
379 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
380 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
381 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
382 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
383 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
384 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
387 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
389 *d = opengl_device_caps;
392 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
394 D3DDEVICEDESC dref, d1, d2;
397 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
398 Let's put the string in a sufficiently sized array in writable memory. */
399 char device_name[50];
400 strcpy(device_name,"direct3d");
402 fill_opengl_caps(&dref);
405 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
406 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
407 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
410 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
411 if (ret_value != D3DENUMRET_OK)
416 char interface_name[] = "WINE Direct3DX using OpenGL";
417 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
420 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
421 if (ret_value != D3DENUMRET_OK)
425 return D3DENUMRET_OK;
428 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
430 D3DDEVICEDESC7 ddesc;
431 char interface_name[] = "WINE Direct3D7 using OpenGL";
432 char device_name[] = "Wine D3D7 device";
434 fill_opengl_caps_7(&ddesc);
436 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
438 return cb(interface_name, device_name, &ddesc, context);
442 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
444 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
445 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
447 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
448 if (!--(This->ref)) {
450 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
452 /* Release texture associated with the device */
453 for (i = 0; i < MAX_TEXTURES; i++) {
454 if (This->current_texture[i] != NULL)
455 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
456 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
459 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
460 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
461 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
462 surf->aux_ctx = NULL;
463 surf->aux_data = NULL;
464 surf->aux_flip = NULL;
468 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
469 IDirectDrawSurfaceImpl *surf2;
470 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
471 for (; surf2 != NULL; surf2 = surf2->next_attached) {
472 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
473 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
474 /* Override the Lock / Unlock function for all these surfaces */
475 surf2->lock_update = surf2->lock_update_prev;
476 surf2->unlock_update = surf2->unlock_update_prev;
477 /* And install also the blt / bltfast overrides */
478 surf2->aux_blt = NULL;
479 surf2->aux_bltfast = NULL;
481 surf2->d3ddevice = NULL;
485 /* And warn the D3D object that this device is no longer active... */
486 This->d3d->d3d_removed_device(This->d3d, This);
488 HeapFree(GetProcessHeap(), 0, This->world_mat);
489 HeapFree(GetProcessHeap(), 0, This->view_mat);
490 HeapFree(GetProcessHeap(), 0, This->proj_mat);
492 if (glThis->surface_ptr)
493 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
495 DeleteCriticalSection(&(This->crit));
498 if (glThis->unlock_tex)
499 glDeleteTextures(1, &(glThis->unlock_tex));
500 glXDestroyContext(glThis->display, glThis->gl_context);
502 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
504 HeapFree(GetProcessHeap(), 0, This);
511 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
512 LPD3DDEVICEDESC lpD3DHWDevDesc,
513 LPD3DDEVICEDESC lpD3DHELDevDesc)
515 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
519 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
521 fill_opengl_caps(&desc);
522 dwSize = lpD3DHWDevDesc->dwSize;
523 memset(lpD3DHWDevDesc, 0, dwSize);
524 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
526 dwSize = lpD3DHELDevDesc->dwSize;
527 memset(lpD3DHELDevDesc, 0, dwSize);
528 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
530 TRACE(" returning caps : (no dump function yet)\n");
535 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
536 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
540 LPDDPIXELFORMAT pformat;
542 /* Do the texture enumeration */
543 sdesc.dwSize = sizeof(DDSURFACEDESC);
544 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
545 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
546 pformat = &(sdesc.ddpfPixelFormat);
547 pformat->dwSize = sizeof(DDPIXELFORMAT);
548 pformat->dwFourCC = 0;
550 TRACE("Enumerating GL_RGBA unpacked (32)\n");
551 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
552 pformat->u1.dwRGBBitCount = 32;
553 pformat->u2.dwRBitMask = 0x00FF0000;
554 pformat->u3.dwGBitMask = 0x0000FF00;
555 pformat->u4.dwBBitMask = 0x000000FF;
556 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
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 unpacked (32)\n");
561 pformat->dwFlags = DDPF_RGB;
562 pformat->u1.dwRGBBitCount = 32;
563 pformat->u2.dwRBitMask = 0x00FF0000;
564 pformat->u3.dwGBitMask = 0x0000FF00;
565 pformat->u4.dwBBitMask = 0x000000FF;
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;
570 TRACE("Enumerating GL_RGB unpacked (24)\n");
571 pformat->dwFlags = DDPF_RGB;
572 pformat->u1.dwRGBBitCount = 24;
573 pformat->u2.dwRBitMask = 0x00FF0000;
574 pformat->u3.dwGBitMask = 0x0000FF00;
575 pformat->u4.dwBBitMask = 0x000000FF;
576 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
577 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
578 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
580 /* Note : even if this is an 'emulated' texture format, it needs to be first
581 as some dumb applications seem to rely on that. */
582 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
583 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
584 pformat->u1.dwRGBBitCount = 16;
585 pformat->u2.dwRBitMask = 0x00007C00;
586 pformat->u3.dwGBitMask = 0x000003E0;
587 pformat->u4.dwBBitMask = 0x0000001F;
588 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
589 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
590 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
592 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
593 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
594 pformat->u1.dwRGBBitCount = 16;
595 pformat->u2.dwRBitMask = 0x00000F00;
596 pformat->u3.dwGBitMask = 0x000000F0;
597 pformat->u4.dwBBitMask = 0x0000000F;
598 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
599 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
600 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
602 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
603 pformat->dwFlags = DDPF_RGB;
604 pformat->u1.dwRGBBitCount = 16;
605 pformat->u2.dwRBitMask = 0x0000F800;
606 pformat->u3.dwGBitMask = 0x000007E0;
607 pformat->u4.dwBBitMask = 0x0000001F;
608 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
609 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
610 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
612 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
613 pformat->dwFlags = DDPF_RGB;
614 pformat->u1.dwRGBBitCount = 16;
615 pformat->u2.dwRBitMask = 0x00007C00;
616 pformat->u3.dwGBitMask = 0x000003E0;
617 pformat->u4.dwBBitMask = 0x0000001F;
618 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
619 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
620 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
623 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
624 find enumerated, others the last one. And both want to have the ARGB one.
626 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
628 /* See argument about the RGBA format for 'packed' texture formats */
629 TRACE("Enumerating GL_RGBA unpacked (32)\n");
630 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
631 pformat->u1.dwRGBBitCount = 32;
632 pformat->u2.dwRBitMask = 0xFF000000;
633 pformat->u3.dwGBitMask = 0x00FF0000;
634 pformat->u4.dwBBitMask = 0x0000FF00;
635 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
636 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
637 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
639 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
640 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
641 pformat->u1.dwRGBBitCount = 16;
642 pformat->u2.dwRBitMask = 0x0000F000;
643 pformat->u3.dwGBitMask = 0x00000F00;
644 pformat->u4.dwBBitMask = 0x000000F0;
645 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
646 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
647 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
649 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
650 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
651 pformat->u1.dwRGBBitCount = 16;
652 pformat->u2.dwRBitMask = 0x0000F800;
653 pformat->u3.dwGBitMask = 0x000007C0;
654 pformat->u4.dwBBitMask = 0x0000003E;
655 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
656 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
657 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
660 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
661 pformat->dwFlags = DDPF_RGB;
662 pformat->u1.dwRGBBitCount = 8;
663 pformat->u2.dwRBitMask = 0x000000E0;
664 pformat->u3.dwGBitMask = 0x0000001C;
665 pformat->u4.dwBBitMask = 0x00000003;
666 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
667 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
668 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
670 TRACE("Enumerating Paletted (8)\n");
671 pformat->dwFlags = DDPF_PALETTEINDEXED8;
672 pformat->u1.dwRGBBitCount = 8;
673 pformat->u2.dwRBitMask = 0x00000000;
674 pformat->u3.dwGBitMask = 0x00000000;
675 pformat->u4.dwBBitMask = 0x00000000;
676 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
677 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
678 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
680 TRACE("End of enumeration\n");
686 d3ddevice_find(IDirectDrawImpl *d3d,
687 LPD3DFINDDEVICESEARCH lpD3DDFS,
688 LPD3DFINDDEVICERESULT lplpD3DDevice)
692 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
693 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
694 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
695 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
697 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
698 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
699 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
700 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
701 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
702 TRACE(" no match for this GUID.\n");
703 return DDERR_INVALIDPARAMS;
707 /* Now return our own GUID */
708 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
709 fill_opengl_caps(&desc);
710 lplpD3DDevice->ddHwDesc = desc;
711 lplpD3DDevice->ddSwDesc = desc;
713 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
719 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
720 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
723 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
724 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
725 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
729 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
730 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
733 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
734 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
735 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
739 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
740 D3DRENDERSTATETYPE dwRenderStateType,
743 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
744 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
746 /* Call the render state functions */
747 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
748 set_render_state(This, dwRenderStateType, &This->state_block);
754 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
755 D3DRENDERSTATETYPE dwRenderStateType,
756 LPDWORD lpdwRenderState)
758 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
759 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
761 /* Call the render state functions */
762 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
764 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
770 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
771 D3DLIGHTSTATETYPE dwLightStateType,
774 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
776 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
778 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
779 TRACE("Unexpected Light State Type\n");
780 return DDERR_INVALIDPARAMS;
783 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
784 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
787 TRACE(" activating material %p.\n", mat);
790 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
791 return DDERR_INVALIDPARAMS;
793 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
794 switch (dwLightState) {
796 ERR("DDCOLOR_MONO should not happen!\n");
799 /* We are already in this mode */
800 TRACE("Setting color model to RGB (no-op).\n");
803 ERR("Unknown color model!\n");
804 return DDERR_INVALIDPARAMS;
807 D3DRENDERSTATETYPE rs;
808 switch (dwLightStateType) {
809 case D3DLIGHTSTATE_AMBIENT: /* 2 */
810 rs = D3DRENDERSTATE_AMBIENT;
812 case D3DLIGHTSTATE_FOGMODE: /* 4 */
813 rs = D3DRENDERSTATE_FOGVERTEXMODE;
815 case D3DLIGHTSTATE_FOGSTART: /* 5 */
816 rs = D3DRENDERSTATE_FOGSTART;
818 case D3DLIGHTSTATE_FOGEND: /* 6 */
819 rs = D3DRENDERSTATE_FOGEND;
821 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
822 rs = D3DRENDERSTATE_FOGDENSITY;
824 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
825 rs = D3DRENDERSTATE_COLORVERTEX;
828 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
829 return DDERR_INVALIDPARAMS;
832 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
839 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
842 case D3DPT_POINTLIST:
843 TRACE("Start POINTS\n");
848 TRACE("Start LINES\n");
852 case D3DPT_LINESTRIP:
853 TRACE("Start LINE_STRIP\n");
854 glBegin(GL_LINE_STRIP);
857 case D3DPT_TRIANGLELIST:
858 TRACE("Start TRIANGLES\n");
859 glBegin(GL_TRIANGLES);
862 case D3DPT_TRIANGLESTRIP:
863 TRACE("Start TRIANGLE_STRIP\n");
864 glBegin(GL_TRIANGLE_STRIP);
867 case D3DPT_TRIANGLEFAN:
868 TRACE("Start TRIANGLE_FAN\n");
869 glBegin(GL_TRIANGLE_FAN);
873 FIXME("Unhandled primitive %08x\n", d3dpt);
878 /* This function calculate the Z coordinate from Zproj */
879 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
882 /* Assume that X = Y = 0 and W = 1 */
883 a = This->proj_mat->_33;
884 b = This->proj_mat->_34;
885 c = This->proj_mat->_43;
886 d = This->proj_mat->_44;
887 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
888 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
889 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
891 return (d*Zproj - c) / (a - b*Zproj);
894 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
897 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
899 for (i = 0; i < 3; i++) {
900 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
902 for (elt = 0; elt < 0x10000; elt++) {
903 /* We apply the fog transformation and cache the result */
904 DWORD fog_intensity = elt & 0xFF;
905 DWORD vertex_color = (elt >> 8) & 0xFF;
906 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
911 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
912 BOOLEAN vertex_transformed,
913 BOOLEAN vertex_lit) {
914 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
916 /* Puts GL in the correct lighting / transformation mode */
917 if ((vertex_transformed == FALSE) &&
918 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
919 /* Need to put the correct transformation again if we go from Transformed
920 vertices to non-transformed ones.
922 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
923 This->world_mat, This->view_mat, This->proj_mat);
924 glThis->transform_state = GL_TRANSFORM_NORMAL;
926 } else if ((vertex_transformed == TRUE) &&
927 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
928 /* Set our orthographic projection */
929 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
930 glThis->transform_state = GL_TRANSFORM_ORTHO;
931 d3ddevice_set_ortho(This);
935 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
936 if no fogging state change occurred */
937 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
938 if (vertex_transformed == TRUE) {
939 if (glThis->fogging != 0) {
943 /* Now check if our fog_table still corresponds to the current vertex color.
944 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
945 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
946 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
947 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
948 /* We need to rebuild our fog table.... */
949 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
952 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
953 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
954 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
955 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
956 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
958 if (vertex_lit == FALSE) {
959 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
960 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
962 /* Special case of 'pixel fog' */
963 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
964 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
966 if (glThis->fogging == 0) {
971 if (glThis->fogging != 0) {
978 if (glThis->fogging != 0) {
984 /* Handle the 'no-normal' case */
985 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
986 if (glThis->lighting == 0) {
987 glEnable(GL_LIGHTING);
988 glThis->lighting = 1;
991 if (glThis->lighting != 0) {
992 glDisable(GL_LIGHTING);
993 glThis->lighting = 0;
997 /* Handle the code for pre-vertex material properties */
998 if (vertex_transformed == FALSE) {
999 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1000 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1001 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1002 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1003 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1004 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
1005 glEnable(GL_COLOR_MATERIAL);
1012 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1013 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1015 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1018 case D3DVT_VERTEX: {
1019 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1020 strided.position.dwStride = sizeof(D3DVERTEX);
1021 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1022 strided.normal.dwStride = sizeof(D3DVERTEX);
1023 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1024 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1025 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1028 case D3DVT_LVERTEX: {
1029 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1030 strided.position.dwStride = sizeof(D3DLVERTEX);
1031 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1032 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1033 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1034 strided.specular.dwStride = sizeof(D3DLVERTEX);
1035 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1036 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1037 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1040 case D3DVT_TLVERTEX: {
1041 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1042 strided.position.dwStride = sizeof(D3DTLVERTEX);
1043 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1044 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1045 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1046 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1047 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1048 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1049 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1053 FIXME("Unhandled vertex type %08x\n", d3dvt);
1059 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1060 D3DPRIMITIVETYPE d3dptPrimitiveType,
1061 D3DVERTEXTYPE d3dvtVertexType,
1063 DWORD dwVertexCount,
1066 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1068 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1069 if (TRACE_ON(ddraw)) {
1070 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1073 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1079 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1080 D3DPRIMITIVETYPE d3dptPrimitiveType,
1081 D3DVERTEXTYPE d3dvtVertexType,
1083 DWORD dwVertexCount,
1088 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1089 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1090 if (TRACE_ON(ddraw)) {
1091 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1094 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1100 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1101 LPD3DEXECUTEBUFFERDESC lpDesc,
1102 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1103 IUnknown* pUnkOuter)
1105 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1106 IDirect3DExecuteBufferImpl *ret;
1109 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1111 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1112 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1114 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1119 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1120 static BOOLEAN first = TRUE;
1121 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1125 if (first == TRUE) {
1126 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1130 TRACE("flushing ZBuffer back to GL\n");
1132 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1133 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1134 d3ddevice_set_ortho(d3d_dev);
1137 glMatrixMode(GL_MODELVIEW);
1140 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1141 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1142 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1144 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1147 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1148 case 16: type = GL_UNSIGNED_SHORT; break;
1149 case 32: type = GL_UNSIGNED_INT; break;
1150 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1153 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1154 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1155 glRasterPos2i(0, row + 1);
1156 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1157 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1161 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1162 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1163 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1164 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1167 /* These are the various handler used in the generic path */
1168 inline static void handle_xyz(D3DVALUE *coords) {
1169 glVertex3fv(coords);
1171 inline static void handle_xyzrhw(D3DVALUE *coords) {
1172 if (coords[3] < 1e-8)
1173 glVertex3fv(coords);
1175 GLfloat w = 1.0 / coords[3];
1177 glVertex4f(coords[0] * w,
1183 inline static void handle_normal(D3DVALUE *coords) {
1184 glNormal3fv(coords);
1187 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1188 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1189 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1190 glColor4ub((*color >> 16) & 0xFF,
1191 (*color >> 8) & 0xFF,
1192 (*color >> 0) & 0xFF,
1193 (*color >> 24) & 0xFF);
1195 glColor3ub((*color >> 16) & 0xFF,
1196 (*color >> 8) & 0xFF,
1197 (*color >> 0) & 0xFF);
1201 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1202 glColor4ub((*color >> 16) & 0xFF,
1203 (*color >> 8) & 0xFF,
1204 (*color >> 0) & 0xFF,
1205 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1208 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1209 if ((lighted == FALSE) &&
1210 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1211 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1212 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1213 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1214 handle_diffuse_base(sb, color);
1216 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1217 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1218 handle_diffuse_base(sb, color);
1220 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1221 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1222 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1223 handle_diffuse_base(sb, color);
1225 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1226 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1227 handle_diffuse_base(sb, color);
1230 handle_diffuse_base(sb, color);
1234 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1235 if ((lighted == FALSE) &&
1236 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1237 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1238 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1239 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1240 handle_specular_base(sb, color);
1242 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1243 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1244 handle_specular_base(sb, color);
1246 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1247 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1248 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1249 handle_specular_base(sb, color);
1251 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1252 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1253 handle_specular_base(sb, color);
1256 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1259 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1260 if (lighted == TRUE) {
1261 DWORD color = *color_d;
1262 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1263 /* Special case where the specular value is used to do fogging */
1264 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1265 color &= 0xFF000000; /* Only keep the alpha component */
1266 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1267 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1268 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1270 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1271 /* Standard specular value in transformed mode. TODO */
1273 handle_diffuse_base(sb, &color);
1275 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1276 handle_diffuse(sb, color_d, FALSE);
1277 handle_specular(sb, color_s, FALSE);
1279 /* In that case, only put the diffuse color... */
1280 handle_diffuse_base(sb, color_d);
1285 inline static void handle_texture(D3DVALUE *coords) {
1286 glTexCoord2fv(coords);
1288 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1289 if (GL_extensions.glMultiTexCoord2fv) {
1290 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1292 if (tex_stage == 0) glTexCoord2fv(coords);
1296 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1297 D3DPRIMITIVETYPE d3dptPrimitiveType,
1298 DWORD d3dvtVertexType,
1299 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1300 DWORD dwVertexCount,
1305 BOOLEAN vertex_lighted = FALSE;
1306 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1307 int num_active_stages = 0;
1309 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1310 if (TRACE_ON(ddraw)) {
1311 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1314 /* This is to prevent 'thread contention' between a thread locking the device and another
1315 doing 3D display on it... */
1316 EnterCriticalSection(&(This->crit));
1319 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1320 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1322 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1324 if (This->current_zbuffer == NULL) {
1325 /* Search for an attached ZBuffer */
1326 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1327 LPDIRECTDRAWSURFACE7 zbuf;
1330 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1331 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1333 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1334 IDirectDrawSurface7_Release(zbuf);
1337 if (This->current_zbuffer != NULL) {
1338 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1339 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1343 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1344 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1345 vertex_lighted = TRUE;
1347 /* Compute the number of active texture stages and set the various texture parameters */
1348 num_active_stages = draw_primitive_handle_textures(This);
1350 /* And restore to handle '0' in the case we use glTexCoord calls */
1351 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1352 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1353 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1356 draw_primitive_handle_GL_state(This,
1357 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1359 draw_primitive_start_GL(d3dptPrimitiveType);
1361 /* Some fast paths first before the generic case.... */
1362 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1365 for (index = 0; index < dwIndexCount; index++) {
1366 int i = (dwIndices == NULL) ? index : dwIndices[index];
1368 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1369 D3DVALUE *tex_coord =
1370 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1371 D3DVALUE *position =
1372 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1374 handle_normal(normal);
1375 handle_texture(tex_coord);
1376 handle_xyz(position);
1378 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1379 position[0], position[1], position[2],
1380 normal[0], normal[1], normal[2],
1381 tex_coord[0], tex_coord[1]);
1383 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1386 for (index = 0; index < dwIndexCount; index++) {
1387 int i = (dwIndices == NULL) ? index : dwIndices[index];
1389 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1391 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1392 D3DVALUE *tex_coord =
1393 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1394 D3DVALUE *position =
1395 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1397 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1398 handle_texture(tex_coord);
1399 handle_xyzrhw(position);
1401 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1402 position[0], position[1], position[2], position[3],
1403 (*color_d >> 16) & 0xFF,
1404 (*color_d >> 8) & 0xFF,
1405 (*color_d >> 0) & 0xFF,
1406 (*color_d >> 24) & 0xFF,
1407 (*color_s >> 16) & 0xFF,
1408 (*color_s >> 8) & 0xFF,
1409 (*color_s >> 0) & 0xFF,
1410 (*color_s >> 24) & 0xFF,
1411 tex_coord[0], tex_coord[1]);
1413 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1414 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1415 /* This is the 'slow path' but that should support all possible vertex formats out there...
1416 Note that people should write a fast path for all vertex formats out there...
1419 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1420 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1422 for (index = 0; index < dwIndexCount; index++) {
1423 int i = (dwIndices == NULL) ? index : dwIndices[index];
1426 if (d3dvtVertexType & D3DFVF_NORMAL) {
1428 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1429 handle_normal(normal);
1431 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1433 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1435 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1436 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1438 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1440 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1441 handle_specular(&(This->state_block), color_s, vertex_lighted);
1442 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1444 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1445 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1449 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1450 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1451 if (tex_index >= num_tex_index) {
1452 handle_textures((D3DVALUE *) no_index, tex_stage);
1454 D3DVALUE *tex_coord =
1455 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1456 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1457 handle_textures(tex_coord, tex_stage);
1461 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1462 D3DVALUE *position =
1463 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1464 handle_xyz(position);
1465 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1466 D3DVALUE *position =
1467 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1468 handle_xyzrhw(position);
1471 if (TRACE_ON(ddraw_geom)) {
1474 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1475 D3DVALUE *position =
1476 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1477 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1478 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1479 D3DVALUE *position =
1480 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1481 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1483 if (d3dvtVertexType & D3DFVF_NORMAL) {
1485 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1486 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1488 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1490 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1491 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1492 (*color_d >> 16) & 0xFF,
1493 (*color_d >> 8) & 0xFF,
1494 (*color_d >> 0) & 0xFF,
1495 (*color_d >> 24) & 0xFF);
1497 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1499 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1500 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1501 (*color_s >> 16) & 0xFF,
1502 (*color_s >> 8) & 0xFF,
1503 (*color_s >> 0) & 0xFF,
1504 (*color_s >> 24) & 0xFF);
1506 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1507 D3DVALUE *tex_coord =
1508 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1509 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1510 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1512 TRACE_(ddraw_geom)("\n");
1516 ERR(" matrix weighting not handled yet....\n");
1521 /* Whatever the case, disable the color material stuff */
1522 glDisable(GL_COLOR_MATERIAL);
1527 LeaveCriticalSection(&(This->crit));
1531 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1532 D3DPRIMITIVETYPE d3dptPrimitiveType,
1533 DWORD d3dvtVertexType,
1535 DWORD dwVertexCount,
1538 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1539 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1541 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1542 if (TRACE_ON(ddraw)) {
1543 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1546 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1547 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1553 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1554 D3DPRIMITIVETYPE d3dptPrimitiveType,
1555 DWORD d3dvtVertexType,
1557 DWORD dwVertexCount,
1562 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1563 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1565 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1566 if (TRACE_ON(ddraw)) {
1567 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1570 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1571 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1577 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1578 D3DPRIMITIVETYPE d3dptPrimitiveType,
1580 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1581 DWORD dwVertexCount,
1584 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1586 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1587 if (TRACE_ON(ddraw)) {
1588 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1590 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1596 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1597 D3DPRIMITIVETYPE d3dptPrimitiveType,
1599 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1600 DWORD dwVertexCount,
1605 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1607 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1608 if (TRACE_ON(ddraw)) {
1609 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1612 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1618 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1619 D3DPRIMITIVETYPE d3dptPrimitiveType,
1620 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1621 DWORD dwStartVertex,
1622 DWORD dwNumVertices,
1625 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1626 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1627 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1629 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1630 if (TRACE_ON(ddraw)) {
1631 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1634 if (vb_impl->processed == TRUE) {
1635 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1636 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1638 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1639 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1640 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1642 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1643 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1646 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1647 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1654 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1655 D3DPRIMITIVETYPE d3dptPrimitiveType,
1656 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1657 DWORD dwStartVertex,
1658 DWORD dwNumVertices,
1663 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1664 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1665 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1667 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1668 if (TRACE_ON(ddraw)) {
1669 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1672 if (vb_impl->processed == TRUE) {
1673 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1674 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1676 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1677 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1678 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1680 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1681 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1684 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1685 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1691 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1693 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1695 BOOLEAN is_complement = FALSE;
1696 BOOLEAN is_alpha_replicate = FALSE;
1697 BOOLEAN handled = TRUE;
1699 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1703 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1704 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1709 if (tex_op == D3DTOP_SELECTARG2) {
1713 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1714 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1719 if (tex_op == D3DTOP_SELECTARG2) {
1724 if (dwState & D3DTA_COMPLEMENT) {
1725 is_complement = TRUE;
1727 if (dwState & D3DTA_ALPHAREPLICATE) {
1728 is_alpha_replicate = TRUE;
1730 dwState &= D3DTA_SELECTMASK;
1731 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1732 dwState = D3DTA_DIFFUSE;
1736 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1737 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1738 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1739 case D3DTA_TFACTOR: {
1740 /* Get the constant value from the current rendering state */
1742 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1744 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1745 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1746 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1747 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1748 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1750 src = GL_CONSTANT_EXT;
1752 default: src = GL_TEXTURE; handled = FALSE; break;
1756 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1757 if (is_alpha_replicate) {
1758 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1760 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1763 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1764 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1771 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1773 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1776 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1777 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1782 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1784 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1785 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1789 unit = GL_TEXTURE0_WINE + dwStage;
1790 if (unit != glThis->current_active_tex_unit) {
1791 GL_extensions.glActiveTexture(unit);
1792 glThis->current_active_tex_unit = unit;
1795 switch (d3dTexStageStateType) {
1796 #define GEN_CASE(a) case a: type = #a; break
1797 GEN_CASE(D3DTSS_COLOROP);
1798 GEN_CASE(D3DTSS_COLORARG1);
1799 GEN_CASE(D3DTSS_COLORARG2);
1800 GEN_CASE(D3DTSS_ALPHAOP);
1801 GEN_CASE(D3DTSS_ALPHAARG1);
1802 GEN_CASE(D3DTSS_ALPHAARG2);
1803 GEN_CASE(D3DTSS_BUMPENVMAT00);
1804 GEN_CASE(D3DTSS_BUMPENVMAT01);
1805 GEN_CASE(D3DTSS_BUMPENVMAT10);
1806 GEN_CASE(D3DTSS_BUMPENVMAT11);
1807 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1808 GEN_CASE(D3DTSS_ADDRESS);
1809 GEN_CASE(D3DTSS_ADDRESSU);
1810 GEN_CASE(D3DTSS_ADDRESSV);
1811 GEN_CASE(D3DTSS_BORDERCOLOR);
1812 GEN_CASE(D3DTSS_MAGFILTER);
1813 GEN_CASE(D3DTSS_MINFILTER);
1814 GEN_CASE(D3DTSS_MIPFILTER);
1815 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1816 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1817 GEN_CASE(D3DTSS_MAXANISOTROPY);
1818 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1819 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1820 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1822 default: type = "UNKNOWN";
1825 /* Store the values in the state array */
1826 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1827 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1828 /* Some special cases when one state modifies more than one... */
1829 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1830 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1831 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1836 switch (d3dTexStageStateType) {
1837 case D3DTSS_MINFILTER:
1838 case D3DTSS_MIPFILTER:
1839 if (TRACE_ON(ddraw)) {
1840 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1841 switch ((D3DTEXTUREMINFILTER) dwState) {
1842 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1843 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1844 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1847 switch ((D3DTEXTUREMIPFILTER) dwState) {
1848 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1849 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1850 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1851 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1857 case D3DTSS_MAGFILTER:
1858 if (TRACE_ON(ddraw)) {
1859 switch ((D3DTEXTUREMAGFILTER) dwState) {
1860 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1861 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1862 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1867 case D3DTSS_ADDRESS:
1868 case D3DTSS_ADDRESSU:
1869 case D3DTSS_ADDRESSV: {
1870 switch ((D3DTEXTUREADDRESS) dwState) {
1871 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1872 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1873 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1874 case D3DTADDRESS_MIRROR:
1875 if (GL_extensions.mirrored_repeat == TRUE) {
1876 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1878 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1881 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1885 case D3DTSS_ALPHAOP:
1886 case D3DTSS_COLOROP: {
1888 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1893 #define GEN_CASE(a) case a: value = #a; break
1894 GEN_CASE(D3DTOP_DISABLE);
1895 GEN_CASE(D3DTOP_SELECTARG1);
1896 GEN_CASE(D3DTOP_SELECTARG2);
1897 GEN_CASE(D3DTOP_MODULATE);
1898 GEN_CASE(D3DTOP_MODULATE2X);
1899 GEN_CASE(D3DTOP_MODULATE4X);
1900 GEN_CASE(D3DTOP_ADD);
1901 GEN_CASE(D3DTOP_ADDSIGNED);
1902 GEN_CASE(D3DTOP_ADDSIGNED2X);
1903 GEN_CASE(D3DTOP_SUBTRACT);
1904 GEN_CASE(D3DTOP_ADDSMOOTH);
1905 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1906 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1907 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1908 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1909 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1910 GEN_CASE(D3DTOP_PREMODULATE);
1911 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1912 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1913 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1914 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1915 GEN_CASE(D3DTOP_BUMPENVMAP);
1916 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1917 GEN_CASE(D3DTOP_DOTPRODUCT3);
1918 GEN_CASE(D3DTOP_FORCE_DWORD);
1920 default: value = "UNKNOWN";
1923 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1924 glDisable(GL_TEXTURE_2D);
1925 TRACE(" disabling 2D texturing.\n");
1927 /* Re-enable texturing only if COLOROP was not already disabled... */
1928 if ((glThis->current_bound_texture[dwStage] != NULL) &&
1929 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1930 glEnable(GL_TEXTURE_2D);
1931 TRACE(" enabling 2D texturing.\n");
1934 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1935 if ((dwState != D3DTOP_DISABLE) &&
1936 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1937 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1938 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1939 glThis->current_tex_env = GL_COMBINE_EXT;
1943 /* Now set up the operand correctly */
1945 case D3DTOP_DISABLE:
1946 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1947 and it works, so ignore this op */
1948 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1951 case D3DTOP_SELECTARG1:
1952 case D3DTOP_SELECTARG2:
1953 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1956 case D3DTOP_MODULATE4X:
1957 scale = scale * 2; /* Drop through */
1958 case D3DTOP_MODULATE2X:
1959 scale = scale * 2; /* Drop through */
1960 case D3DTOP_MODULATE:
1961 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1965 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1968 case D3DTOP_ADDSIGNED2X:
1969 scale = scale * 2; /* Drop through */
1970 case D3DTOP_ADDSIGNED:
1971 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1974 /* For the four blending modes, use the Arg2 parameter */
1975 case D3DTOP_BLENDDIFFUSEALPHA:
1976 case D3DTOP_BLENDTEXTUREALPHA:
1977 case D3DTOP_BLENDFACTORALPHA:
1978 case D3DTOP_BLENDCURRENTALPHA: {
1979 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1982 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1983 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1984 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1985 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1988 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1989 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1990 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1991 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1992 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2001 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2002 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2003 /* Switch the arguments if needed... */
2004 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2005 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2006 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2008 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2009 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2012 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2013 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2015 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2016 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2022 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2023 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2025 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2027 TRACE(" Stage type is : %s => %s\n", type, value);
2029 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2033 case D3DTSS_COLORARG1:
2034 case D3DTSS_COLORARG2:
2035 case D3DTSS_ALPHAARG1:
2036 case D3DTSS_ALPHAARG2: {
2037 const char *value, *value_comp = "", *value_alpha = "";
2039 D3DTEXTUREOP tex_op;
2041 switch (dwState & D3DTA_SELECTMASK) {
2042 #define GEN_CASE(a) case a: value = #a; break
2043 GEN_CASE(D3DTA_DIFFUSE);
2044 GEN_CASE(D3DTA_CURRENT);
2045 GEN_CASE(D3DTA_TEXTURE);
2046 GEN_CASE(D3DTA_TFACTOR);
2047 GEN_CASE(D3DTA_SPECULAR);
2049 default: value = "UNKNOWN";
2051 if (dwState & D3DTA_COMPLEMENT) {
2052 value_comp = " | D3DTA_COMPLEMENT";
2054 if (dwState & D3DTA_ALPHAREPLICATE) {
2055 value_alpha = " | D3DTA_ALPHAREPLICATE";
2058 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2059 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2061 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2064 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2067 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2069 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2073 case D3DTSS_MIPMAPLODBIAS: {
2074 D3DVALUE value = *((D3DVALUE *) &dwState);
2075 BOOLEAN handled = TRUE;
2077 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2081 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2082 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2084 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2088 case D3DTSS_MAXMIPLEVEL:
2089 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2092 case D3DTSS_BORDERCOLOR:
2093 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2094 ((dwState >> 16) & 0xFF),
2095 ((dwState >> 8) & 0xFF),
2096 ((dwState >> 0) & 0xFF),
2097 ((dwState >> 24) & 0xFF));
2100 case D3DTSS_TEXCOORDINDEX: {
2101 BOOLEAN handled = TRUE;
2104 switch (dwState & 0xFFFF0000) {
2105 #define GEN_CASE(a) case a: value = #a; break
2106 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2107 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2108 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2109 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2111 default: value = "UNKNOWN";
2113 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2117 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2119 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2123 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2124 const char *projected = "", *value;
2125 BOOLEAN handled = TRUE;
2126 switch (dwState & 0xFF) {
2127 #define GEN_CASE(a) case a: value = #a; break
2128 GEN_CASE(D3DTTFF_DISABLE);
2129 GEN_CASE(D3DTTFF_COUNT1);
2130 GEN_CASE(D3DTTFF_COUNT2);
2131 GEN_CASE(D3DTTFF_COUNT3);
2132 GEN_CASE(D3DTTFF_COUNT4);
2134 default: value = "UNKNOWN";
2136 if (dwState & D3DTTFF_PROJECTED) {
2137 projected = " | D3DTTFF_PROJECTED";
2141 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2142 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2145 if (handled == TRUE) {
2146 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2148 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2153 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2163 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2165 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2167 BOOLEAN enable_colorkey = FALSE;
2169 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2170 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2173 /* If this stage is disabled, no need to go further... */
2174 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2177 /* First check if we need to bind any other texture for this stage */
2178 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2179 if (This->current_texture[stage] == NULL) {
2180 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2182 unit = GL_TEXTURE0_WINE + stage;
2183 if (unit != glThis->current_active_tex_unit) {
2184 GL_extensions.glActiveTexture(unit);
2185 glThis->current_active_tex_unit = unit;
2187 glBindTexture(GL_TEXTURE_2D, 0);
2188 glDisable(GL_TEXTURE_2D);
2190 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2192 unit = GL_TEXTURE0_WINE + stage;
2193 if (unit != glThis->current_active_tex_unit) {
2194 GL_extensions.glActiveTexture(unit);
2195 glThis->current_active_tex_unit = unit;
2198 if (glThis->current_bound_texture[stage] == NULL) {
2199 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2200 TRACE(" enabling 2D texturing and");
2201 glEnable(GL_TEXTURE_2D);
2204 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2205 glBindTexture(GL_TEXTURE_2D, tex_name);
2208 glThis->current_bound_texture[stage] = This->current_texture[stage];
2210 if (glThis->current_bound_texture[stage] == NULL) {
2211 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2213 TRACE(" using already bound texture id %d for stage %ld.\n",
2214 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2218 /* If no texure valid for this stage, go out of the loop */
2219 if (This->current_texture[stage] == NULL) break;
2221 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2222 This will also update the various texture parameters if needed.
2224 gltex_upload_texture(surf_ptr, This, stage);
2226 /* And finally check for color-keying (only on first stage) */
2227 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2229 enable_colorkey = TRUE;
2231 static BOOL warn = FALSE;
2232 if (warn == FALSE) {
2234 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2239 enable_colorkey = FALSE;
2244 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2245 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2246 (glThis->version == 1)) &&
2247 (enable_colorkey)) {
2248 TRACE(" colorkey activated.\n");
2250 if (glThis->alpha_test == FALSE) {
2251 glEnable(GL_ALPHA_TEST);
2252 glThis->alpha_test = TRUE;
2254 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2255 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2256 static BOOL warn = FALSE;
2257 if (warn == FALSE) {
2259 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2262 glThis->current_alpha_test_func = GL_NOTEQUAL;
2263 glThis->current_alpha_test_ref = 0.0;
2264 glAlphaFunc(GL_NOTEQUAL, 0.0);
2266 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2267 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2269 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2270 glDisable(GL_ALPHA_TEST);
2271 glThis->alpha_test = FALSE;
2273 /* Maybe we should restore here the application-given alpha test states ? */
2280 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2282 LPDIRECTDRAWSURFACE7 lpTexture2)
2284 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2286 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2288 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2289 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2290 if (lpTexture2 != NULL) {
2291 WARN(" setting a texture to a non-supported texture stage !\n");
2296 if (This->current_texture[dwStage] != NULL) {
2297 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2300 if (lpTexture2 == NULL) {
2301 This->current_texture[dwStage] = NULL;
2303 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2304 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2305 This->current_texture[dwStage] = tex_impl;
2312 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2313 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2315 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2316 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2318 fill_opengl_caps_7(lpD3DHELDevDesc);
2320 TRACE(" returning caps : no dump function yet.\n");
2326 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2327 LPD3DMATERIAL7 lpMat)
2329 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2330 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2332 if (TRACE_ON(ddraw)) {
2333 TRACE(" material is : \n");
2334 dump_D3DMATERIAL7(lpMat);
2337 This->current_material = *lpMat;
2340 glMaterialfv(GL_FRONT_AND_BACK,
2342 (float *) &(This->current_material.u.diffuse));
2343 glMaterialfv(GL_FRONT_AND_BACK,
2345 (float *) &(This->current_material.u1.ambient));
2346 glMaterialfv(GL_FRONT_AND_BACK,
2348 (float *) &(This->current_material.u2.specular));
2349 glMaterialfv(GL_FRONT_AND_BACK,
2351 (float *) &(This->current_material.u3.emissive));
2352 glMaterialf(GL_FRONT_AND_BACK,
2354 This->current_material.u4.power); /* Not sure about this... */
2362 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2364 LPD3DLIGHT7 lpLight)
2366 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2367 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2368 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2370 if (TRACE_ON(ddraw)) {
2371 TRACE(" setting light : \n");
2372 dump_D3DLIGHT7(lpLight);
2375 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2376 This->set_lights |= 0x00000001 << dwLightIndex;
2377 This->light_parameters[dwLightIndex] = *lpLight;
2379 /* Some checks to print out nice warnings :-) */
2380 switch (lpLight->dltType) {
2381 case D3DLIGHT_DIRECTIONAL:
2382 case D3DLIGHT_POINT:
2383 /* These are handled properly... */
2387 if ((lpLight->dvTheta != 0.0) ||
2388 (lpLight->dvTheta != lpLight->dvPhi)) {
2389 ERR("dvTheta not fully supported yet !\n");
2394 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2397 /* This will force the Light setting on next drawing of primitives */
2398 glThis->transform_state = GL_TRANSFORM_NONE;
2404 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2408 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2409 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2411 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2415 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2416 /* Set the default parameters.. */
2417 TRACE(" setting default light parameters...\n");
2418 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2420 glEnable(GL_LIGHT0 + dwLightIndex);
2421 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2422 /* This light gets active... Need to update its parameters to GL before the next drawing */
2423 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2425 This->active_lights |= 0x00000001 << dwLightIndex;
2426 glThis->transform_state = GL_TRANSFORM_NONE;
2429 glDisable(GL_LIGHT0 + dwLightIndex);
2430 This->active_lights &= ~(0x00000001 << dwLightIndex);
2438 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2440 ICOM_THIS(IDirect3DDeviceImpl,iface);
2441 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2443 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2445 if (dwIndex >= This->max_clipping_planes) {
2446 return DDERR_INVALIDPARAMS;
2449 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2451 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2453 /* This is to force the reset of the transformation matrices on the next drawing.
2454 * This is needed to use the correct matrices for the various clipping planes.
2456 glThis->transform_state = GL_TRANSFORM_NONE;
2462 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2463 LPD3DVIEWPORT7 lpData)
2465 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2466 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2468 if (TRACE_ON(ddraw)) {
2469 TRACE(" viewport is : \n");
2470 TRACE(" - dwX = %ld dwY = %ld\n",
2471 lpData->dwX, lpData->dwY);
2472 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2473 lpData->dwWidth, lpData->dwHeight);
2474 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2475 lpData->dvMinZ, lpData->dvMaxZ);
2479 /* Set the viewport */
2480 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2481 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2482 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2484 if ((lpData->dwX != This->active_viewport.dwX) ||
2485 (lpData->dwY != This->active_viewport.dwY) ||
2486 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2487 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2488 glViewport(lpData->dwX,
2489 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2490 lpData->dwWidth, lpData->dwHeight);
2495 This->active_viewport = *lpData;
2500 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2501 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2503 # define XCAST(fun) (void*)
2506 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2508 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2509 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2510 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2511 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2512 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2513 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2514 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2515 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2516 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2517 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2518 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2519 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2520 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2521 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2522 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2523 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2524 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2525 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2526 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2527 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2528 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2529 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2530 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2531 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2532 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2533 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2534 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2535 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2536 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2537 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2538 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2539 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2540 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2541 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2542 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2543 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2544 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2545 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2546 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2547 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2548 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2549 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2550 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2551 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2552 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2553 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2554 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2555 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2556 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2557 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2560 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2565 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2566 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2568 # define XCAST(fun) (void*)
2571 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2573 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2574 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2575 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2576 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2577 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2578 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2579 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2580 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2581 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2582 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2583 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2584 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2585 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2586 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2587 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2588 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2589 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2590 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2591 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2592 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2593 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2594 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2595 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2596 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2597 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2598 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2599 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2600 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2601 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2602 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2603 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2604 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2605 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2606 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2607 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2608 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2609 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2610 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2611 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2612 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2613 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2614 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2615 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2618 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2623 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2624 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2626 # define XCAST(fun) (void*)
2629 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2631 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2632 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2633 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2634 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2635 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2636 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2637 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2638 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2639 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2640 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2641 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2642 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2643 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2644 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2645 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2646 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2647 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2648 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2649 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2650 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2651 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2652 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2653 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2654 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2655 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2656 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2657 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2658 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2659 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2660 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2661 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2662 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2663 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2664 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2667 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2672 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2673 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2675 # define XCAST(fun) (void*)
2678 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2680 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2681 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2682 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2683 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2684 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2685 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2686 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2687 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2688 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2689 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2690 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2691 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2692 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2693 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2694 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2695 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2696 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2697 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2698 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2699 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2700 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2701 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2702 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2705 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2709 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2710 WINE_GL_BUFFER_TYPE buffer_type,
2718 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2719 GLbitfield bitfield = 0;
2723 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2724 if (TRACE_ON(ddraw)) {
2727 TRACE(" rectangles : \n");
2728 for (i = 0; i < dwCount; i++) {
2729 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2738 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2739 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2743 /* Clears the screen */
2746 if (dwFlags & D3DCLEAR_TARGET) {
2747 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2748 /* TODO: optimize here the case where Clear changes all the screen... */
2749 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2751 glThis->state[buffer_type] = SURFACE_GL;
2754 if (dwFlags & D3DCLEAR_ZBUFFER) {
2755 bitfield |= GL_DEPTH_BUFFER_BIT;
2756 if (glThis->depth_mask == FALSE) {
2757 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2759 if (dvZ != glThis->prev_clear_Z) {
2761 glThis->prev_clear_Z = dvZ;
2763 TRACE(" depth value : %f\n", dvZ);
2765 if (dwFlags & D3DCLEAR_STENCIL) {
2766 bitfield |= GL_STENCIL_BUFFER_BIT;
2767 if (dwStencil != glThis->prev_clear_stencil) {
2768 glClearStencil(dwStencil);
2769 glThis->prev_clear_stencil = dwStencil;
2771 TRACE(" stencil value : %ld\n", dwStencil);
2773 if (dwFlags & D3DCLEAR_TARGET) {
2774 bitfield |= GL_COLOR_BUFFER_BIT;
2775 if (dwColor != glThis->prev_clear_color) {
2776 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2777 ((dwColor >> 8) & 0xFF) / 255.0,
2778 ((dwColor >> 0) & 0xFF) / 255.0,
2779 ((dwColor >> 24) & 0xFF) / 255.0);
2780 glThis->prev_clear_color = dwColor;
2782 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2785 glEnable(GL_SCISSOR_TEST);
2786 for (i = 0; i < dwCount; i++) {
2787 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2788 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2791 glDisable(GL_SCISSOR_TEST);
2793 if (dwFlags & D3DCLEAR_ZBUFFER) {
2794 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2802 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2810 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2814 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2815 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2817 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2818 WINE_GL_BUFFER_TYPE buffer_type;
2820 /* First check if we BLT to the backbuffer... */
2821 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2822 buffer_type = WINE_GL_BUFFER_BACK;
2823 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2824 buffer_type = WINE_GL_BUFFER_FRONT;
2826 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2827 return DDERR_INVALIDPARAMS;
2830 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2831 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2832 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2833 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2834 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2835 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2838 return DDERR_INVALIDPARAMS;
2840 *buffer_type_p = buffer_type;
2846 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2847 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2848 DWORD dwFlags, LPDDBLTFX lpbltfx)
2850 WINE_GL_BUFFER_TYPE buffer_type;
2854 rect.u1.x1 = rdst->left;
2855 rect.u2.y1 = rdst->top;
2856 rect.u3.x2 = rdst->right;
2857 rect.u4.y2 = rdst->bottom;
2861 rect.u3.x2 = This->surface_desc.dwWidth;
2862 rect.u4.y2 = This->surface_desc.dwHeight;
2865 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2867 if (dwFlags & DDBLT_COLORFILL) {
2868 /* This is easy to handle for the D3D Device... */
2872 /* The color as given in the Blt function is in the format of the frame-buffer...
2873 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2875 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2876 if (This->palette) {
2877 color = ((0xFF000000) |
2878 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2879 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2880 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2884 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2885 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2886 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2887 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2888 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2889 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2890 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2891 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2894 color = ((0xFF000000) |
2895 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2896 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2897 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2899 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2900 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2901 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2902 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2903 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2904 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2906 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2907 return DDERR_INVALIDPARAMS;
2910 ERR("Wrong surface type for BLT override !\n");
2911 return DDERR_INVALIDPARAMS;
2914 TRACE(" executing D3D Device override.\n");
2918 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2919 if (buffer_type == WINE_GL_BUFFER_FRONT)
2920 glDrawBuffer(GL_FRONT);
2922 glDrawBuffer(GL_BACK);
2924 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2926 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2927 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2928 glDrawBuffer(prev_draw);
2933 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2934 /* Normal blit without any special case... */
2936 /* And which has a SRC surface */
2937 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2939 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2940 (src_impl->d3ddevice == This->d3ddevice) &&
2941 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2942 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2946 WINE_GL_BUFFER_TYPE src_buffer_type;
2947 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2953 src_rect.u1.x1 = rsrc->left;
2954 src_rect.u2.y1 = rsrc->top;
2955 src_rect.u3.x2 = rsrc->right;
2956 src_rect.u4.y2 = rsrc->bottom;
2960 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2961 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2964 width = src_rect.u3.x2 - src_rect.u1.x1;
2965 height = src_rect.u4.y2 - src_rect.u2.y1;
2967 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2968 (height != (rect.u4.y2 - rect.u2.y1))) {
2969 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2970 return DDERR_INVALIDPARAMS;
2973 /* First check if we BLT from the backbuffer... */
2974 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2975 src_buffer_type = WINE_GL_BUFFER_BACK;
2976 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2977 src_buffer_type = WINE_GL_BUFFER_FRONT;
2979 ERR("Unexpected case in direct buffer to buffer copy !\n");
2980 return DDERR_INVALIDPARAMS;
2983 TRACE(" using direct buffer to buffer copy.\n");
2987 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2989 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2990 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2991 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2993 return DDERR_INVALIDPARAMS;
2996 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2997 if (buffer_type == WINE_GL_BUFFER_FRONT)
2998 glDrawBuffer(GL_FRONT);
3000 glDrawBuffer(GL_BACK);
3002 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3003 glReadBuffer(GL_FRONT);
3005 glReadBuffer(GL_BACK);
3007 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3008 And directly re-draws this on the destination buffer. */
3009 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3012 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3013 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3015 get_height = UNLOCK_TEX_SIZE;
3017 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3020 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3021 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3023 get_width = UNLOCK_TEX_SIZE;
3025 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3026 0, UNLOCK_TEX_SIZE - get_height,
3027 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3028 get_width, get_height);
3031 glTexCoord2f(0.0, 0.0);
3032 glVertex3d(rect.u1.x1 + x,
3033 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3035 glTexCoord2f(1.0, 0.0);
3036 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3037 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3039 glTexCoord2f(1.0, 1.0);
3040 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3043 glTexCoord2f(0.0, 1.0);
3044 glVertex3d(rect.u1.x1 + x,
3051 upload_surface_to_tex_memory_release();
3052 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3054 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3055 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3056 glDrawBuffer(prev_draw);
3062 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3063 (this prevents calling glReadPixels) */
3067 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3071 double x_stretch, y_stretch;
3074 src_rect.u1.x1 = rsrc->left;
3075 src_rect.u2.y1 = rsrc->top;
3076 src_rect.u3.x2 = rsrc->right;
3077 src_rect.u4.y2 = rsrc->bottom;
3081 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3082 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3085 width = src_rect.u3.x2 - src_rect.u1.x1;
3086 height = src_rect.u4.y2 - src_rect.u2.y1;
3088 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3089 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3091 TRACE(" using memory to buffer Blt overide.\n");
3095 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3097 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3098 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3099 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3101 return DDERR_INVALIDPARAMS;
3104 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3105 if (buffer_type == WINE_GL_BUFFER_FRONT)
3106 glDrawBuffer(GL_FRONT);
3108 glDrawBuffer(GL_BACK);
3110 /* Now the serious stuff happens. This is basically the same code that for the memory
3111 flush to frame buffer ... with stretching and different rectangles added :-) */
3112 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3115 flush_rect.top = src_rect.u2.y1 + y;
3116 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3118 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3120 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3121 flush_rect.left = src_rect.u1.x1 + x;
3122 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3124 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3126 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3129 glTexCoord2f(0.0, 0.0);
3130 glVertex3d(rect.u1.x1 + (x * x_stretch),
3131 rect.u2.y1 + (y * y_stretch),
3133 glTexCoord2f(1.0, 0.0);
3134 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3135 rect.u2.y1 + (y * y_stretch),
3137 glTexCoord2f(1.0, 1.0);
3138 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3139 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3141 glTexCoord2f(0.0, 1.0);
3142 glVertex3d(rect.u1.x1 + (x * x_stretch),
3143 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3149 upload_surface_to_tex_memory_release();
3150 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3152 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3153 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3154 glDrawBuffer(prev_draw);
3162 return DDERR_INVALIDPARAMS;
3166 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3167 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3168 LPRECT rsrc, DWORD trans)
3172 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3173 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3174 WINE_GL_BUFFER_TYPE buffer_type;
3178 int width, height, x, y;
3180 /* Cannot support DSTCOLORKEY blitting... */
3181 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3184 WARN("rsrc is NULL - getting the whole surface !!\n");
3186 rsrc->left = rsrc->top = 0;
3187 rsrc->right = src_impl->surface_desc.dwWidth;
3188 rsrc->bottom = src_impl->surface_desc.dwHeight;
3196 rdst.right = dstx + (rsrc->right - rsrc->left);
3197 if (rdst.right > This->surface_desc.dwWidth) {
3198 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3199 rdst.right = This->surface_desc.dwWidth;
3201 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3202 if (rdst.bottom > This->surface_desc.dwHeight) {
3203 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3204 rdst.bottom = This->surface_desc.dwHeight;
3207 width = rsrc->right - rsrc->left;
3208 height = rsrc->bottom - rsrc->top;
3210 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3212 TRACE(" using BltFast memory to frame buffer overide.\n");
3216 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3218 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3219 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3220 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3221 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3223 return DDERR_INVALIDPARAMS;
3226 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3227 if (buffer_type == WINE_GL_BUFFER_FRONT)
3228 glDrawBuffer(GL_FRONT);
3230 glDrawBuffer(GL_BACK);
3232 /* Now the serious stuff happens. This is basically the same code that for the memory
3233 flush to frame buffer but with different rectangles for source and destination :-) */
3234 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3237 flush_rect.top = rsrc->top + y;
3238 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3240 (rsrc->top + y + UNLOCK_TEX_SIZE));
3242 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3243 flush_rect.left = rsrc->left + x;
3244 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3246 (rsrc->left + x + UNLOCK_TEX_SIZE));
3248 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3251 glTexCoord2f(0.0, 0.0);
3252 glVertex3d(rdst.left + x,
3255 glTexCoord2f(1.0, 0.0);
3256 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3259 glTexCoord2f(1.0, 1.0);
3260 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3261 rdst.top + (y + UNLOCK_TEX_SIZE),
3263 glTexCoord2f(0.0, 1.0);
3264 glVertex3d(rdst.left + x,
3265 rdst.top + (y + UNLOCK_TEX_SIZE),
3271 upload_surface_to_tex_memory_release();
3272 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3274 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3275 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3276 glDrawBuffer(prev_draw);
3284 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3286 GLfloat height, width;
3287 GLfloat trans_mat[16];
3289 TRACE("(%p)\n", This);
3291 width = This->surface->surface_desc.dwWidth;
3292 height = This->surface->surface_desc.dwHeight;
3294 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3295 to OpenGL screen coordinates (ie the upper left corner is not the same).
3296 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3297 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3298 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3299 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3300 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3301 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3304 glMatrixMode(GL_MODELVIEW);
3306 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3307 Correctness Tips section).
3309 Basically, from what I understood, if the game does not filter the font texture,
3310 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3311 one and we will have strange artifacts (as the rounding and stuff may give different results
3312 for different pixels, ie sometimes take the left pixel, sometimes the right).
3314 glTranslatef(0.375, 0.375, 0);
3315 glMatrixMode(GL_PROJECTION);
3316 glLoadMatrixf(trans_mat);
3321 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3322 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3324 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3327 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3328 glMatrixMode(GL_MODELVIEW);
3329 glLoadMatrixf((float *) view_mat);
3331 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3332 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3335 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3336 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3339 plane[0] = This->clipping_planes[i].plane[0];
3340 plane[1] = This->clipping_planes[i].plane[1];
3341 plane[2] = This->clipping_planes[i].plane[2];
3342 plane[3] = This->clipping_planes[i].plane[3];
3344 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3348 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3352 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3353 if (runner & This->active_lights) {
3354 switch (This->light_parameters[i].dltType) {
3355 case D3DLIGHT_DIRECTIONAL: {
3357 float cut_off = 180.0;
3359 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3360 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3361 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3362 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3364 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3365 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3366 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3368 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3371 case D3DLIGHT_POINT: {
3373 float cut_off = 180.0;
3375 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3376 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3377 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3378 position[0] = This->light_parameters[i].dvPosition.u1.x;
3379 position[1] = This->light_parameters[i].dvPosition.u2.y;
3380 position[2] = This->light_parameters[i].dvPosition.u3.z;
3382 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3383 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3384 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3385 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3386 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3389 case D3DLIGHT_SPOT: {
3392 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3394 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3395 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3396 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3398 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3399 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3400 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3402 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3403 position[0] = This->light_parameters[i].dvPosition.u1.x;
3404 position[1] = This->light_parameters[i].dvPosition.u2.y;
3405 position[2] = This->light_parameters[i].dvPosition.u3.z;
3407 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3408 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3409 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3410 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3411 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3412 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3416 /* No warning here as it's already done at light setting */
3423 glMultMatrixf((float *) world_mat);
3425 if ((matrices & PROJMAT_CHANGED) != 0) {
3426 glMatrixMode(GL_PROJECTION);
3427 glLoadMatrixf((float *) proj_mat);
3433 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3435 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3436 DWORD tex_mat, tex_stage;
3438 TRACE("(%p,%08lx)\n", This, matrices);
3440 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3441 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3442 /* This will force an update of the transform state at the next drawing. */
3443 glThis->transform_state = GL_TRANSFORM_NONE;
3446 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3447 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3450 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3451 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3452 if (matrices & tex_mat) {
3453 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3454 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3456 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3457 if (glThis->current_active_tex_unit != unit) {
3458 GL_extensions.glActiveTexture(unit);
3459 glThis->current_active_tex_unit = unit;
3461 glMatrixMode(GL_TEXTURE);
3462 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3464 This->tex_mat_is_identity[tex_stage] = is_identity;
3466 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3467 if (glThis->current_active_tex_unit != unit) {
3468 GL_extensions.glActiveTexture(unit);
3469 glThis->current_active_tex_unit = unit;
3471 glMatrixMode(GL_TEXTURE);
3473 This->tex_mat_is_identity[tex_stage] = TRUE;
3482 /* TODO for both these functions :
3483 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3484 by other OpenGL code in D3D
3485 - handle the case where no 'Begin / EndScene' was done between two locks
3486 - handle the rectangles in the unlock too
3487 - handle pitch correctly...
3489 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3491 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3492 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3493 WINE_GL_BUFFER_TYPE buffer_type;
3496 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3497 buffer_type = WINE_GL_BUFFER_FRONT;
3498 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3499 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3500 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3502 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3503 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3504 buffer_type = WINE_GL_BUFFER_BACK;
3505 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3506 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3507 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3509 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3511 ERR("Wrong surface type for locking !\n");
3515 if (pRect == NULL) {
3518 loc_rect.bottom = This->surface_desc.dwHeight;
3519 loc_rect.right = This->surface_desc.dwWidth;
3523 /* Try to acquire the device critical section */
3524 EnterCriticalSection(&(d3d_dev->crit));
3526 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3527 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3528 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3530 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3532 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3533 /* Check if the new rectangle is in the previous one or not.
3534 If it is not, flush first the previous locks on screen.
3536 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3537 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3538 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3539 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3540 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3541 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3542 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3543 pRect->left, pRect->top, pRect->right, pRect->bottom,
3544 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3545 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3546 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3548 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3549 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3551 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3553 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3556 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3557 /* If the surface is already in memory, no need to do anything here... */
3558 GLenum buffer_format;
3559 GLenum buffer_color;
3563 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3564 pRect->left, pRect->top, pRect->right, pRect->bottom);
3566 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3567 may only write to the device... But when we will blit it back to the screen, we need
3568 also to blit correctly the parts the application did not overwrite... */
3570 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3571 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3572 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3573 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3574 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3575 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3576 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3577 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3578 buffer_color = GL_RGB;
3579 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3580 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3581 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3582 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3583 buffer_format = GL_UNSIGNED_BYTE;
3584 buffer_color = GL_RGB;
3585 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3586 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3587 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3588 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3589 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3590 buffer_color = GL_BGRA;
3592 ERR(" unsupported pixel format at device locking.\n");
3596 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3602 if (buffer_type == WINE_GL_BUFFER_FRONT)
3603 /* Application wants to lock the front buffer */
3604 glReadBuffer(GL_FRONT);
3606 /* Application wants to lock the back buffer */
3607 glReadBuffer(GL_BACK);
3609 dst = ((char *)This->surface_desc.lpSurface) +
3610 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3611 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3612 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3614 glReadPixels(pRect->left, y,
3615 pRect->right - pRect->left, 1,
3616 buffer_color, buffer_format, dst);
3617 dst += This->surface_desc.u1.lPitch;
3620 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3623 /* I keep this code here as it's very useful to debug :-) */
3625 static int flush_count = 0;
3629 if ((++flush_count % 50) == 0) {
3630 sprintf(buf, "lock_%06d.pnm", flush_count);
3631 f = fopen(buf, "wb");
3632 DDRAW_dump_surface_to_disk(This, f);
3641 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3643 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3648 /* Note : no need here to lock the 'device critical section' as we are already protected by
3649 the GL critical section. */
3651 if (pRect == NULL) {
3654 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3655 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3659 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3661 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3663 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3664 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3665 ERR(" unsupported pixel format at frame buffer flush.\n");
3669 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3673 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3675 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3676 /* First, upload the texture... */
3677 flush_rect.left = x;
3678 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3680 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3683 glTexCoord2f(0.0, 0.0);
3684 glVertex3d(x, y, 0.5);
3685 glTexCoord2f(1.0, 0.0);
3686 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3687 glTexCoord2f(1.0, 1.0);
3688 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3689 glTexCoord2f(0.0, 1.0);
3690 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3695 upload_surface_to_tex_memory_release();
3696 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3699 /* I keep this code here as it's very useful to debug :-) */
3701 static int flush_count = 0;
3705 if ((++flush_count % 50) == 0) {
3706 sprintf(buf, "flush_%06d.pnm", flush_count);
3707 f = fopen(buf, "wb");
3708 DDRAW_dump_surface_to_disk(surf, f);
3714 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3716 WINE_GL_BUFFER_TYPE buffer_type;
3717 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3718 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3720 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3721 buffer_type = WINE_GL_BUFFER_FRONT;
3722 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3723 buffer_type = WINE_GL_BUFFER_BACK;
3725 ERR("Wrong surface type for locking !\n");
3729 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3730 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3731 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3733 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3735 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3736 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3737 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3740 TRACE(" flushing front buffer immediatly on screen.\n");
3743 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3744 glDrawBuffer(GL_FRONT);
3745 /* Note: we do not use the application provided lock rectangle but our own stored at
3746 lock time. This is because in old D3D versions, the 'lock' parameter did not
3749 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]);
3750 glDrawBuffer(prev_draw);
3753 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3757 /* And 'frees' the device critical section */
3758 LeaveCriticalSection(&(d3d_dev->crit));
3762 apply_texture_state(IDirect3DDeviceImpl *This)
3766 /* Initialize texture stages states */
3767 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3768 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3769 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3770 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3771 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3778 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3780 IDirect3DDeviceImpl *object;
3781 IDirect3DDeviceGLImpl *gl_object;
3782 IDirectDrawSurfaceImpl *surf;
3787 XVisualInfo template;
3788 GLenum buffer = GL_FRONT;
3791 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3792 if (object == NULL) return DDERR_OUTOFMEMORY;
3794 gl_object = (IDirect3DDeviceGLImpl *) object;
3798 object->surface = surface;
3799 object->set_context = set_context;
3800 object->clear = d3ddevice_clear_back;
3801 object->set_matrices = d3ddevice_set_matrices;
3802 object->matrices_updated = d3ddevice_matrices_updated;
3803 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3805 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3807 InitializeCriticalSection(&(object->crit));
3809 TRACE(" device critical section : %p\n", &(object->crit));
3811 /* This is just a hack for some badly done games :-/ */
3813 gl_object->version = 1;
3814 TRACE(" using D3D1 special hacks.\n");
3816 gl_object->version = 7;
3818 device_context = GetDC(surface->ddraw_owner->window);
3819 gl_object->display = get_display(device_context);
3820 gl_object->drawable = get_drawable(device_context);
3821 ReleaseDC(surface->ddraw_owner->window,device_context);
3824 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3825 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3827 HeapFree(GetProcessHeap(), 0, object);
3828 ERR("No visual found !\n");
3830 return DDERR_INVALIDPARAMS;
3832 TRACE(" visual found\n");
3835 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3838 if (gl_object->gl_context == NULL) {
3839 HeapFree(GetProcessHeap(), 0, object);
3840 ERR("Error in context creation !\n");
3842 return DDERR_INVALIDPARAMS;
3844 TRACE(" context created (%p)\n", gl_object->gl_context);
3847 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3848 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3849 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3850 surf->aux_ctx = (LPVOID) object;
3851 surf->aux_data = (LPVOID) gl_object->drawable;
3852 surf->aux_flip = opengl_flip;
3857 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3859 TRACE(" no double buffering : drawing on the front buffer\n");
3863 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3864 IDirectDrawSurfaceImpl *surf2;
3865 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3866 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3867 TRACE(" checking surface %p :", surf2);
3868 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3869 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3870 /* Override the Lock / Unlock function for all these surfaces */
3871 surf2->lock_update_prev = surf2->lock_update;
3872 surf2->lock_update = d3ddevice_lock_update;
3873 surf2->unlock_update_prev = surf2->unlock_update;
3874 surf2->unlock_update = d3ddevice_unlock_update;
3875 /* And install also the blt / bltfast overrides */
3876 surf2->aux_blt = d3ddevice_blt;
3877 surf2->aux_bltfast = d3ddevice_bltfast;
3879 TRACE(" overiding direct surface access.\n");
3881 TRACE(" no overide.\n");
3883 surf2->d3ddevice = object;
3887 /* Set the various light parameters */
3888 for (light = 0; light < MAX_LIGHTS; light++) {
3889 /* Only set the fields that are not zero-created */
3890 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3891 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3892 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3893 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3894 object->light_parameters[light].dvDirection.u3.z = 1.0;
3897 /* Allocate memory for the matrices */
3898 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3899 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3900 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3901 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3902 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3903 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3904 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3905 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3906 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3907 object->tex_mat_is_identity[tex_num] = TRUE;
3910 /* Initialisation */
3911 TRACE(" setting current context\n");
3912 object->set_context(object);
3913 TRACE(" current context set\n");
3915 /* allocate the clipping planes */
3916 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3917 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3919 glHint(GL_FOG_HINT,GL_NICEST);
3921 /* Initialize the various GL contexts to be in sync with what we store locally */
3924 glClearColor(0.0, 0.0, 0.0, 0.0);
3925 glDepthMask(GL_TRUE);
3926 gl_object->depth_mask = TRUE;
3927 glEnable(GL_DEPTH_TEST);
3928 gl_object->depth_test = TRUE;
3929 glDisable(GL_ALPHA_TEST);
3930 glDisable(GL_STENCIL_TEST);
3931 glDisable(GL_CULL_FACE);
3932 glDisable(GL_LIGHTING);
3933 glDisable(GL_BLEND);
3935 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3936 gl_object->current_tex_env = GL_REPLACE;
3937 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3938 if (GL_extensions.glActiveTexture != NULL) {
3939 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3941 gl_object->current_alpha_test_ref = 0.0;
3942 gl_object->current_alpha_test_func = GL_ALWAYS;
3943 glAlphaFunc(GL_ALWAYS, 0.0);
3945 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3946 glDrawBuffer(buffer);
3947 glReadBuffer(buffer);
3948 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3951 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3952 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3954 /* fill_device_capabilities(d3d->ddraw); */
3956 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3957 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3958 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3959 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3963 TRACE(" creating implementation at %p.\n", *obj);
3965 /* And finally warn D3D that this device is now present */
3966 object->d3d->d3d_added_device(object->d3d, object);
3968 /* FIXME: Should handle other versions than just 7 */
3969 InitDefaultStateBlock(&object->state_block, 7);
3970 /* Apply default render state and texture stage state values */
3971 apply_render_state(object, &object->state_block);
3972 apply_texture_state(object);
3974 /* And fill the fog table with the default fog value */
3975 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3980 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3982 pc->dwSize = sizeof(*pc);
3983 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3984 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3985 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3986 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3987 D3DPRASTERCAPS_ZFOG;
3988 if (GL_extensions.mipmap_lodbias == TRUE) {
3989 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3991 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3992 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3993 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3994 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3995 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3996 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3997 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3998 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3999 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4000 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4001 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4002 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4003 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4004 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4005 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4006 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4007 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4008 D3DPTFILTERCAPS_MIPFPOINT;
4009 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4010 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4011 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4012 if (GL_extensions.mirrored_repeat == TRUE) {
4013 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4015 pc->dwStippleWidth = 32;
4016 pc->dwStippleHeight = 32;
4019 static void fill_caps(void)
4021 GLint max_clip_planes;
4024 /* Fill first all the fields with default values which will be overriden later on with
4025 correct ones from the GL code
4027 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4028 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4029 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4030 /* D3D 7 capabilities */
4031 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
4032 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4033 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4034 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4035 opengl_device_caps.dwMinTextureWidth = 1;
4036 opengl_device_caps.dwMinTextureHeight = 1;
4037 opengl_device_caps.dwMaxTextureWidth = 1024;
4038 opengl_device_caps.dwMaxTextureHeight = 1024;
4039 opengl_device_caps.dwMaxTextureRepeat = 16;
4040 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4041 opengl_device_caps.dwMaxAnisotropy = 0;
4042 opengl_device_caps.dvGuardBandLeft = 0.0;
4043 opengl_device_caps.dvGuardBandRight = 0.0;
4044 opengl_device_caps.dvGuardBandTop = 0.0;
4045 opengl_device_caps.dvGuardBandBottom = 0.0;
4046 opengl_device_caps.dvExtentsAdjust = 0.0;
4047 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4048 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4049 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4050 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4051 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4052 if (GL_extensions.max_texture_units != 0) {
4053 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4054 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4055 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4057 opengl_device_caps.wMaxTextureBlendStages = 1;
4058 opengl_device_caps.wMaxSimultaneousTextures = 1;
4059 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4061 opengl_device_caps.dwMaxActiveLights = 16;
4062 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4063 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4064 opengl_device_caps.wMaxUserClipPlanes = 1;
4065 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4066 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4067 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4068 opengl_device_caps.dwReserved1 = 0;
4069 opengl_device_caps.dwReserved2 = 0;
4070 opengl_device_caps.dwReserved3 = 0;
4071 opengl_device_caps.dwReserved4 = 0;
4073 /* And now some GL overides :-) */
4074 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4075 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4076 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4077 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4079 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4080 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4082 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4083 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4084 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4086 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4087 TRACE(": Z bits = %d\n", depth_bits);
4088 switch (depth_bits) {
4089 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4090 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4092 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4097 d3ddevice_init_at_startup(void *gl_handle)
4099 XVisualInfo template;
4104 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4105 XWindowAttributes win_attr;
4106 GLXContext gl_context;
4108 const char *glExtensions;
4109 const char *glVersion;
4110 const char *glXExtensions = NULL;
4111 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4112 int major, minor, patch, num_parsed;
4114 TRACE("Initializing GL...\n");
4116 /* Get a default rendering context to have the 'caps' function query some info from GL */
4117 device_context = GetDC(0);
4118 display = get_display(device_context);
4119 ReleaseDC(0, device_context);
4122 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4123 visual = win_attr.visual;
4125 visual = DefaultVisual(display, DefaultScreen(display));
4127 template.visualid = XVisualIDFromVisual(visual);
4128 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4131 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4134 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4136 if (gl_context == NULL) {
4138 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4141 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4142 glXDestroyContext(display, gl_context);
4144 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4148 /* Then, query all extensions */
4149 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4150 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4151 glVersion = (const char *) glGetString(GL_VERSION);
4152 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4153 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4156 /* Parse the GL version string */
4157 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4158 if (num_parsed == 1) {
4161 } else if (num_parsed == 2) {
4164 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4166 /* And starts to fill the extension context properly */
4167 memset(&GL_extensions, 0, sizeof(GL_extensions));
4168 TRACE("GL supports following extensions used by Wine :\n");
4170 /* Mirrored Repeat extension :
4171 - GL_ARB_texture_mirrored_repeat
4172 - GL_IBM_texture_mirrored_repeat
4175 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4176 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4178 ((major == 1) && (minor >= 4))) {
4179 TRACE(" - mirrored repeat\n");
4180 GL_extensions.mirrored_repeat = TRUE;
4183 /* Texture LOD Bias :
4184 - GL_EXT_texture_lod_bias
4186 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4187 TRACE(" - texture lod bias\n");
4188 GL_extensions.mipmap_lodbias = TRUE;
4191 /* For all subsequent extensions, we need glXGetProcAddress */
4192 if (pglXGetProcAddressARB != NULL) {
4193 /* Multi-texturing :
4194 - GL_ARB_multitexture
4197 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4199 ((major == 1) && (minor > 2)) ||
4200 ((major == 1) && (minor == 2) && (patch >= 1))) {
4201 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4202 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4203 /* We query the ARB version to be the most portable we can... */
4204 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4205 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4209 /* Fill the D3D capabilities according to what GL tells us... */
4212 /* And frees this now-useless context */
4213 glXMakeCurrent(display, None, NULL);
4214 glXDestroyContext(display, gl_context);