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 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
792 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
793 switch (dwLightState) {
795 ERR("DDCOLOR_MONO should not happen!\n");
798 /* We are already in this mode */
799 TRACE("Setting color model to RGB (no-op).\n");
802 ERR("Unknown color model!\n");
803 return DDERR_INVALIDPARAMS;
806 D3DRENDERSTATETYPE rs;
807 switch (dwLightStateType) {
808 case D3DLIGHTSTATE_AMBIENT: /* 2 */
809 rs = D3DRENDERSTATE_AMBIENT;
811 case D3DLIGHTSTATE_FOGMODE: /* 4 */
812 rs = D3DRENDERSTATE_FOGVERTEXMODE;
814 case D3DLIGHTSTATE_FOGSTART: /* 5 */
815 rs = D3DRENDERSTATE_FOGSTART;
817 case D3DLIGHTSTATE_FOGEND: /* 6 */
818 rs = D3DRENDERSTATE_FOGEND;
820 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
821 rs = D3DRENDERSTATE_FOGDENSITY;
823 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
824 rs = D3DRENDERSTATE_COLORVERTEX;
827 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
828 return DDERR_INVALIDPARAMS;
831 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
838 static GLenum convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt)
841 case D3DPT_POINTLIST:
842 TRACE(" primitive type is POINTS\n");
846 TRACE(" primitive type is LINES\n");
849 case D3DPT_LINESTRIP:
850 TRACE(" primitive type is LINE_STRIP\n");
851 return GL_LINE_STRIP;
853 case D3DPT_TRIANGLELIST:
854 TRACE(" primitive type is TRIANGLES\n");
857 case D3DPT_TRIANGLESTRIP:
858 TRACE(" primitive type is TRIANGLE_STRIP\n");
859 return GL_TRIANGLE_STRIP;
861 case D3DPT_TRIANGLEFAN:
862 TRACE(" primitive type is TRIANGLE_FAN\n");
863 return GL_TRIANGLE_FAN;
866 FIXME("Unhandled primitive %08x\n", d3dpt);
871 /* This function calculate the Z coordinate from Zproj */
872 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
875 /* Assume that X = Y = 0 and W = 1 */
876 a = This->proj_mat->_33;
877 b = This->proj_mat->_34;
878 c = This->proj_mat->_43;
879 d = This->proj_mat->_44;
880 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
881 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
882 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
884 return (d*Zproj - c) / (a - b*Zproj);
887 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
890 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
892 for (i = 0; i < 3; i++) {
893 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
895 for (elt = 0; elt < 0x10000; elt++) {
896 /* We apply the fog transformation and cache the result */
897 DWORD fog_intensity = elt & 0xFF;
898 DWORD vertex_color = (elt >> 8) & 0xFF;
899 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
904 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
905 BOOLEAN vertex_transformed,
906 BOOLEAN vertex_lit) {
907 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
909 /* Puts GL in the correct lighting / transformation mode */
910 if ((vertex_transformed == FALSE) &&
911 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
912 /* Need to put the correct transformation again if we go from Transformed
913 vertices to non-transformed ones.
915 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
916 This->world_mat, This->view_mat, This->proj_mat);
917 glThis->transform_state = GL_TRANSFORM_NORMAL;
919 } else if ((vertex_transformed == TRUE) &&
920 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
921 /* Set our orthographic projection */
922 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
923 glThis->transform_state = GL_TRANSFORM_ORTHO;
924 d3ddevice_set_ortho(This);
928 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
929 if no fogging state change occurred */
930 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
931 if (vertex_transformed == TRUE) {
932 if (glThis->fogging != 0) {
936 /* Now check if our fog_table still corresponds to the current vertex color.
937 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
938 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
939 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
940 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
941 /* We need to rebuild our fog table.... */
942 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
945 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
946 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
947 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
948 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
949 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
951 if (vertex_lit == FALSE) {
952 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
953 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
955 /* Special case of 'pixel fog' */
956 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
957 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
959 if (glThis->fogging == 0) {
964 if (glThis->fogging != 0) {
971 if (glThis->fogging != 0) {
977 /* Handle the 'no-normal' case */
978 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
979 if (glThis->lighting == 0) {
980 glEnable(GL_LIGHTING);
981 glThis->lighting = 1;
984 if (glThis->lighting != 0) {
985 glDisable(GL_LIGHTING);
986 glThis->lighting = 0;
990 /* Handle the code for pre-vertex material properties */
991 if (vertex_transformed == FALSE) {
992 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
993 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
994 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
995 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
996 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
997 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
998 glEnable(GL_COLOR_MATERIAL);
1005 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1006 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1008 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1011 case D3DVT_VERTEX: {
1012 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1013 strided.position.dwStride = sizeof(D3DVERTEX);
1014 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1015 strided.normal.dwStride = sizeof(D3DVERTEX);
1016 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1017 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1018 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1021 case D3DVT_LVERTEX: {
1022 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1023 strided.position.dwStride = sizeof(D3DLVERTEX);
1024 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1025 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1026 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1027 strided.specular.dwStride = sizeof(D3DLVERTEX);
1028 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1029 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1030 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1033 case D3DVT_TLVERTEX: {
1034 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1035 strided.position.dwStride = sizeof(D3DTLVERTEX);
1036 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1037 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1038 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1039 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1040 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1041 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1042 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1046 FIXME("Unhandled vertex type %08x\n", d3dvt);
1052 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1053 D3DPRIMITIVETYPE d3dptPrimitiveType,
1054 D3DVERTEXTYPE d3dvtVertexType,
1056 DWORD dwVertexCount,
1059 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1061 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1062 if (TRACE_ON(ddraw)) {
1063 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1066 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1072 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1073 D3DPRIMITIVETYPE d3dptPrimitiveType,
1074 D3DVERTEXTYPE d3dvtVertexType,
1076 DWORD dwVertexCount,
1081 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1082 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1083 if (TRACE_ON(ddraw)) {
1084 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1087 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1093 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1094 LPD3DEXECUTEBUFFERDESC lpDesc,
1095 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1096 IUnknown* pUnkOuter)
1098 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1099 IDirect3DExecuteBufferImpl *ret;
1102 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1104 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1105 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1107 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1112 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1113 static BOOLEAN first = TRUE;
1114 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1118 if (first == TRUE) {
1119 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1123 TRACE("flushing ZBuffer back to GL\n");
1125 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1126 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1127 d3ddevice_set_ortho(d3d_dev);
1130 glMatrixMode(GL_MODELVIEW);
1133 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1134 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1135 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1137 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1140 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1141 case 16: type = GL_UNSIGNED_SHORT; break;
1142 case 32: type = GL_UNSIGNED_INT; break;
1143 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1146 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1147 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1148 glRasterPos2i(0, row + 1);
1149 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1150 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1154 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1155 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1156 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1157 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1160 /* These are the various handler used in the generic path */
1161 inline static void handle_xyz(D3DVALUE *coords) {
1162 glVertex3fv(coords);
1164 inline static void handle_xyzrhw(D3DVALUE *coords) {
1165 if (coords[3] < 1e-8)
1166 glVertex3fv(coords);
1168 GLfloat w = 1.0 / coords[3];
1170 glVertex4f(coords[0] * w,
1176 inline static void handle_normal(D3DVALUE *coords) {
1177 glNormal3fv(coords);
1180 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1181 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1182 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1183 glColor4ub((*color >> 16) & 0xFF,
1184 (*color >> 8) & 0xFF,
1185 (*color >> 0) & 0xFF,
1186 (*color >> 24) & 0xFF);
1188 glColor3ub((*color >> 16) & 0xFF,
1189 (*color >> 8) & 0xFF,
1190 (*color >> 0) & 0xFF);
1194 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1195 glColor4ub((*color >> 16) & 0xFF,
1196 (*color >> 8) & 0xFF,
1197 (*color >> 0) & 0xFF,
1198 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1201 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1202 if ((lighted == FALSE) &&
1203 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1204 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1205 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1206 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1207 handle_diffuse_base(sb, color);
1209 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1210 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1211 handle_diffuse_base(sb, color);
1213 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1214 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1215 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1216 handle_diffuse_base(sb, color);
1218 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1219 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1220 handle_diffuse_base(sb, color);
1223 handle_diffuse_base(sb, color);
1227 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1228 if ((lighted == FALSE) &&
1229 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1230 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1231 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1232 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1233 handle_specular_base(sb, color);
1235 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1236 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1237 handle_specular_base(sb, color);
1239 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1240 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1241 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1242 handle_specular_base(sb, color);
1244 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1245 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1246 handle_specular_base(sb, color);
1249 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1252 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1253 if (lighted == TRUE) {
1254 DWORD color = *color_d;
1255 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1256 /* Special case where the specular value is used to do fogging */
1257 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1258 color &= 0xFF000000; /* Only keep the alpha component */
1259 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1260 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1261 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1263 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1264 /* Standard specular value in transformed mode. TODO */
1266 handle_diffuse_base(sb, &color);
1268 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1269 handle_diffuse(sb, color_d, FALSE);
1270 handle_specular(sb, color_s, FALSE);
1272 /* In that case, only put the diffuse color... */
1273 handle_diffuse_base(sb, color_d);
1278 inline static void handle_texture(D3DVALUE *coords) {
1279 glTexCoord2fv(coords);
1281 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1282 if (GL_extensions.glMultiTexCoord2fv) {
1283 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1285 if (tex_stage == 0) glTexCoord2fv(coords);
1289 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1290 D3DPRIMITIVETYPE d3dptPrimitiveType,
1291 DWORD d3dvtVertexType,
1292 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1293 DWORD dwVertexCount,
1298 BOOLEAN vertex_lighted = FALSE;
1299 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1300 int num_active_stages = 0;
1301 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1303 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1304 if (TRACE_ON(ddraw)) {
1305 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1308 /* This is to prevent 'thread contention' between a thread locking the device and another
1309 doing 3D display on it... */
1310 EnterCriticalSection(&(This->crit));
1313 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1314 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1316 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1318 if (This->current_zbuffer == NULL) {
1319 /* Search for an attached ZBuffer */
1320 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1321 LPDIRECTDRAWSURFACE7 zbuf;
1324 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1325 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1327 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1328 IDirectDrawSurface7_Release(zbuf);
1331 if (This->current_zbuffer != NULL) {
1332 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1333 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1337 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1338 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1339 vertex_lighted = TRUE;
1341 /* Compute the number of active texture stages and set the various texture parameters */
1342 num_active_stages = draw_primitive_handle_textures(This);
1344 /* And restore to handle '0' in the case we use glTexCoord calls */
1345 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1346 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1347 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1350 draw_primitive_handle_GL_state(This,
1351 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1354 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1355 for now to some 'special' cases where we can do a direct mapping between D3D
1358 Note: in the future all calls will go through vertex arrays but the arrays
1359 will be generated by this function.
1361 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1362 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1363 which, as we are little indian, gives a B, G, R, A storage in memory.
1365 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
1366 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
1368 TRACE(" using GL vertex arrays for performance !\n");
1369 /* First, the vertices (we are sure we have some :-) */
1370 glEnableClientState(GL_VERTEX_ARRAY);
1371 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1372 /* Then the normals */
1373 if (d3dvtVertexType & D3DFVF_NORMAL) {
1374 glEnableClientState(GL_NORMAL_ARRAY);
1375 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
1377 /* Then the diffuse colour */
1378 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1379 glEnableClientState(GL_COLOR_ARRAY);
1380 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1381 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1383 /* Then the various textures */
1384 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1385 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1386 if (tex_index >= num_tex_index) {
1387 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1388 tex_index = num_tex_index - 1;
1390 if (GL_extensions.glClientActiveTexture) {
1391 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1393 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1394 glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
1395 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1397 if (dwIndices != NULL) {
1398 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1400 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1402 glDisableClientState(GL_VERTEX_ARRAY);
1403 if (d3dvtVertexType & D3DFVF_NORMAL) {
1404 glDisableClientState(GL_NORMAL_ARRAY);
1406 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1407 glDisableClientState(GL_COLOR_ARRAY);
1409 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1410 if (GL_extensions.glClientActiveTexture) {
1411 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
1413 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1416 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1418 /* Some fast paths first before the generic case.... */
1419 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1422 for (index = 0; index < dwIndexCount; index++) {
1423 int i = (dwIndices == NULL) ? index : dwIndices[index];
1425 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1426 D3DVALUE *tex_coord =
1427 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1428 D3DVALUE *position =
1429 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1431 handle_normal(normal);
1432 handle_texture(tex_coord);
1433 handle_xyz(position);
1435 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1436 position[0], position[1], position[2],
1437 normal[0], normal[1], normal[2],
1438 tex_coord[0], tex_coord[1]);
1440 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1443 for (index = 0; index < dwIndexCount; index++) {
1444 int i = (dwIndices == NULL) ? index : dwIndices[index];
1446 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1448 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1449 D3DVALUE *tex_coord =
1450 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1451 D3DVALUE *position =
1452 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1454 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1455 handle_texture(tex_coord);
1456 handle_xyzrhw(position);
1458 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1459 position[0], position[1], position[2], position[3],
1460 (*color_d >> 16) & 0xFF,
1461 (*color_d >> 8) & 0xFF,
1462 (*color_d >> 0) & 0xFF,
1463 (*color_d >> 24) & 0xFF,
1464 (*color_s >> 16) & 0xFF,
1465 (*color_s >> 8) & 0xFF,
1466 (*color_s >> 0) & 0xFF,
1467 (*color_s >> 24) & 0xFF,
1468 tex_coord[0], tex_coord[1]);
1470 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1471 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1472 /* This is the 'slow path' but that should support all possible vertex formats out there...
1473 Note that people should write a fast path for all vertex formats out there...
1476 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1478 for (index = 0; index < dwIndexCount; index++) {
1479 int i = (dwIndices == NULL) ? index : dwIndices[index];
1482 if (d3dvtVertexType & D3DFVF_NORMAL) {
1484 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1485 handle_normal(normal);
1487 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1489 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1491 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1492 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1494 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1496 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1497 handle_specular(&(This->state_block), color_s, vertex_lighted);
1498 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1500 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1501 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1505 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1506 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1507 if (tex_index >= num_tex_index) {
1508 handle_textures((D3DVALUE *) no_index, tex_stage);
1510 D3DVALUE *tex_coord =
1511 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1512 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1513 handle_textures(tex_coord, tex_stage);
1517 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1518 D3DVALUE *position =
1519 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1520 handle_xyz(position);
1521 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1522 D3DVALUE *position =
1523 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1524 handle_xyzrhw(position);
1527 if (TRACE_ON(ddraw_geom)) {
1530 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1531 D3DVALUE *position =
1532 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1533 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1534 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1535 D3DVALUE *position =
1536 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1537 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1539 if (d3dvtVertexType & D3DFVF_NORMAL) {
1541 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1542 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1544 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1546 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1547 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1548 (*color_d >> 16) & 0xFF,
1549 (*color_d >> 8) & 0xFF,
1550 (*color_d >> 0) & 0xFF,
1551 (*color_d >> 24) & 0xFF);
1553 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1555 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1556 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1557 (*color_s >> 16) & 0xFF,
1558 (*color_s >> 8) & 0xFF,
1559 (*color_s >> 0) & 0xFF,
1560 (*color_s >> 24) & 0xFF);
1562 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1563 D3DVALUE *tex_coord =
1564 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1565 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1566 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1568 TRACE_(ddraw_geom)("\n");
1572 ERR(" matrix weighting not handled yet....\n");
1578 /* Whatever the case, disable the color material stuff */
1579 glDisable(GL_COLOR_MATERIAL);
1584 LeaveCriticalSection(&(This->crit));
1588 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1589 D3DPRIMITIVETYPE d3dptPrimitiveType,
1590 DWORD d3dvtVertexType,
1592 DWORD dwVertexCount,
1595 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1596 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1598 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1599 if (TRACE_ON(ddraw)) {
1600 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1603 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1604 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1610 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1611 D3DPRIMITIVETYPE d3dptPrimitiveType,
1612 DWORD d3dvtVertexType,
1614 DWORD dwVertexCount,
1619 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1620 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1622 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1623 if (TRACE_ON(ddraw)) {
1624 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1627 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1628 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1634 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1635 D3DPRIMITIVETYPE d3dptPrimitiveType,
1637 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1638 DWORD dwVertexCount,
1641 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1643 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1644 if (TRACE_ON(ddraw)) {
1645 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1647 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1653 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1654 D3DPRIMITIVETYPE d3dptPrimitiveType,
1656 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1657 DWORD dwVertexCount,
1662 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1664 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1665 if (TRACE_ON(ddraw)) {
1666 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1669 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1675 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1676 D3DPRIMITIVETYPE d3dptPrimitiveType,
1677 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1678 DWORD dwStartVertex,
1679 DWORD dwNumVertices,
1682 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1683 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1684 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1686 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1687 if (TRACE_ON(ddraw)) {
1688 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1691 if (vb_impl->processed == TRUE) {
1692 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1693 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1695 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1696 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1697 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1699 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1700 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1703 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1704 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1711 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1712 D3DPRIMITIVETYPE d3dptPrimitiveType,
1713 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1714 DWORD dwStartVertex,
1715 DWORD dwNumVertices,
1720 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1721 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1722 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1724 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1725 if (TRACE_ON(ddraw)) {
1726 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1729 if (vb_impl->processed == TRUE) {
1730 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1731 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1733 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1734 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1735 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1737 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1738 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1741 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1742 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1748 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1750 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1752 BOOLEAN is_complement = FALSE;
1753 BOOLEAN is_alpha_replicate = FALSE;
1754 BOOLEAN handled = TRUE;
1756 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1760 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1761 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1766 if (tex_op == D3DTOP_SELECTARG2) {
1770 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1771 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1776 if (tex_op == D3DTOP_SELECTARG2) {
1781 if (dwState & D3DTA_COMPLEMENT) {
1782 is_complement = TRUE;
1784 if (dwState & D3DTA_ALPHAREPLICATE) {
1785 is_alpha_replicate = TRUE;
1787 dwState &= D3DTA_SELECTMASK;
1788 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1789 dwState = D3DTA_DIFFUSE;
1793 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1794 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1795 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1796 case D3DTA_TFACTOR: {
1797 /* Get the constant value from the current rendering state */
1799 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1801 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1802 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1803 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1804 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1805 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1807 src = GL_CONSTANT_EXT;
1809 default: src = GL_TEXTURE; handled = FALSE; break;
1813 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1814 if (is_alpha_replicate) {
1815 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1817 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1820 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1821 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1828 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1830 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1833 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1834 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1839 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1841 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1842 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1846 unit = GL_TEXTURE0_WINE + dwStage;
1847 if (unit != glThis->current_active_tex_unit) {
1848 GL_extensions.glActiveTexture(unit);
1849 glThis->current_active_tex_unit = unit;
1852 switch (d3dTexStageStateType) {
1853 #define GEN_CASE(a) case a: type = #a; break
1854 GEN_CASE(D3DTSS_COLOROP);
1855 GEN_CASE(D3DTSS_COLORARG1);
1856 GEN_CASE(D3DTSS_COLORARG2);
1857 GEN_CASE(D3DTSS_ALPHAOP);
1858 GEN_CASE(D3DTSS_ALPHAARG1);
1859 GEN_CASE(D3DTSS_ALPHAARG2);
1860 GEN_CASE(D3DTSS_BUMPENVMAT00);
1861 GEN_CASE(D3DTSS_BUMPENVMAT01);
1862 GEN_CASE(D3DTSS_BUMPENVMAT10);
1863 GEN_CASE(D3DTSS_BUMPENVMAT11);
1864 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1865 GEN_CASE(D3DTSS_ADDRESS);
1866 GEN_CASE(D3DTSS_ADDRESSU);
1867 GEN_CASE(D3DTSS_ADDRESSV);
1868 GEN_CASE(D3DTSS_BORDERCOLOR);
1869 GEN_CASE(D3DTSS_MAGFILTER);
1870 GEN_CASE(D3DTSS_MINFILTER);
1871 GEN_CASE(D3DTSS_MIPFILTER);
1872 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1873 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1874 GEN_CASE(D3DTSS_MAXANISOTROPY);
1875 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1876 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1877 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1879 default: type = "UNKNOWN";
1882 /* Store the values in the state array */
1883 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1884 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1885 /* Some special cases when one state modifies more than one... */
1886 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1887 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1888 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1893 switch (d3dTexStageStateType) {
1894 case D3DTSS_MINFILTER:
1895 case D3DTSS_MIPFILTER:
1896 if (TRACE_ON(ddraw)) {
1897 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1898 switch ((D3DTEXTUREMINFILTER) dwState) {
1899 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1900 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1901 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1904 switch ((D3DTEXTUREMIPFILTER) dwState) {
1905 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1906 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1907 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1908 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1914 case D3DTSS_MAGFILTER:
1915 if (TRACE_ON(ddraw)) {
1916 switch ((D3DTEXTUREMAGFILTER) dwState) {
1917 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1918 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1919 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1924 case D3DTSS_ADDRESS:
1925 case D3DTSS_ADDRESSU:
1926 case D3DTSS_ADDRESSV: {
1927 switch ((D3DTEXTUREADDRESS) dwState) {
1928 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1929 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1930 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1931 case D3DTADDRESS_MIRROR:
1932 if (GL_extensions.mirrored_repeat == TRUE) {
1933 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1935 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1938 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1942 case D3DTSS_ALPHAOP:
1943 case D3DTSS_COLOROP: {
1945 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1950 #define GEN_CASE(a) case a: value = #a; break
1951 GEN_CASE(D3DTOP_DISABLE);
1952 GEN_CASE(D3DTOP_SELECTARG1);
1953 GEN_CASE(D3DTOP_SELECTARG2);
1954 GEN_CASE(D3DTOP_MODULATE);
1955 GEN_CASE(D3DTOP_MODULATE2X);
1956 GEN_CASE(D3DTOP_MODULATE4X);
1957 GEN_CASE(D3DTOP_ADD);
1958 GEN_CASE(D3DTOP_ADDSIGNED);
1959 GEN_CASE(D3DTOP_ADDSIGNED2X);
1960 GEN_CASE(D3DTOP_SUBTRACT);
1961 GEN_CASE(D3DTOP_ADDSMOOTH);
1962 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1963 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1964 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1965 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1966 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1967 GEN_CASE(D3DTOP_PREMODULATE);
1968 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1969 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1970 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1971 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1972 GEN_CASE(D3DTOP_BUMPENVMAP);
1973 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1974 GEN_CASE(D3DTOP_DOTPRODUCT3);
1975 GEN_CASE(D3DTOP_FORCE_DWORD);
1977 default: value = "UNKNOWN";
1980 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1981 glDisable(GL_TEXTURE_2D);
1982 TRACE(" disabling 2D texturing.\n");
1984 /* Re-enable texturing only if COLOROP was not already disabled... */
1985 if ((glThis->current_bound_texture[dwStage] != NULL) &&
1986 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1987 glEnable(GL_TEXTURE_2D);
1988 TRACE(" enabling 2D texturing.\n");
1991 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1992 if ((dwState != D3DTOP_DISABLE) &&
1993 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
1994 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1995 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1996 glThis->current_tex_env = GL_COMBINE_EXT;
2000 /* Now set up the operand correctly */
2002 case D3DTOP_DISABLE:
2003 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2004 and it works, so ignore this op */
2005 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2008 case D3DTOP_SELECTARG1:
2009 case D3DTOP_SELECTARG2:
2010 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2013 case D3DTOP_MODULATE4X:
2014 scale = scale * 2; /* Drop through */
2015 case D3DTOP_MODULATE2X:
2016 scale = scale * 2; /* Drop through */
2017 case D3DTOP_MODULATE:
2018 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2022 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2025 case D3DTOP_ADDSIGNED2X:
2026 scale = scale * 2; /* Drop through */
2027 case D3DTOP_ADDSIGNED:
2028 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
2031 /* For the four blending modes, use the Arg2 parameter */
2032 case D3DTOP_BLENDDIFFUSEALPHA:
2033 case D3DTOP_BLENDTEXTUREALPHA:
2034 case D3DTOP_BLENDFACTORALPHA:
2035 case D3DTOP_BLENDCURRENTALPHA: {
2036 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2039 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2040 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2041 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2042 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2045 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
2046 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2047 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2048 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2049 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2058 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2059 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2060 /* Switch the arguments if needed... */
2061 if (d3dTexStageStateType == D3DTSS_COLOROP) {
2062 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
2063 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2065 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
2066 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2069 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2070 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2072 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2073 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2079 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2080 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2082 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2084 TRACE(" Stage type is : %s => %s\n", type, value);
2086 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2090 case D3DTSS_COLORARG1:
2091 case D3DTSS_COLORARG2:
2092 case D3DTSS_ALPHAARG1:
2093 case D3DTSS_ALPHAARG2: {
2094 const char *value, *value_comp = "", *value_alpha = "";
2096 D3DTEXTUREOP tex_op;
2098 switch (dwState & D3DTA_SELECTMASK) {
2099 #define GEN_CASE(a) case a: value = #a; break
2100 GEN_CASE(D3DTA_DIFFUSE);
2101 GEN_CASE(D3DTA_CURRENT);
2102 GEN_CASE(D3DTA_TEXTURE);
2103 GEN_CASE(D3DTA_TFACTOR);
2104 GEN_CASE(D3DTA_SPECULAR);
2106 default: value = "UNKNOWN";
2108 if (dwState & D3DTA_COMPLEMENT) {
2109 value_comp = " | D3DTA_COMPLEMENT";
2111 if (dwState & D3DTA_ALPHAREPLICATE) {
2112 value_alpha = " | D3DTA_ALPHAREPLICATE";
2115 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2116 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2118 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2121 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2124 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2126 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2130 case D3DTSS_MIPMAPLODBIAS: {
2131 D3DVALUE value = *((D3DVALUE *) &dwState);
2132 BOOLEAN handled = TRUE;
2134 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2138 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2139 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2141 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2145 case D3DTSS_MAXMIPLEVEL:
2146 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2149 case D3DTSS_BORDERCOLOR:
2150 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2151 ((dwState >> 16) & 0xFF),
2152 ((dwState >> 8) & 0xFF),
2153 ((dwState >> 0) & 0xFF),
2154 ((dwState >> 24) & 0xFF));
2157 case D3DTSS_TEXCOORDINDEX: {
2158 BOOLEAN handled = TRUE;
2161 switch (dwState & 0xFFFF0000) {
2162 #define GEN_CASE(a) case a: value = #a; break
2163 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2164 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2165 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2166 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2168 default: value = "UNKNOWN";
2170 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2174 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2176 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2180 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2181 const char *projected = "", *value;
2182 BOOLEAN handled = TRUE;
2183 switch (dwState & 0xFF) {
2184 #define GEN_CASE(a) case a: value = #a; break
2185 GEN_CASE(D3DTTFF_DISABLE);
2186 GEN_CASE(D3DTTFF_COUNT1);
2187 GEN_CASE(D3DTTFF_COUNT2);
2188 GEN_CASE(D3DTTFF_COUNT3);
2189 GEN_CASE(D3DTTFF_COUNT4);
2191 default: value = "UNKNOWN";
2193 if (dwState & D3DTTFF_PROJECTED) {
2194 projected = " | D3DTTFF_PROJECTED";
2198 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2199 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2202 if (handled == TRUE) {
2203 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2205 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2210 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2220 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2222 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2224 BOOLEAN enable_colorkey = FALSE;
2226 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2227 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2230 /* If this stage is disabled, no need to go further... */
2231 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2234 /* First check if we need to bind any other texture for this stage */
2235 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2236 if (This->current_texture[stage] == NULL) {
2237 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2239 unit = GL_TEXTURE0_WINE + stage;
2240 if (unit != glThis->current_active_tex_unit) {
2241 GL_extensions.glActiveTexture(unit);
2242 glThis->current_active_tex_unit = unit;
2244 glBindTexture(GL_TEXTURE_2D, 0);
2245 glDisable(GL_TEXTURE_2D);
2247 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2249 unit = GL_TEXTURE0_WINE + stage;
2250 if (unit != glThis->current_active_tex_unit) {
2251 GL_extensions.glActiveTexture(unit);
2252 glThis->current_active_tex_unit = unit;
2255 if (glThis->current_bound_texture[stage] == NULL) {
2256 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2257 TRACE(" enabling 2D texturing and");
2258 glEnable(GL_TEXTURE_2D);
2261 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2262 glBindTexture(GL_TEXTURE_2D, tex_name);
2265 glThis->current_bound_texture[stage] = This->current_texture[stage];
2267 if (glThis->current_bound_texture[stage] == NULL) {
2268 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2270 TRACE(" using already bound texture id %d for stage %ld.\n",
2271 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2275 /* If no texure valid for this stage, go out of the loop */
2276 if (This->current_texture[stage] == NULL) break;
2278 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2279 This will also update the various texture parameters if needed.
2281 gltex_upload_texture(surf_ptr, This, stage);
2283 /* And finally check for color-keying (only on first stage) */
2284 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2286 enable_colorkey = TRUE;
2288 static BOOL warn = FALSE;
2289 if (warn == FALSE) {
2291 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2296 enable_colorkey = FALSE;
2301 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2302 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
2303 (glThis->version == 1)) &&
2304 (enable_colorkey)) {
2305 TRACE(" colorkey activated.\n");
2307 if (glThis->alpha_test == FALSE) {
2308 glEnable(GL_ALPHA_TEST);
2309 glThis->alpha_test = TRUE;
2311 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
2312 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
2313 static BOOL warn = FALSE;
2314 if (warn == FALSE) {
2316 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2319 glThis->current_alpha_test_func = GL_NOTEQUAL;
2320 glThis->current_alpha_test_ref = 0.0;
2321 glAlphaFunc(GL_NOTEQUAL, 0.0);
2323 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2324 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2326 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2327 glDisable(GL_ALPHA_TEST);
2328 glThis->alpha_test = FALSE;
2330 /* Maybe we should restore here the application-given alpha test states ? */
2337 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2339 LPDIRECTDRAWSURFACE7 lpTexture2)
2341 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2343 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2345 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2346 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2347 if (lpTexture2 != NULL) {
2348 WARN(" setting a texture to a non-supported texture stage !\n");
2353 if (This->current_texture[dwStage] != NULL) {
2354 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2357 if (lpTexture2 == NULL) {
2358 This->current_texture[dwStage] = NULL;
2360 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2361 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2362 This->current_texture[dwStage] = tex_impl;
2369 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2370 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2372 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2373 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2375 fill_opengl_caps_7(lpD3DHELDevDesc);
2377 TRACE(" returning caps : no dump function yet.\n");
2383 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2384 LPD3DMATERIAL7 lpMat)
2386 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2387 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2389 if (TRACE_ON(ddraw)) {
2390 TRACE(" material is : \n");
2391 dump_D3DMATERIAL7(lpMat);
2394 This->current_material = *lpMat;
2397 glMaterialfv(GL_FRONT_AND_BACK,
2399 (float *) &(This->current_material.u.diffuse));
2400 glMaterialfv(GL_FRONT_AND_BACK,
2402 (float *) &(This->current_material.u1.ambient));
2403 glMaterialfv(GL_FRONT_AND_BACK,
2405 (float *) &(This->current_material.u2.specular));
2406 glMaterialfv(GL_FRONT_AND_BACK,
2408 (float *) &(This->current_material.u3.emissive));
2409 glMaterialf(GL_FRONT_AND_BACK,
2411 This->current_material.u4.power); /* Not sure about this... */
2419 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2421 LPD3DLIGHT7 lpLight)
2423 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2424 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2425 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2427 if (TRACE_ON(ddraw)) {
2428 TRACE(" setting light : \n");
2429 dump_D3DLIGHT7(lpLight);
2432 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2433 This->set_lights |= 0x00000001 << dwLightIndex;
2434 This->light_parameters[dwLightIndex] = *lpLight;
2436 /* Some checks to print out nice warnings :-) */
2437 switch (lpLight->dltType) {
2438 case D3DLIGHT_DIRECTIONAL:
2439 case D3DLIGHT_POINT:
2440 /* These are handled properly... */
2444 if ((lpLight->dvTheta != 0.0) ||
2445 (lpLight->dvTheta != lpLight->dvPhi)) {
2446 ERR("dvTheta not fully supported yet !\n");
2451 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2454 /* This will force the Light setting on next drawing of primitives */
2455 glThis->transform_state = GL_TRANSFORM_NONE;
2461 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2465 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2466 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2468 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2472 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2473 /* Set the default parameters.. */
2474 TRACE(" setting default light parameters...\n");
2475 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2477 glEnable(GL_LIGHT0 + dwLightIndex);
2478 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2479 /* This light gets active... Need to update its parameters to GL before the next drawing */
2480 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2482 This->active_lights |= 0x00000001 << dwLightIndex;
2483 glThis->transform_state = GL_TRANSFORM_NONE;
2486 glDisable(GL_LIGHT0 + dwLightIndex);
2487 This->active_lights &= ~(0x00000001 << dwLightIndex);
2495 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2497 ICOM_THIS(IDirect3DDeviceImpl,iface);
2498 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2500 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2502 if (dwIndex >= This->max_clipping_planes) {
2503 return DDERR_INVALIDPARAMS;
2506 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2508 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2510 /* This is to force the reset of the transformation matrices on the next drawing.
2511 * This is needed to use the correct matrices for the various clipping planes.
2513 glThis->transform_state = GL_TRANSFORM_NONE;
2519 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2520 LPD3DVIEWPORT7 lpData)
2522 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2523 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2525 if (TRACE_ON(ddraw)) {
2526 TRACE(" viewport is : \n");
2527 TRACE(" - dwX = %ld dwY = %ld\n",
2528 lpData->dwX, lpData->dwY);
2529 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2530 lpData->dwWidth, lpData->dwHeight);
2531 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2532 lpData->dvMinZ, lpData->dvMaxZ);
2536 /* Set the viewport */
2537 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2538 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2539 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2541 if ((lpData->dwX != This->active_viewport.dwX) ||
2542 (lpData->dwY != This->active_viewport.dwY) ||
2543 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2544 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2545 glViewport(lpData->dwX,
2546 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2547 lpData->dwWidth, lpData->dwHeight);
2552 This->active_viewport = *lpData;
2557 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2558 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2560 # define XCAST(fun) (void*)
2563 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2565 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2566 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2567 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2568 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2569 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2570 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2571 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2572 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2573 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2574 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2575 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2576 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2577 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2578 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2579 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2580 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2581 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2582 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2583 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2584 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2585 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2586 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2587 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2588 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2589 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2590 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2591 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2592 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2593 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2594 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2595 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2596 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2597 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2598 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2599 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2600 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2601 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2602 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2603 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2604 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2605 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2606 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2607 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2608 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2609 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2610 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2611 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2612 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2613 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2614 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2617 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2622 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2623 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2625 # define XCAST(fun) (void*)
2628 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2630 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2631 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2632 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2633 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2634 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2635 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2636 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2637 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2638 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2639 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2640 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2641 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2642 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2643 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2644 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2645 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2646 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2647 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2648 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2649 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2650 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2651 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2652 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2653 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2654 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2655 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2656 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2657 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2658 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2659 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2660 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2661 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2662 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2663 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2664 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2665 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2666 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2667 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2668 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2669 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2670 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2671 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2672 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2675 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2680 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2681 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2683 # define XCAST(fun) (void*)
2686 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2688 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2689 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2690 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2691 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2692 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2693 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2694 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2695 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2696 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2697 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2698 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2699 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2700 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2701 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2702 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2703 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2704 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2705 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2706 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2707 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2708 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2709 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2710 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2711 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2712 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2713 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2714 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2715 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2716 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2717 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2718 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2719 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2720 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2721 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2724 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2729 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2730 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2732 # define XCAST(fun) (void*)
2735 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2737 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2738 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2739 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2740 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2741 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2742 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2743 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2744 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2745 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2746 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2747 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2748 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2749 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2750 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2751 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2752 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2753 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2754 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2755 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2756 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2757 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2758 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2759 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2762 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2766 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2767 WINE_GL_BUFFER_TYPE buffer_type,
2775 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2776 GLbitfield bitfield = 0;
2780 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2781 if (TRACE_ON(ddraw)) {
2784 TRACE(" rectangles : \n");
2785 for (i = 0; i < dwCount; i++) {
2786 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2795 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2796 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2800 /* Clears the screen */
2803 if (dwFlags & D3DCLEAR_TARGET) {
2804 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2805 /* TODO: optimize here the case where Clear changes all the screen... */
2806 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2808 glThis->state[buffer_type] = SURFACE_GL;
2811 if (dwFlags & D3DCLEAR_ZBUFFER) {
2812 bitfield |= GL_DEPTH_BUFFER_BIT;
2813 if (glThis->depth_mask == FALSE) {
2814 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2816 if (dvZ != glThis->prev_clear_Z) {
2818 glThis->prev_clear_Z = dvZ;
2820 TRACE(" depth value : %f\n", dvZ);
2822 if (dwFlags & D3DCLEAR_STENCIL) {
2823 bitfield |= GL_STENCIL_BUFFER_BIT;
2824 if (dwStencil != glThis->prev_clear_stencil) {
2825 glClearStencil(dwStencil);
2826 glThis->prev_clear_stencil = dwStencil;
2828 TRACE(" stencil value : %ld\n", dwStencil);
2830 if (dwFlags & D3DCLEAR_TARGET) {
2831 bitfield |= GL_COLOR_BUFFER_BIT;
2832 if (dwColor != glThis->prev_clear_color) {
2833 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2834 ((dwColor >> 8) & 0xFF) / 255.0,
2835 ((dwColor >> 0) & 0xFF) / 255.0,
2836 ((dwColor >> 24) & 0xFF) / 255.0);
2837 glThis->prev_clear_color = dwColor;
2839 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2842 glEnable(GL_SCISSOR_TEST);
2843 for (i = 0; i < dwCount; i++) {
2844 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2845 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2848 glDisable(GL_SCISSOR_TEST);
2850 if (dwFlags & D3DCLEAR_ZBUFFER) {
2851 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2859 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2867 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2871 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2872 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2874 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2875 WINE_GL_BUFFER_TYPE buffer_type;
2877 /* First check if we BLT to the backbuffer... */
2878 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2879 buffer_type = WINE_GL_BUFFER_BACK;
2880 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2881 buffer_type = WINE_GL_BUFFER_FRONT;
2883 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2884 return DDERR_INVALIDPARAMS;
2887 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2888 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2889 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2890 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2891 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2892 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2895 return DDERR_INVALIDPARAMS;
2897 *buffer_type_p = buffer_type;
2903 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2904 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2905 DWORD dwFlags, LPDDBLTFX lpbltfx)
2907 WINE_GL_BUFFER_TYPE buffer_type;
2911 rect.u1.x1 = rdst->left;
2912 rect.u2.y1 = rdst->top;
2913 rect.u3.x2 = rdst->right;
2914 rect.u4.y2 = rdst->bottom;
2918 rect.u3.x2 = This->surface_desc.dwWidth;
2919 rect.u4.y2 = This->surface_desc.dwHeight;
2922 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2924 if (dwFlags & DDBLT_COLORFILL) {
2925 /* This is easy to handle for the D3D Device... */
2929 /* The color as given in the Blt function is in the format of the frame-buffer...
2930 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2932 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2933 if (This->palette) {
2934 color = ((0xFF000000) |
2935 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2936 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2937 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2941 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2942 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2943 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2944 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2945 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2946 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2947 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2948 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2951 color = ((0xFF000000) |
2952 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2953 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2954 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2956 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2957 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2958 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2959 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2960 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2961 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2963 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2964 return DDERR_INVALIDPARAMS;
2967 ERR("Wrong surface type for BLT override !\n");
2968 return DDERR_INVALIDPARAMS;
2971 TRACE(" executing D3D Device override.\n");
2975 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2976 if (buffer_type == WINE_GL_BUFFER_FRONT)
2977 glDrawBuffer(GL_FRONT);
2979 glDrawBuffer(GL_BACK);
2981 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2983 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2984 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2985 glDrawBuffer(prev_draw);
2990 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2991 /* Normal blit without any special case... */
2993 /* And which has a SRC surface */
2994 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2996 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2997 (src_impl->d3ddevice == This->d3ddevice) &&
2998 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2999 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3003 WINE_GL_BUFFER_TYPE src_buffer_type;
3004 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3010 src_rect.u1.x1 = rsrc->left;
3011 src_rect.u2.y1 = rsrc->top;
3012 src_rect.u3.x2 = rsrc->right;
3013 src_rect.u4.y2 = rsrc->bottom;
3017 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3018 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3021 width = src_rect.u3.x2 - src_rect.u1.x1;
3022 height = src_rect.u4.y2 - src_rect.u2.y1;
3024 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3025 (height != (rect.u4.y2 - rect.u2.y1))) {
3026 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3027 return DDERR_INVALIDPARAMS;
3030 /* First check if we BLT from the backbuffer... */
3031 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3032 src_buffer_type = WINE_GL_BUFFER_BACK;
3033 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3034 src_buffer_type = WINE_GL_BUFFER_FRONT;
3036 ERR("Unexpected case in direct buffer to buffer copy !\n");
3037 return DDERR_INVALIDPARAMS;
3040 TRACE(" using direct buffer to buffer copy.\n");
3044 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3046 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3047 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3048 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3050 return DDERR_INVALIDPARAMS;
3053 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3054 if (buffer_type == WINE_GL_BUFFER_FRONT)
3055 glDrawBuffer(GL_FRONT);
3057 glDrawBuffer(GL_BACK);
3059 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3060 glReadBuffer(GL_FRONT);
3062 glReadBuffer(GL_BACK);
3064 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3065 And directly re-draws this on the destination buffer. */
3066 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3069 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3070 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3072 get_height = UNLOCK_TEX_SIZE;
3074 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3077 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3078 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3080 get_width = UNLOCK_TEX_SIZE;
3082 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3083 0, UNLOCK_TEX_SIZE - get_height,
3084 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3085 get_width, get_height);
3088 glTexCoord2f(0.0, 0.0);
3089 glVertex3d(rect.u1.x1 + x,
3090 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3092 glTexCoord2f(1.0, 0.0);
3093 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3094 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3096 glTexCoord2f(1.0, 1.0);
3097 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3100 glTexCoord2f(0.0, 1.0);
3101 glVertex3d(rect.u1.x1 + x,
3108 upload_surface_to_tex_memory_release();
3109 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3111 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3112 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3113 glDrawBuffer(prev_draw);
3119 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3120 (this prevents calling glReadPixels) */
3124 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3128 double x_stretch, y_stretch;
3131 src_rect.u1.x1 = rsrc->left;
3132 src_rect.u2.y1 = rsrc->top;
3133 src_rect.u3.x2 = rsrc->right;
3134 src_rect.u4.y2 = rsrc->bottom;
3138 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3139 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3142 width = src_rect.u3.x2 - src_rect.u1.x1;
3143 height = src_rect.u4.y2 - src_rect.u2.y1;
3145 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3146 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3148 TRACE(" using memory to buffer Blt overide.\n");
3152 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3154 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3155 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3156 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3158 return DDERR_INVALIDPARAMS;
3161 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3162 if (buffer_type == WINE_GL_BUFFER_FRONT)
3163 glDrawBuffer(GL_FRONT);
3165 glDrawBuffer(GL_BACK);
3167 /* Now the serious stuff happens. This is basically the same code that for the memory
3168 flush to frame buffer ... with stretching and different rectangles added :-) */
3169 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3172 flush_rect.top = src_rect.u2.y1 + y;
3173 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3175 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3177 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3178 flush_rect.left = src_rect.u1.x1 + x;
3179 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3181 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3183 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3186 glTexCoord2f(0.0, 0.0);
3187 glVertex3d(rect.u1.x1 + (x * x_stretch),
3188 rect.u2.y1 + (y * y_stretch),
3190 glTexCoord2f(1.0, 0.0);
3191 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3192 rect.u2.y1 + (y * y_stretch),
3194 glTexCoord2f(1.0, 1.0);
3195 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3196 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3198 glTexCoord2f(0.0, 1.0);
3199 glVertex3d(rect.u1.x1 + (x * x_stretch),
3200 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3206 upload_surface_to_tex_memory_release();
3207 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3209 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3210 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3211 glDrawBuffer(prev_draw);
3219 return DDERR_INVALIDPARAMS;
3223 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3224 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3225 LPRECT rsrc, DWORD trans)
3229 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3230 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3231 WINE_GL_BUFFER_TYPE buffer_type;
3235 int width, height, x, y;
3237 /* Cannot support DSTCOLORKEY blitting... */
3238 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3241 WARN("rsrc is NULL - getting the whole surface !!\n");
3243 rsrc->left = rsrc->top = 0;
3244 rsrc->right = src_impl->surface_desc.dwWidth;
3245 rsrc->bottom = src_impl->surface_desc.dwHeight;
3253 rdst.right = dstx + (rsrc->right - rsrc->left);
3254 if (rdst.right > This->surface_desc.dwWidth) {
3255 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3256 rdst.right = This->surface_desc.dwWidth;
3258 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3259 if (rdst.bottom > This->surface_desc.dwHeight) {
3260 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3261 rdst.bottom = This->surface_desc.dwHeight;
3264 width = rsrc->right - rsrc->left;
3265 height = rsrc->bottom - rsrc->top;
3267 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3269 TRACE(" using BltFast memory to frame buffer overide.\n");
3273 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3275 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3276 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3277 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3278 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3280 return DDERR_INVALIDPARAMS;
3283 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3284 if (buffer_type == WINE_GL_BUFFER_FRONT)
3285 glDrawBuffer(GL_FRONT);
3287 glDrawBuffer(GL_BACK);
3289 /* Now the serious stuff happens. This is basically the same code that for the memory
3290 flush to frame buffer but with different rectangles for source and destination :-) */
3291 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3294 flush_rect.top = rsrc->top + y;
3295 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3297 (rsrc->top + y + UNLOCK_TEX_SIZE));
3299 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3300 flush_rect.left = rsrc->left + x;
3301 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3303 (rsrc->left + x + UNLOCK_TEX_SIZE));
3305 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3308 glTexCoord2f(0.0, 0.0);
3309 glVertex3d(rdst.left + x,
3312 glTexCoord2f(1.0, 0.0);
3313 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3316 glTexCoord2f(1.0, 1.0);
3317 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3318 rdst.top + (y + UNLOCK_TEX_SIZE),
3320 glTexCoord2f(0.0, 1.0);
3321 glVertex3d(rdst.left + x,
3322 rdst.top + (y + UNLOCK_TEX_SIZE),
3328 upload_surface_to_tex_memory_release();
3329 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3331 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3332 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3333 glDrawBuffer(prev_draw);
3341 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3343 GLfloat height, width;
3344 GLfloat trans_mat[16];
3346 TRACE("(%p)\n", This);
3348 width = This->surface->surface_desc.dwWidth;
3349 height = This->surface->surface_desc.dwHeight;
3351 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3352 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3354 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3355 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3357 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3358 * that the Z coordinate needs to be given to GL unchanged.
3360 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3362 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = 0.0;
3363 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3366 glMatrixMode(GL_MODELVIEW);
3368 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3369 Correctness Tips section).
3371 Basically, from what I understood, if the game does not filter the font texture,
3372 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3373 one and we will have strange artifacts (as the rounding and stuff may give different results
3374 for different pixels, ie sometimes take the left pixel, sometimes the right).
3376 glTranslatef(0.375, 0.375, 0);
3377 glMatrixMode(GL_PROJECTION);
3378 glLoadMatrixf(trans_mat);
3383 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3384 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3386 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3389 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3390 glMatrixMode(GL_MODELVIEW);
3391 glLoadMatrixf((float *) view_mat);
3393 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3394 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3397 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3398 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3401 plane[0] = This->clipping_planes[i].plane[0];
3402 plane[1] = This->clipping_planes[i].plane[1];
3403 plane[2] = This->clipping_planes[i].plane[2];
3404 plane[3] = This->clipping_planes[i].plane[3];
3406 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3410 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3414 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3415 if (runner & This->active_lights) {
3416 switch (This->light_parameters[i].dltType) {
3417 case D3DLIGHT_DIRECTIONAL: {
3419 float cut_off = 180.0;
3421 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3422 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3423 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3424 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3426 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3427 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3428 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3430 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3433 case D3DLIGHT_POINT: {
3435 float cut_off = 180.0;
3437 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3438 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3439 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3440 position[0] = This->light_parameters[i].dvPosition.u1.x;
3441 position[1] = This->light_parameters[i].dvPosition.u2.y;
3442 position[2] = This->light_parameters[i].dvPosition.u3.z;
3444 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3445 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3446 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3447 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3448 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3451 case D3DLIGHT_SPOT: {
3454 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3456 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3457 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3458 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3460 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3461 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3462 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3464 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3465 position[0] = This->light_parameters[i].dvPosition.u1.x;
3466 position[1] = This->light_parameters[i].dvPosition.u2.y;
3467 position[2] = This->light_parameters[i].dvPosition.u3.z;
3469 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3470 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3471 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3472 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3473 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3474 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3478 /* No warning here as it's already done at light setting */
3485 glMultMatrixf((float *) world_mat);
3487 if ((matrices & PROJMAT_CHANGED) != 0) {
3488 glMatrixMode(GL_PROJECTION);
3489 glLoadMatrixf((float *) proj_mat);
3495 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3497 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3498 DWORD tex_mat, tex_stage;
3500 TRACE("(%p,%08lx)\n", This, matrices);
3502 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3503 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3504 /* This will force an update of the transform state at the next drawing. */
3505 glThis->transform_state = GL_TRANSFORM_NONE;
3508 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3509 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3512 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3513 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3514 if (matrices & tex_mat) {
3515 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3516 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3518 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3519 if (glThis->current_active_tex_unit != unit) {
3520 GL_extensions.glActiveTexture(unit);
3521 glThis->current_active_tex_unit = unit;
3523 glMatrixMode(GL_TEXTURE);
3524 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3526 This->tex_mat_is_identity[tex_stage] = is_identity;
3528 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3529 if (glThis->current_active_tex_unit != unit) {
3530 GL_extensions.glActiveTexture(unit);
3531 glThis->current_active_tex_unit = unit;
3533 glMatrixMode(GL_TEXTURE);
3535 This->tex_mat_is_identity[tex_stage] = TRUE;
3544 /* TODO for both these functions :
3545 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3546 by other OpenGL code in D3D
3547 - handle the case where no 'Begin / EndScene' was done between two locks
3548 - handle the rectangles in the unlock too
3549 - handle pitch correctly...
3551 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3553 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3554 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3555 WINE_GL_BUFFER_TYPE buffer_type;
3558 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3559 buffer_type = WINE_GL_BUFFER_FRONT;
3560 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3561 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3562 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3564 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3565 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3566 buffer_type = WINE_GL_BUFFER_BACK;
3567 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3568 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3569 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3571 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3573 ERR("Wrong surface type for locking !\n");
3577 if (pRect == NULL) {
3580 loc_rect.bottom = This->surface_desc.dwHeight;
3581 loc_rect.right = This->surface_desc.dwWidth;
3585 /* Try to acquire the device critical section */
3586 EnterCriticalSection(&(d3d_dev->crit));
3588 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3589 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3590 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3592 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3594 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3595 /* Check if the new rectangle is in the previous one or not.
3596 If it is not, flush first the previous locks on screen.
3598 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3599 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3600 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3601 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3602 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3603 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3604 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3605 pRect->left, pRect->top, pRect->right, pRect->bottom,
3606 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3607 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3608 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3610 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3611 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3613 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3615 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3618 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3619 /* If the surface is already in memory, no need to do anything here... */
3620 GLenum buffer_format;
3621 GLenum buffer_color;
3625 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3626 pRect->left, pRect->top, pRect->right, pRect->bottom);
3628 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3629 may only write to the device... But when we will blit it back to the screen, we need
3630 also to blit correctly the parts the application did not overwrite... */
3632 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3633 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3634 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3635 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3636 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3637 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3638 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3639 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3640 buffer_color = GL_RGB;
3641 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3642 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3643 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3644 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3645 buffer_format = GL_UNSIGNED_BYTE;
3646 buffer_color = GL_RGB;
3647 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3648 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3649 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3650 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3651 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3652 buffer_color = GL_BGRA;
3654 ERR(" unsupported pixel format at device locking.\n");
3658 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3664 if (buffer_type == WINE_GL_BUFFER_FRONT)
3665 /* Application wants to lock the front buffer */
3666 glReadBuffer(GL_FRONT);
3668 /* Application wants to lock the back buffer */
3669 glReadBuffer(GL_BACK);
3671 dst = ((char *)This->surface_desc.lpSurface) +
3672 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3673 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3674 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3676 glReadPixels(pRect->left, y,
3677 pRect->right - pRect->left, 1,
3678 buffer_color, buffer_format, dst);
3679 dst += This->surface_desc.u1.lPitch;
3682 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3685 /* I keep this code here as it's very useful to debug :-) */
3687 static int flush_count = 0;
3691 if ((++flush_count % 50) == 0) {
3692 sprintf(buf, "lock_%06d.pnm", flush_count);
3693 f = fopen(buf, "wb");
3694 DDRAW_dump_surface_to_disk(This, f);
3703 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3705 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3710 /* Note : no need here to lock the 'device critical section' as we are already protected by
3711 the GL critical section. */
3713 if (pRect == NULL) {
3716 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3717 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3721 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3723 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3725 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3726 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3727 ERR(" unsupported pixel format at frame buffer flush.\n");
3731 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3735 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3737 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3738 /* First, upload the texture... */
3739 flush_rect.left = x;
3740 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3742 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3745 glTexCoord2f(0.0, 0.0);
3746 glVertex3d(x, y, 0.5);
3747 glTexCoord2f(1.0, 0.0);
3748 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3749 glTexCoord2f(1.0, 1.0);
3750 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3751 glTexCoord2f(0.0, 1.0);
3752 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3757 upload_surface_to_tex_memory_release();
3758 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3761 /* I keep this code here as it's very useful to debug :-) */
3763 static int flush_count = 0;
3767 if ((++flush_count % 50) == 0) {
3768 sprintf(buf, "flush_%06d.pnm", flush_count);
3769 f = fopen(buf, "wb");
3770 DDRAW_dump_surface_to_disk(surf, f);
3776 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3778 WINE_GL_BUFFER_TYPE buffer_type;
3779 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3780 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3782 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3783 buffer_type = WINE_GL_BUFFER_FRONT;
3784 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3785 buffer_type = WINE_GL_BUFFER_BACK;
3787 ERR("Wrong surface type for locking !\n");
3791 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3792 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3793 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3795 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3797 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3798 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3799 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3802 TRACE(" flushing front buffer immediatly on screen.\n");
3805 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3806 glDrawBuffer(GL_FRONT);
3807 /* Note: we do not use the application provided lock rectangle but our own stored at
3808 lock time. This is because in old D3D versions, the 'lock' parameter did not
3811 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]);
3812 glDrawBuffer(prev_draw);
3815 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3819 /* And 'frees' the device critical section */
3820 LeaveCriticalSection(&(d3d_dev->crit));
3824 apply_texture_state(IDirect3DDeviceImpl *This)
3828 /* Initialize texture stages states */
3829 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3830 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3831 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3832 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3833 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3840 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
3842 IDirect3DDeviceImpl *object;
3843 IDirect3DDeviceGLImpl *gl_object;
3844 IDirectDrawSurfaceImpl *surf;
3849 XVisualInfo template;
3850 GLenum buffer = GL_FRONT;
3853 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3854 if (object == NULL) return DDERR_OUTOFMEMORY;
3856 gl_object = (IDirect3DDeviceGLImpl *) object;
3860 object->surface = surface;
3861 object->set_context = set_context;
3862 object->clear = d3ddevice_clear_back;
3863 object->set_matrices = d3ddevice_set_matrices;
3864 object->matrices_updated = d3ddevice_matrices_updated;
3865 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3867 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3869 InitializeCriticalSection(&(object->crit));
3871 TRACE(" device critical section : %p\n", &(object->crit));
3873 /* This is just a hack for some badly done games :-/ */
3875 gl_object->version = 1;
3876 TRACE(" using D3D1 special hacks.\n");
3878 gl_object->version = 7;
3880 device_context = GetDC(surface->ddraw_owner->window);
3881 gl_object->display = get_display(device_context);
3882 gl_object->drawable = get_drawable(device_context);
3883 ReleaseDC(surface->ddraw_owner->window,device_context);
3886 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3887 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3889 HeapFree(GetProcessHeap(), 0, object);
3890 ERR("No visual found !\n");
3892 return DDERR_INVALIDPARAMS;
3894 TRACE(" visual found\n");
3897 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3900 if (gl_object->gl_context == NULL) {
3901 HeapFree(GetProcessHeap(), 0, object);
3902 ERR("Error in context creation !\n");
3904 return DDERR_INVALIDPARAMS;
3906 TRACE(" context created (%p)\n", gl_object->gl_context);
3909 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3910 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3911 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3912 surf->aux_ctx = (LPVOID) object;
3913 surf->aux_data = (LPVOID) gl_object->drawable;
3914 surf->aux_flip = opengl_flip;
3919 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3921 TRACE(" no double buffering : drawing on the front buffer\n");
3925 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3926 IDirectDrawSurfaceImpl *surf2;
3927 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3928 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3929 TRACE(" checking surface %p :", surf2);
3930 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3931 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3932 /* Override the Lock / Unlock function for all these surfaces */
3933 surf2->lock_update_prev = surf2->lock_update;
3934 surf2->lock_update = d3ddevice_lock_update;
3935 surf2->unlock_update_prev = surf2->unlock_update;
3936 surf2->unlock_update = d3ddevice_unlock_update;
3937 /* And install also the blt / bltfast overrides */
3938 surf2->aux_blt = d3ddevice_blt;
3939 surf2->aux_bltfast = d3ddevice_bltfast;
3941 TRACE(" overiding direct surface access.\n");
3943 TRACE(" no overide.\n");
3945 surf2->d3ddevice = object;
3949 /* Set the various light parameters */
3950 for (light = 0; light < MAX_LIGHTS; light++) {
3951 /* Only set the fields that are not zero-created */
3952 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3953 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3954 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3955 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3956 object->light_parameters[light].dvDirection.u3.z = 1.0;
3959 /* Allocate memory for the matrices */
3960 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3961 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3962 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3963 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3964 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3965 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3966 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3967 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3968 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3969 object->tex_mat_is_identity[tex_num] = TRUE;
3972 /* Initialisation */
3973 TRACE(" setting current context\n");
3974 object->set_context(object);
3975 TRACE(" current context set\n");
3977 /* allocate the clipping planes */
3978 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3979 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3981 glHint(GL_FOG_HINT,GL_NICEST);
3983 /* Initialize the various GL contexts to be in sync with what we store locally */
3986 glClearColor(0.0, 0.0, 0.0, 0.0);
3987 glDepthMask(GL_TRUE);
3988 gl_object->depth_mask = TRUE;
3989 glEnable(GL_DEPTH_TEST);
3990 gl_object->depth_test = TRUE;
3991 glDisable(GL_ALPHA_TEST);
3992 glDisable(GL_STENCIL_TEST);
3993 glDisable(GL_CULL_FACE);
3994 glDisable(GL_LIGHTING);
3995 glDisable(GL_BLEND);
3997 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3998 gl_object->current_tex_env = GL_REPLACE;
3999 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
4000 if (GL_extensions.glActiveTexture != NULL) {
4001 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
4003 gl_object->current_alpha_test_ref = 0.0;
4004 gl_object->current_alpha_test_func = GL_ALWAYS;
4005 glAlphaFunc(GL_ALWAYS, 0.0);
4007 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4008 glDrawBuffer(buffer);
4009 glReadBuffer(buffer);
4010 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4013 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4014 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
4016 /* fill_device_capabilities(d3d->ddraw); */
4018 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4019 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4020 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4021 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
4025 TRACE(" creating implementation at %p.\n", *obj);
4027 /* And finally warn D3D that this device is now present */
4028 object->d3d->d3d_added_device(object->d3d, object);
4030 /* FIXME: Should handle other versions than just 7 */
4031 InitDefaultStateBlock(&object->state_block, 7);
4032 /* Apply default render state and texture stage state values */
4033 apply_render_state(object, &object->state_block);
4034 apply_texture_state(object);
4036 /* And fill the fog table with the default fog value */
4037 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4042 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4044 pc->dwSize = sizeof(*pc);
4045 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
4046 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
4047 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
4048 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4049 D3DPRASTERCAPS_ZFOG;
4050 if (GL_extensions.mipmap_lodbias == TRUE) {
4051 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4053 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4054 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4055 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4056 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4057 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4058 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4059 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4060 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4061 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4062 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4063 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4064 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4065 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4066 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4067 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
4068 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4069 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4070 D3DPTFILTERCAPS_MIPFPOINT;
4071 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4072 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4073 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
4074 if (GL_extensions.mirrored_repeat == TRUE) {
4075 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4077 pc->dwStippleWidth = 32;
4078 pc->dwStippleHeight = 32;
4081 static void fill_caps(void)
4083 GLint max_clip_planes;
4086 /* Fill first all the fields with default values which will be overriden later on with
4087 correct ones from the GL code
4089 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4090 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4091 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4092 /* D3D 7 capabilities */
4093 D3DDEVCAPS_DRAWPRIMITIVES2 /*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_DRAWPRIMITIVES2EX;
4094 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4095 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4096 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
4097 opengl_device_caps.dwMinTextureWidth = 1;
4098 opengl_device_caps.dwMinTextureHeight = 1;
4099 opengl_device_caps.dwMaxTextureWidth = 1024;
4100 opengl_device_caps.dwMaxTextureHeight = 1024;
4101 opengl_device_caps.dwMaxTextureRepeat = 16;
4102 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4103 opengl_device_caps.dwMaxAnisotropy = 0;
4104 opengl_device_caps.dvGuardBandLeft = 0.0;
4105 opengl_device_caps.dvGuardBandRight = 0.0;
4106 opengl_device_caps.dvGuardBandTop = 0.0;
4107 opengl_device_caps.dvGuardBandBottom = 0.0;
4108 opengl_device_caps.dvExtentsAdjust = 0.0;
4109 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4110 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
4111 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4112 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4113 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4114 if (GL_extensions.max_texture_units != 0) {
4115 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4116 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4117 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4119 opengl_device_caps.wMaxTextureBlendStages = 1;
4120 opengl_device_caps.wMaxSimultaneousTextures = 1;
4121 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4123 opengl_device_caps.dwMaxActiveLights = 16;
4124 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4125 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4126 opengl_device_caps.wMaxUserClipPlanes = 1;
4127 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4128 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4129 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4130 opengl_device_caps.dwReserved1 = 0;
4131 opengl_device_caps.dwReserved2 = 0;
4132 opengl_device_caps.dwReserved3 = 0;
4133 opengl_device_caps.dwReserved4 = 0;
4135 /* And now some GL overides :-) */
4136 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4137 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4138 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4139 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4141 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4142 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4144 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4145 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4146 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4148 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4149 TRACE(": Z bits = %d\n", depth_bits);
4150 switch (depth_bits) {
4151 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4152 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4154 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4159 d3ddevice_init_at_startup(void *gl_handle)
4161 XVisualInfo template;
4166 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4167 XWindowAttributes win_attr;
4168 GLXContext gl_context;
4170 const char *glExtensions;
4171 const char *glVersion;
4172 const char *glXExtensions = NULL;
4173 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4174 int major, minor, patch, num_parsed;
4176 TRACE("Initializing GL...\n");
4178 /* Get a default rendering context to have the 'caps' function query some info from GL */
4179 device_context = GetDC(0);
4180 display = get_display(device_context);
4181 ReleaseDC(0, device_context);
4184 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4185 visual = win_attr.visual;
4187 visual = DefaultVisual(display, DefaultScreen(display));
4189 template.visualid = XVisualIDFromVisual(visual);
4190 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4193 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4196 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4198 if (gl_context == NULL) {
4200 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4203 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4204 glXDestroyContext(display, gl_context);
4206 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4210 /* Then, query all extensions */
4211 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); /* Note: not used right now but will for PBuffers */
4212 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4213 glVersion = (const char *) glGetString(GL_VERSION);
4214 if (gl_handle != NULL) {
4215 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4218 /* Parse the GL version string */
4219 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4220 if (num_parsed == 1) {
4223 } else if (num_parsed == 2) {
4226 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4228 /* And starts to fill the extension context properly */
4229 memset(&GL_extensions, 0, sizeof(GL_extensions));
4230 TRACE("GL supports following extensions used by Wine :\n");
4232 /* Mirrored Repeat extension :
4233 - GL_ARB_texture_mirrored_repeat
4234 - GL_IBM_texture_mirrored_repeat
4237 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4238 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4240 ((major == 1) && (minor >= 4))) {
4241 TRACE(" - mirrored repeat\n");
4242 GL_extensions.mirrored_repeat = TRUE;
4245 /* Texture LOD Bias :
4246 - GL_EXT_texture_lod_bias
4248 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4249 TRACE(" - texture lod bias\n");
4250 GL_extensions.mipmap_lodbias = TRUE;
4253 /* For all subsequent extensions, we need glXGetProcAddress */
4254 if (pglXGetProcAddressARB != NULL) {
4255 /* Multi-texturing :
4256 - GL_ARB_multitexture
4259 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4261 ((major == 1) && (minor > 2)) ||
4262 ((major == 1) && (minor == 2) && (patch >= 1))) {
4263 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4264 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4265 /* We query the ARB version to be the most portable we can... */
4266 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4267 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4268 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
4272 /* Fill the D3D capabilities according to what GL tells us... */
4275 /* And frees this now-useless context */
4276 glXMakeCurrent(display, None, NULL);
4277 glXDestroyContext(display, gl_context);