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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 #include "mesa_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
41 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
43 /* x11drv GDI escapes */
44 #define X11DRV_ESCAPE 6789
45 enum x11drv_escape_codes
47 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
48 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
49 X11DRV_GET_FONT, /* get current X font for a DC */
52 /* They are non-static as they are used by Direct3D in the creation function */
53 const GUID IID_D3DDEVICE_OpenGL = {
57 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
60 const float id_mat[16] = {
67 /* This is filled at DLL loading time */
68 static D3DDEVICEDESC7 opengl_device_caps;
70 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
71 D3DPRIMITIVETYPE d3dptPrimitiveType,
72 DWORD d3dvtVertexType,
73 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
79 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
81 /* retrieve the X display to use on a given DC */
82 inline static Display *get_display( HDC hdc )
85 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
87 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
88 sizeof(display), (LPSTR)&display )) display = NULL;
93 #define UNLOCK_TEX_SIZE 256
95 #define DEPTH_RANGE_BIT (0x00000001 << 0)
96 #define VIEWPORT_BIT (0x00000001 << 1)
98 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
99 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
100 DWORD opt_bitmap = 0x00000000;
102 if (gl_d3d_dev->unlock_tex == 0) {
103 glGenTextures(1, &gl_d3d_dev->unlock_tex);
104 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
111 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
114 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
115 glMatrixMode(GL_TEXTURE);
119 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
120 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
121 d3ddevice_set_ortho(d3d_dev);
124 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
125 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
126 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
127 glEnable(GL_TEXTURE_2D);
128 glEnable(GL_SCISSOR_TEST);
129 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
130 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
131 glDepthRange(0.0, 1.0);
132 opt_bitmap |= DEPTH_RANGE_BIT;
134 if ((d3d_dev->active_viewport.dwX != 0) ||
135 (d3d_dev->active_viewport.dwY != 0) ||
136 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
137 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
138 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
139 opt_bitmap |= VIEWPORT_BIT;
141 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
142 pRect->right - pRect->left, pRect->bottom - pRect->top);
143 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
144 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
146 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
147 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
148 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
149 glAlphaFunc(GL_GREATER, 0.0);
152 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
154 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
155 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
156 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
157 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
158 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
163 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
164 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
166 /* And restore all the various states modified by this code */
167 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
168 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
169 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
170 glEnable(GL_ALPHA_TEST);
171 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
172 glDisable(GL_ALPHA_TEST);
174 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
175 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
176 glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
177 (d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
180 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
181 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
182 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
183 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
184 glDisable(GL_SCISSOR_TEST);
185 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
186 if (opt_bitmap & DEPTH_RANGE_BIT) {
187 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
189 if (opt_bitmap & VIEWPORT_BIT) {
190 glViewport(d3d_dev->active_viewport.dwX,
191 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
192 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
194 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
195 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
198 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
199 DrawPrimitive call, this will bind the correct texture to this stage. */
200 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
201 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
204 /* retrieve the X drawable to use on a given DC */
205 inline static Drawable get_drawable( HDC hdc )
208 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
210 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
211 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
216 /* This is unnecessarely complicated :-) */
217 #define MEASUREMENT_WINDOW 5
218 #define NUMBER_OF_WINDOWS 10
220 static LONGLONG perf_freq;
221 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
222 static LONGLONG prev_time = 0;
223 static unsigned int current_window;
224 static unsigned int measurements_in_window;
225 static unsigned int valid_windows;
227 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
229 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
230 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
232 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
234 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
235 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]);
237 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
238 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
239 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
242 if (TRACE_ON(ddraw_fps)) {
243 LONGLONG current_time;
244 LONGLONG frame_duration;
245 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
247 if (prev_time != 0) {
248 LONGLONG total_time = 0;
251 frame_duration = current_time - prev_time;
252 prev_time = current_time;
254 perf_storage[current_window] += frame_duration;
255 measurements_in_window++;
257 if (measurements_in_window >= MEASUREMENT_WINDOW) {
261 if (valid_windows < NUMBER_OF_WINDOWS) {
263 tot_meas = valid_windows * MEASUREMENT_WINDOW;
264 for (i = 0; i < valid_windows; i++) {
265 total_time += perf_storage[i];
269 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
270 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
271 total_time += perf_storage[i];
275 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
277 if (current_window >= NUMBER_OF_WINDOWS) {
280 perf_storage[current_window] = 0;
281 measurements_in_window = 0;
284 prev_time = current_time;
285 memset(perf_storage, 0, sizeof(perf_storage));
288 measurements_in_window = 0;
289 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
297 /*******************************************************************************
298 * OpenGL static functions
300 static void set_context(IDirect3DDeviceImpl* This)
302 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
304 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
306 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
307 ERR("Error in setting current context (context %p drawable %ld)!\n",
308 glThis->gl_context, glThis->drawable);
313 static void fill_opengl_caps(D3DDEVICEDESC *d1)
315 d1->dwSize = sizeof(*d1);
316 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
317 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
318 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
319 d1->dcmColorModel = D3DCOLOR_RGB;
320 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
321 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
322 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
323 d1->bClipping = TRUE;
324 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
325 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
326 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
327 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
328 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
329 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
330 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
331 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
332 d1->dwMaxBufferSize = 0;
333 d1->dwMaxVertexCount = 65536;
334 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
335 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
336 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
337 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
338 d1->dwMinStippleWidth = 1;
339 d1->dwMinStippleHeight = 1;
340 d1->dwMaxStippleWidth = 32;
341 d1->dwMaxStippleHeight = 32;
342 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
343 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
344 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
345 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
346 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
347 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
348 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
349 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
350 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
351 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
352 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
353 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
354 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
357 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
359 *d = opengl_device_caps;
362 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
364 D3DDEVICEDESC dref, d1, d2;
367 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
368 Let's put the string in a sufficiently sized array in writable memory. */
369 char device_name[50];
370 strcpy(device_name,"direct3d");
372 fill_opengl_caps(&dref);
375 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
376 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
379 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
380 if (ret_value != D3DENUMRET_OK)
384 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
387 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
388 if (ret_value != D3DENUMRET_OK)
391 return D3DENUMRET_OK;
394 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
396 D3DDEVICEDESC7 ddesc;
398 fill_opengl_caps_7(&ddesc);
400 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
402 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
406 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
408 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
409 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
411 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
412 if (!--(This->ref)) {
414 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
416 /* Release texture associated with the device */
417 for (i = 0; i < MAX_TEXTURES; i++) {
418 if (This->current_texture[i] != NULL)
419 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
420 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
423 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
424 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
425 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
426 surf->aux_ctx = NULL;
427 surf->aux_data = NULL;
428 surf->aux_flip = NULL;
432 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
433 IDirectDrawSurfaceImpl *surf2;
434 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
435 for (; surf2 != NULL; surf2 = surf2->next_attached) {
436 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
437 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
438 /* Override the Lock / Unlock function for all these surfaces */
439 surf2->lock_update = surf2->lock_update_prev;
440 surf2->unlock_update = surf2->unlock_update_prev;
441 /* And install also the blt / bltfast overrides */
442 surf2->aux_blt = NULL;
443 surf2->aux_bltfast = NULL;
445 surf2->d3ddevice = NULL;
449 /* And warn the D3D object that this device is no longer active... */
450 This->d3d->d3d_removed_device(This->d3d, This);
452 HeapFree(GetProcessHeap(), 0, This->world_mat);
453 HeapFree(GetProcessHeap(), 0, This->view_mat);
454 HeapFree(GetProcessHeap(), 0, This->proj_mat);
456 if (glThis->surface_ptr)
457 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
459 DeleteCriticalSection(&(This->crit));
462 if (glThis->unlock_tex)
463 glDeleteTextures(1, &(glThis->unlock_tex));
464 glXDestroyContext(glThis->display, glThis->gl_context);
466 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
468 HeapFree(GetProcessHeap(), 0, This);
475 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
476 LPD3DDEVICEDESC lpD3DHWDevDesc,
477 LPD3DDEVICEDESC lpD3DHELDevDesc)
479 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
483 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
485 fill_opengl_caps(&desc);
486 dwSize = lpD3DHWDevDesc->dwSize;
487 memset(lpD3DHWDevDesc, 0, dwSize);
488 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
490 dwSize = lpD3DHELDevDesc->dwSize;
491 memset(lpD3DHELDevDesc, 0, dwSize);
492 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
494 TRACE(" returning caps : (no dump function yet)\n");
499 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
500 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
504 LPDDPIXELFORMAT pformat;
506 /* Do the texture enumeration */
507 sdesc.dwSize = sizeof(DDSURFACEDESC);
508 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
509 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
510 pformat = &(sdesc.ddpfPixelFormat);
511 pformat->dwSize = sizeof(DDPIXELFORMAT);
512 pformat->dwFourCC = 0;
514 TRACE("Enumerating GL_RGBA unpacked (32)\n");
515 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
516 pformat->u1.dwRGBBitCount = 32;
517 pformat->u2.dwRBitMask = 0x00FF0000;
518 pformat->u3.dwGBitMask = 0x0000FF00;
519 pformat->u4.dwBBitMask = 0x000000FF;
520 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
521 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
522 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
524 TRACE("Enumerating GL_RGB unpacked (32)\n");
525 pformat->dwFlags = DDPF_RGB;
526 pformat->u1.dwRGBBitCount = 32;
527 pformat->u2.dwRBitMask = 0x00FF0000;
528 pformat->u3.dwGBitMask = 0x0000FF00;
529 pformat->u4.dwBBitMask = 0x000000FF;
530 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
531 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
532 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
534 TRACE("Enumerating GL_RGB unpacked (24)\n");
535 pformat->dwFlags = DDPF_RGB;
536 pformat->u1.dwRGBBitCount = 24;
537 pformat->u2.dwRBitMask = 0x00FF0000;
538 pformat->u3.dwGBitMask = 0x0000FF00;
539 pformat->u4.dwBBitMask = 0x000000FF;
540 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
541 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
542 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
544 /* Note : even if this is an 'emulated' texture format, it needs to be first
545 as some dumb applications seem to rely on that. */
546 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
547 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
548 pformat->u1.dwRGBBitCount = 16;
549 pformat->u2.dwRBitMask = 0x00007C00;
550 pformat->u3.dwGBitMask = 0x000003E0;
551 pformat->u4.dwBBitMask = 0x0000001F;
552 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
553 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
554 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
556 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
557 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
558 pformat->u1.dwRGBBitCount = 16;
559 pformat->u2.dwRBitMask = 0x00000F00;
560 pformat->u3.dwGBitMask = 0x000000F0;
561 pformat->u4.dwBBitMask = 0x0000000F;
562 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
563 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
564 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
566 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
567 pformat->dwFlags = DDPF_RGB;
568 pformat->u1.dwRGBBitCount = 16;
569 pformat->u2.dwRBitMask = 0x0000F800;
570 pformat->u3.dwGBitMask = 0x000007E0;
571 pformat->u4.dwBBitMask = 0x0000001F;
572 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
573 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
574 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
576 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
577 pformat->dwFlags = DDPF_RGB;
578 pformat->u1.dwRGBBitCount = 16;
579 pformat->u2.dwRBitMask = 0x00007C00;
580 pformat->u3.dwGBitMask = 0x000003E0;
581 pformat->u4.dwBBitMask = 0x0000001F;
582 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
583 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
584 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
587 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
588 find enumerated, others the last one. And both want to have the ARGB one.
590 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
592 /* See argument about the RGBA format for 'packed' texture formats */
593 TRACE("Enumerating GL_RGBA unpacked (32)\n");
594 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
595 pformat->u1.dwRGBBitCount = 32;
596 pformat->u2.dwRBitMask = 0xFF000000;
597 pformat->u3.dwGBitMask = 0x00FF0000;
598 pformat->u4.dwBBitMask = 0x0000FF00;
599 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
600 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
601 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
603 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
604 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
605 pformat->u1.dwRGBBitCount = 16;
606 pformat->u2.dwRBitMask = 0x0000F000;
607 pformat->u3.dwGBitMask = 0x00000F00;
608 pformat->u4.dwBBitMask = 0x000000F0;
609 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
610 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
611 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
613 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
614 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
615 pformat->u1.dwRGBBitCount = 16;
616 pformat->u2.dwRBitMask = 0x0000F800;
617 pformat->u3.dwGBitMask = 0x000007C0;
618 pformat->u4.dwBBitMask = 0x0000003E;
619 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
620 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
621 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
624 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
625 pformat->dwFlags = DDPF_RGB;
626 pformat->u1.dwRGBBitCount = 8;
627 pformat->u2.dwRBitMask = 0x000000E0;
628 pformat->u3.dwGBitMask = 0x0000001C;
629 pformat->u4.dwBBitMask = 0x00000003;
630 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
631 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
632 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
634 TRACE("Enumerating Paletted (8)\n");
635 pformat->dwFlags = DDPF_PALETTEINDEXED8;
636 pformat->u1.dwRGBBitCount = 8;
637 pformat->u2.dwRBitMask = 0x00000000;
638 pformat->u3.dwGBitMask = 0x00000000;
639 pformat->u4.dwBBitMask = 0x00000000;
640 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
641 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
642 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
644 TRACE("End of enumeration\n");
650 d3ddevice_find(IDirectDrawImpl *d3d,
651 LPD3DFINDDEVICESEARCH lpD3DDFS,
652 LPD3DFINDDEVICERESULT lplpD3DDevice)
656 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
657 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
658 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
659 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
661 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
662 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
663 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
664 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
665 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
666 TRACE(" no match for this GUID.\n");
667 return DDERR_INVALIDPARAMS;
671 /* Now return our own GUID */
672 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
673 fill_opengl_caps(&desc);
674 lplpD3DDevice->ddHwDesc = desc;
675 lplpD3DDevice->ddSwDesc = desc;
677 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
683 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
684 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
687 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
688 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
689 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
693 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
694 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
697 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
698 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
699 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
703 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
704 D3DRENDERSTATETYPE dwRenderStateType,
707 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
708 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
710 /* Call the render state functions */
711 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
712 set_render_state(This, dwRenderStateType, &This->state_block);
718 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
719 D3DRENDERSTATETYPE dwRenderStateType,
720 LPDWORD lpdwRenderState)
722 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
723 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
725 /* Call the render state functions */
726 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
728 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
734 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
735 D3DLIGHTSTATETYPE dwLightStateType,
738 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
740 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
742 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
743 TRACE("Unexpected Light State Type\n");
744 return DDERR_INVALIDPARAMS;
746 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
747 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
752 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
754 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
755 switch (dwLightState) {
757 ERR("DDCOLOR_MONO should not happen!\n");
760 /* We are already in this mode */
763 ERR("Unknown color model!\n");
767 D3DRENDERSTATETYPE rs;
768 switch (dwLightStateType) {
770 case D3DLIGHTSTATE_AMBIENT: /* 2 */
771 rs = D3DRENDERSTATE_AMBIENT;
773 case D3DLIGHTSTATE_FOGMODE: /* 4 */
774 rs = D3DRENDERSTATE_FOGVERTEXMODE;
776 case D3DLIGHTSTATE_FOGSTART: /* 5 */
777 rs = D3DRENDERSTATE_FOGSTART;
779 case D3DLIGHTSTATE_FOGEND: /* 6 */
780 rs = D3DRENDERSTATE_FOGEND;
782 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
783 rs = D3DRENDERSTATE_FOGDENSITY;
785 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
786 rs = D3DRENDERSTATE_COLORVERTEX;
792 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
799 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
802 case D3DPT_POINTLIST:
803 TRACE("Start POINTS\n");
808 TRACE("Start LINES\n");
812 case D3DPT_LINESTRIP:
813 TRACE("Start LINE_STRIP\n");
814 glBegin(GL_LINE_STRIP);
817 case D3DPT_TRIANGLELIST:
818 TRACE("Start TRIANGLES\n");
819 glBegin(GL_TRIANGLES);
822 case D3DPT_TRIANGLESTRIP:
823 TRACE("Start TRIANGLE_STRIP\n");
824 glBegin(GL_TRIANGLE_STRIP);
827 case D3DPT_TRIANGLEFAN:
828 TRACE("Start TRIANGLE_FAN\n");
829 glBegin(GL_TRIANGLE_FAN);
833 FIXME("Unhandled primitive %08x\n", d3dpt);
838 /* This function calculate the Z coordinate from Zproj */
839 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
842 /* Assume that X = Y = 0 and W = 1 */
843 a = This->proj_mat->_33;
844 b = This->proj_mat->_34;
845 c = This->proj_mat->_43;
846 d = This->proj_mat->_44;
847 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
848 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
849 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
851 return (d*Zproj - c) / (a - b*Zproj);
854 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
857 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
859 for (i = 0; i < 3; i++) {
860 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
862 for (elt = 0; elt < 0x10000; elt++) {
863 /* We apply the fog transformation and cache the result */
864 DWORD fog_intensity = elt & 0xFF;
865 DWORD vertex_color = (elt >> 8) & 0xFF;
866 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
871 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
872 BOOLEAN vertex_transformed,
873 BOOLEAN vertex_lit) {
874 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
876 /* Puts GL in the correct lighting / transformation mode */
877 if ((vertex_transformed == FALSE) &&
878 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
879 /* Need to put the correct transformation again if we go from Transformed
880 vertices to non-transformed ones.
882 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
883 This->world_mat, This->view_mat, This->proj_mat);
884 glThis->transform_state = GL_TRANSFORM_NORMAL;
886 } else if ((vertex_transformed == TRUE) &&
887 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
888 /* Set our orthographic projection */
889 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
890 glThis->transform_state = GL_TRANSFORM_ORTHO;
891 d3ddevice_set_ortho(This);
895 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
896 if no fogging state change occurred */
897 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
898 if (vertex_transformed == TRUE) {
899 if (glThis->fogging != 0) {
903 /* Now check if our fog_table still corresponds to the current vertex color.
904 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
905 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
906 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
907 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
908 /* We need to rebuild our fog table.... */
909 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
912 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
913 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
914 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
915 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
916 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
918 if (vertex_lit == FALSE) {
919 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
920 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
922 /* Special case of 'pixel fog' */
923 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
924 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
926 if (glThis->fogging == 0) {
931 if (glThis->fogging != 0) {
938 if (glThis->fogging != 0) {
944 /* Handle the 'no-normal' case */
945 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
946 if (glThis->lighting == 0) {
947 glEnable(GL_LIGHTING);
948 glThis->lighting = 1;
951 if (glThis->lighting != 0) {
952 glDisable(GL_LIGHTING);
953 glThis->lighting = 0;
957 /* Handle the code for pre-vertex material properties */
958 if (vertex_transformed == FALSE) {
959 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
960 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
961 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
962 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
963 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
964 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
965 glEnable(GL_COLOR_MATERIAL);
972 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
973 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
975 D3DDRAWPRIMITIVESTRIDEDDATA strided;
979 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
980 strided.position.dwStride = sizeof(D3DVERTEX);
981 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
982 strided.normal.dwStride = sizeof(D3DVERTEX);
983 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
984 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
985 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
988 case D3DVT_LVERTEX: {
989 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
990 strided.position.dwStride = sizeof(D3DLVERTEX);
991 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
992 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
993 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
994 strided.specular.dwStride = sizeof(D3DLVERTEX);
995 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
996 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
997 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1000 case D3DVT_TLVERTEX: {
1001 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1002 strided.position.dwStride = sizeof(D3DTLVERTEX);
1003 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1004 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1005 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1006 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1007 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1008 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1009 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1013 FIXME("Unhandled vertex type %08x\n", d3dvt);
1019 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1020 D3DPRIMITIVETYPE d3dptPrimitiveType,
1021 D3DVERTEXTYPE d3dvtVertexType,
1023 DWORD dwVertexCount,
1026 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1028 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1029 if (TRACE_ON(ddraw)) {
1030 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1033 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1039 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1040 D3DPRIMITIVETYPE d3dptPrimitiveType,
1041 D3DVERTEXTYPE d3dvtVertexType,
1043 DWORD dwVertexCount,
1048 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1049 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1050 if (TRACE_ON(ddraw)) {
1051 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1054 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1060 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1061 LPD3DEXECUTEBUFFERDESC lpDesc,
1062 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1063 IUnknown* pUnkOuter)
1065 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1066 IDirect3DExecuteBufferImpl *ret;
1069 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1071 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1072 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1074 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1079 /* These are the various handler used in the generic path */
1080 inline static void handle_xyz(D3DVALUE *coords) {
1081 glVertex3fv(coords);
1083 inline static void handle_xyzrhw(D3DVALUE *coords) {
1084 if (coords[3] < 1e-8)
1085 glVertex3fv(coords);
1087 GLfloat w = 1.0 / coords[3];
1089 glVertex4f(coords[0] * w,
1095 inline static void handle_normal(D3DVALUE *coords) {
1096 glNormal3fv(coords);
1099 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1100 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1101 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1102 glColor4ub((*color >> 16) & 0xFF,
1103 (*color >> 8) & 0xFF,
1104 (*color >> 0) & 0xFF,
1105 (*color >> 24) & 0xFF);
1107 glColor3ub((*color >> 16) & 0xFF,
1108 (*color >> 8) & 0xFF,
1109 (*color >> 0) & 0xFF);
1113 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1114 glColor4ub((*color >> 16) & 0xFF,
1115 (*color >> 8) & 0xFF,
1116 (*color >> 0) & 0xFF,
1117 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1120 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1121 if ((lighted == FALSE) &&
1122 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1123 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1124 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1125 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1126 handle_diffuse_base(sb, color);
1128 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1129 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1130 handle_diffuse_base(sb, color);
1132 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1133 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1134 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1135 handle_diffuse_base(sb, color);
1137 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1138 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1139 handle_diffuse_base(sb, color);
1142 handle_diffuse_base(sb, color);
1146 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1147 if ((lighted == FALSE) &&
1148 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1149 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1150 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1151 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1152 handle_specular_base(sb, color);
1154 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1155 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1156 handle_specular_base(sb, color);
1158 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1159 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1160 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1161 handle_specular_base(sb, color);
1163 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1164 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1165 handle_specular_base(sb, color);
1168 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1171 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1172 if (lighted == TRUE) {
1173 DWORD color = *color_d;
1174 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1175 /* Special case where the specular value is used to do fogging */
1176 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1177 color &= 0xFF000000; /* Only keep the alpha component */
1178 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1179 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1180 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1182 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1183 /* Standard specular value in transformed mode. TODO */
1185 handle_diffuse_base(sb, &color);
1187 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1188 handle_diffuse(sb, color_d, FALSE);
1189 handle_specular(sb, color_s, FALSE);
1191 /* In that case, only put the diffuse color... */
1192 handle_diffuse_base(sb, color_d);
1197 inline static void handle_texture(D3DVALUE *coords) {
1198 glTexCoord2fv(coords);
1200 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1201 /* For the moment, draw only the first texture.. */
1202 if (tex_stage == 0) glTexCoord2fv(coords);
1205 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1206 D3DPRIMITIVETYPE d3dptPrimitiveType,
1207 DWORD d3dvtVertexType,
1208 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1209 DWORD dwVertexCount,
1214 BOOLEAN vertex_lighted = FALSE;
1215 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1216 int num_active_stages = 0;
1218 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1219 if (TRACE_ON(ddraw)) {
1220 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1223 /* This is to prevent 'thread contention' between a thread locking the device and another
1224 doing 3D display on it... */
1225 EnterCriticalSection(&(This->crit));
1228 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1229 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1232 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1234 /* Just a hack for now.. Will have to find better algorithm :-/ */
1235 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1236 vertex_lighted = TRUE;
1238 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1241 /* Compute the number of active texture stages and set the various texture parameters */
1242 num_active_stages = draw_primitive_handle_textures(This);
1244 draw_primitive_handle_GL_state(This,
1245 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1247 draw_primitive_start_GL(d3dptPrimitiveType);
1249 /* Some fast paths first before the generic case.... */
1250 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1253 for (index = 0; index < dwIndexCount; index++) {
1254 int i = (dwIndices == NULL) ? index : dwIndices[index];
1256 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1257 D3DVALUE *tex_coord =
1258 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1259 D3DVALUE *position =
1260 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1262 handle_normal(normal);
1263 handle_texture(tex_coord);
1264 handle_xyz(position);
1266 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1267 position[0], position[1], position[2],
1268 normal[0], normal[1], normal[2],
1269 tex_coord[0], tex_coord[1]);
1271 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1274 for (index = 0; index < dwIndexCount; index++) {
1275 int i = (dwIndices == NULL) ? index : dwIndices[index];
1277 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1279 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1280 D3DVALUE *tex_coord =
1281 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1282 D3DVALUE *position =
1283 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1285 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1286 handle_texture(tex_coord);
1287 handle_xyzrhw(position);
1289 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1290 position[0], position[1], position[2], position[3],
1291 (*color_d >> 16) & 0xFF,
1292 (*color_d >> 8) & 0xFF,
1293 (*color_d >> 0) & 0xFF,
1294 (*color_d >> 24) & 0xFF,
1295 (*color_s >> 16) & 0xFF,
1296 (*color_s >> 8) & 0xFF,
1297 (*color_s >> 0) & 0xFF,
1298 (*color_s >> 24) & 0xFF,
1299 tex_coord[0], tex_coord[1]);
1301 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1302 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1303 /* This is the 'slow path' but that should support all possible vertex formats out there...
1304 Note that people should write a fast path for all vertex formats out there...
1307 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1308 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1310 for (index = 0; index < dwIndexCount; index++) {
1311 int i = (dwIndices == NULL) ? index : dwIndices[index];
1314 if (d3dvtVertexType & D3DFVF_NORMAL) {
1316 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1317 handle_normal(normal);
1319 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1321 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1323 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1324 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1326 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1328 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1329 handle_specular(&(This->state_block), color_s, vertex_lighted);
1330 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1332 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1333 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1337 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1338 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1339 if (tex_index >= num_tex_index) {
1340 handle_textures((D3DVALUE *) no_index, tex_stage);
1342 D3DVALUE *tex_coord =
1343 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1344 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1345 handle_textures(tex_coord, tex_stage);
1349 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1350 D3DVALUE *position =
1351 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1352 handle_xyz(position);
1353 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1354 D3DVALUE *position =
1355 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1356 handle_xyzrhw(position);
1359 if (TRACE_ON(ddraw_geom)) {
1362 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1363 D3DVALUE *position =
1364 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1365 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1366 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1367 D3DVALUE *position =
1368 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1369 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1371 if (d3dvtVertexType & D3DFVF_NORMAL) {
1373 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1374 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1376 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1378 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1379 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1380 (*color_d >> 16) & 0xFF,
1381 (*color_d >> 8) & 0xFF,
1382 (*color_d >> 0) & 0xFF,
1383 (*color_d >> 24) & 0xFF);
1385 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1387 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1388 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1389 (*color_s >> 16) & 0xFF,
1390 (*color_s >> 8) & 0xFF,
1391 (*color_s >> 0) & 0xFF,
1392 (*color_s >> 24) & 0xFF);
1394 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1395 D3DVALUE *tex_coord =
1396 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1397 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1398 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1400 TRACE_(ddraw_geom)("\n");
1404 ERR(" matrix weighting not handled yet....\n");
1409 /* Whatever the case, disable the color material stuff */
1410 glDisable(GL_COLOR_MATERIAL);
1415 LeaveCriticalSection(&(This->crit));
1419 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1420 D3DPRIMITIVETYPE d3dptPrimitiveType,
1421 DWORD d3dvtVertexType,
1423 DWORD dwVertexCount,
1426 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1427 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1429 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1430 if (TRACE_ON(ddraw)) {
1431 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1434 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1435 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1441 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1442 D3DPRIMITIVETYPE d3dptPrimitiveType,
1443 DWORD d3dvtVertexType,
1445 DWORD dwVertexCount,
1450 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1451 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1453 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1454 if (TRACE_ON(ddraw)) {
1455 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1458 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1459 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1465 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1466 D3DPRIMITIVETYPE d3dptPrimitiveType,
1468 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1469 DWORD dwVertexCount,
1472 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1474 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1475 if (TRACE_ON(ddraw)) {
1476 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1478 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1484 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1485 D3DPRIMITIVETYPE d3dptPrimitiveType,
1487 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1488 DWORD dwVertexCount,
1493 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1495 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1496 if (TRACE_ON(ddraw)) {
1497 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1500 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1506 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1507 D3DPRIMITIVETYPE d3dptPrimitiveType,
1508 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1509 DWORD dwStartVertex,
1510 DWORD dwNumVertices,
1513 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1514 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1515 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1517 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1518 if (TRACE_ON(ddraw)) {
1519 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1522 if (vb_impl->processed == TRUE) {
1523 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1524 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1526 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1527 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1528 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1530 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1531 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1534 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1535 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1542 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1543 D3DPRIMITIVETYPE d3dptPrimitiveType,
1544 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1545 DWORD dwStartVertex,
1546 DWORD dwNumVertices,
1551 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1552 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1553 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1555 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1556 if (TRACE_ON(ddraw)) {
1557 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1560 if (vb_impl->processed == TRUE) {
1561 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1562 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1564 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1565 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1566 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1568 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1569 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1572 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1573 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1579 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1581 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1583 BOOLEAN is_complement = FALSE;
1584 BOOLEAN is_alpha_replicate = FALSE;
1585 BOOLEAN handled = TRUE;
1587 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1591 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1592 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1597 if (tex_op == D3DTOP_SELECTARG2) {
1601 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1602 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1607 if (tex_op == D3DTOP_SELECTARG2) {
1612 if (dwState & D3DTA_COMPLEMENT) {
1613 is_complement = TRUE;
1615 if (dwState & D3DTA_ALPHAREPLICATE) {
1616 is_alpha_replicate = TRUE;
1618 dwState &= D3DTA_SELECTMASK;
1619 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1620 dwState = D3DTA_DIFFUSE;
1624 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1625 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1626 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1627 case D3DTA_TFACTOR: {
1628 /* Get the constant value from the current rendering state */
1630 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1632 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1633 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1634 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1635 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1636 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1638 src = GL_CONSTANT_EXT;
1640 default: src = GL_TEXTURE; handled = FALSE; break;
1644 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1645 if (is_alpha_replicate) {
1646 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1648 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1651 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1652 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1659 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1661 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1664 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1665 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1669 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1671 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1673 switch (d3dTexStageStateType) {
1674 #define GEN_CASE(a) case a: type = #a; break
1675 GEN_CASE(D3DTSS_COLOROP);
1676 GEN_CASE(D3DTSS_COLORARG1);
1677 GEN_CASE(D3DTSS_COLORARG2);
1678 GEN_CASE(D3DTSS_ALPHAOP);
1679 GEN_CASE(D3DTSS_ALPHAARG1);
1680 GEN_CASE(D3DTSS_ALPHAARG2);
1681 GEN_CASE(D3DTSS_BUMPENVMAT00);
1682 GEN_CASE(D3DTSS_BUMPENVMAT01);
1683 GEN_CASE(D3DTSS_BUMPENVMAT10);
1684 GEN_CASE(D3DTSS_BUMPENVMAT11);
1685 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1686 GEN_CASE(D3DTSS_ADDRESS);
1687 GEN_CASE(D3DTSS_ADDRESSU);
1688 GEN_CASE(D3DTSS_ADDRESSV);
1689 GEN_CASE(D3DTSS_BORDERCOLOR);
1690 GEN_CASE(D3DTSS_MAGFILTER);
1691 GEN_CASE(D3DTSS_MINFILTER);
1692 GEN_CASE(D3DTSS_MIPFILTER);
1693 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1694 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1695 GEN_CASE(D3DTSS_MAXANISOTROPY);
1696 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1697 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1698 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1700 default: type = "UNKNOWN";
1703 /* Store the values in the state array */
1704 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1705 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1706 /* Some special cases when one state modifies more than one... */
1707 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1708 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1709 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1714 switch (d3dTexStageStateType) {
1715 case D3DTSS_MINFILTER:
1716 case D3DTSS_MIPFILTER:
1717 if (TRACE_ON(ddraw)) {
1718 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1719 switch ((D3DTEXTUREMINFILTER) dwState) {
1720 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1721 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1722 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1725 switch ((D3DTEXTUREMIPFILTER) dwState) {
1726 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1727 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1728 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1729 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1735 case D3DTSS_MAGFILTER:
1736 if (TRACE_ON(ddraw)) {
1737 switch ((D3DTEXTUREMAGFILTER) dwState) {
1738 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1739 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1740 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1745 case D3DTSS_ADDRESS:
1746 case D3DTSS_ADDRESSU:
1747 case D3DTSS_ADDRESSV: {
1748 switch ((D3DTEXTUREADDRESS) dwState) {
1749 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1750 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1751 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1752 #if defined(GL_VERSION_1_4)
1753 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1754 #elif defined(GL_ARB_texture_mirrored_repeat)
1755 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1757 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1761 case D3DTSS_ALPHAOP:
1762 case D3DTSS_COLOROP: {
1764 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1769 #define GEN_CASE(a) case a: value = #a; break
1770 GEN_CASE(D3DTOP_DISABLE);
1771 GEN_CASE(D3DTOP_SELECTARG1);
1772 GEN_CASE(D3DTOP_SELECTARG2);
1773 GEN_CASE(D3DTOP_MODULATE);
1774 GEN_CASE(D3DTOP_MODULATE2X);
1775 GEN_CASE(D3DTOP_MODULATE4X);
1776 GEN_CASE(D3DTOP_ADD);
1777 GEN_CASE(D3DTOP_ADDSIGNED);
1778 GEN_CASE(D3DTOP_ADDSIGNED2X);
1779 GEN_CASE(D3DTOP_SUBTRACT);
1780 GEN_CASE(D3DTOP_ADDSMOOTH);
1781 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1782 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1783 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1784 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1785 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1786 GEN_CASE(D3DTOP_PREMODULATE);
1787 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1788 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1789 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1790 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1791 GEN_CASE(D3DTOP_BUMPENVMAP);
1792 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1793 GEN_CASE(D3DTOP_DOTPRODUCT3);
1794 GEN_CASE(D3DTOP_FORCE_DWORD);
1796 default: value = "UNKNOWN";
1799 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1800 glDisable(GL_TEXTURE_2D);
1801 TRACE(" disabling 2D texturing.\n");
1803 /* Re-enable texturing */
1804 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1805 glEnable(GL_TEXTURE_2D);
1806 TRACE(" enabling 2D texturing.\n");
1809 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1810 if (dwState != D3DTOP_DISABLE) {
1811 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1812 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1813 glThis->current_tex_env = GL_COMBINE_EXT;
1817 /* Now set up the operand correctly */
1819 case D3DTOP_DISABLE:
1820 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1821 and it works, so ignore this op */
1822 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1825 case D3DTOP_SELECTARG1:
1826 case D3DTOP_SELECTARG2:
1827 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1830 case D3DTOP_MODULATE4X:
1831 scale = scale * 2; /* Drop through */
1832 case D3DTOP_MODULATE2X:
1833 scale = scale * 2; /* Drop through */
1834 case D3DTOP_MODULATE:
1835 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1839 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1842 case D3DTOP_ADDSIGNED2X:
1843 scale = scale * 2; /* Drop through */
1844 case D3DTOP_ADDSIGNED:
1845 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1848 /* For the four blending modes, use the Arg2 parameter */
1849 case D3DTOP_BLENDDIFFUSEALPHA:
1850 case D3DTOP_BLENDTEXTUREALPHA:
1851 case D3DTOP_BLENDFACTORALPHA:
1852 case D3DTOP_BLENDCURRENTALPHA: {
1853 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1856 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1857 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1858 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1859 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1862 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1863 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1864 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1865 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1866 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1875 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1876 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1877 /* Switch the arguments if needed... */
1878 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1879 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1880 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1882 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1883 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1886 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1887 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1889 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1890 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1896 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1897 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1899 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1901 TRACE(" Stage type is : %s => %s\n", type, value);
1903 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1907 case D3DTSS_COLORARG1:
1908 case D3DTSS_COLORARG2:
1909 case D3DTSS_ALPHAARG1:
1910 case D3DTSS_ALPHAARG2: {
1911 const char *value, *value_comp = "", *value_alpha = "";
1913 D3DTEXTUREOP tex_op;
1915 switch (dwState & D3DTA_SELECTMASK) {
1916 #define GEN_CASE(a) case a: value = #a; break
1917 GEN_CASE(D3DTA_DIFFUSE);
1918 GEN_CASE(D3DTA_CURRENT);
1919 GEN_CASE(D3DTA_TEXTURE);
1920 GEN_CASE(D3DTA_TFACTOR);
1921 GEN_CASE(D3DTA_SPECULAR);
1923 default: value = "UNKNOWN";
1925 if (dwState & D3DTA_COMPLEMENT) {
1926 value_comp = " | D3DTA_COMPLEMENT";
1928 if (dwState & D3DTA_ALPHAREPLICATE) {
1929 value_alpha = " | D3DTA_ALPHAREPLICATE";
1932 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1933 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1935 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1938 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1941 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1943 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1947 case D3DTSS_MIPMAPLODBIAS: {
1948 D3DVALUE value = *((D3DVALUE *) &dwState);
1949 BOOLEAN handled = TRUE;
1955 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1957 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1961 case D3DTSS_MAXMIPLEVEL:
1962 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1965 case D3DTSS_BORDERCOLOR:
1966 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1967 ((dwState >> 16) & 0xFF),
1968 ((dwState >> 8) & 0xFF),
1969 ((dwState >> 0) & 0xFF),
1970 ((dwState >> 24) & 0xFF));
1973 case D3DTSS_TEXCOORDINDEX: {
1974 BOOLEAN handled = TRUE;
1977 switch (dwState & 0xFFFF0000) {
1978 #define GEN_CASE(a) case a: value = #a; break
1979 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1980 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1981 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1982 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1984 default: value = "UNKNOWN";
1986 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1990 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1992 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1996 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1997 const char *projected = "", *value;
1998 BOOLEAN handled = TRUE;
1999 switch (dwState & 0xFF) {
2000 #define GEN_CASE(a) case a: value = #a; break
2001 GEN_CASE(D3DTTFF_DISABLE);
2002 GEN_CASE(D3DTTFF_COUNT1);
2003 GEN_CASE(D3DTTFF_COUNT2);
2004 GEN_CASE(D3DTTFF_COUNT3);
2005 GEN_CASE(D3DTTFF_COUNT4);
2007 default: value = "UNKNOWN";
2009 if (dwState & D3DTTFF_PROJECTED) {
2010 projected = " | D3DTTFF_PROJECTED";
2014 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2015 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2018 if (handled == TRUE) {
2019 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2021 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2026 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2036 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2038 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2041 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2042 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2044 /* First check if we need to bind any other texture for this stage */
2045 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2046 if (This->current_texture[stage] == NULL) {
2047 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2048 glBindTexture(GL_TEXTURE_2D, 0);
2049 glDisable(GL_TEXTURE_2D);
2051 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2053 if (glThis->current_bound_texture[stage] == NULL) {
2054 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2055 TRACE(" enabling 2D texturing and");
2056 glEnable(GL_TEXTURE_2D);
2059 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2060 glBindTexture(GL_TEXTURE_2D, tex_name);
2063 glThis->current_bound_texture[stage] = This->current_texture[stage];
2065 if (glThis->current_bound_texture[stage] == NULL) {
2066 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2068 TRACE(" using already bound texture id %d for stage %ld.\n",
2069 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2073 /* If no texure valid for this stage, go out of the loop */
2074 if (This->current_texture[stage] == NULL) break;
2076 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2077 This will also update the various texture parameters if needed.
2079 gltex_upload_texture(surf_ptr, This, stage);
2086 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2088 LPDIRECTDRAWSURFACE7 lpTexture2)
2090 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2092 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2094 if (dwStage > 0) return DD_OK;
2096 if (This->current_texture[dwStage] != NULL) {
2097 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2100 if (lpTexture2 == NULL) {
2101 This->current_texture[dwStage] = NULL;
2103 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2104 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2105 This->current_texture[dwStage] = tex_impl;
2112 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2113 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2115 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2116 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2118 fill_opengl_caps_7(lpD3DHELDevDesc);
2120 TRACE(" returning caps : no dump function yet.\n");
2126 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2127 LPD3DMATERIAL7 lpMat)
2129 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2130 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2132 if (TRACE_ON(ddraw)) {
2133 TRACE(" material is : \n");
2134 dump_D3DMATERIAL7(lpMat);
2137 This->current_material = *lpMat;
2140 glMaterialfv(GL_FRONT_AND_BACK,
2142 (float *) &(This->current_material.u.diffuse));
2143 glMaterialfv(GL_FRONT_AND_BACK,
2145 (float *) &(This->current_material.u1.ambient));
2146 glMaterialfv(GL_FRONT_AND_BACK,
2148 (float *) &(This->current_material.u2.specular));
2149 glMaterialfv(GL_FRONT_AND_BACK,
2151 (float *) &(This->current_material.u3.emissive));
2152 glMaterialf(GL_FRONT_AND_BACK,
2154 This->current_material.u4.power); /* Not sure about this... */
2162 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2164 LPD3DLIGHT7 lpLight)
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2167 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2168 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2170 if (TRACE_ON(ddraw)) {
2171 TRACE(" setting light : \n");
2172 dump_D3DLIGHT7(lpLight);
2175 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2176 This->set_lights |= 0x00000001 << dwLightIndex;
2177 This->light_parameters[dwLightIndex] = *lpLight;
2179 /* Some checks to print out nice warnings :-) */
2180 switch (lpLight->dltType) {
2181 case D3DLIGHT_DIRECTIONAL:
2182 case D3DLIGHT_POINT:
2183 /* These are handled properly... */
2187 if ((lpLight->dvTheta != 0.0) ||
2188 (lpLight->dvTheta != lpLight->dvPhi)) {
2189 ERR("dvTheta not fully supported yet !\n");
2194 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2197 /* This will force the Light setting on next drawing of primitives */
2198 glThis->transform_state = GL_TRANSFORM_NONE;
2204 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2208 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2209 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2211 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2215 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2216 /* Set the default parameters.. */
2217 TRACE(" setting default light parameters...\n");
2218 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2220 glEnable(GL_LIGHT0 + dwLightIndex);
2221 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2222 /* This light gets active... Need to update its parameters to GL before the next drawing */
2223 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2225 This->active_lights |= 0x00000001 << dwLightIndex;
2226 glThis->transform_state = GL_TRANSFORM_NONE;
2229 glDisable(GL_LIGHT0 + dwLightIndex);
2230 This->active_lights &= ~(0x00000001 << dwLightIndex);
2238 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2240 ICOM_THIS(IDirect3DDeviceImpl,iface);
2241 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2243 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2245 if (dwIndex >= This->max_clipping_planes) {
2246 return DDERR_INVALIDPARAMS;
2249 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2251 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2253 /* This is to force the reset of the transformation matrices on the next drawing.
2254 * This is needed to use the correct matrices for the various clipping planes.
2256 glThis->transform_state = GL_TRANSFORM_NONE;
2262 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2263 LPD3DVIEWPORT7 lpData)
2265 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2266 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2268 if (TRACE_ON(ddraw)) {
2269 TRACE(" viewport is : \n");
2270 TRACE(" - dwX = %ld dwY = %ld\n",
2271 lpData->dwX, lpData->dwY);
2272 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2273 lpData->dwWidth, lpData->dwHeight);
2274 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2275 lpData->dvMinZ, lpData->dvMaxZ);
2279 /* Set the viewport */
2280 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2281 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2282 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2284 if ((lpData->dwX != This->active_viewport.dwX) ||
2285 (lpData->dwY != This->active_viewport.dwY) ||
2286 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2287 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2288 glViewport(lpData->dwX,
2289 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2290 lpData->dwWidth, lpData->dwHeight);
2295 This->active_viewport = *lpData;
2300 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2301 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2303 # define XCAST(fun) (void*)
2306 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2308 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2309 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2310 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2311 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2312 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2313 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2314 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2315 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2316 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2317 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2318 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2319 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2320 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2321 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2322 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2323 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2324 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2325 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2326 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2327 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2328 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2329 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2330 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2331 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2332 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2333 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2334 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2335 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2336 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2337 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2338 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2339 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2340 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2341 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2342 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2343 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2344 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2345 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2346 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2347 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2348 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2349 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2350 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2351 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2352 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2353 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2354 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2355 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2356 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2357 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2360 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2365 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2366 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2368 # define XCAST(fun) (void*)
2371 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2373 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2374 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2375 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2376 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2377 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2378 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2379 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2380 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2381 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2382 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2383 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2384 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2385 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2386 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2387 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2388 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2389 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2390 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2391 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2392 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2393 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2394 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2395 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2396 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2397 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2398 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2399 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2400 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2401 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2402 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2403 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2404 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2405 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2406 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2407 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2408 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2409 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2410 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2411 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2412 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2413 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2414 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2415 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2418 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2423 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2424 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2426 # define XCAST(fun) (void*)
2429 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2431 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2432 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2433 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2434 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2435 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2436 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2437 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2438 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2439 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2440 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2441 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2442 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2443 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2444 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2445 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2446 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2447 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2448 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2449 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2450 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2451 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2452 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2453 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2454 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2455 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2456 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2457 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2458 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2459 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2460 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2461 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2462 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2463 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2464 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2467 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2472 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2473 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2475 # define XCAST(fun) (void*)
2478 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2480 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2481 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2482 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2483 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2484 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2485 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2486 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2487 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2488 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2489 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2490 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2491 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2492 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2493 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2494 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2495 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2496 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2497 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2498 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2499 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2500 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2501 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2502 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2505 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2509 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2510 WINE_GL_BUFFER_TYPE buffer_type,
2518 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2519 GLbitfield bitfield = 0;
2523 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2524 if (TRACE_ON(ddraw)) {
2527 TRACE(" rectangles : \n");
2528 for (i = 0; i < dwCount; i++) {
2529 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2538 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2539 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2543 /* Clears the screen */
2546 if (dwFlags & D3DCLEAR_TARGET) {
2547 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2548 /* TODO: optimize here the case where Clear changes all the screen... */
2549 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2551 glThis->state[buffer_type] = SURFACE_GL;
2554 if (dwFlags & D3DCLEAR_ZBUFFER) {
2555 bitfield |= GL_DEPTH_BUFFER_BIT;
2556 if (glThis->depth_mask == FALSE) {
2557 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2559 if (dvZ != glThis->prev_clear_Z) {
2561 glThis->prev_clear_Z = dvZ;
2563 TRACE(" depth value : %f\n", dvZ);
2565 if (dwFlags & D3DCLEAR_STENCIL) {
2566 bitfield |= GL_STENCIL_BUFFER_BIT;
2567 if (dwStencil != glThis->prev_clear_stencil) {
2568 glClearStencil(dwStencil);
2569 glThis->prev_clear_stencil = dwStencil;
2571 TRACE(" stencil value : %ld\n", dwStencil);
2573 if (dwFlags & D3DCLEAR_TARGET) {
2574 bitfield |= GL_COLOR_BUFFER_BIT;
2575 if (dwColor != glThis->prev_clear_color) {
2576 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2577 ((dwColor >> 8) & 0xFF) / 255.0,
2578 ((dwColor >> 0) & 0xFF) / 255.0,
2579 ((dwColor >> 24) & 0xFF) / 255.0);
2580 glThis->prev_clear_color = dwColor;
2582 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2585 glEnable(GL_SCISSOR_TEST);
2586 for (i = 0; i < dwCount; i++) {
2587 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2588 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2591 glDisable(GL_SCISSOR_TEST);
2593 if (dwFlags & D3DCLEAR_ZBUFFER) {
2594 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2602 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2610 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2614 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2615 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2617 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2618 WINE_GL_BUFFER_TYPE buffer_type;
2620 /* First check if we BLT to the backbuffer... */
2621 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2622 buffer_type = WINE_GL_BUFFER_BACK;
2623 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2624 buffer_type = WINE_GL_BUFFER_FRONT;
2626 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2627 return DDERR_INVALIDPARAMS;
2630 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2631 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2632 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2633 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2634 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2635 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2638 return DDERR_INVALIDPARAMS;
2640 *buffer_type_p = buffer_type;
2646 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2647 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2648 DWORD dwFlags, LPDDBLTFX lpbltfx)
2650 WINE_GL_BUFFER_TYPE buffer_type;
2654 rect.u1.x1 = rdst->left;
2655 rect.u2.y1 = rdst->top;
2656 rect.u3.x2 = rdst->right;
2657 rect.u4.y2 = rdst->bottom;
2661 rect.u3.x2 = This->surface_desc.dwWidth;
2662 rect.u4.y2 = This->surface_desc.dwHeight;
2665 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2667 if (dwFlags & DDBLT_COLORFILL) {
2668 /* This is easy to handle for the D3D Device... */
2672 /* The color as given in the Blt function is in the format of the frame-buffer...
2673 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2675 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2676 if (This->palette) {
2677 color = ((0xFF000000) |
2678 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2679 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2680 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2684 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2685 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2686 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2687 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2688 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2689 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2690 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2691 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2694 color = ((0xFF000000) |
2695 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2696 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2697 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2699 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2700 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2701 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2702 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2703 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2704 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2706 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2707 return DDERR_INVALIDPARAMS;
2710 ERR("Wrong surface type for BLT override !\n");
2711 return DDERR_INVALIDPARAMS;
2714 TRACE(" executing D3D Device override.\n");
2718 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2719 if (buffer_type == WINE_GL_BUFFER_FRONT)
2720 glDrawBuffer(GL_FRONT);
2722 glDrawBuffer(GL_BACK);
2724 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2726 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2727 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2728 glDrawBuffer(prev_draw);
2733 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2734 /* Normal blit without any special case... */
2736 /* And which has a SRC surface */
2737 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2739 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2740 (src_impl->d3ddevice == This->d3ddevice) &&
2741 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2742 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2746 WINE_GL_BUFFER_TYPE src_buffer_type;
2747 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2753 src_rect.u1.x1 = rsrc->left;
2754 src_rect.u2.y1 = rsrc->top;
2755 src_rect.u3.x2 = rsrc->right;
2756 src_rect.u4.y2 = rsrc->bottom;
2760 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2761 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2764 width = src_rect.u3.x2 - src_rect.u1.x1;
2765 height = src_rect.u4.y2 - src_rect.u2.y1;
2767 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2768 (height != (rect.u4.y2 - rect.u2.y1))) {
2769 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2770 return DDERR_INVALIDPARAMS;
2773 /* First check if we BLT from the backbuffer... */
2774 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2775 src_buffer_type = WINE_GL_BUFFER_BACK;
2776 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2777 src_buffer_type = WINE_GL_BUFFER_FRONT;
2779 ERR("Unexpected case in direct buffer to buffer copy !\n");
2780 return DDERR_INVALIDPARAMS;
2783 TRACE(" using direct buffer to buffer copy.\n");
2787 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2789 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2790 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2791 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2793 return DDERR_INVALIDPARAMS;
2796 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2797 if (buffer_type == WINE_GL_BUFFER_FRONT)
2798 glDrawBuffer(GL_FRONT);
2800 glDrawBuffer(GL_BACK);
2802 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2803 glReadBuffer(GL_FRONT);
2805 glReadBuffer(GL_BACK);
2807 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2808 And directly re-draws this on the destination buffer. */
2809 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2812 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2813 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2815 get_height = UNLOCK_TEX_SIZE;
2817 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2820 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2821 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2823 get_width = UNLOCK_TEX_SIZE;
2825 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2826 0, UNLOCK_TEX_SIZE - get_height,
2827 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2828 get_width, get_height);
2831 glTexCoord2f(0.0, 0.0);
2832 glVertex3d(rect.u1.x1 + x,
2833 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2835 glTexCoord2f(1.0, 0.0);
2836 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2837 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2839 glTexCoord2f(1.0, 1.0);
2840 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2843 glTexCoord2f(0.0, 1.0);
2844 glVertex3d(rect.u1.x1 + x,
2851 upload_surface_to_tex_memory_release();
2852 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2854 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2855 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2856 glDrawBuffer(prev_draw);
2862 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
2863 (this prevents calling glReadPixels) */
2867 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2871 double x_stretch, y_stretch;
2874 src_rect.u1.x1 = rsrc->left;
2875 src_rect.u2.y1 = rsrc->top;
2876 src_rect.u3.x2 = rsrc->right;
2877 src_rect.u4.y2 = rsrc->bottom;
2881 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2882 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2885 width = src_rect.u3.x2 - src_rect.u1.x1;
2886 height = src_rect.u4.y2 - src_rect.u2.y1;
2888 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
2889 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
2891 TRACE(" using memory to buffer Blt overide.\n");
2895 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
2897 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
2898 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2899 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
2901 return DDERR_INVALIDPARAMS;
2904 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2905 if (buffer_type == WINE_GL_BUFFER_FRONT)
2906 glDrawBuffer(GL_FRONT);
2908 glDrawBuffer(GL_BACK);
2910 /* Now the serious stuff happens. This is basically the same code that for the memory
2911 flush to frame buffer ... with stretching and different rectangles added :-) */
2912 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2915 flush_rect.top = src_rect.u2.y1 + y;
2916 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
2918 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
2920 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2921 flush_rect.left = src_rect.u1.x1 + x;
2922 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
2924 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
2926 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
2929 glTexCoord2f(0.0, 0.0);
2930 glVertex3d(rect.u1.x1 + (x * x_stretch),
2931 rect.u2.y1 + (y * y_stretch),
2933 glTexCoord2f(1.0, 0.0);
2934 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
2935 rect.u2.y1 + (y * y_stretch),
2937 glTexCoord2f(1.0, 1.0);
2938 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
2939 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
2941 glTexCoord2f(0.0, 1.0);
2942 glVertex3d(rect.u1.x1 + (x * x_stretch),
2943 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
2949 upload_surface_to_tex_memory_release();
2950 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
2952 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2953 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2954 glDrawBuffer(prev_draw);
2962 return DDERR_INVALIDPARAMS;
2966 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2967 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2968 LPRECT rsrc, DWORD trans)
2972 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2973 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2974 WINE_GL_BUFFER_TYPE buffer_type;
2978 int width, height, x, y;
2980 /* Cannot support DSTCOLORKEY blitting... */
2981 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
2984 WARN("rsrc is NULL - getting the whole surface !!\n");
2986 rsrc->left = rsrc->top = 0;
2987 rsrc->right = src_impl->surface_desc.dwWidth;
2988 rsrc->bottom = src_impl->surface_desc.dwHeight;
2996 rdst.right = dstx + (rsrc->right - rsrc->left);
2997 if (rdst.right > This->surface_desc.dwWidth) {
2998 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
2999 rdst.right = This->surface_desc.dwWidth;
3001 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3002 if (rdst.bottom > This->surface_desc.dwHeight) {
3003 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3004 rdst.bottom = This->surface_desc.dwHeight;
3007 width = rsrc->right - rsrc->left;
3008 height = rsrc->bottom - rsrc->top;
3010 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3012 TRACE(" using BltFast memory to frame buffer overide.\n");
3016 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3018 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3019 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3020 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3021 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3023 return DDERR_INVALIDPARAMS;
3026 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3027 if (buffer_type == WINE_GL_BUFFER_FRONT)
3028 glDrawBuffer(GL_FRONT);
3030 glDrawBuffer(GL_BACK);
3032 /* Now the serious stuff happens. This is basically the same code that for the memory
3033 flush to frame buffer but with different rectangles for source and destination :-) */
3034 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3037 flush_rect.top = rsrc->top + y;
3038 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3040 (rsrc->top + y + UNLOCK_TEX_SIZE));
3042 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3043 flush_rect.left = rsrc->left + x;
3044 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3046 (rsrc->left + x + UNLOCK_TEX_SIZE));
3048 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3051 glTexCoord2f(0.0, 0.0);
3052 glVertex3d(rdst.left + x,
3055 glTexCoord2f(1.0, 0.0);
3056 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3059 glTexCoord2f(1.0, 1.0);
3060 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3061 rdst.top + (y + UNLOCK_TEX_SIZE),
3063 glTexCoord2f(0.0, 1.0);
3064 glVertex3d(rdst.left + x,
3065 rdst.top + (y + UNLOCK_TEX_SIZE),
3071 upload_surface_to_tex_memory_release();
3072 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3074 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3075 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3076 glDrawBuffer(prev_draw);
3084 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3086 GLfloat height, width;
3087 GLfloat trans_mat[16];
3089 TRACE("(%p)\n", This);
3091 width = This->surface->surface_desc.dwWidth;
3092 height = This->surface->surface_desc.dwHeight;
3094 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3095 to OpenGL screen coordinates (ie the upper left corner is not the same).
3096 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3097 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3098 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3099 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3100 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
3101 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3104 glMatrixMode(GL_MODELVIEW);
3106 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3107 Correctness Tips section).
3109 Basically, from what I understood, if the game does not filter the font texture,
3110 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3111 one and we will have strange artifacts (as the rounding and stuff may give different results
3112 for different pixels, ie sometimes take the left pixel, sometimes the right).
3114 glTranslatef(0.375, 0.375, 0);
3115 glMatrixMode(GL_PROJECTION);
3116 glLoadMatrixf(trans_mat);
3121 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3122 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3124 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3127 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3128 glMatrixMode(GL_MODELVIEW);
3129 glLoadMatrixf((float *) view_mat);
3131 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3132 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3135 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3136 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3139 plane[0] = This->clipping_planes[i].plane[0];
3140 plane[1] = This->clipping_planes[i].plane[1];
3141 plane[2] = This->clipping_planes[i].plane[2];
3142 plane[3] = This->clipping_planes[i].plane[3];
3144 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3148 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3152 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3153 if (runner & This->active_lights) {
3154 switch (This->light_parameters[i].dltType) {
3155 case D3DLIGHT_DIRECTIONAL: {
3157 float cut_off = 180.0;
3159 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3160 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3161 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3162 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3164 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3165 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3166 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3168 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3171 case D3DLIGHT_POINT: {
3173 float cut_off = 180.0;
3175 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3176 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3177 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3178 position[0] = This->light_parameters[i].dvPosition.u1.x;
3179 position[1] = This->light_parameters[i].dvPosition.u2.y;
3180 position[2] = This->light_parameters[i].dvPosition.u3.z;
3182 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3183 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3184 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3185 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3186 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3189 case D3DLIGHT_SPOT: {
3192 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3194 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3195 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3196 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3198 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3199 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3200 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3202 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3203 position[0] = This->light_parameters[i].dvPosition.u1.x;
3204 position[1] = This->light_parameters[i].dvPosition.u2.y;
3205 position[2] = This->light_parameters[i].dvPosition.u3.z;
3207 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3208 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3209 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3210 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3211 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3212 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3216 /* No warning here as it's already done at light setting */
3223 glMultMatrixf((float *) world_mat);
3225 if ((matrices & PROJMAT_CHANGED) != 0) {
3226 glMatrixMode(GL_PROJECTION);
3227 glLoadMatrixf((float *) proj_mat);
3233 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3235 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3236 DWORD tex_mat, tex_stage;
3238 TRACE("(%p,%08lx)\n", This, matrices);
3240 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3241 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3242 /* This will force an update of the transform state at the next drawing. */
3243 glThis->transform_state = GL_TRANSFORM_NONE;
3246 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3247 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3250 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3251 if (matrices & tex_mat) {
3252 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3253 if (tex_stage == 0) {
3254 /* No multi-texturing support for now ... */
3255 glMatrixMode(GL_TEXTURE);
3256 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3257 if (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE))) {
3258 This->tex_mat_is_identity[tex_stage] = FALSE;
3260 This->tex_mat_is_identity[tex_stage] = TRUE;
3264 if (tex_stage == 0) {
3265 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3266 glMatrixMode(GL_TEXTURE);
3268 This->tex_mat_is_identity[tex_stage] = TRUE;
3278 /* TODO for both these functions :
3279 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3280 by other OpenGL code in D3D
3281 - handle the case where no 'Begin / EndScene' was done between two locks
3282 - handle the rectangles in the unlock too
3283 - handle pitch correctly...
3285 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3287 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3288 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3289 WINE_GL_BUFFER_TYPE buffer_type;
3292 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3293 buffer_type = WINE_GL_BUFFER_FRONT;
3294 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3295 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3296 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3298 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3299 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3300 buffer_type = WINE_GL_BUFFER_BACK;
3301 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3302 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3303 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3305 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3307 ERR("Wrong surface type for locking !\n");
3311 if (pRect == NULL) {
3314 loc_rect.bottom = This->surface_desc.dwHeight;
3315 loc_rect.right = This->surface_desc.dwWidth;
3319 /* Try to acquire the device critical section */
3320 EnterCriticalSection(&(d3d_dev->crit));
3322 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3323 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3324 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3326 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3328 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3329 /* Check if the new rectangle is in the previous one or not.
3330 If it is not, flush first the previous locks on screen.
3332 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3333 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3334 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3335 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3336 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3337 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3338 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3339 pRect->left, pRect->top, pRect->right, pRect->bottom,
3340 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3341 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3342 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3344 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3345 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3347 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3349 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3352 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3353 /* If the surface is already in memory, no need to do anything here... */
3354 GLenum buffer_format;
3355 GLenum buffer_color;
3359 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3360 pRect->left, pRect->top, pRect->right, pRect->bottom);
3362 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3363 may only write to the device... But when we will blit it back to the screen, we need
3364 also to blit correctly the parts the application did not overwrite... */
3366 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3367 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3368 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3369 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3370 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3371 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3372 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3373 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3374 buffer_color = GL_RGB;
3375 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3376 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3377 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3378 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3379 buffer_format = GL_UNSIGNED_BYTE;
3380 buffer_color = GL_RGB;
3381 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3382 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3383 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3384 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3385 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3386 buffer_color = GL_BGRA;
3388 ERR(" unsupported pixel format at device locking.\n");
3392 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3398 if (buffer_type == WINE_GL_BUFFER_FRONT)
3399 /* Application wants to lock the front buffer */
3400 glReadBuffer(GL_FRONT);
3402 /* Application wants to lock the back buffer */
3403 glReadBuffer(GL_BACK);
3405 dst = ((char *)This->surface_desc.lpSurface) +
3406 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3407 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3408 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3410 glReadPixels(pRect->left, y,
3411 pRect->right - pRect->left, 1,
3412 buffer_color, buffer_format, dst);
3413 dst += This->surface_desc.u1.lPitch;
3416 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3419 /* I keep this code here as it's very useful to debug :-) */
3421 static int flush_count = 0;
3425 if ((++flush_count % 50) == 0) {
3426 sprintf(buf, "lock_%06d.pnm", flush_count);
3427 f = fopen(buf, "wb");
3428 DDRAW_dump_surface_to_disk(This, f);
3437 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3439 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3444 /* Note : no need here to lock the 'device critical section' as we are already protected by
3445 the GL critical section. */
3447 if (pRect == NULL) {
3450 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3451 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3455 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3457 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3459 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3460 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3461 ERR(" unsupported pixel format at frame buffer flush.\n");
3465 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3469 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3471 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3472 /* First, upload the texture... */
3473 flush_rect.left = x;
3474 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3476 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3479 glTexCoord2f(0.0, 0.0);
3480 glVertex3d(x, y, 0.5);
3481 glTexCoord2f(1.0, 0.0);
3482 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3483 glTexCoord2f(1.0, 1.0);
3484 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3485 glTexCoord2f(0.0, 1.0);
3486 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3491 upload_surface_to_tex_memory_release();
3492 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3495 /* I keep this code here as it's very useful to debug :-) */
3497 static int flush_count = 0;
3501 if ((++flush_count % 50) == 0) {
3502 sprintf(buf, "flush_%06d.pnm", flush_count);
3503 f = fopen(buf, "wb");
3504 DDRAW_dump_surface_to_disk(surf, f);
3510 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3512 WINE_GL_BUFFER_TYPE buffer_type;
3513 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3514 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3516 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3517 buffer_type = WINE_GL_BUFFER_FRONT;
3518 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3519 buffer_type = WINE_GL_BUFFER_BACK;
3521 ERR("Wrong surface type for locking !\n");
3525 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3526 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3527 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3529 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3531 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3532 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3533 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3536 TRACE(" flushing front buffer immediatly on screen.\n");
3539 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3540 glDrawBuffer(GL_FRONT);
3541 /* Note: we do not use the application provided lock rectangle but our own stored at
3542 lock time. This is because in old D3D versions, the 'lock' parameter did not
3545 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]);
3546 glDrawBuffer(prev_draw);
3549 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3553 /* And 'frees' the device critical section */
3554 LeaveCriticalSection(&(d3d_dev->crit));
3558 apply_texture_state(IDirect3DDeviceImpl *This)
3562 /* Initialize texture stages states */
3563 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3564 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3565 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3566 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3567 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3574 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3576 IDirect3DDeviceImpl *object;
3577 IDirect3DDeviceGLImpl *gl_object;
3578 IDirectDrawSurfaceImpl *surf;
3583 XVisualInfo template;
3584 GLenum buffer = GL_FRONT;
3587 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3588 if (object == NULL) return DDERR_OUTOFMEMORY;
3590 gl_object = (IDirect3DDeviceGLImpl *) object;
3594 object->surface = surface;
3595 object->set_context = set_context;
3596 object->clear = d3ddevice_clear_back;
3597 object->set_matrices = d3ddevice_set_matrices;
3598 object->matrices_updated = d3ddevice_matrices_updated;
3599 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3601 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3603 InitializeCriticalSection(&(object->crit));
3605 TRACE(" device critical section : %p\n", &(object->crit));
3607 device_context = GetDC(surface->ddraw_owner->window);
3608 gl_object->display = get_display(device_context);
3609 gl_object->drawable = get_drawable(device_context);
3610 ReleaseDC(surface->ddraw_owner->window,device_context);
3613 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3614 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3616 HeapFree(GetProcessHeap(), 0, object);
3617 ERR("No visual found !\n");
3619 return DDERR_INVALIDPARAMS;
3621 TRACE(" visual found\n");
3624 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3627 if (gl_object->gl_context == NULL) {
3628 HeapFree(GetProcessHeap(), 0, object);
3629 ERR("Error in context creation !\n");
3631 return DDERR_INVALIDPARAMS;
3633 TRACE(" context created (%p)\n", gl_object->gl_context);
3636 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3637 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3638 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3639 surf->aux_ctx = (LPVOID) object;
3640 surf->aux_data = (LPVOID) gl_object->drawable;
3641 surf->aux_flip = opengl_flip;
3646 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3648 TRACE(" no double buffering : drawing on the front buffer\n");
3652 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3653 IDirectDrawSurfaceImpl *surf2;
3654 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3655 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3656 TRACE(" checking surface %p :", surf2);
3657 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3658 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3659 /* Override the Lock / Unlock function for all these surfaces */
3660 surf2->lock_update_prev = surf2->lock_update;
3661 surf2->lock_update = d3ddevice_lock_update;
3662 surf2->unlock_update_prev = surf2->unlock_update;
3663 surf2->unlock_update = d3ddevice_unlock_update;
3664 /* And install also the blt / bltfast overrides */
3665 surf2->aux_blt = d3ddevice_blt;
3666 surf2->aux_bltfast = d3ddevice_bltfast;
3668 TRACE(" overiding direct surface access.\n");
3670 TRACE(" no overide.\n");
3672 surf2->d3ddevice = object;
3676 /* Set the various light parameters */
3677 for (light = 0; light < MAX_LIGHTS; light++) {
3678 /* Only set the fields that are not zero-created */
3679 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3680 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3681 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3682 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3683 object->light_parameters[light].dvDirection.u3.z = 1.0;
3686 /* Allocate memory for the matrices */
3687 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3688 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3689 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3690 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3691 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3692 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3693 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3694 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3695 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3696 object->tex_mat_is_identity[tex_num] = TRUE;
3699 /* Initialisation */
3700 TRACE(" setting current context\n");
3701 object->set_context(object);
3702 TRACE(" current context set\n");
3704 /* allocate the clipping planes */
3705 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3706 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3708 glHint(GL_FOG_HINT,GL_NICEST);
3710 /* Initialize the various GL contexts to be in sync with what we store locally */
3713 glClearColor(0.0, 0.0, 0.0, 0.0);
3714 glDepthMask(GL_TRUE);
3715 gl_object->depth_mask = TRUE;
3716 glEnable(GL_DEPTH_TEST);
3717 gl_object->depth_test = TRUE;
3718 glDisable(GL_ALPHA_TEST);
3719 glDisable(GL_STENCIL_TEST);
3720 glDisable(GL_CULL_FACE);
3721 glDisable(GL_LIGHTING);
3722 glDisable(GL_BLEND);
3724 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3725 gl_object->current_tex_env = GL_REPLACE;
3727 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3728 glDrawBuffer(buffer);
3729 glReadBuffer(buffer);
3730 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3733 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3734 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3736 /* fill_device_capabilities(d3d->ddraw); */
3738 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3739 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3740 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3741 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3745 TRACE(" creating implementation at %p.\n", *obj);
3747 /* And finally warn D3D that this device is now present */
3748 object->d3d->d3d_added_device(object->d3d, object);
3750 /* FIXME: Should handle other versions than just 7 */
3751 InitDefaultStateBlock(&object->state_block, 7);
3752 /* Apply default render state and texture stage state values */
3753 apply_render_state(object, &object->state_block);
3754 apply_texture_state(object);
3756 /* And fill the fog table with the default fog value */
3757 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3762 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3764 pc->dwSize = sizeof(*pc);
3765 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3766 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3767 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3768 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
3769 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3770 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3771 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3772 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3773 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3774 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3775 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3776 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3777 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3778 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3779 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3780 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3781 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3782 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3783 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3784 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3785 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3786 D3DPTFILTERCAPS_MIPFPOINT;
3787 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3788 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3789 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3790 pc->dwStippleWidth = 32;
3791 pc->dwStippleHeight = 32;
3794 static void fill_caps(void)
3796 GLint max_clip_planes;
3798 /* Fill first all the fields with default values which will be overriden later on with
3799 corrent one from the GL code
3801 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
3802 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
3803 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3804 /* D3D 7 capabilities */
3805 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
3806 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
3807 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
3808 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
3809 opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
3810 opengl_device_caps.dwMinTextureWidth = 1;
3811 opengl_device_caps.dwMinTextureHeight = 1;
3812 opengl_device_caps.dwMaxTextureWidth = 1024;
3813 opengl_device_caps.dwMaxTextureHeight = 1024;
3814 opengl_device_caps.dwMaxTextureRepeat = 16;
3815 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
3816 opengl_device_caps.dwMaxAnisotropy = 0;
3817 opengl_device_caps.dvGuardBandLeft = 0.0;
3818 opengl_device_caps.dvGuardBandRight = 0.0;
3819 opengl_device_caps.dvGuardBandTop = 0.0;
3820 opengl_device_caps.dvGuardBandBottom = 0.0;
3821 opengl_device_caps.dvExtentsAdjust = 0.0;
3822 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
3823 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
3824 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
3825 opengl_device_caps.dwTextureOpCaps = 0;
3826 opengl_device_caps.wMaxTextureBlendStages = 1;
3827 opengl_device_caps.wMaxSimultaneousTextures = 1;
3828 opengl_device_caps.dwMaxActiveLights = 16;
3829 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
3830 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
3831 opengl_device_caps.wMaxUserClipPlanes = 1;
3832 opengl_device_caps.wMaxVertexBlendMatrices = 0;
3833 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
3834 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
3835 opengl_device_caps.dwReserved1 = 0;
3836 opengl_device_caps.dwReserved2 = 0;
3837 opengl_device_caps.dwReserved3 = 0;
3838 opengl_device_caps.dwReserved4 = 0;
3840 /* And now some GL overides :-) */
3841 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
3842 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
3843 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
3844 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
3846 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
3847 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
3849 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
3850 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
3851 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
3855 d3ddevice_init_at_startup(void *gl_handle)
3857 XVisualInfo template;
3862 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
3863 XWindowAttributes win_attr;
3864 GLXContext gl_context;
3867 TRACE("Initializing GL...\n");
3869 /* Get a default rendering context to have the 'caps' function query some info from GL */
3870 device_context = GetDC(0);
3871 display = get_display(device_context);
3872 ReleaseDC(0, device_context);
3875 if (XGetWindowAttributes(display, drawable, &win_attr)) {
3876 visual = win_attr.visual;
3878 visual = DefaultVisual(display, DefaultScreen(display));
3880 template.visualid = XVisualIDFromVisual(visual);
3881 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
3884 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
3887 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
3889 if (gl_context == NULL) {
3891 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
3894 if (glXMakeCurrent(display, drawable, gl_context) == False) {
3895 glXDestroyContext(display, gl_context);
3897 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
3901 /* Then, query all extensions and fill our extension context. TODO :-) */
3903 /* Fill the D3D capabilities according to what GL tells us... */
3906 /* And frees this now-useless context */
3907 glXMakeCurrent(display, None, NULL);
3908 glXDestroyContext(display, gl_context);