2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/port.h"
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "wine/debug.h"
39 #include "wine/library.h"
41 #include "mesa_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
45 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
54 X11DRV_GET_FONT, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL = {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps;
74 GL_EXTENSIONS_LIST GL_extensions;
76 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
77 D3DPRIMITIVETYPE d3dptPrimitiveType,
78 DWORD d3dvtVertexType,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
85 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
87 /* retrieve the X display to use on a given DC */
88 inline static Display *get_display( HDC hdc )
91 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
93 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94 sizeof(display), (LPSTR)&display )) display = NULL;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
105 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
106 DWORD opt_bitmap = 0x00000000;
108 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
109 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
110 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
112 if (gl_d3d_dev->unlock_tex == 0) {
113 glGenTextures(1, &gl_d3d_dev->unlock_tex);
114 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
121 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
124 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
125 glMatrixMode(GL_TEXTURE);
129 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
130 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
131 d3ddevice_set_ortho(d3d_dev);
134 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
135 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
136 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
137 glEnable(GL_TEXTURE_2D);
138 if (gl_d3d_dev->current_bound_texture[1] != NULL) {
139 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
140 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
141 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
143 /* 'unbound' texture level 1 in that case to disable multi-texturing */
144 glBindTexture(GL_TEXTURE_2D, 0);
145 glDisable(GL_TEXTURE_2D);
147 glEnable(GL_SCISSOR_TEST);
148 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
149 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap |= DEPTH_RANGE_BIT;
153 if ((d3d_dev->active_viewport.dwX != 0) ||
154 (d3d_dev->active_viewport.dwY != 0) ||
155 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
156 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
157 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
158 opt_bitmap |= VIEWPORT_BIT;
160 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
161 pRect->right - pRect->left, pRect->bottom - pRect->top);
162 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
163 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
165 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
166 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
167 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
168 glAlphaFunc(GL_GREATER, 0.0);
171 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
173 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
174 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
175 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
176 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
177 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
182 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
183 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
185 /* And restore all the various states modified by this code */
186 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
187 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
188 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
189 glEnable(GL_ALPHA_TEST);
190 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
191 glDisable(GL_ALPHA_TEST);
193 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
194 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
195 glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
196 (d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
199 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
200 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
201 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
202 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
203 glDisable(GL_SCISSOR_TEST);
204 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
205 if (opt_bitmap & DEPTH_RANGE_BIT) {
206 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
208 if (opt_bitmap & VIEWPORT_BIT) {
209 glViewport(d3d_dev->active_viewport.dwX,
210 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
211 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
213 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
214 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
217 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
218 DrawPrimitive call, this will bind the correct texture to this stage. */
219 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
220 gl_d3d_dev->current_bound_texture[1] = (IDirectDrawSurfaceImpl *) 0x00000000;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
224 /* retrieve the X drawable to use on a given DC */
225 inline static Drawable get_drawable( HDC hdc )
228 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
230 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
231 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
236 /* This is unnecessarely complicated :-) */
237 #define MEASUREMENT_WINDOW 5
238 #define NUMBER_OF_WINDOWS 10
240 static LONGLONG perf_freq;
241 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
242 static LONGLONG prev_time = 0;
243 static unsigned int current_window;
244 static unsigned int measurements_in_window;
245 static unsigned int valid_windows;
247 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
249 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
250 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
252 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
254 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
255 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]);
257 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
258 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
259 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
262 if (TRACE_ON(ddraw_fps)) {
263 LONGLONG current_time;
264 LONGLONG frame_duration;
265 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
267 if (prev_time != 0) {
268 LONGLONG total_time = 0;
271 frame_duration = current_time - prev_time;
272 prev_time = current_time;
274 perf_storage[current_window] += frame_duration;
275 measurements_in_window++;
277 if (measurements_in_window >= MEASUREMENT_WINDOW) {
281 if (valid_windows < NUMBER_OF_WINDOWS) {
283 tot_meas = valid_windows * MEASUREMENT_WINDOW;
284 for (i = 0; i < valid_windows; i++) {
285 total_time += perf_storage[i];
289 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
290 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
291 total_time += perf_storage[i];
295 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
297 if (current_window >= NUMBER_OF_WINDOWS) {
300 perf_storage[current_window] = 0;
301 measurements_in_window = 0;
304 prev_time = current_time;
305 memset(perf_storage, 0, sizeof(perf_storage));
308 measurements_in_window = 0;
309 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
317 /*******************************************************************************
318 * OpenGL static functions
320 static void set_context(IDirect3DDeviceImpl* This)
322 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
324 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
326 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
327 ERR("Error in setting current context (context %p drawable %ld)!\n",
328 glThis->gl_context, glThis->drawable);
333 static void fill_opengl_caps(D3DDEVICEDESC *d1)
335 d1->dwSize = sizeof(*d1);
336 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
337 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
338 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
339 d1->dcmColorModel = D3DCOLOR_RGB;
340 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
341 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
342 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
343 d1->bClipping = TRUE;
344 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
345 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
346 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
347 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
348 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
349 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
350 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
351 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
352 d1->dwMaxBufferSize = 0;
353 d1->dwMaxVertexCount = 65536;
354 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
355 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
356 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
357 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
358 d1->dwMinStippleWidth = 1;
359 d1->dwMinStippleHeight = 1;
360 d1->dwMaxStippleWidth = 32;
361 d1->dwMaxStippleHeight = 32;
362 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
363 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
364 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
365 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
366 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
367 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
368 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
369 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
370 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
371 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
372 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
373 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
374 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
377 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
379 *d = opengl_device_caps;
382 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
384 D3DDEVICEDESC dref, d1, d2;
387 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
388 Let's put the string in a sufficiently sized array in writable memory. */
389 char device_name[50];
390 strcpy(device_name,"direct3d");
392 fill_opengl_caps(&dref);
395 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
396 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
399 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
400 if (ret_value != D3DENUMRET_OK)
404 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
407 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
408 if (ret_value != D3DENUMRET_OK)
411 return D3DENUMRET_OK;
414 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
416 D3DDEVICEDESC7 ddesc;
418 fill_opengl_caps_7(&ddesc);
420 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
422 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
426 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
428 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
429 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
431 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
432 if (!--(This->ref)) {
434 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
436 /* Release texture associated with the device */
437 for (i = 0; i < MAX_TEXTURES; i++) {
438 if (This->current_texture[i] != NULL)
439 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
440 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
443 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
444 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
445 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
446 surf->aux_ctx = NULL;
447 surf->aux_data = NULL;
448 surf->aux_flip = NULL;
452 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
453 IDirectDrawSurfaceImpl *surf2;
454 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
455 for (; surf2 != NULL; surf2 = surf2->next_attached) {
456 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
457 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
458 /* Override the Lock / Unlock function for all these surfaces */
459 surf2->lock_update = surf2->lock_update_prev;
460 surf2->unlock_update = surf2->unlock_update_prev;
461 /* And install also the blt / bltfast overrides */
462 surf2->aux_blt = NULL;
463 surf2->aux_bltfast = NULL;
465 surf2->d3ddevice = NULL;
469 /* And warn the D3D object that this device is no longer active... */
470 This->d3d->d3d_removed_device(This->d3d, This);
472 HeapFree(GetProcessHeap(), 0, This->world_mat);
473 HeapFree(GetProcessHeap(), 0, This->view_mat);
474 HeapFree(GetProcessHeap(), 0, This->proj_mat);
476 if (glThis->surface_ptr)
477 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
479 DeleteCriticalSection(&(This->crit));
482 if (glThis->unlock_tex)
483 glDeleteTextures(1, &(glThis->unlock_tex));
484 glXDestroyContext(glThis->display, glThis->gl_context);
486 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
488 HeapFree(GetProcessHeap(), 0, This);
495 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
496 LPD3DDEVICEDESC lpD3DHWDevDesc,
497 LPD3DDEVICEDESC lpD3DHELDevDesc)
499 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
503 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
505 fill_opengl_caps(&desc);
506 dwSize = lpD3DHWDevDesc->dwSize;
507 memset(lpD3DHWDevDesc, 0, dwSize);
508 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
510 dwSize = lpD3DHELDevDesc->dwSize;
511 memset(lpD3DHELDevDesc, 0, dwSize);
512 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
514 TRACE(" returning caps : (no dump function yet)\n");
519 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
520 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
524 LPDDPIXELFORMAT pformat;
526 /* Do the texture enumeration */
527 sdesc.dwSize = sizeof(DDSURFACEDESC);
528 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
529 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
530 pformat = &(sdesc.ddpfPixelFormat);
531 pformat->dwSize = sizeof(DDPIXELFORMAT);
532 pformat->dwFourCC = 0;
534 TRACE("Enumerating GL_RGBA unpacked (32)\n");
535 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
536 pformat->u1.dwRGBBitCount = 32;
537 pformat->u2.dwRBitMask = 0x00FF0000;
538 pformat->u3.dwGBitMask = 0x0000FF00;
539 pformat->u4.dwBBitMask = 0x000000FF;
540 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
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 TRACE("Enumerating GL_RGB unpacked (32)\n");
545 pformat->dwFlags = DDPF_RGB;
546 pformat->u1.dwRGBBitCount = 32;
547 pformat->u2.dwRBitMask = 0x00FF0000;
548 pformat->u3.dwGBitMask = 0x0000FF00;
549 pformat->u4.dwBBitMask = 0x000000FF;
550 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
551 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
552 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
554 TRACE("Enumerating GL_RGB unpacked (24)\n");
555 pformat->dwFlags = DDPF_RGB;
556 pformat->u1.dwRGBBitCount = 24;
557 pformat->u2.dwRBitMask = 0x00FF0000;
558 pformat->u3.dwGBitMask = 0x0000FF00;
559 pformat->u4.dwBBitMask = 0x000000FF;
560 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
564 /* Note : even if this is an 'emulated' texture format, it needs to be first
565 as some dumb applications seem to rely on that. */
566 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
567 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
568 pformat->u1.dwRGBBitCount = 16;
569 pformat->u2.dwRBitMask = 0x00007C00;
570 pformat->u3.dwGBitMask = 0x000003E0;
571 pformat->u4.dwBBitMask = 0x0000001F;
572 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
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_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
577 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
578 pformat->u1.dwRGBBitCount = 16;
579 pformat->u2.dwRBitMask = 0x00000F00;
580 pformat->u3.dwGBitMask = 0x000000F0;
581 pformat->u4.dwBBitMask = 0x0000000F;
582 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
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;
586 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
587 pformat->dwFlags = DDPF_RGB;
588 pformat->u1.dwRGBBitCount = 16;
589 pformat->u2.dwRBitMask = 0x0000F800;
590 pformat->u3.dwGBitMask = 0x000007E0;
591 pformat->u4.dwBBitMask = 0x0000001F;
592 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
593 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
594 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
596 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
597 pformat->dwFlags = DDPF_RGB;
598 pformat->u1.dwRGBBitCount = 16;
599 pformat->u2.dwRBitMask = 0x00007C00;
600 pformat->u3.dwGBitMask = 0x000003E0;
601 pformat->u4.dwBBitMask = 0x0000001F;
602 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
603 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
604 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
607 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
608 find enumerated, others the last one. And both want to have the ARGB one.
610 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
612 /* See argument about the RGBA format for 'packed' texture formats */
613 TRACE("Enumerating GL_RGBA unpacked (32)\n");
614 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
615 pformat->u1.dwRGBBitCount = 32;
616 pformat->u2.dwRBitMask = 0xFF000000;
617 pformat->u3.dwGBitMask = 0x00FF0000;
618 pformat->u4.dwBBitMask = 0x0000FF00;
619 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
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;
623 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
624 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
625 pformat->u1.dwRGBBitCount = 16;
626 pformat->u2.dwRBitMask = 0x0000F000;
627 pformat->u3.dwGBitMask = 0x00000F00;
628 pformat->u4.dwBBitMask = 0x000000F0;
629 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
630 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
631 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
633 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
634 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
635 pformat->u1.dwRGBBitCount = 16;
636 pformat->u2.dwRBitMask = 0x0000F800;
637 pformat->u3.dwGBitMask = 0x000007C0;
638 pformat->u4.dwBBitMask = 0x0000003E;
639 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
640 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
641 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
644 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
645 pformat->dwFlags = DDPF_RGB;
646 pformat->u1.dwRGBBitCount = 8;
647 pformat->u2.dwRBitMask = 0x000000E0;
648 pformat->u3.dwGBitMask = 0x0000001C;
649 pformat->u4.dwBBitMask = 0x00000003;
650 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
651 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
652 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
654 TRACE("Enumerating Paletted (8)\n");
655 pformat->dwFlags = DDPF_PALETTEINDEXED8;
656 pformat->u1.dwRGBBitCount = 8;
657 pformat->u2.dwRBitMask = 0x00000000;
658 pformat->u3.dwGBitMask = 0x00000000;
659 pformat->u4.dwBBitMask = 0x00000000;
660 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
661 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
662 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
664 TRACE("End of enumeration\n");
670 d3ddevice_find(IDirectDrawImpl *d3d,
671 LPD3DFINDDEVICESEARCH lpD3DDFS,
672 LPD3DFINDDEVICERESULT lplpD3DDevice)
676 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
677 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
678 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
679 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
681 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
682 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
683 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
684 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
685 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
686 TRACE(" no match for this GUID.\n");
687 return DDERR_INVALIDPARAMS;
691 /* Now return our own GUID */
692 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
693 fill_opengl_caps(&desc);
694 lplpD3DDevice->ddHwDesc = desc;
695 lplpD3DDevice->ddSwDesc = desc;
697 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
703 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
704 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
707 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
708 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
709 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
713 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
714 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
717 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
718 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
719 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
723 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
724 D3DRENDERSTATETYPE dwRenderStateType,
727 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
728 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
730 /* Call the render state functions */
731 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
732 set_render_state(This, dwRenderStateType, &This->state_block);
738 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
739 D3DRENDERSTATETYPE dwRenderStateType,
740 LPDWORD lpdwRenderState)
742 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
743 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
745 /* Call the render state functions */
746 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
748 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
754 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
755 D3DLIGHTSTATETYPE dwLightStateType,
758 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
760 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
762 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
763 TRACE("Unexpected Light State Type\n");
764 return DDERR_INVALIDPARAMS;
766 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
767 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
772 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
774 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
775 switch (dwLightState) {
777 ERR("DDCOLOR_MONO should not happen!\n");
780 /* We are already in this mode */
783 ERR("Unknown color model!\n");
787 D3DRENDERSTATETYPE rs;
788 switch (dwLightStateType) {
790 case D3DLIGHTSTATE_AMBIENT: /* 2 */
791 rs = D3DRENDERSTATE_AMBIENT;
793 case D3DLIGHTSTATE_FOGMODE: /* 4 */
794 rs = D3DRENDERSTATE_FOGVERTEXMODE;
796 case D3DLIGHTSTATE_FOGSTART: /* 5 */
797 rs = D3DRENDERSTATE_FOGSTART;
799 case D3DLIGHTSTATE_FOGEND: /* 6 */
800 rs = D3DRENDERSTATE_FOGEND;
802 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
803 rs = D3DRENDERSTATE_FOGDENSITY;
805 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
806 rs = D3DRENDERSTATE_COLORVERTEX;
812 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
819 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
822 case D3DPT_POINTLIST:
823 TRACE("Start POINTS\n");
828 TRACE("Start LINES\n");
832 case D3DPT_LINESTRIP:
833 TRACE("Start LINE_STRIP\n");
834 glBegin(GL_LINE_STRIP);
837 case D3DPT_TRIANGLELIST:
838 TRACE("Start TRIANGLES\n");
839 glBegin(GL_TRIANGLES);
842 case D3DPT_TRIANGLESTRIP:
843 TRACE("Start TRIANGLE_STRIP\n");
844 glBegin(GL_TRIANGLE_STRIP);
847 case D3DPT_TRIANGLEFAN:
848 TRACE("Start TRIANGLE_FAN\n");
849 glBegin(GL_TRIANGLE_FAN);
853 FIXME("Unhandled primitive %08x\n", d3dpt);
858 /* This function calculate the Z coordinate from Zproj */
859 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
862 /* Assume that X = Y = 0 and W = 1 */
863 a = This->proj_mat->_33;
864 b = This->proj_mat->_34;
865 c = This->proj_mat->_43;
866 d = This->proj_mat->_44;
867 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
868 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
869 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
871 return (d*Zproj - c) / (a - b*Zproj);
874 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
877 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
879 for (i = 0; i < 3; i++) {
880 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
882 for (elt = 0; elt < 0x10000; elt++) {
883 /* We apply the fog transformation and cache the result */
884 DWORD fog_intensity = elt & 0xFF;
885 DWORD vertex_color = (elt >> 8) & 0xFF;
886 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
891 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
892 BOOLEAN vertex_transformed,
893 BOOLEAN vertex_lit) {
894 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
896 /* Puts GL in the correct lighting / transformation mode */
897 if ((vertex_transformed == FALSE) &&
898 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
899 /* Need to put the correct transformation again if we go from Transformed
900 vertices to non-transformed ones.
902 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
903 This->world_mat, This->view_mat, This->proj_mat);
904 glThis->transform_state = GL_TRANSFORM_NORMAL;
906 } else if ((vertex_transformed == TRUE) &&
907 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
908 /* Set our orthographic projection */
909 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
910 glThis->transform_state = GL_TRANSFORM_ORTHO;
911 d3ddevice_set_ortho(This);
915 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
916 if no fogging state change occurred */
917 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
918 if (vertex_transformed == TRUE) {
919 if (glThis->fogging != 0) {
923 /* Now check if our fog_table still corresponds to the current vertex color.
924 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
925 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
926 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
927 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
928 /* We need to rebuild our fog table.... */
929 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
932 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
933 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
934 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
935 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
936 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
938 if (vertex_lit == FALSE) {
939 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
940 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
942 /* Special case of 'pixel fog' */
943 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
944 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
946 if (glThis->fogging == 0) {
951 if (glThis->fogging != 0) {
958 if (glThis->fogging != 0) {
964 /* Handle the 'no-normal' case */
965 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
966 if (glThis->lighting == 0) {
967 glEnable(GL_LIGHTING);
968 glThis->lighting = 1;
971 if (glThis->lighting != 0) {
972 glDisable(GL_LIGHTING);
973 glThis->lighting = 0;
977 /* Handle the code for pre-vertex material properties */
978 if (vertex_transformed == FALSE) {
979 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
980 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
981 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
982 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
983 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
984 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
985 glEnable(GL_COLOR_MATERIAL);
992 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
993 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
995 D3DDRAWPRIMITIVESTRIDEDDATA strided;
999 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1000 strided.position.dwStride = sizeof(D3DVERTEX);
1001 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1002 strided.normal.dwStride = sizeof(D3DVERTEX);
1003 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1004 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1005 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1008 case D3DVT_LVERTEX: {
1009 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1010 strided.position.dwStride = sizeof(D3DLVERTEX);
1011 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1012 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1013 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1014 strided.specular.dwStride = sizeof(D3DLVERTEX);
1015 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1016 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1017 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1020 case D3DVT_TLVERTEX: {
1021 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1022 strided.position.dwStride = sizeof(D3DTLVERTEX);
1023 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1024 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1025 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1026 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1027 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1028 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1029 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1033 FIXME("Unhandled vertex type %08x\n", d3dvt);
1039 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1040 D3DPRIMITIVETYPE d3dptPrimitiveType,
1041 D3DVERTEXTYPE d3dvtVertexType,
1043 DWORD dwVertexCount,
1046 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1048 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1049 if (TRACE_ON(ddraw)) {
1050 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1053 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1059 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1060 D3DPRIMITIVETYPE d3dptPrimitiveType,
1061 D3DVERTEXTYPE d3dvtVertexType,
1063 DWORD dwVertexCount,
1068 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1069 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1070 if (TRACE_ON(ddraw)) {
1071 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1074 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1080 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1081 LPD3DEXECUTEBUFFERDESC lpDesc,
1082 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1083 IUnknown* pUnkOuter)
1085 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1086 IDirect3DExecuteBufferImpl *ret;
1089 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1091 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1092 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1094 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1099 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1100 static BOOLEAN first = TRUE;
1101 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1105 if (first == TRUE) {
1106 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1110 TRACE("flushing ZBuffer back to GL\n");
1112 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1113 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1114 d3ddevice_set_ortho(d3d_dev);
1117 glMatrixMode(GL_MODELVIEW);
1120 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1121 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1122 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1124 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1127 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1128 case 16: type = GL_UNSIGNED_SHORT; break;
1129 case 32: type = GL_UNSIGNED_INT; break;
1130 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1133 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1134 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1135 glRasterPos2i(0, row + 1);
1136 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1137 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1141 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1142 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1143 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1144 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1147 /* These are the various handler used in the generic path */
1148 inline static void handle_xyz(D3DVALUE *coords) {
1149 glVertex3fv(coords);
1151 inline static void handle_xyzrhw(D3DVALUE *coords) {
1152 if (coords[3] < 1e-8)
1153 glVertex3fv(coords);
1155 GLfloat w = 1.0 / coords[3];
1157 glVertex4f(coords[0] * w,
1163 inline static void handle_normal(D3DVALUE *coords) {
1164 glNormal3fv(coords);
1167 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1168 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1169 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1170 glColor4ub((*color >> 16) & 0xFF,
1171 (*color >> 8) & 0xFF,
1172 (*color >> 0) & 0xFF,
1173 (*color >> 24) & 0xFF);
1175 glColor3ub((*color >> 16) & 0xFF,
1176 (*color >> 8) & 0xFF,
1177 (*color >> 0) & 0xFF);
1181 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1182 glColor4ub((*color >> 16) & 0xFF,
1183 (*color >> 8) & 0xFF,
1184 (*color >> 0) & 0xFF,
1185 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1188 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1189 if ((lighted == FALSE) &&
1190 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1191 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1192 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1193 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1194 handle_diffuse_base(sb, color);
1196 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1197 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1198 handle_diffuse_base(sb, color);
1200 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1201 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1202 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1203 handle_diffuse_base(sb, color);
1205 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1206 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1207 handle_diffuse_base(sb, color);
1210 handle_diffuse_base(sb, color);
1214 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1215 if ((lighted == FALSE) &&
1216 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1217 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1218 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1219 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1220 handle_specular_base(sb, color);
1222 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1223 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1224 handle_specular_base(sb, color);
1226 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1227 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1228 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1229 handle_specular_base(sb, color);
1231 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1232 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1233 handle_specular_base(sb, color);
1236 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1239 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1240 if (lighted == TRUE) {
1241 DWORD color = *color_d;
1242 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1243 /* Special case where the specular value is used to do fogging */
1244 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1245 color &= 0xFF000000; /* Only keep the alpha component */
1246 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1247 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1248 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1250 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1251 /* Standard specular value in transformed mode. TODO */
1253 handle_diffuse_base(sb, &color);
1255 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1256 handle_diffuse(sb, color_d, FALSE);
1257 handle_specular(sb, color_s, FALSE);
1259 /* In that case, only put the diffuse color... */
1260 handle_diffuse_base(sb, color_d);
1265 inline static void handle_texture(D3DVALUE *coords) {
1266 glTexCoord2fv(coords);
1268 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1269 if (GL_extensions.glMultiTexCoord2fv) {
1270 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1272 if (tex_stage == 0) glTexCoord2fv(coords);
1276 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1277 D3DPRIMITIVETYPE d3dptPrimitiveType,
1278 DWORD d3dvtVertexType,
1279 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1280 DWORD dwVertexCount,
1285 BOOLEAN vertex_lighted = FALSE;
1286 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1287 int num_active_stages = 0;
1289 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1290 if (TRACE_ON(ddraw)) {
1291 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1294 /* This is to prevent 'thread contention' between a thread locking the device and another
1295 doing 3D display on it... */
1296 EnterCriticalSection(&(This->crit));
1299 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1300 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1302 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1304 if (This->current_zbuffer == NULL) {
1305 /* Search for an attached ZBuffer */
1306 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1307 LPDIRECTDRAWSURFACE7 zbuf;
1310 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1311 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1313 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1314 IDirectDrawSurface7_Release(zbuf);
1317 if (This->current_zbuffer != NULL) {
1318 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1319 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1323 /* Just a hack for now.. Will have to find better algorithm :-/ */
1324 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1325 vertex_lighted = TRUE;
1327 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1330 /* Compute the number of active texture stages and set the various texture parameters */
1331 num_active_stages = draw_primitive_handle_textures(This);
1333 /* And restore to handle '0' in the case we use glTexCorrd calls */
1334 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1335 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1336 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1339 draw_primitive_handle_GL_state(This,
1340 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1342 draw_primitive_start_GL(d3dptPrimitiveType);
1344 /* Some fast paths first before the generic case.... */
1345 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1348 for (index = 0; index < dwIndexCount; index++) {
1349 int i = (dwIndices == NULL) ? index : dwIndices[index];
1351 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1352 D3DVALUE *tex_coord =
1353 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1354 D3DVALUE *position =
1355 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1357 handle_normal(normal);
1358 handle_texture(tex_coord);
1359 handle_xyz(position);
1361 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1362 position[0], position[1], position[2],
1363 normal[0], normal[1], normal[2],
1364 tex_coord[0], tex_coord[1]);
1366 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1369 for (index = 0; index < dwIndexCount; index++) {
1370 int i = (dwIndices == NULL) ? index : dwIndices[index];
1372 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1374 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1375 D3DVALUE *tex_coord =
1376 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1377 D3DVALUE *position =
1378 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1380 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1381 handle_texture(tex_coord);
1382 handle_xyzrhw(position);
1384 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1385 position[0], position[1], position[2], position[3],
1386 (*color_d >> 16) & 0xFF,
1387 (*color_d >> 8) & 0xFF,
1388 (*color_d >> 0) & 0xFF,
1389 (*color_d >> 24) & 0xFF,
1390 (*color_s >> 16) & 0xFF,
1391 (*color_s >> 8) & 0xFF,
1392 (*color_s >> 0) & 0xFF,
1393 (*color_s >> 24) & 0xFF,
1394 tex_coord[0], tex_coord[1]);
1396 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1397 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1398 /* This is the 'slow path' but that should support all possible vertex formats out there...
1399 Note that people should write a fast path for all vertex formats out there...
1402 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1403 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1405 for (index = 0; index < dwIndexCount; index++) {
1406 int i = (dwIndices == NULL) ? index : dwIndices[index];
1409 if (d3dvtVertexType & D3DFVF_NORMAL) {
1411 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1412 handle_normal(normal);
1414 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1416 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1418 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1419 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1421 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1423 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1424 handle_specular(&(This->state_block), color_s, vertex_lighted);
1425 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1427 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1428 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1432 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1433 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1434 if (tex_index >= num_tex_index) {
1435 handle_textures((D3DVALUE *) no_index, tex_stage);
1437 D3DVALUE *tex_coord =
1438 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1439 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1440 handle_textures(tex_coord, tex_stage);
1444 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1445 D3DVALUE *position =
1446 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1447 handle_xyz(position);
1448 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1449 D3DVALUE *position =
1450 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1451 handle_xyzrhw(position);
1454 if (TRACE_ON(ddraw_geom)) {
1457 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1458 D3DVALUE *position =
1459 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1460 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1461 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1462 D3DVALUE *position =
1463 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1464 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1466 if (d3dvtVertexType & D3DFVF_NORMAL) {
1468 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1469 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1471 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1473 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1474 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1475 (*color_d >> 16) & 0xFF,
1476 (*color_d >> 8) & 0xFF,
1477 (*color_d >> 0) & 0xFF,
1478 (*color_d >> 24) & 0xFF);
1480 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1482 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1483 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1484 (*color_s >> 16) & 0xFF,
1485 (*color_s >> 8) & 0xFF,
1486 (*color_s >> 0) & 0xFF,
1487 (*color_s >> 24) & 0xFF);
1489 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1490 D3DVALUE *tex_coord =
1491 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1492 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1493 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1495 TRACE_(ddraw_geom)("\n");
1499 ERR(" matrix weighting not handled yet....\n");
1504 /* Whatever the case, disable the color material stuff */
1505 glDisable(GL_COLOR_MATERIAL);
1510 LeaveCriticalSection(&(This->crit));
1514 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1515 D3DPRIMITIVETYPE d3dptPrimitiveType,
1516 DWORD d3dvtVertexType,
1518 DWORD dwVertexCount,
1521 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1522 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1524 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1525 if (TRACE_ON(ddraw)) {
1526 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1529 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1530 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1536 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1537 D3DPRIMITIVETYPE d3dptPrimitiveType,
1538 DWORD d3dvtVertexType,
1540 DWORD dwVertexCount,
1545 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1546 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1548 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1549 if (TRACE_ON(ddraw)) {
1550 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1553 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1554 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1560 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1561 D3DPRIMITIVETYPE d3dptPrimitiveType,
1563 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1564 DWORD dwVertexCount,
1567 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1569 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1570 if (TRACE_ON(ddraw)) {
1571 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1573 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1579 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1580 D3DPRIMITIVETYPE d3dptPrimitiveType,
1582 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1583 DWORD dwVertexCount,
1588 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1590 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1591 if (TRACE_ON(ddraw)) {
1592 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1595 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1601 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1602 D3DPRIMITIVETYPE d3dptPrimitiveType,
1603 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1604 DWORD dwStartVertex,
1605 DWORD dwNumVertices,
1608 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1609 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1610 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1612 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1613 if (TRACE_ON(ddraw)) {
1614 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1617 if (vb_impl->processed == TRUE) {
1618 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1619 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1621 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1622 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1623 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1625 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1626 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1629 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1630 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1637 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1638 D3DPRIMITIVETYPE d3dptPrimitiveType,
1639 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1640 DWORD dwStartVertex,
1641 DWORD dwNumVertices,
1646 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1647 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1648 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1650 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1651 if (TRACE_ON(ddraw)) {
1652 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1655 if (vb_impl->processed == TRUE) {
1656 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1657 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1659 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1660 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1661 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1663 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1664 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1667 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1668 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1674 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1676 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1678 BOOLEAN is_complement = FALSE;
1679 BOOLEAN is_alpha_replicate = FALSE;
1680 BOOLEAN handled = TRUE;
1682 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1686 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1687 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1692 if (tex_op == D3DTOP_SELECTARG2) {
1696 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1697 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1702 if (tex_op == D3DTOP_SELECTARG2) {
1707 if (dwState & D3DTA_COMPLEMENT) {
1708 is_complement = TRUE;
1710 if (dwState & D3DTA_ALPHAREPLICATE) {
1711 is_alpha_replicate = TRUE;
1713 dwState &= D3DTA_SELECTMASK;
1714 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1715 dwState = D3DTA_DIFFUSE;
1719 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1720 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1721 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1722 case D3DTA_TFACTOR: {
1723 /* Get the constant value from the current rendering state */
1725 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1727 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1728 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1729 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1730 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1731 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1733 src = GL_CONSTANT_EXT;
1735 default: src = GL_TEXTURE; handled = FALSE; break;
1739 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1740 if (is_alpha_replicate) {
1741 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1743 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1746 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1747 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1754 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1756 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1759 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1760 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1765 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1767 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1768 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1772 unit = GL_TEXTURE0_WINE + dwStage;
1773 if (unit != glThis->current_active_tex_unit) {
1774 GL_extensions.glActiveTexture(unit);
1775 glThis->current_active_tex_unit = unit;
1778 switch (d3dTexStageStateType) {
1779 #define GEN_CASE(a) case a: type = #a; break
1780 GEN_CASE(D3DTSS_COLOROP);
1781 GEN_CASE(D3DTSS_COLORARG1);
1782 GEN_CASE(D3DTSS_COLORARG2);
1783 GEN_CASE(D3DTSS_ALPHAOP);
1784 GEN_CASE(D3DTSS_ALPHAARG1);
1785 GEN_CASE(D3DTSS_ALPHAARG2);
1786 GEN_CASE(D3DTSS_BUMPENVMAT00);
1787 GEN_CASE(D3DTSS_BUMPENVMAT01);
1788 GEN_CASE(D3DTSS_BUMPENVMAT10);
1789 GEN_CASE(D3DTSS_BUMPENVMAT11);
1790 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1791 GEN_CASE(D3DTSS_ADDRESS);
1792 GEN_CASE(D3DTSS_ADDRESSU);
1793 GEN_CASE(D3DTSS_ADDRESSV);
1794 GEN_CASE(D3DTSS_BORDERCOLOR);
1795 GEN_CASE(D3DTSS_MAGFILTER);
1796 GEN_CASE(D3DTSS_MINFILTER);
1797 GEN_CASE(D3DTSS_MIPFILTER);
1798 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1799 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1800 GEN_CASE(D3DTSS_MAXANISOTROPY);
1801 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1802 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1803 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1805 default: type = "UNKNOWN";
1808 /* Store the values in the state array */
1809 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1810 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1811 /* Some special cases when one state modifies more than one... */
1812 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1813 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1814 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1819 switch (d3dTexStageStateType) {
1820 case D3DTSS_MINFILTER:
1821 case D3DTSS_MIPFILTER:
1822 if (TRACE_ON(ddraw)) {
1823 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1824 switch ((D3DTEXTUREMINFILTER) dwState) {
1825 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1826 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1827 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1830 switch ((D3DTEXTUREMIPFILTER) dwState) {
1831 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1832 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1833 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1834 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1840 case D3DTSS_MAGFILTER:
1841 if (TRACE_ON(ddraw)) {
1842 switch ((D3DTEXTUREMAGFILTER) dwState) {
1843 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1844 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1845 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1850 case D3DTSS_ADDRESS:
1851 case D3DTSS_ADDRESSU:
1852 case D3DTSS_ADDRESSV: {
1853 switch ((D3DTEXTUREADDRESS) dwState) {
1854 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1855 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1856 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1857 case D3DTADDRESS_MIRROR:
1858 if (GL_extensions.mirrored_repeat == TRUE) {
1859 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1861 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1864 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1868 case D3DTSS_ALPHAOP:
1869 case D3DTSS_COLOROP: {
1871 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1876 #define GEN_CASE(a) case a: value = #a; break
1877 GEN_CASE(D3DTOP_DISABLE);
1878 GEN_CASE(D3DTOP_SELECTARG1);
1879 GEN_CASE(D3DTOP_SELECTARG2);
1880 GEN_CASE(D3DTOP_MODULATE);
1881 GEN_CASE(D3DTOP_MODULATE2X);
1882 GEN_CASE(D3DTOP_MODULATE4X);
1883 GEN_CASE(D3DTOP_ADD);
1884 GEN_CASE(D3DTOP_ADDSIGNED);
1885 GEN_CASE(D3DTOP_ADDSIGNED2X);
1886 GEN_CASE(D3DTOP_SUBTRACT);
1887 GEN_CASE(D3DTOP_ADDSMOOTH);
1888 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1889 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1890 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1891 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1892 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1893 GEN_CASE(D3DTOP_PREMODULATE);
1894 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1895 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1896 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1897 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1898 GEN_CASE(D3DTOP_BUMPENVMAP);
1899 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1900 GEN_CASE(D3DTOP_DOTPRODUCT3);
1901 GEN_CASE(D3DTOP_FORCE_DWORD);
1903 default: value = "UNKNOWN";
1906 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1907 glDisable(GL_TEXTURE_2D);
1908 TRACE(" disabling 2D texturing.\n");
1910 /* Re-enable texturing */
1911 if (This->current_texture[0] != NULL) {
1912 glEnable(GL_TEXTURE_2D);
1913 TRACE(" enabling 2D texturing.\n");
1916 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1917 if (dwState != D3DTOP_DISABLE) {
1918 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1919 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1920 glThis->current_tex_env = GL_COMBINE_EXT;
1924 /* Now set up the operand correctly */
1926 case D3DTOP_DISABLE:
1927 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1928 and it works, so ignore this op */
1929 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1932 case D3DTOP_SELECTARG1:
1933 case D3DTOP_SELECTARG2:
1934 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1937 case D3DTOP_MODULATE4X:
1938 scale = scale * 2; /* Drop through */
1939 case D3DTOP_MODULATE2X:
1940 scale = scale * 2; /* Drop through */
1941 case D3DTOP_MODULATE:
1942 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1946 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1949 case D3DTOP_ADDSIGNED2X:
1950 scale = scale * 2; /* Drop through */
1951 case D3DTOP_ADDSIGNED:
1952 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1955 /* For the four blending modes, use the Arg2 parameter */
1956 case D3DTOP_BLENDDIFFUSEALPHA:
1957 case D3DTOP_BLENDTEXTUREALPHA:
1958 case D3DTOP_BLENDFACTORALPHA:
1959 case D3DTOP_BLENDCURRENTALPHA: {
1960 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1963 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1964 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1965 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1966 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1969 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1970 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1971 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1972 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1973 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1982 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1983 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1984 /* Switch the arguments if needed... */
1985 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1986 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1987 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1989 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1990 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1993 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1994 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1996 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1997 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2003 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2004 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2006 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2008 TRACE(" Stage type is : %s => %s\n", type, value);
2010 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2014 case D3DTSS_COLORARG1:
2015 case D3DTSS_COLORARG2:
2016 case D3DTSS_ALPHAARG1:
2017 case D3DTSS_ALPHAARG2: {
2018 const char *value, *value_comp = "", *value_alpha = "";
2020 D3DTEXTUREOP tex_op;
2022 switch (dwState & D3DTA_SELECTMASK) {
2023 #define GEN_CASE(a) case a: value = #a; break
2024 GEN_CASE(D3DTA_DIFFUSE);
2025 GEN_CASE(D3DTA_CURRENT);
2026 GEN_CASE(D3DTA_TEXTURE);
2027 GEN_CASE(D3DTA_TFACTOR);
2028 GEN_CASE(D3DTA_SPECULAR);
2030 default: value = "UNKNOWN";
2032 if (dwState & D3DTA_COMPLEMENT) {
2033 value_comp = " | D3DTA_COMPLEMENT";
2035 if (dwState & D3DTA_ALPHAREPLICATE) {
2036 value_alpha = " | D3DTA_ALPHAREPLICATE";
2039 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2040 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2042 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2045 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2048 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2050 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2054 case D3DTSS_MIPMAPLODBIAS: {
2055 D3DVALUE value = *((D3DVALUE *) &dwState);
2056 BOOLEAN handled = TRUE;
2058 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2062 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2063 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2065 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2069 case D3DTSS_MAXMIPLEVEL:
2070 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2073 case D3DTSS_BORDERCOLOR:
2074 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2075 ((dwState >> 16) & 0xFF),
2076 ((dwState >> 8) & 0xFF),
2077 ((dwState >> 0) & 0xFF),
2078 ((dwState >> 24) & 0xFF));
2081 case D3DTSS_TEXCOORDINDEX: {
2082 BOOLEAN handled = TRUE;
2085 switch (dwState & 0xFFFF0000) {
2086 #define GEN_CASE(a) case a: value = #a; break
2087 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2088 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2089 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2090 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2092 default: value = "UNKNOWN";
2094 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2098 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2100 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2104 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2105 const char *projected = "", *value;
2106 BOOLEAN handled = TRUE;
2107 switch (dwState & 0xFF) {
2108 #define GEN_CASE(a) case a: value = #a; break
2109 GEN_CASE(D3DTTFF_DISABLE);
2110 GEN_CASE(D3DTTFF_COUNT1);
2111 GEN_CASE(D3DTTFF_COUNT2);
2112 GEN_CASE(D3DTTFF_COUNT3);
2113 GEN_CASE(D3DTTFF_COUNT4);
2115 default: value = "UNKNOWN";
2117 if (dwState & D3DTTFF_PROJECTED) {
2118 projected = " | D3DTTFF_PROJECTED";
2122 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2123 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2126 if (handled == TRUE) {
2127 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2129 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2134 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2144 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2146 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2149 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2150 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2153 /* First check if we need to bind any other texture for this stage */
2154 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2155 if (This->current_texture[stage] == NULL) {
2156 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2158 unit = GL_TEXTURE0_WINE + stage;
2159 if (unit != glThis->current_active_tex_unit) {
2160 GL_extensions.glActiveTexture(unit);
2161 glThis->current_active_tex_unit = unit;
2163 glBindTexture(GL_TEXTURE_2D, 0);
2166 glDisable(GL_TEXTURE_2D);
2169 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2171 unit = GL_TEXTURE0_WINE + stage;
2172 if (unit != glThis->current_active_tex_unit) {
2173 GL_extensions.glActiveTexture(unit);
2174 glThis->current_active_tex_unit = unit;
2177 if (glThis->current_bound_texture[stage] == NULL) {
2178 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2179 TRACE(" enabling 2D texturing and");
2180 glEnable(GL_TEXTURE_2D);
2183 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2184 glBindTexture(GL_TEXTURE_2D, tex_name);
2187 glThis->current_bound_texture[stage] = This->current_texture[stage];
2189 if (glThis->current_bound_texture[stage] == NULL) {
2190 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2192 TRACE(" using already bound texture id %d for stage %ld.\n",
2193 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2197 /* If no texure valid for this stage, go out of the loop */
2198 if (This->current_texture[stage] == NULL) break;
2200 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2201 This will also update the various texture parameters if needed.
2203 gltex_upload_texture(surf_ptr, This, stage);
2210 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2212 LPDIRECTDRAWSURFACE7 lpTexture2)
2214 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2216 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2218 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2219 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2220 if (lpTexture2 != NULL) {
2221 WARN(" setting a texture to a non-supported texture stage !\n");
2226 if (This->current_texture[dwStage] != NULL) {
2227 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2230 if (lpTexture2 == NULL) {
2231 This->current_texture[dwStage] = NULL;
2233 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2234 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2235 This->current_texture[dwStage] = tex_impl;
2242 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2243 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2245 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2246 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2248 fill_opengl_caps_7(lpD3DHELDevDesc);
2250 TRACE(" returning caps : no dump function yet.\n");
2256 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2257 LPD3DMATERIAL7 lpMat)
2259 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2260 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2262 if (TRACE_ON(ddraw)) {
2263 TRACE(" material is : \n");
2264 dump_D3DMATERIAL7(lpMat);
2267 This->current_material = *lpMat;
2270 glMaterialfv(GL_FRONT_AND_BACK,
2272 (float *) &(This->current_material.u.diffuse));
2273 glMaterialfv(GL_FRONT_AND_BACK,
2275 (float *) &(This->current_material.u1.ambient));
2276 glMaterialfv(GL_FRONT_AND_BACK,
2278 (float *) &(This->current_material.u2.specular));
2279 glMaterialfv(GL_FRONT_AND_BACK,
2281 (float *) &(This->current_material.u3.emissive));
2282 glMaterialf(GL_FRONT_AND_BACK,
2284 This->current_material.u4.power); /* Not sure about this... */
2292 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2294 LPD3DLIGHT7 lpLight)
2296 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2297 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2298 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2300 if (TRACE_ON(ddraw)) {
2301 TRACE(" setting light : \n");
2302 dump_D3DLIGHT7(lpLight);
2305 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2306 This->set_lights |= 0x00000001 << dwLightIndex;
2307 This->light_parameters[dwLightIndex] = *lpLight;
2309 /* Some checks to print out nice warnings :-) */
2310 switch (lpLight->dltType) {
2311 case D3DLIGHT_DIRECTIONAL:
2312 case D3DLIGHT_POINT:
2313 /* These are handled properly... */
2317 if ((lpLight->dvTheta != 0.0) ||
2318 (lpLight->dvTheta != lpLight->dvPhi)) {
2319 ERR("dvTheta not fully supported yet !\n");
2324 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2327 /* This will force the Light setting on next drawing of primitives */
2328 glThis->transform_state = GL_TRANSFORM_NONE;
2334 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2338 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2339 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2341 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2345 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2346 /* Set the default parameters.. */
2347 TRACE(" setting default light parameters...\n");
2348 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2350 glEnable(GL_LIGHT0 + dwLightIndex);
2351 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2352 /* This light gets active... Need to update its parameters to GL before the next drawing */
2353 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2355 This->active_lights |= 0x00000001 << dwLightIndex;
2356 glThis->transform_state = GL_TRANSFORM_NONE;
2359 glDisable(GL_LIGHT0 + dwLightIndex);
2360 This->active_lights &= ~(0x00000001 << dwLightIndex);
2368 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2370 ICOM_THIS(IDirect3DDeviceImpl,iface);
2371 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2373 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2375 if (dwIndex >= This->max_clipping_planes) {
2376 return DDERR_INVALIDPARAMS;
2379 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2381 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2383 /* This is to force the reset of the transformation matrices on the next drawing.
2384 * This is needed to use the correct matrices for the various clipping planes.
2386 glThis->transform_state = GL_TRANSFORM_NONE;
2392 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2393 LPD3DVIEWPORT7 lpData)
2395 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2396 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2398 if (TRACE_ON(ddraw)) {
2399 TRACE(" viewport is : \n");
2400 TRACE(" - dwX = %ld dwY = %ld\n",
2401 lpData->dwX, lpData->dwY);
2402 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2403 lpData->dwWidth, lpData->dwHeight);
2404 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2405 lpData->dvMinZ, lpData->dvMaxZ);
2409 /* Set the viewport */
2410 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2411 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2412 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2414 if ((lpData->dwX != This->active_viewport.dwX) ||
2415 (lpData->dwY != This->active_viewport.dwY) ||
2416 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2417 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2418 glViewport(lpData->dwX,
2419 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2420 lpData->dwWidth, lpData->dwHeight);
2425 This->active_viewport = *lpData;
2430 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2431 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2433 # define XCAST(fun) (void*)
2436 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2438 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2439 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2440 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2441 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2442 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2443 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2444 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2445 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2446 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2447 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2448 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2449 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2450 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2451 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2452 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2453 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2454 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2455 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2456 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2457 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2458 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2459 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2460 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2461 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2462 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2463 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2464 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2465 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2466 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2467 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2468 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2469 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2470 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2471 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2472 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2473 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2474 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2475 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2476 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2477 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2478 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2479 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2480 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2481 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2482 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2483 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2484 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2485 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2486 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2487 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2490 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2495 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2496 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2498 # define XCAST(fun) (void*)
2501 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2503 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2504 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2505 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2506 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2507 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2508 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2509 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2510 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2511 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2512 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2513 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2514 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2515 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2516 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2517 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2518 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2519 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2520 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2521 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2522 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2523 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2524 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2525 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2526 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2527 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2528 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2529 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2530 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2531 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2532 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2533 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2534 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2535 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2536 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2537 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2538 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2539 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2540 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2541 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2542 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2543 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2544 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2545 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2548 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2553 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2554 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2556 # define XCAST(fun) (void*)
2559 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2561 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2562 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2563 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2564 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2565 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2566 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2567 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2568 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2569 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2570 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2571 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2572 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2573 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2574 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2575 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2576 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2577 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2578 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2579 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2580 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2581 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2582 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2583 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2584 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2585 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2586 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2587 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2588 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2589 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2590 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2591 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2592 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2593 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2594 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2597 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2602 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2603 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2605 # define XCAST(fun) (void*)
2608 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2610 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2611 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2612 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2613 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2614 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2615 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2616 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2617 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2618 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2619 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2620 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2621 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2622 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2623 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2624 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2625 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2626 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2627 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2628 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2629 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2630 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2631 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2632 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2635 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2639 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2640 WINE_GL_BUFFER_TYPE buffer_type,
2648 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2649 GLbitfield bitfield = 0;
2653 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2654 if (TRACE_ON(ddraw)) {
2657 TRACE(" rectangles : \n");
2658 for (i = 0; i < dwCount; i++) {
2659 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2668 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2669 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2673 /* Clears the screen */
2676 if (dwFlags & D3DCLEAR_TARGET) {
2677 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2678 /* TODO: optimize here the case where Clear changes all the screen... */
2679 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2681 glThis->state[buffer_type] = SURFACE_GL;
2684 if (dwFlags & D3DCLEAR_ZBUFFER) {
2685 bitfield |= GL_DEPTH_BUFFER_BIT;
2686 if (glThis->depth_mask == FALSE) {
2687 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2689 if (dvZ != glThis->prev_clear_Z) {
2691 glThis->prev_clear_Z = dvZ;
2693 TRACE(" depth value : %f\n", dvZ);
2695 if (dwFlags & D3DCLEAR_STENCIL) {
2696 bitfield |= GL_STENCIL_BUFFER_BIT;
2697 if (dwStencil != glThis->prev_clear_stencil) {
2698 glClearStencil(dwStencil);
2699 glThis->prev_clear_stencil = dwStencil;
2701 TRACE(" stencil value : %ld\n", dwStencil);
2703 if (dwFlags & D3DCLEAR_TARGET) {
2704 bitfield |= GL_COLOR_BUFFER_BIT;
2705 if (dwColor != glThis->prev_clear_color) {
2706 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2707 ((dwColor >> 8) & 0xFF) / 255.0,
2708 ((dwColor >> 0) & 0xFF) / 255.0,
2709 ((dwColor >> 24) & 0xFF) / 255.0);
2710 glThis->prev_clear_color = dwColor;
2712 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2715 glEnable(GL_SCISSOR_TEST);
2716 for (i = 0; i < dwCount; i++) {
2717 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2718 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2721 glDisable(GL_SCISSOR_TEST);
2723 if (dwFlags & D3DCLEAR_ZBUFFER) {
2724 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2732 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2740 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2744 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2745 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2747 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2748 WINE_GL_BUFFER_TYPE buffer_type;
2750 /* First check if we BLT to the backbuffer... */
2751 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2752 buffer_type = WINE_GL_BUFFER_BACK;
2753 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2754 buffer_type = WINE_GL_BUFFER_FRONT;
2756 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2757 return DDERR_INVALIDPARAMS;
2760 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2761 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2762 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2763 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2764 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2765 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2768 return DDERR_INVALIDPARAMS;
2770 *buffer_type_p = buffer_type;
2776 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2777 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2778 DWORD dwFlags, LPDDBLTFX lpbltfx)
2780 WINE_GL_BUFFER_TYPE buffer_type;
2784 rect.u1.x1 = rdst->left;
2785 rect.u2.y1 = rdst->top;
2786 rect.u3.x2 = rdst->right;
2787 rect.u4.y2 = rdst->bottom;
2791 rect.u3.x2 = This->surface_desc.dwWidth;
2792 rect.u4.y2 = This->surface_desc.dwHeight;
2795 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2797 if (dwFlags & DDBLT_COLORFILL) {
2798 /* This is easy to handle for the D3D Device... */
2802 /* The color as given in the Blt function is in the format of the frame-buffer...
2803 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2805 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2806 if (This->palette) {
2807 color = ((0xFF000000) |
2808 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2809 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2810 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2814 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2815 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2816 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2817 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2818 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2819 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2820 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2821 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2824 color = ((0xFF000000) |
2825 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2826 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2827 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2829 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2830 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2831 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2832 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2833 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2834 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2836 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2837 return DDERR_INVALIDPARAMS;
2840 ERR("Wrong surface type for BLT override !\n");
2841 return DDERR_INVALIDPARAMS;
2844 TRACE(" executing D3D Device override.\n");
2848 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2849 if (buffer_type == WINE_GL_BUFFER_FRONT)
2850 glDrawBuffer(GL_FRONT);
2852 glDrawBuffer(GL_BACK);
2854 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2856 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2857 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2858 glDrawBuffer(prev_draw);
2863 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2864 /* Normal blit without any special case... */
2866 /* And which has a SRC surface */
2867 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2869 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2870 (src_impl->d3ddevice == This->d3ddevice) &&
2871 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2872 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2876 WINE_GL_BUFFER_TYPE src_buffer_type;
2877 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2883 src_rect.u1.x1 = rsrc->left;
2884 src_rect.u2.y1 = rsrc->top;
2885 src_rect.u3.x2 = rsrc->right;
2886 src_rect.u4.y2 = rsrc->bottom;
2890 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2891 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2894 width = src_rect.u3.x2 - src_rect.u1.x1;
2895 height = src_rect.u4.y2 - src_rect.u2.y1;
2897 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2898 (height != (rect.u4.y2 - rect.u2.y1))) {
2899 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2900 return DDERR_INVALIDPARAMS;
2903 /* First check if we BLT from the backbuffer... */
2904 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2905 src_buffer_type = WINE_GL_BUFFER_BACK;
2906 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2907 src_buffer_type = WINE_GL_BUFFER_FRONT;
2909 ERR("Unexpected case in direct buffer to buffer copy !\n");
2910 return DDERR_INVALIDPARAMS;
2913 TRACE(" using direct buffer to buffer copy.\n");
2917 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2919 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2920 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2921 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2923 return DDERR_INVALIDPARAMS;
2926 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2927 if (buffer_type == WINE_GL_BUFFER_FRONT)
2928 glDrawBuffer(GL_FRONT);
2930 glDrawBuffer(GL_BACK);
2932 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2933 glReadBuffer(GL_FRONT);
2935 glReadBuffer(GL_BACK);
2937 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2938 And directly re-draws this on the destination buffer. */
2939 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2942 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2943 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2945 get_height = UNLOCK_TEX_SIZE;
2947 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2950 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2951 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2953 get_width = UNLOCK_TEX_SIZE;
2955 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2956 0, UNLOCK_TEX_SIZE - get_height,
2957 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2958 get_width, get_height);
2961 glTexCoord2f(0.0, 0.0);
2962 glVertex3d(rect.u1.x1 + x,
2963 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2965 glTexCoord2f(1.0, 0.0);
2966 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2967 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2969 glTexCoord2f(1.0, 1.0);
2970 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2973 glTexCoord2f(0.0, 1.0);
2974 glVertex3d(rect.u1.x1 + x,
2981 upload_surface_to_tex_memory_release();
2982 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2984 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2985 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2986 glDrawBuffer(prev_draw);
2992 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
2993 (this prevents calling glReadPixels) */
2997 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3001 double x_stretch, y_stretch;
3004 src_rect.u1.x1 = rsrc->left;
3005 src_rect.u2.y1 = rsrc->top;
3006 src_rect.u3.x2 = rsrc->right;
3007 src_rect.u4.y2 = rsrc->bottom;
3011 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3012 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3015 width = src_rect.u3.x2 - src_rect.u1.x1;
3016 height = src_rect.u4.y2 - src_rect.u2.y1;
3018 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3019 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3021 TRACE(" using memory to buffer Blt overide.\n");
3025 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3027 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3028 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3029 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3031 return DDERR_INVALIDPARAMS;
3034 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3035 if (buffer_type == WINE_GL_BUFFER_FRONT)
3036 glDrawBuffer(GL_FRONT);
3038 glDrawBuffer(GL_BACK);
3040 /* Now the serious stuff happens. This is basically the same code that for the memory
3041 flush to frame buffer ... with stretching and different rectangles added :-) */
3042 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3045 flush_rect.top = src_rect.u2.y1 + y;
3046 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3048 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3050 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3051 flush_rect.left = src_rect.u1.x1 + x;
3052 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3054 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3056 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3059 glTexCoord2f(0.0, 0.0);
3060 glVertex3d(rect.u1.x1 + (x * x_stretch),
3061 rect.u2.y1 + (y * y_stretch),
3063 glTexCoord2f(1.0, 0.0);
3064 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3065 rect.u2.y1 + (y * y_stretch),
3067 glTexCoord2f(1.0, 1.0);
3068 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3069 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3071 glTexCoord2f(0.0, 1.0);
3072 glVertex3d(rect.u1.x1 + (x * x_stretch),
3073 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3079 upload_surface_to_tex_memory_release();
3080 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3082 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3083 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3084 glDrawBuffer(prev_draw);
3092 return DDERR_INVALIDPARAMS;
3096 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3097 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3098 LPRECT rsrc, DWORD trans)
3102 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3103 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3104 WINE_GL_BUFFER_TYPE buffer_type;
3108 int width, height, x, y;
3110 /* Cannot support DSTCOLORKEY blitting... */
3111 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3114 WARN("rsrc is NULL - getting the whole surface !!\n");
3116 rsrc->left = rsrc->top = 0;
3117 rsrc->right = src_impl->surface_desc.dwWidth;
3118 rsrc->bottom = src_impl->surface_desc.dwHeight;
3126 rdst.right = dstx + (rsrc->right - rsrc->left);
3127 if (rdst.right > This->surface_desc.dwWidth) {
3128 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3129 rdst.right = This->surface_desc.dwWidth;
3131 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3132 if (rdst.bottom > This->surface_desc.dwHeight) {
3133 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3134 rdst.bottom = This->surface_desc.dwHeight;
3137 width = rsrc->right - rsrc->left;
3138 height = rsrc->bottom - rsrc->top;
3140 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3142 TRACE(" using BltFast memory to frame buffer overide.\n");
3146 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3148 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3149 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3150 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3151 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3153 return DDERR_INVALIDPARAMS;
3156 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3157 if (buffer_type == WINE_GL_BUFFER_FRONT)
3158 glDrawBuffer(GL_FRONT);
3160 glDrawBuffer(GL_BACK);
3162 /* Now the serious stuff happens. This is basically the same code that for the memory
3163 flush to frame buffer but with different rectangles for source and destination :-) */
3164 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3167 flush_rect.top = rsrc->top + y;
3168 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3170 (rsrc->top + y + UNLOCK_TEX_SIZE));
3172 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3173 flush_rect.left = rsrc->left + x;
3174 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3176 (rsrc->left + x + UNLOCK_TEX_SIZE));
3178 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3181 glTexCoord2f(0.0, 0.0);
3182 glVertex3d(rdst.left + x,
3185 glTexCoord2f(1.0, 0.0);
3186 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3189 glTexCoord2f(1.0, 1.0);
3190 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3191 rdst.top + (y + UNLOCK_TEX_SIZE),
3193 glTexCoord2f(0.0, 1.0);
3194 glVertex3d(rdst.left + x,
3195 rdst.top + (y + UNLOCK_TEX_SIZE),
3201 upload_surface_to_tex_memory_release();
3202 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3204 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3205 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3206 glDrawBuffer(prev_draw);
3214 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3216 GLfloat height, width;
3217 GLfloat trans_mat[16];
3219 TRACE("(%p)\n", This);
3221 width = This->surface->surface_desc.dwWidth;
3222 height = This->surface->surface_desc.dwHeight;
3224 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3225 to OpenGL screen coordinates (ie the upper left corner is not the same).
3226 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3227 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3228 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3229 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3230 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3231 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3234 glMatrixMode(GL_MODELVIEW);
3236 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3237 Correctness Tips section).
3239 Basically, from what I understood, if the game does not filter the font texture,
3240 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3241 one and we will have strange artifacts (as the rounding and stuff may give different results
3242 for different pixels, ie sometimes take the left pixel, sometimes the right).
3244 glTranslatef(0.375, 0.375, 0);
3245 glMatrixMode(GL_PROJECTION);
3246 glLoadMatrixf(trans_mat);
3251 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3252 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3254 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3257 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3258 glMatrixMode(GL_MODELVIEW);
3259 glLoadMatrixf((float *) view_mat);
3261 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3262 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3265 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3266 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3269 plane[0] = This->clipping_planes[i].plane[0];
3270 plane[1] = This->clipping_planes[i].plane[1];
3271 plane[2] = This->clipping_planes[i].plane[2];
3272 plane[3] = This->clipping_planes[i].plane[3];
3274 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3278 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3282 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3283 if (runner & This->active_lights) {
3284 switch (This->light_parameters[i].dltType) {
3285 case D3DLIGHT_DIRECTIONAL: {
3287 float cut_off = 180.0;
3289 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3290 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3291 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3292 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3294 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3295 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3296 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3298 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3301 case D3DLIGHT_POINT: {
3303 float cut_off = 180.0;
3305 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3306 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3307 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3308 position[0] = This->light_parameters[i].dvPosition.u1.x;
3309 position[1] = This->light_parameters[i].dvPosition.u2.y;
3310 position[2] = This->light_parameters[i].dvPosition.u3.z;
3312 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3313 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3314 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3315 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3316 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3319 case D3DLIGHT_SPOT: {
3322 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3324 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3325 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3326 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3328 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3329 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3330 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3332 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3333 position[0] = This->light_parameters[i].dvPosition.u1.x;
3334 position[1] = This->light_parameters[i].dvPosition.u2.y;
3335 position[2] = This->light_parameters[i].dvPosition.u3.z;
3337 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3338 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3339 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3340 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3341 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3342 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3346 /* No warning here as it's already done at light setting */
3353 glMultMatrixf((float *) world_mat);
3355 if ((matrices & PROJMAT_CHANGED) != 0) {
3356 glMatrixMode(GL_PROJECTION);
3357 glLoadMatrixf((float *) proj_mat);
3363 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3365 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3366 DWORD tex_mat, tex_stage;
3368 TRACE("(%p,%08lx)\n", This, matrices);
3370 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3371 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3372 /* This will force an update of the transform state at the next drawing. */
3373 glThis->transform_state = GL_TRANSFORM_NONE;
3376 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3377 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3380 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3381 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3382 if (matrices & tex_mat) {
3383 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3384 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3386 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3387 if (glThis->current_active_tex_unit != unit) {
3388 GL_extensions.glActiveTexture(unit);
3389 glThis->current_active_tex_unit = unit;
3391 glMatrixMode(GL_TEXTURE);
3392 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3394 This->tex_mat_is_identity[tex_stage] = is_identity;
3396 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3397 if (glThis->current_active_tex_unit != unit) {
3398 GL_extensions.glActiveTexture(unit);
3399 glThis->current_active_tex_unit = unit;
3401 glMatrixMode(GL_TEXTURE);
3403 This->tex_mat_is_identity[tex_stage] = TRUE;
3412 /* TODO for both these functions :
3413 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3414 by other OpenGL code in D3D
3415 - handle the case where no 'Begin / EndScene' was done between two locks
3416 - handle the rectangles in the unlock too
3417 - handle pitch correctly...
3419 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3421 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3422 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3423 WINE_GL_BUFFER_TYPE buffer_type;
3426 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3427 buffer_type = WINE_GL_BUFFER_FRONT;
3428 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3429 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3430 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3432 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3433 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3434 buffer_type = WINE_GL_BUFFER_BACK;
3435 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3436 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3437 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3439 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3441 ERR("Wrong surface type for locking !\n");
3445 if (pRect == NULL) {
3448 loc_rect.bottom = This->surface_desc.dwHeight;
3449 loc_rect.right = This->surface_desc.dwWidth;
3453 /* Try to acquire the device critical section */
3454 EnterCriticalSection(&(d3d_dev->crit));
3456 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3457 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3458 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3460 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3462 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3463 /* Check if the new rectangle is in the previous one or not.
3464 If it is not, flush first the previous locks on screen.
3466 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3467 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3468 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3469 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3470 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3471 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3472 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3473 pRect->left, pRect->top, pRect->right, pRect->bottom,
3474 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3475 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3476 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3478 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3479 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3481 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3483 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3486 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3487 /* If the surface is already in memory, no need to do anything here... */
3488 GLenum buffer_format;
3489 GLenum buffer_color;
3493 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3494 pRect->left, pRect->top, pRect->right, pRect->bottom);
3496 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3497 may only write to the device... But when we will blit it back to the screen, we need
3498 also to blit correctly the parts the application did not overwrite... */
3500 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3501 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3502 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3503 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3504 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3505 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3506 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3507 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3508 buffer_color = GL_RGB;
3509 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3510 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3511 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3512 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3513 buffer_format = GL_UNSIGNED_BYTE;
3514 buffer_color = GL_RGB;
3515 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3516 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3517 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3518 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3519 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3520 buffer_color = GL_BGRA;
3522 ERR(" unsupported pixel format at device locking.\n");
3526 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3532 if (buffer_type == WINE_GL_BUFFER_FRONT)
3533 /* Application wants to lock the front buffer */
3534 glReadBuffer(GL_FRONT);
3536 /* Application wants to lock the back buffer */
3537 glReadBuffer(GL_BACK);
3539 dst = ((char *)This->surface_desc.lpSurface) +
3540 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3541 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3542 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3544 glReadPixels(pRect->left, y,
3545 pRect->right - pRect->left, 1,
3546 buffer_color, buffer_format, dst);
3547 dst += This->surface_desc.u1.lPitch;
3550 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3553 /* I keep this code here as it's very useful to debug :-) */
3555 static int flush_count = 0;
3559 if ((++flush_count % 50) == 0) {
3560 sprintf(buf, "lock_%06d.pnm", flush_count);
3561 f = fopen(buf, "wb");
3562 DDRAW_dump_surface_to_disk(This, f);
3571 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3573 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3578 /* Note : no need here to lock the 'device critical section' as we are already protected by
3579 the GL critical section. */
3581 if (pRect == NULL) {
3584 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3585 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3589 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3591 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3593 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3594 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3595 ERR(" unsupported pixel format at frame buffer flush.\n");
3599 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3603 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3605 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3606 /* First, upload the texture... */
3607 flush_rect.left = x;
3608 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3610 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3613 glTexCoord2f(0.0, 0.0);
3614 glVertex3d(x, y, 0.5);
3615 glTexCoord2f(1.0, 0.0);
3616 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3617 glTexCoord2f(1.0, 1.0);
3618 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3619 glTexCoord2f(0.0, 1.0);
3620 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3625 upload_surface_to_tex_memory_release();
3626 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3629 /* I keep this code here as it's very useful to debug :-) */
3631 static int flush_count = 0;
3635 if ((++flush_count % 50) == 0) {
3636 sprintf(buf, "flush_%06d.pnm", flush_count);
3637 f = fopen(buf, "wb");
3638 DDRAW_dump_surface_to_disk(surf, f);
3644 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3646 WINE_GL_BUFFER_TYPE buffer_type;
3647 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3648 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3650 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3651 buffer_type = WINE_GL_BUFFER_FRONT;
3652 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3653 buffer_type = WINE_GL_BUFFER_BACK;
3655 ERR("Wrong surface type for locking !\n");
3659 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3660 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3661 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3663 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3665 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3666 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3667 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3670 TRACE(" flushing front buffer immediatly on screen.\n");
3673 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3674 glDrawBuffer(GL_FRONT);
3675 /* Note: we do not use the application provided lock rectangle but our own stored at
3676 lock time. This is because in old D3D versions, the 'lock' parameter did not
3679 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]);
3680 glDrawBuffer(prev_draw);
3683 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3687 /* And 'frees' the device critical section */
3688 LeaveCriticalSection(&(d3d_dev->crit));
3692 apply_texture_state(IDirect3DDeviceImpl *This)
3696 /* Initialize texture stages states */
3697 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3698 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3699 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3700 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3701 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3708 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3710 IDirect3DDeviceImpl *object;
3711 IDirect3DDeviceGLImpl *gl_object;
3712 IDirectDrawSurfaceImpl *surf;
3717 XVisualInfo template;
3718 GLenum buffer = GL_FRONT;
3721 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3722 if (object == NULL) return DDERR_OUTOFMEMORY;
3724 gl_object = (IDirect3DDeviceGLImpl *) object;
3728 object->surface = surface;
3729 object->set_context = set_context;
3730 object->clear = d3ddevice_clear_back;
3731 object->set_matrices = d3ddevice_set_matrices;
3732 object->matrices_updated = d3ddevice_matrices_updated;
3733 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3735 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3737 InitializeCriticalSection(&(object->crit));
3739 TRACE(" device critical section : %p\n", &(object->crit));
3741 device_context = GetDC(surface->ddraw_owner->window);
3742 gl_object->display = get_display(device_context);
3743 gl_object->drawable = get_drawable(device_context);
3744 ReleaseDC(surface->ddraw_owner->window,device_context);
3747 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3748 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3750 HeapFree(GetProcessHeap(), 0, object);
3751 ERR("No visual found !\n");
3753 return DDERR_INVALIDPARAMS;
3755 TRACE(" visual found\n");
3758 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3761 if (gl_object->gl_context == NULL) {
3762 HeapFree(GetProcessHeap(), 0, object);
3763 ERR("Error in context creation !\n");
3765 return DDERR_INVALIDPARAMS;
3767 TRACE(" context created (%p)\n", gl_object->gl_context);
3770 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3771 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3772 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3773 surf->aux_ctx = (LPVOID) object;
3774 surf->aux_data = (LPVOID) gl_object->drawable;
3775 surf->aux_flip = opengl_flip;
3780 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3782 TRACE(" no double buffering : drawing on the front buffer\n");
3786 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3787 IDirectDrawSurfaceImpl *surf2;
3788 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3789 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3790 TRACE(" checking surface %p :", surf2);
3791 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3792 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3793 /* Override the Lock / Unlock function for all these surfaces */
3794 surf2->lock_update_prev = surf2->lock_update;
3795 surf2->lock_update = d3ddevice_lock_update;
3796 surf2->unlock_update_prev = surf2->unlock_update;
3797 surf2->unlock_update = d3ddevice_unlock_update;
3798 /* And install also the blt / bltfast overrides */
3799 surf2->aux_blt = d3ddevice_blt;
3800 surf2->aux_bltfast = d3ddevice_bltfast;
3802 TRACE(" overiding direct surface access.\n");
3804 TRACE(" no overide.\n");
3806 surf2->d3ddevice = object;
3810 /* Set the various light parameters */
3811 for (light = 0; light < MAX_LIGHTS; light++) {
3812 /* Only set the fields that are not zero-created */
3813 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3814 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3815 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3816 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3817 object->light_parameters[light].dvDirection.u3.z = 1.0;
3820 /* Allocate memory for the matrices */
3821 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3822 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3823 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3824 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3825 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3826 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3827 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3828 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3829 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3830 object->tex_mat_is_identity[tex_num] = TRUE;
3833 /* Initialisation */
3834 TRACE(" setting current context\n");
3835 object->set_context(object);
3836 TRACE(" current context set\n");
3838 /* allocate the clipping planes */
3839 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3840 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3842 glHint(GL_FOG_HINT,GL_NICEST);
3844 /* Initialize the various GL contexts to be in sync with what we store locally */
3847 glClearColor(0.0, 0.0, 0.0, 0.0);
3848 glDepthMask(GL_TRUE);
3849 gl_object->depth_mask = TRUE;
3850 glEnable(GL_DEPTH_TEST);
3851 gl_object->depth_test = TRUE;
3852 glDisable(GL_ALPHA_TEST);
3853 glDisable(GL_STENCIL_TEST);
3854 glDisable(GL_CULL_FACE);
3855 glDisable(GL_LIGHTING);
3856 glDisable(GL_BLEND);
3858 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3859 gl_object->current_tex_env = GL_REPLACE;
3860 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3861 if (GL_extensions.glActiveTexture != NULL) {
3862 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3865 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3866 glDrawBuffer(buffer);
3867 glReadBuffer(buffer);
3868 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3871 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3872 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3874 /* fill_device_capabilities(d3d->ddraw); */
3876 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3877 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3878 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3879 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3883 TRACE(" creating implementation at %p.\n", *obj);
3885 /* And finally warn D3D that this device is now present */
3886 object->d3d->d3d_added_device(object->d3d, object);
3888 /* FIXME: Should handle other versions than just 7 */
3889 InitDefaultStateBlock(&object->state_block, 7);
3890 /* Apply default render state and texture stage state values */
3891 apply_render_state(object, &object->state_block);
3892 apply_texture_state(object);
3894 /* And fill the fog table with the default fog value */
3895 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3900 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3902 pc->dwSize = sizeof(*pc);
3903 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3904 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3905 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3906 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3907 D3DPRASTERCAPS_ZFOG;
3908 if (GL_extensions.mipmap_lodbias == TRUE) {
3909 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3911 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3912 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3913 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3914 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3915 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3916 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3917 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3918 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3919 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3920 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3921 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3922 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3923 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3924 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3925 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3926 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3927 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3928 D3DPTFILTERCAPS_MIPFPOINT;
3929 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3930 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3931 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3932 if (GL_extensions.mirrored_repeat == TRUE) {
3933 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
3935 pc->dwStippleWidth = 32;
3936 pc->dwStippleHeight = 32;
3939 static void fill_caps(void)
3941 GLint max_clip_planes;
3944 /* Fill first all the fields with default values which will be overriden later on with
3945 correct ones from the GL code
3947 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
3948 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
3949 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3950 /* D3D 7 capabilities */
3951 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
3952 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
3953 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
3954 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
3955 opengl_device_caps.dwMinTextureWidth = 1;
3956 opengl_device_caps.dwMinTextureHeight = 1;
3957 opengl_device_caps.dwMaxTextureWidth = 1024;
3958 opengl_device_caps.dwMaxTextureHeight = 1024;
3959 opengl_device_caps.dwMaxTextureRepeat = 16;
3960 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
3961 opengl_device_caps.dwMaxAnisotropy = 0;
3962 opengl_device_caps.dvGuardBandLeft = 0.0;
3963 opengl_device_caps.dvGuardBandRight = 0.0;
3964 opengl_device_caps.dvGuardBandTop = 0.0;
3965 opengl_device_caps.dvGuardBandBottom = 0.0;
3966 opengl_device_caps.dvExtentsAdjust = 0.0;
3967 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
3968 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
3969 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
3970 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
3971 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
3972 if (GL_extensions.max_texture_units != 0) {
3973 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
3974 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
3975 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
3977 opengl_device_caps.wMaxTextureBlendStages = 1;
3978 opengl_device_caps.wMaxSimultaneousTextures = 1;
3979 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
3981 opengl_device_caps.dwMaxActiveLights = 16;
3982 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
3983 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
3984 opengl_device_caps.wMaxUserClipPlanes = 1;
3985 opengl_device_caps.wMaxVertexBlendMatrices = 0;
3986 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
3987 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
3988 opengl_device_caps.dwReserved1 = 0;
3989 opengl_device_caps.dwReserved2 = 0;
3990 opengl_device_caps.dwReserved3 = 0;
3991 opengl_device_caps.dwReserved4 = 0;
3993 /* And now some GL overides :-) */
3994 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
3995 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
3996 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
3997 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
3999 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4000 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4002 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4003 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4004 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4006 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4007 TRACE(": Z bits = %d\n", depth_bits);
4008 switch (depth_bits) {
4009 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4010 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_24; break;
4011 case 32: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_32; break;
4012 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4017 d3ddevice_init_at_startup(void *gl_handle)
4019 XVisualInfo template;
4024 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4025 XWindowAttributes win_attr;
4026 GLXContext gl_context;
4028 const char *glExtensions;
4029 const char *glVersion;
4030 const char *glXExtensions = NULL;
4031 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4032 int major, minor, patch;
4034 TRACE("Initializing GL...\n");
4036 /* Get a default rendering context to have the 'caps' function query some info from GL */
4037 device_context = GetDC(0);
4038 display = get_display(device_context);
4039 ReleaseDC(0, device_context);
4042 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4043 visual = win_attr.visual;
4045 visual = DefaultVisual(display, DefaultScreen(display));
4047 template.visualid = XVisualIDFromVisual(visual);
4048 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4051 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4054 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4056 if (gl_context == NULL) {
4058 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4061 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4062 glXDestroyContext(display, gl_context);
4064 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4068 /* Then, query all extensions */
4069 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4070 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4071 glVersion = (const char *) glGetString(GL_VERSION);
4072 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4073 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4076 /* Parse the GL version string */
4077 sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4078 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4080 /* And starts to fill the extension context properly */
4081 memset(&GL_extensions, 0, sizeof(GL_extensions));
4082 TRACE("GL supports following extensions used by Wine :\n");
4084 /* Mirrored Repeat extension :
4085 - GL_ARB_texture_mirrored_repeat
4086 - GL_IBM_texture_mirrored_repeat
4089 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4090 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4092 ((major == 1) && (minor >= 4))) {
4093 TRACE(" - mirrored repeat\n");
4094 GL_extensions.mirrored_repeat = TRUE;
4097 /* Texture LOD Bias :
4098 - GL_EXT_texture_lod_bias
4100 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4101 TRACE(" - texture lod bias\n");
4102 GL_extensions.mipmap_lodbias = TRUE;
4105 /* For all subsequent extensions, we need glXGetProcAddress */
4106 if (pglXGetProcAddressARB != NULL) {
4107 /* Multi-texturing :
4108 - GL_ARB_multitexture
4111 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4113 ((major == 1) && (minor > 2)) ||
4114 ((major == 1) && (minor == 2) && (patch >= 1))) {
4115 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4116 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4117 /* We query the ARB version to be the most portable we can... */
4118 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4119 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4123 /* Fill the D3D capabilities according to what GL tells us... */
4126 /* And frees this now-useless context */
4127 glXMakeCurrent(display, None, NULL);
4128 glXDestroyContext(display, gl_context);