2 * Copyright (c) 1998-2004 Lionel ULMER
3 * Copyright (c) 2002-2004 Christian Costa
5 * This file contains the MESA implementation of all the D3D devices that
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
39 #include "wine/debug.h"
40 #include "wine/library.h"
42 #include "mesa_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom
);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
54 X11DRV_GET_FONT
, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL
= {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat
[16] = {
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps
;
74 GL_EXTENSIONS_LIST GL_extensions
;
76 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
77 D3DPRIMITIVETYPE d3dptPrimitiveType
,
78 DWORD d3dvtVertexType
,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
85 static DWORD
draw_primitive_handle_textures(IDirect3DDeviceImpl
*This
);
87 /* retrieve the X display to use on a given DC */
88 inline static Display
*get_display( HDC hdc
)
91 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
93 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
94 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD
d3ddevice_set_state_for_flush(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, BOOLEAN use_alpha
, BOOLEAN
*initial
) {
105 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
106 DWORD opt_bitmap
= 0x00000000;
108 if ((gl_d3d_dev
->current_bound_texture
[1] != NULL
) &&
109 ((d3d_dev
->state_block
.texture_stage_state
[1][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
))) {
110 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE1_WINE
) {
111 GL_extensions
.glActiveTexture(GL_TEXTURE1_WINE
);
112 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE1_WINE
;
114 /* Disable multi-texturing for level 1 to disable all others */
115 glDisable(GL_TEXTURE_2D
);
117 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
118 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
119 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
121 if ((gl_d3d_dev
->current_bound_texture
[0] == NULL
) ||
122 (d3d_dev
->state_block
.texture_stage_state
[0][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
))
123 glEnable(GL_TEXTURE_2D
);
124 if (gl_d3d_dev
->unlock_tex
== 0) {
125 glGenTextures(1, &gl_d3d_dev
->unlock_tex
);
126 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
128 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
129 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
130 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
131 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
133 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
136 if (d3d_dev
->tex_mat_is_identity
[0] == FALSE
) {
137 glMatrixMode(GL_TEXTURE
);
141 if (gl_d3d_dev
->transform_state
!= GL_TRANSFORM_ORTHO
) {
142 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
143 d3ddevice_set_ortho(d3d_dev
);
146 if (gl_d3d_dev
->depth_test
!= FALSE
) glDisable(GL_DEPTH_TEST
);
147 glEnable(GL_SCISSOR_TEST
);
148 if ((d3d_dev
->active_viewport
.dvMinZ
!= 0.0) ||
149 (d3d_dev
->active_viewport
.dvMaxZ
!= 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap
|= DEPTH_RANGE_BIT
;
153 if ((d3d_dev
->active_viewport
.dwX
!= 0) ||
154 (d3d_dev
->active_viewport
.dwY
!= 0) ||
155 (d3d_dev
->active_viewport
.dwWidth
!= d3d_dev
->surface
->surface_desc
.dwWidth
) ||
156 (d3d_dev
->active_viewport
.dwHeight
!= d3d_dev
->surface
->surface_desc
.dwHeight
)) {
157 glViewport(0, 0, d3d_dev
->surface
->surface_desc
.dwWidth
, d3d_dev
->surface
->surface_desc
.dwHeight
);
158 opt_bitmap
|= VIEWPORT_BIT
;
160 glScissor(pRect
->left
, d3d_dev
->surface
->surface_desc
.dwHeight
- pRect
->bottom
,
161 pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
);
162 if (gl_d3d_dev
->lighting
!= FALSE
) glDisable(GL_LIGHTING
);
163 if (gl_d3d_dev
->cull_face
!= FALSE
) glDisable(GL_CULL_FACE
);
165 if (gl_d3d_dev
->alpha_test
== FALSE
) glEnable(GL_ALPHA_TEST
);
166 if ((gl_d3d_dev
->current_alpha_test_func
!= GL_NOTEQUAL
) || (gl_d3d_dev
->current_alpha_test_ref
!= 0.0))
167 glAlphaFunc(GL_NOTEQUAL
, 0.0);
169 if (gl_d3d_dev
->alpha_test
!= FALSE
) glDisable(GL_ALPHA_TEST
);
171 if (gl_d3d_dev
->stencil_test
!= FALSE
) glDisable(GL_STENCIL_TEST
);
172 if (gl_d3d_dev
->blending
!= FALSE
) glDisable(GL_BLEND
);
173 if (gl_d3d_dev
->fogging
!= FALSE
) glDisable(GL_FOG
);
174 if (gl_d3d_dev
->current_tex_env
!= GL_REPLACE
)
175 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
180 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl
*d3d_dev
, DWORD opt_bitmap
, BOOLEAN use_alpha
) {
181 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
183 /* And restore all the various states modified by this code */
184 if (gl_d3d_dev
->depth_test
!= 0) glEnable(GL_DEPTH_TEST
);
185 if (gl_d3d_dev
->lighting
!= 0) glEnable(GL_LIGHTING
);
186 if ((gl_d3d_dev
->alpha_test
!= 0) && (use_alpha
== 0))
187 glEnable(GL_ALPHA_TEST
);
188 else if ((gl_d3d_dev
->alpha_test
== 0) && (use_alpha
!= 0))
189 glDisable(GL_ALPHA_TEST
);
191 if ((gl_d3d_dev
->current_alpha_test_func
!= GL_NOTEQUAL
) || (gl_d3d_dev
->current_alpha_test_ref
!= 0.0))
192 glAlphaFunc(gl_d3d_dev
->current_alpha_test_func
, gl_d3d_dev
->current_alpha_test_ref
);
194 if (gl_d3d_dev
->stencil_test
!= 0) glEnable(GL_STENCIL_TEST
);
195 if (gl_d3d_dev
->cull_face
!= 0) glEnable(GL_CULL_FACE
);
196 if (gl_d3d_dev
->blending
!= 0) glEnable(GL_BLEND
);
197 if (gl_d3d_dev
->fogging
!= 0) glEnable(GL_FOG
);
198 glDisable(GL_SCISSOR_TEST
);
199 if (opt_bitmap
& DEPTH_RANGE_BIT
) {
200 glDepthRange(d3d_dev
->active_viewport
.dvMinZ
, d3d_dev
->active_viewport
.dvMaxZ
);
202 if (opt_bitmap
& VIEWPORT_BIT
) {
203 glViewport(d3d_dev
->active_viewport
.dwX
,
204 d3d_dev
->surface
->surface_desc
.dwHeight
- (d3d_dev
->active_viewport
.dwHeight
+ d3d_dev
->active_viewport
.dwY
),
205 d3d_dev
->active_viewport
.dwWidth
, d3d_dev
->active_viewport
.dwHeight
);
207 if (d3d_dev
->tex_mat_is_identity
[0] == FALSE
) {
208 d3d_dev
->matrices_updated(d3d_dev
, TEXMAT0_CHANGED
);
211 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
212 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
213 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
215 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, gl_d3d_dev
->current_tex_env
);
216 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
217 bind if ever the game changes the texture just after.
219 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
220 gl_d3d_dev
->current_bound_texture
[0] = (IDirectDrawSurfaceImpl
*) 0x00000001;
221 if (d3d_dev
->state_block
.texture_stage_state
[0][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
) glDisable(GL_TEXTURE_2D
);
223 /* And re-enabled if needed texture level 1 */
224 if ((gl_d3d_dev
->current_bound_texture
[1] != NULL
) &&
225 (d3d_dev
->state_block
.texture_stage_state
[1][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
226 if (gl_d3d_dev
->current_active_tex_unit
!= GL_TEXTURE1_WINE
) {
227 GL_extensions
.glActiveTexture(GL_TEXTURE1_WINE
);
228 gl_d3d_dev
->current_active_tex_unit
= GL_TEXTURE1_WINE
;
230 glEnable(GL_TEXTURE_2D
);
234 /* retrieve the X drawable to use on a given DC */
235 inline static Drawable
get_drawable( HDC hdc
)
238 enum x11drv_escape_codes escape
= X11DRV_GET_DRAWABLE
;
240 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
241 sizeof(drawable
), (LPSTR
)&drawable
)) drawable
= 0;
246 static BOOL
opengl_flip( LPVOID dev
, LPVOID drawable
)
248 IDirect3DDeviceImpl
*d3d_dev
= (IDirect3DDeviceImpl
*) dev
;
249 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) dev
;
251 TRACE("(%p, %ld)\n", gl_d3d_dev
->display
,(Drawable
)drawable
);
253 if (gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] == SURFACE_MEMORY_DIRTY
) {
254 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
]);
256 gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
257 gl_d3d_dev
->state
[WINE_GL_BUFFER_FRONT
] = SURFACE_GL
;
258 glXSwapBuffers(gl_d3d_dev
->display
, (Drawable
)drawable
);
265 /*******************************************************************************
266 * OpenGL static functions
268 static void set_context(IDirect3DDeviceImpl
* This
)
270 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
272 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis
->display
,glThis
->drawable
, glThis
->gl_context
);
274 if (glXMakeCurrent(glThis
->display
, glThis
->drawable
, glThis
->gl_context
) == False
) {
275 ERR("Error in setting current context (context %p drawable %ld)!\n",
276 glThis
->gl_context
, glThis
->drawable
);
281 static void fill_opengl_caps(D3DDEVICEDESC
*d1
)
283 d1
->dwSize
= sizeof(*d1
);
284 d1
->dwFlags
= D3DDD_COLORMODEL
| D3DDD_DEVCAPS
| D3DDD_TRANSFORMCAPS
| D3DDD_BCLIPPING
| D3DDD_LIGHTINGCAPS
|
285 D3DDD_LINECAPS
| D3DDD_TRICAPS
| D3DDD_DEVICERENDERBITDEPTH
| D3DDD_DEVICEZBUFFERBITDEPTH
|
286 D3DDD_MAXBUFFERSIZE
| D3DDD_MAXVERTEXCOUNT
;
287 d1
->dcmColorModel
= D3DCOLOR_RGB
;
288 d1
->dwDevCaps
= opengl_device_caps
.dwDevCaps
;
289 d1
->dtcTransformCaps
.dwSize
= sizeof(D3DTRANSFORMCAPS
);
290 d1
->dtcTransformCaps
.dwCaps
= D3DTRANSFORMCAPS_CLIP
;
291 d1
->bClipping
= TRUE
;
292 d1
->dlcLightingCaps
.dwSize
= sizeof(D3DLIGHTINGCAPS
);
293 d1
->dlcLightingCaps
.dwCaps
= D3DLIGHTCAPS_DIRECTIONAL
| D3DLIGHTCAPS_PARALLELPOINT
| D3DLIGHTCAPS_POINT
| D3DLIGHTCAPS_SPOT
;
294 d1
->dlcLightingCaps
.dwLightingModel
= D3DLIGHTINGMODEL_RGB
;
295 d1
->dlcLightingCaps
.dwNumLights
= opengl_device_caps
.dwMaxActiveLights
;
296 d1
->dpcLineCaps
= opengl_device_caps
.dpcLineCaps
;
297 d1
->dpcTriCaps
= opengl_device_caps
.dpcTriCaps
;
298 d1
->dwDeviceRenderBitDepth
= opengl_device_caps
.dwDeviceRenderBitDepth
;
299 d1
->dwDeviceZBufferBitDepth
= opengl_device_caps
.dwDeviceZBufferBitDepth
;
300 d1
->dwMaxBufferSize
= 0;
301 d1
->dwMaxVertexCount
= 65536;
302 d1
->dwMinTextureWidth
= opengl_device_caps
.dwMinTextureWidth
;
303 d1
->dwMinTextureHeight
= opengl_device_caps
.dwMinTextureHeight
;
304 d1
->dwMaxTextureWidth
= opengl_device_caps
.dwMaxTextureWidth
;
305 d1
->dwMaxTextureHeight
= opengl_device_caps
.dwMaxTextureHeight
;
306 d1
->dwMinStippleWidth
= 1;
307 d1
->dwMinStippleHeight
= 1;
308 d1
->dwMaxStippleWidth
= 32;
309 d1
->dwMaxStippleHeight
= 32;
310 d1
->dwMaxTextureRepeat
= opengl_device_caps
.dwMaxTextureRepeat
;
311 d1
->dwMaxTextureAspectRatio
= opengl_device_caps
.dwMaxTextureAspectRatio
;
312 d1
->dwMaxAnisotropy
= opengl_device_caps
.dwMaxAnisotropy
;
313 d1
->dvGuardBandLeft
= opengl_device_caps
.dvGuardBandLeft
;
314 d1
->dvGuardBandRight
= opengl_device_caps
.dvGuardBandRight
;
315 d1
->dvGuardBandTop
= opengl_device_caps
.dvGuardBandTop
;
316 d1
->dvGuardBandBottom
= opengl_device_caps
.dvGuardBandBottom
;
317 d1
->dvExtentsAdjust
= opengl_device_caps
.dvExtentsAdjust
;
318 d1
->dwStencilCaps
= opengl_device_caps
.dwStencilCaps
;
319 d1
->dwFVFCaps
= opengl_device_caps
.dwFVFCaps
;
320 d1
->dwTextureOpCaps
= opengl_device_caps
.dwTextureOpCaps
;
321 d1
->wMaxTextureBlendStages
= opengl_device_caps
.wMaxTextureBlendStages
;
322 d1
->wMaxSimultaneousTextures
= opengl_device_caps
.wMaxSimultaneousTextures
;
325 static void fill_opengl_caps_7(D3DDEVICEDESC7
*d
)
327 *d
= opengl_device_caps
;
330 HRESULT
d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
, DWORD version
)
332 D3DDEVICEDESC dref
, d1
, d2
;
335 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
336 Let's put the string in a sufficiently sized array in writable memory. */
337 char device_name
[50];
338 strcpy(device_name
,"direct3d");
340 fill_opengl_caps(&dref
);
343 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
344 char interface_name
[] = "WINE Reference Direct3DX using OpenGL";
345 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice
));
348 ret_value
= cb((LPIID
) &IID_IDirect3DRefDevice
, interface_name
, device_name
, &d1
, &d2
, context
);
349 if (ret_value
!= D3DENUMRET_OK
)
354 char interface_name
[] = "WINE Direct3DX using OpenGL";
355 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
358 ret_value
= cb((LPIID
) &IID_D3DDEVICE_OpenGL
, interface_name
, device_name
, &d1
, &d2
, context
);
359 if (ret_value
!= D3DENUMRET_OK
)
363 return D3DENUMRET_OK
;
366 HRESULT
d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb
, LPVOID context
)
368 D3DDEVICEDESC7 ddesc
;
369 char interface_name
[] = "WINE Direct3D7 using OpenGL";
370 char device_name
[] = "Wine D3D7 device";
372 fill_opengl_caps_7(&ddesc
);
374 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
376 return cb(interface_name
, device_name
, &ddesc
, context
);
380 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface
)
382 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
383 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
384 ULONG ref
= InterlockedDecrement(&This
->ref
);
386 TRACE("(%p/%p)->() decrementing from %lu.\n", This
, iface
, ref
+ 1);
390 IDirectDrawSurfaceImpl
*surface
= This
->surface
, *surf
;
392 /* Release texture associated with the device */
393 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
394 if (This
->current_texture
[i
] != NULL
)
395 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[i
], IDirectDrawSurface7
));
396 HeapFree(GetProcessHeap(), 0, This
->tex_mat
[i
]);
399 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
400 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
401 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
402 surf
->aux_ctx
= NULL
;
403 surf
->aux_data
= NULL
;
404 surf
->aux_flip
= NULL
;
408 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
409 IDirectDrawSurfaceImpl
*surf2
;
410 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
411 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
412 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
413 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
414 /* Override the Lock / Unlock function for all these surfaces */
415 surf2
->lock_update
= surf2
->lock_update_prev
;
416 surf2
->unlock_update
= surf2
->unlock_update_prev
;
417 /* And install also the blt / bltfast overrides */
418 surf2
->aux_blt
= NULL
;
419 surf2
->aux_bltfast
= NULL
;
421 surf2
->d3ddevice
= NULL
;
425 /* And warn the D3D object that this device is no longer active... */
426 This
->d3d
->d3d_removed_device(This
->d3d
, This
);
428 HeapFree(GetProcessHeap(), 0, This
->world_mat
);
429 HeapFree(GetProcessHeap(), 0, This
->view_mat
);
430 HeapFree(GetProcessHeap(), 0, This
->proj_mat
);
432 if (glThis
->surface_ptr
)
433 HeapFree(GetProcessHeap(), 0, glThis
->surface_ptr
);
435 DeleteCriticalSection(&(This
->crit
));
438 if (glThis
->unlock_tex
)
439 glDeleteTextures(1, &(glThis
->unlock_tex
));
440 glXDestroyContext(glThis
->display
, glThis
->gl_context
);
442 HeapFree(GetProcessHeap(), 0, This
->clipping_planes
);
444 HeapFree(GetProcessHeap(), 0, This
);
451 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface
,
452 LPD3DDEVICEDESC lpD3DHWDevDesc
,
453 LPD3DDEVICEDESC lpD3DHELDevDesc
)
455 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
459 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DHWDevDesc
, lpD3DHELDevDesc
);
461 fill_opengl_caps(&desc
);
462 dwSize
= lpD3DHWDevDesc
->dwSize
;
463 memset(lpD3DHWDevDesc
, 0, dwSize
);
464 memcpy(lpD3DHWDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
466 dwSize
= lpD3DHELDevDesc
->dwSize
;
467 memset(lpD3DHELDevDesc
, 0, dwSize
);
468 memcpy(lpD3DHELDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
470 TRACE(" returning caps : (no dump function yet)\n");
475 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1
,
476 LPD3DENUMPIXELFORMATSCALLBACK cb_2
,
480 LPDDPIXELFORMAT pformat
;
482 /* Do the texture enumeration */
483 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
484 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
485 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
486 pformat
= &(sdesc
.ddpfPixelFormat
);
487 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
488 pformat
->dwFourCC
= 0;
490 TRACE("Enumerating GL_RGBA unpacked (32)\n");
491 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
492 pformat
->u1
.dwRGBBitCount
= 32;
493 pformat
->u2
.dwRBitMask
= 0x00FF0000;
494 pformat
->u3
.dwGBitMask
= 0x0000FF00;
495 pformat
->u4
.dwBBitMask
= 0x000000FF;
496 pformat
->u5
.dwRGBAlphaBitMask
= 0xFF000000;
497 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
498 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
500 TRACE("Enumerating GL_RGB unpacked (32)\n");
501 pformat
->dwFlags
= DDPF_RGB
;
502 pformat
->u1
.dwRGBBitCount
= 32;
503 pformat
->u2
.dwRBitMask
= 0x00FF0000;
504 pformat
->u3
.dwGBitMask
= 0x0000FF00;
505 pformat
->u4
.dwBBitMask
= 0x000000FF;
506 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
507 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
508 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
510 TRACE("Enumerating GL_RGB unpacked (24)\n");
511 pformat
->dwFlags
= DDPF_RGB
;
512 pformat
->u1
.dwRGBBitCount
= 24;
513 pformat
->u2
.dwRBitMask
= 0x00FF0000;
514 pformat
->u3
.dwGBitMask
= 0x0000FF00;
515 pformat
->u4
.dwBBitMask
= 0x000000FF;
516 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
517 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
518 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
520 /* Note : even if this is an 'emulated' texture format, it needs to be first
521 as some dumb applications seem to rely on that. */
522 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
523 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
524 pformat
->u1
.dwRGBBitCount
= 16;
525 pformat
->u2
.dwRBitMask
= 0x00007C00;
526 pformat
->u3
.dwGBitMask
= 0x000003E0;
527 pformat
->u4
.dwBBitMask
= 0x0000001F;
528 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
529 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
530 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
532 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
533 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
534 pformat
->u1
.dwRGBBitCount
= 16;
535 pformat
->u2
.dwRBitMask
= 0x00000F00;
536 pformat
->u3
.dwGBitMask
= 0x000000F0;
537 pformat
->u4
.dwBBitMask
= 0x0000000F;
538 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000F000;
539 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
540 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
542 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
543 pformat
->dwFlags
= DDPF_RGB
;
544 pformat
->u1
.dwRGBBitCount
= 16;
545 pformat
->u2
.dwRBitMask
= 0x0000F800;
546 pformat
->u3
.dwGBitMask
= 0x000007E0;
547 pformat
->u4
.dwBBitMask
= 0x0000001F;
548 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
549 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
550 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
552 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
553 pformat
->dwFlags
= DDPF_RGB
;
554 pformat
->u1
.dwRGBBitCount
= 16;
555 pformat
->u2
.dwRBitMask
= 0x00007C00;
556 pformat
->u3
.dwGBitMask
= 0x000003E0;
557 pformat
->u4
.dwBBitMask
= 0x0000001F;
558 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
559 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
560 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
563 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
564 find enumerated, others the last one. And both want to have the ARGB one.
566 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
568 /* See argument about the RGBA format for 'packed' texture formats */
569 TRACE("Enumerating GL_RGBA unpacked (32)\n");
570 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
571 pformat
->u1
.dwRGBBitCount
= 32;
572 pformat
->u2
.dwRBitMask
= 0xFF000000;
573 pformat
->u3
.dwGBitMask
= 0x00FF0000;
574 pformat
->u4
.dwBBitMask
= 0x0000FF00;
575 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
576 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
577 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
579 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
580 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
581 pformat
->u1
.dwRGBBitCount
= 16;
582 pformat
->u2
.dwRBitMask
= 0x0000F000;
583 pformat
->u3
.dwGBitMask
= 0x00000F00;
584 pformat
->u4
.dwBBitMask
= 0x000000F0;
585 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
586 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
587 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
589 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
590 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
591 pformat
->u1
.dwRGBBitCount
= 16;
592 pformat
->u2
.dwRBitMask
= 0x0000F800;
593 pformat
->u3
.dwGBitMask
= 0x000007C0;
594 pformat
->u4
.dwBBitMask
= 0x0000003E;
595 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
596 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
597 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
600 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
601 pformat
->dwFlags
= DDPF_RGB
;
602 pformat
->u1
.dwRGBBitCount
= 8;
603 pformat
->u2
.dwRBitMask
= 0x000000E0;
604 pformat
->u3
.dwGBitMask
= 0x0000001C;
605 pformat
->u4
.dwBBitMask
= 0x00000003;
606 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
607 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
608 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
610 TRACE("Enumerating Paletted (8)\n");
611 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
612 pformat
->u1
.dwRGBBitCount
= 8;
613 pformat
->u2
.dwRBitMask
= 0x00000000;
614 pformat
->u3
.dwGBitMask
= 0x00000000;
615 pformat
->u4
.dwBBitMask
= 0x00000000;
616 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
617 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
618 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
620 if (GL_extensions
.s3tc_compressed_texture
) {
621 TRACE("Enumerating DXT1\n");
622 pformat
->dwFlags
= DDPF_FOURCC
;
623 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','1');
624 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
625 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
627 TRACE("Enumerating DXT3\n");
628 pformat
->dwFlags
= DDPF_FOURCC
;
629 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','3');
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 DXT5\n");
634 pformat
->dwFlags
= DDPF_FOURCC
;
635 pformat
->dwFourCC
= MAKE_FOURCC('D','X','T','5');
636 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
637 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
640 TRACE("End of enumeration\n");
646 d3ddevice_find(IDirectDrawImpl
*d3d
,
647 LPD3DFINDDEVICESEARCH lpD3DDFS
,
648 LPD3DFINDDEVICERESULT lplpD3DDevice
)
652 if ((lpD3DDFS
->dwFlags
& D3DFDS_COLORMODEL
) &&
653 (lpD3DDFS
->dcmColorModel
!= D3DCOLOR_RGB
)) {
654 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
655 return DDERR_INVALIDPARAMS
; /* No real idea what to return here :-) */
657 if (lpD3DDFS
->dwFlags
& D3DFDS_GUID
) {
658 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS
->guid
)));
659 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
660 (IsEqualGUID(&IID_IDirect3DHALDevice
, &(lpD3DDFS
->guid
)) == 0) &&
661 (IsEqualGUID(&IID_IDirect3DRefDevice
, &(lpD3DDFS
->guid
)) == 0)) {
662 TRACE(" no match for this GUID.\n");
663 return DDERR_INVALIDPARAMS
;
667 /* Now return our own GUID */
668 lplpD3DDevice
->guid
= IID_D3DDEVICE_OpenGL
;
669 fill_opengl_caps(&desc
);
670 lplpD3DDevice
->ddHwDesc
= desc
;
671 lplpD3DDevice
->ddSwDesc
= desc
;
673 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
679 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface
,
680 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc
,
683 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
684 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumTextureProc
, lpArg
);
685 return enum_texture_format_OpenGL(lpD3DEnumTextureProc
, NULL
, lpArg
);
689 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface
,
690 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc
,
693 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
694 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumPixelProc
, lpArg
);
695 return enum_texture_format_OpenGL(NULL
, lpD3DEnumPixelProc
, lpArg
);
699 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface
,
700 D3DRENDERSTATETYPE dwRenderStateType
,
703 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
704 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwRenderStateType
, dwRenderState
);
706 /* Call the render state functions */
707 store_render_state(This
, dwRenderStateType
, dwRenderState
, &This
->state_block
);
708 set_render_state(This
, dwRenderStateType
, &This
->state_block
);
714 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface
,
715 D3DRENDERSTATETYPE dwRenderStateType
,
716 LPDWORD lpdwRenderState
)
718 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
719 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwRenderStateType
, lpdwRenderState
);
721 /* Call the render state functions */
722 get_render_state(This
, dwRenderStateType
, lpdwRenderState
, &This
->state_block
);
724 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType
), *lpdwRenderState
);
730 GL_IDirect3DDeviceImpl_3_2T_GetLightState(LPDIRECT3DDEVICE3 iface
,
731 D3DLIGHTSTATETYPE dwLightStateType
,
732 LPDWORD lpdwLightState
)
734 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
736 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwLightStateType
, lpdwLightState
);
738 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
)) {
739 TRACE("Unexpected Light State Type\n");
740 return DDERR_INVALIDPARAMS
;
743 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
744 *lpdwLightState
= This
->material
;
745 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
746 *lpdwLightState
= D3DCOLOR_RGB
;
748 D3DRENDERSTATETYPE rs
;
749 switch (dwLightStateType
) {
750 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
751 rs
= D3DRENDERSTATE_AMBIENT
;
753 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
754 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
756 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
757 rs
= D3DRENDERSTATE_FOGSTART
;
759 case D3DLIGHTSTATE_FOGEND
: /* 6 */
760 rs
= D3DRENDERSTATE_FOGEND
;
762 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
763 rs
= D3DRENDERSTATE_FOGDENSITY
;
765 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
766 rs
= D3DRENDERSTATE_COLORVERTEX
;
769 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType
);
770 return DDERR_INVALIDPARAMS
;
773 IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
781 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface
,
782 D3DLIGHTSTATETYPE dwLightStateType
,
785 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
787 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwLightStateType
, dwLightState
);
789 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
)) {
790 TRACE("Unexpected Light State Type\n");
791 return DDERR_INVALIDPARAMS
;
794 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
795 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) dwLightState
;
798 TRACE(" activating material %p.\n", mat
);
801 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
803 This
->material
= dwLightState
;
804 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
805 switch (dwLightState
) {
807 ERR("DDCOLOR_MONO should not happen!\n");
810 /* We are already in this mode */
811 TRACE("Setting color model to RGB (no-op).\n");
814 ERR("Unknown color model!\n");
815 return DDERR_INVALIDPARAMS
;
818 D3DRENDERSTATETYPE rs
;
819 switch (dwLightStateType
) {
820 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
821 rs
= D3DRENDERSTATE_AMBIENT
;
823 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
824 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
826 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
827 rs
= D3DRENDERSTATE_FOGSTART
;
829 case D3DLIGHTSTATE_FOGEND
: /* 6 */
830 rs
= D3DRENDERSTATE_FOGEND
;
832 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
833 rs
= D3DRENDERSTATE_FOGDENSITY
;
835 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
836 rs
= D3DRENDERSTATE_COLORVERTEX
;
839 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType
);
840 return DDERR_INVALIDPARAMS
;
843 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
850 static GLenum
convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt
)
853 case D3DPT_POINTLIST
:
854 TRACE(" primitive type is POINTS\n");
858 TRACE(" primitive type is LINES\n");
861 case D3DPT_LINESTRIP
:
862 TRACE(" primitive type is LINE_STRIP\n");
863 return GL_LINE_STRIP
;
865 case D3DPT_TRIANGLELIST
:
866 TRACE(" primitive type is TRIANGLES\n");
869 case D3DPT_TRIANGLESTRIP
:
870 TRACE(" primitive type is TRIANGLE_STRIP\n");
871 return GL_TRIANGLE_STRIP
;
873 case D3DPT_TRIANGLEFAN
:
874 TRACE(" primitive type is TRIANGLE_FAN\n");
875 return GL_TRIANGLE_FAN
;
878 FIXME("Unhandled primitive %08x\n", d3dpt
);
883 /* This function calculate the Z coordinate from Zproj */
884 static float ZfromZproj(IDirect3DDeviceImpl
*This
, D3DVALUE Zproj
)
887 /* Assume that X = Y = 0 and W = 1 */
888 a
= This
->proj_mat
->_33
;
889 b
= This
->proj_mat
->_34
;
890 c
= This
->proj_mat
->_43
;
891 d
= This
->proj_mat
->_44
;
892 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
893 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
894 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
896 return (d
*Zproj
- c
) / (a
- b
*Zproj
);
899 static void build_fog_table(BYTE
*fog_table
, DWORD fog_color
) {
902 TRACE(" rebuilding fog table (%06lx)...\n", fog_color
& 0x00FFFFFF);
904 for (i
= 0; i
< 3; i
++) {
905 BYTE fog_color_component
= (fog_color
>> (8 * i
)) & 0xFF;
907 for (elt
= 0; elt
< 0x10000; elt
++) {
908 /* We apply the fog transformation and cache the result */
909 DWORD fog_intensity
= elt
& 0xFF;
910 DWORD vertex_color
= (elt
>> 8) & 0xFF;
911 fog_table
[(i
* 0x10000) + elt
] = ((fog_intensity
* vertex_color
) + ((0xFF - fog_intensity
) * fog_color_component
)) / 0xFF;
916 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl
*This
,
917 BOOLEAN vertex_transformed
,
918 BOOLEAN vertex_lit
) {
919 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
921 /* Puts GL in the correct lighting / transformation mode */
922 if ((vertex_transformed
== FALSE
) &&
923 (glThis
->transform_state
!= GL_TRANSFORM_NORMAL
)) {
924 /* Need to put the correct transformation again if we go from Transformed
925 vertices to non-transformed ones.
927 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
928 This
->world_mat
, This
->view_mat
, This
->proj_mat
);
929 glThis
->transform_state
= GL_TRANSFORM_NORMAL
;
931 } else if (vertex_transformed
&&
932 (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
)) {
933 /* Set our orthographic projection */
934 if (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
) {
935 glThis
->transform_state
= GL_TRANSFORM_ORTHO
;
936 d3ddevice_set_ortho(This
);
940 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
941 if no fogging state change occurred */
942 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGENABLE
- 1]) {
943 if (vertex_transformed
) {
944 if (glThis
->fogging
!= 0) {
948 /* Now check if our fog_table still corresponds to the current vertex color.
949 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
950 if ((glThis
->fog_table
[0 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 0) & 0xFF)) ||
951 (glThis
->fog_table
[1 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 8) & 0xFF)) ||
952 (glThis
->fog_table
[2 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 16) & 0xFF))) {
953 /* We need to rebuild our fog table.... */
954 build_fog_table(glThis
->fog_table
, This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
957 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1] != D3DFOG_NONE
) {
958 switch (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1]) {
959 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); break;
960 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); break;
961 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); break;
963 if (vertex_lit
== FALSE
) {
964 glFogf(GL_FOG_START
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]);
965 glFogf(GL_FOG_END
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]);
967 /* Special case of 'pixel fog' */
968 glFogf(GL_FOG_START
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]));
969 glFogf(GL_FOG_END
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]));
971 if (glThis
->fogging
== 0) {
976 if (glThis
->fogging
!= 0) {
983 if (glThis
->fogging
!= 0) {
989 /* Handle the 'no-normal' case */
990 if ((vertex_lit
== FALSE
) && This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1]) {
991 if (glThis
->lighting
== 0) {
992 glEnable(GL_LIGHTING
);
993 glThis
->lighting
= 1;
996 if (glThis
->lighting
!= 0) {
997 glDisable(GL_LIGHTING
);
998 glThis
->lighting
= 0;
1002 /* Handle the code for pre-vertex material properties */
1003 if (vertex_transformed
== FALSE
) {
1004 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1005 This
->state_block
.render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1006 if ((This
->state_block
.render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1007 (This
->state_block
.render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1008 (This
->state_block
.render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
1009 (This
->state_block
.render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
)) {
1010 glEnable(GL_COLOR_MATERIAL
);
1017 inline static void draw_primitive(IDirect3DDeviceImpl
*This
, DWORD maxvert
, WORD
*index
,
1018 D3DVERTEXTYPE d3dvt
, D3DPRIMITIVETYPE d3dpt
, void *lpvertex
)
1020 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1023 case D3DVT_VERTEX
: {
1024 strided
.position
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u1
.x
;
1025 strided
.position
.dwStride
= sizeof(D3DVERTEX
);
1026 strided
.normal
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u4
.nx
;
1027 strided
.normal
.dwStride
= sizeof(D3DVERTEX
);
1028 strided
.textureCoords
[0].lpvData
= &((D3DVERTEX
*) lpvertex
)->u7
.tu
;
1029 strided
.textureCoords
[0].dwStride
= sizeof(D3DVERTEX
);
1030 draw_primitive_strided(This
, d3dpt
, D3DFVF_VERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1033 case D3DVT_LVERTEX
: {
1034 strided
.position
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u1
.x
;
1035 strided
.position
.dwStride
= sizeof(D3DLVERTEX
);
1036 strided
.diffuse
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u4
.color
;
1037 strided
.diffuse
.dwStride
= sizeof(D3DLVERTEX
);
1038 strided
.specular
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u5
.specular
;
1039 strided
.specular
.dwStride
= sizeof(D3DLVERTEX
);
1040 strided
.textureCoords
[0].lpvData
= &((D3DLVERTEX
*) lpvertex
)->u6
.tu
;
1041 strided
.textureCoords
[0].dwStride
= sizeof(D3DLVERTEX
);
1042 draw_primitive_strided(This
, d3dpt
, D3DFVF_LVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1045 case D3DVT_TLVERTEX
: {
1046 strided
.position
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u1
.sx
;
1047 strided
.position
.dwStride
= sizeof(D3DTLVERTEX
);
1048 strided
.diffuse
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u5
.color
;
1049 strided
.diffuse
.dwStride
= sizeof(D3DTLVERTEX
);
1050 strided
.specular
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u6
.specular
;
1051 strided
.specular
.dwStride
= sizeof(D3DTLVERTEX
);
1052 strided
.textureCoords
[0].lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u7
.tu
;
1053 strided
.textureCoords
[0].dwStride
= sizeof(D3DTLVERTEX
);
1054 draw_primitive_strided(This
, d3dpt
, D3DFVF_TLVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1058 FIXME("Unhandled vertex type %08x\n", d3dvt
);
1064 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface
,
1065 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1066 D3DVERTEXTYPE d3dvtVertexType
,
1068 DWORD dwVertexCount
,
1071 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1073 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1074 if (TRACE_ON(ddraw
)) {
1075 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1078 draw_primitive(This
, dwVertexCount
, NULL
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1084 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface
,
1085 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1086 D3DVERTEXTYPE d3dvtVertexType
,
1088 DWORD dwVertexCount
,
1093 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1094 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1095 if (TRACE_ON(ddraw
)) {
1096 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1099 draw_primitive(This
, dwIndexCount
, dwIndices
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1105 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface
,
1106 LPD3DEXECUTEBUFFERDESC lpDesc
,
1107 LPDIRECT3DEXECUTEBUFFER
* lplpDirect3DExecuteBuffer
,
1108 IUnknown
* pUnkOuter
)
1110 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice
, iface
);
1111 IDirect3DExecuteBufferImpl
*ret
;
1114 TRACE("(%p/%p)->(%p,%p,%p)\n", This
, iface
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
1116 ret_value
= d3dexecutebuffer_create(&ret
, This
->d3d
, This
, lpDesc
);
1117 *lplpDirect3DExecuteBuffer
= ICOM_INTERFACE(ret
, IDirect3DExecuteBuffer
);
1119 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer
);
1124 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
1125 static BOOLEAN first
= TRUE
;
1126 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
1131 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1135 TRACE("flushing ZBuffer back to GL\n");
1137 if (gl_d3d_dev
->transform_state
!= GL_TRANSFORM_ORTHO
) {
1138 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
1139 d3ddevice_set_ortho(d3d_dev
);
1142 glMatrixMode(GL_MODELVIEW
);
1145 if (gl_d3d_dev
->depth_test
== 0) glEnable(GL_DEPTH_TEST
);
1146 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
) glDepthFunc(GL_ALWAYS
);
1147 glColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
1149 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1152 switch (surf
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwZBufferBitDepth
) {
1153 case 16: type
= GL_UNSIGNED_SHORT
; break;
1154 case 32: type
= GL_UNSIGNED_INT
; break;
1155 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state
;
1158 for (row
= 0; row
< surf
->surface_desc
.dwHeight
; row
++) {
1159 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1160 glRasterPos2i(0, row
+ 1);
1161 glDrawPixels(surf
->surface_desc
.dwWidth
, 1, GL_DEPTH_COMPONENT
, type
,
1162 ((unsigned char *) surf
->surface_desc
.lpSurface
) + (row
* surf
->surface_desc
.u1
.lPitch
));
1166 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
1167 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
)
1168 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1]));
1169 if (gl_d3d_dev
->depth_test
== 0) glDisable(GL_DEPTH_TEST
);
1172 /* These are the various handler used in the generic path */
1173 inline static void handle_xyz(D3DVALUE
*coords
) {
1174 glVertex3fv(coords
);
1176 inline static void handle_xyzrhw(D3DVALUE
*coords
) {
1177 if ((coords
[3] < 1e-8) && (coords
[3] > -1e-8))
1178 glVertex3fv(coords
);
1180 GLfloat w
= 1.0 / coords
[3];
1182 glVertex4f(coords
[0] * w
,
1188 inline static void handle_normal(D3DVALUE
*coords
) {
1189 glNormal3fv(coords
);
1192 inline static void handle_diffuse_base(STATEBLOCK
*sb
, DWORD
*color
) {
1193 if (sb
->render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] ||
1194 sb
->render_state
[D3DRENDERSTATE_ALPHABLENDENABLE
- 1]) {
1195 glColor4ub((*color
>> 16) & 0xFF,
1196 (*color
>> 8) & 0xFF,
1197 (*color
>> 0) & 0xFF,
1198 (*color
>> 24) & 0xFF);
1200 glColor3ub((*color
>> 16) & 0xFF,
1201 (*color
>> 8) & 0xFF,
1202 (*color
>> 0) & 0xFF);
1206 inline static void handle_specular_base(STATEBLOCK
*sb
, DWORD
*color
) {
1207 glColor4ub((*color
>> 16) & 0xFF,
1208 (*color
>> 8) & 0xFF,
1209 (*color
>> 0) & 0xFF,
1210 (*color
>> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1213 inline static void handle_diffuse(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1214 if ((lighted
== FALSE
) &&
1215 sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1216 sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1217 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1218 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1219 handle_diffuse_base(sb
, color
);
1221 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1222 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1223 handle_diffuse_base(sb
, color
);
1225 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) &&
1226 sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1227 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1228 handle_diffuse_base(sb
, color
);
1230 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1231 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1232 handle_diffuse_base(sb
, color
);
1235 handle_diffuse_base(sb
, color
);
1239 inline static void handle_specular(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1240 if ((lighted
== FALSE
) &&
1241 sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] &&
1242 sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1]) {
1243 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1244 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1245 handle_specular_base(sb
, color
);
1247 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1248 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1249 handle_specular_base(sb
, color
);
1251 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) &&
1252 sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1253 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1254 handle_specular_base(sb
, color
);
1256 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1257 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1258 handle_specular_base(sb
, color
);
1261 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1264 inline static void handle_diffuse_and_specular(STATEBLOCK
*sb
, BYTE
*fog_table
, DWORD
*color_d
, DWORD
*color_s
, BOOLEAN lighted
) {
1266 DWORD color
= *color_d
;
1267 if (sb
->render_state
[D3DRENDERSTATE_FOGENABLE
- 1]) {
1268 /* Special case where the specular value is used to do fogging */
1269 BYTE fog_intensity
= *color_s
>> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1270 color
&= 0xFF000000; /* Only keep the alpha component */
1271 color
|= fog_table
[((*color_d
>> 0) & 0xFF) << 8 | fog_intensity
] << 0;
1272 color
|= fog_table
[((*color_d
>> 8) & 0xFF) << 8 | fog_intensity
] << 8;
1273 color
|= fog_table
[((*color_d
>> 16) & 0xFF) << 8 | fog_intensity
] << 16;
1275 if (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1]) {
1276 /* Standard specular value in transformed mode. TODO */
1278 handle_diffuse_base(sb
, &color
);
1280 if (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1]) {
1281 handle_diffuse(sb
, color_d
, FALSE
);
1282 handle_specular(sb
, color_s
, FALSE
);
1284 /* In that case, only put the diffuse color... */
1285 handle_diffuse_base(sb
, color_d
);
1290 inline static void handle_texture(D3DVALUE
*coords
) {
1291 glTexCoord2fv(coords
);
1293 inline static void handle_textures(const D3DVALUE
*coords
, int tex_stage
) {
1294 if (GL_extensions
.glMultiTexCoord2fv
) {
1295 GL_extensions
.glMultiTexCoord2fv(GL_TEXTURE0_WINE
+ tex_stage
, coords
);
1297 if (tex_stage
== 0) glTexCoord2fv(coords
);
1301 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
1302 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1303 DWORD d3dvtVertexType
,
1304 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1305 DWORD dwVertexCount
,
1310 BOOLEAN vertex_lighted
= FALSE
;
1311 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
1312 int num_active_stages
= 0;
1313 int num_tex_index
= ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
);
1315 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1316 if (TRACE_ON(ddraw
)) {
1317 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType
);
1320 /* This is to prevent 'thread contention' between a thread locking the device and another
1321 doing 3D display on it... */
1322 EnterCriticalSection(&(This
->crit
));
1325 if (glThis
->state
[WINE_GL_BUFFER_BACK
] == SURFACE_MEMORY_DIRTY
) {
1326 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[WINE_GL_BUFFER_BACK
]), glThis
->lock_surf
[WINE_GL_BUFFER_BACK
]);
1328 glThis
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
1330 if (This
->current_zbuffer
== NULL
) {
1331 /* Search for an attached ZBuffer */
1332 static const DDSCAPS2 zbuf_caps
= { DDSCAPS_ZBUFFER
, 0, 0, 0 };
1333 LPDIRECTDRAWSURFACE7 zbuf
;
1336 hr
= IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This
->surface
, IDirectDrawSurface7
),
1337 (DDSCAPS2
*) &zbuf_caps
, &zbuf
);
1339 This
->current_zbuffer
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, zbuf
);
1340 IDirectDrawSurface7_Release(zbuf
);
1343 if (This
->current_zbuffer
!= NULL
) {
1344 if (This
->current_zbuffer
->get_dirty_status(This
->current_zbuffer
, NULL
)) {
1345 flush_zbuffer_to_GL(This
, NULL
, This
->current_zbuffer
);
1349 if ( ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) ||
1350 ((d3dvtVertexType
& D3DFVF_NORMAL
) == 0) )
1351 vertex_lighted
= TRUE
;
1353 /* Compute the number of active texture stages and set the various texture parameters */
1354 num_active_stages
= draw_primitive_handle_textures(This
);
1356 /* And restore to handle '0' in the case we use glTexCoord calls */
1357 if (glThis
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
1358 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
1359 glThis
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
1362 draw_primitive_handle_GL_state(This
,
1363 (d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
,
1366 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1367 for now to some 'special' cases where we can do a direct mapping between D3D
1370 Note: in the future all calls will go through vertex arrays but the arrays
1371 will be generated by this function.
1373 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1374 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1375 which, as we are little indian, gives a B, G, R, A storage in memory.
1377 if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) && /* Standard XYZ vertices */
1378 ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == 0)) {
1380 TRACE(" using GL vertex arrays for performance !\n");
1381 /* First, the vertices (we are sure we have some :-) */
1382 glEnableClientState(GL_VERTEX_ARRAY
);
1383 glVertexPointer(3, GL_FLOAT
, lpD3DDrawPrimStrideData
->position
.dwStride
, lpD3DDrawPrimStrideData
->position
.lpvData
);
1384 /* Then the normals */
1385 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1386 glEnableClientState(GL_NORMAL_ARRAY
);
1387 glNormalPointer(GL_FLOAT
, lpD3DDrawPrimStrideData
->normal
.dwStride
, lpD3DDrawPrimStrideData
->normal
.lpvData
);
1389 /* Then the diffuse colour */
1390 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1391 glEnableClientState(GL_COLOR_ARRAY
);
1392 glColorPointer(3, GL_UNSIGNED_BYTE
, lpD3DDrawPrimStrideData
->normal
.dwStride
,
1393 ((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
));
1395 /* Then the various textures */
1396 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1397 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0x0000FFFF;
1398 if (tex_index
>= num_tex_index
) {
1399 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1400 tex_index
= num_tex_index
- 1;
1402 if (GL_extensions
.glClientActiveTexture
) {
1403 GL_extensions
.glClientActiveTexture(GL_TEXTURE0_WINE
+ tex_stage
);
1405 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
1406 glTexCoordPointer(2, GL_FLOAT
, lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
,
1407 lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
);
1409 if (dwIndices
!= NULL
) {
1410 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType
), dwIndexCount
, GL_UNSIGNED_SHORT
, dwIndices
);
1412 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType
), 0, dwIndexCount
);
1414 glDisableClientState(GL_VERTEX_ARRAY
);
1415 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1416 glDisableClientState(GL_NORMAL_ARRAY
);
1418 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1419 glDisableClientState(GL_COLOR_ARRAY
);
1421 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1422 if (GL_extensions
.glClientActiveTexture
) {
1423 GL_extensions
.glClientActiveTexture(GL_TEXTURE0_WINE
+ tex_stage
);
1425 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
1428 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType
));
1430 /* Some fast paths first before the generic case.... */
1431 if ((d3dvtVertexType
== D3DFVF_VERTEX
) && (num_active_stages
<= 1)) {
1434 for (index
= 0; index
< dwIndexCount
; index
++) {
1435 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1437 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1438 D3DVALUE
*tex_coord
=
1439 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1440 D3DVALUE
*position
=
1441 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1443 handle_normal(normal
);
1444 handle_texture(tex_coord
);
1445 handle_xyz(position
);
1447 TRACE_(ddraw_geom
)(" %f %f %f / %f %f %f (%f %f)\n",
1448 position
[0], position
[1], position
[2],
1449 normal
[0], normal
[1], normal
[2],
1450 tex_coord
[0], tex_coord
[1]);
1452 } else if ((d3dvtVertexType
== D3DFVF_TLVERTEX
) && (num_active_stages
<= 1)) {
1455 for (index
= 0; index
< dwIndexCount
; index
++) {
1456 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1458 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1460 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1461 D3DVALUE
*tex_coord
=
1462 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1463 D3DVALUE
*position
=
1464 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1466 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, TRUE
);
1467 handle_texture(tex_coord
);
1468 handle_xyzrhw(position
);
1470 TRACE_(ddraw_geom
)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1471 position
[0], position
[1], position
[2], position
[3],
1472 (*color_d
>> 16) & 0xFF,
1473 (*color_d
>> 8) & 0xFF,
1474 (*color_d
>> 0) & 0xFF,
1475 (*color_d
>> 24) & 0xFF,
1476 (*color_s
>> 16) & 0xFF,
1477 (*color_s
>> 8) & 0xFF,
1478 (*color_s
>> 0) & 0xFF,
1479 (*color_s
>> 24) & 0xFF,
1480 tex_coord
[0], tex_coord
[1]);
1482 } else if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
1483 ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)) {
1484 /* This is the 'slow path' but that should support all possible vertex formats out there...
1485 Note that people should write a fast path for all vertex formats out there...
1488 static const D3DVALUE no_index
[] = { 0.0, 0.0, 0.0, 0.0 };
1490 for (index
= 0; index
< dwIndexCount
; index
++) {
1491 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1494 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1496 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1497 handle_normal(normal
);
1499 if ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) {
1501 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1503 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1504 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, vertex_lighted
);
1506 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1508 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1509 handle_specular(&(This
->state_block
), color_s
, vertex_lighted
);
1510 } else if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1512 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1513 handle_diffuse(&(This
->state_block
), color_d
, vertex_lighted
);
1517 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1518 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0x0000FFFF;
1519 if (tex_index
>= num_tex_index
) {
1520 handle_textures((const D3DVALUE
*) no_index
, tex_stage
);
1522 D3DVALUE
*tex_coord
=
1523 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1524 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1525 handle_textures(tex_coord
, tex_stage
);
1529 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1530 D3DVALUE
*position
=
1531 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1532 handle_xyz(position
);
1533 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1534 D3DVALUE
*position
=
1535 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1536 handle_xyzrhw(position
);
1539 if (TRACE_ON(ddraw_geom
)) {
1540 unsigned int tex_index
;
1542 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1543 D3DVALUE
*position
=
1544 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1545 TRACE_(ddraw_geom
)(" %f %f %f", position
[0], position
[1], position
[2]);
1546 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1547 D3DVALUE
*position
=
1548 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1549 TRACE_(ddraw_geom
)(" %f %f %f %f", position
[0], position
[1], position
[2], position
[3]);
1551 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1553 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1554 TRACE_(ddraw_geom
)(" / %f %f %f", normal
[0], normal
[1], normal
[2]);
1556 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1558 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1559 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1560 (*color_d
>> 16) & 0xFF,
1561 (*color_d
>> 8) & 0xFF,
1562 (*color_d
>> 0) & 0xFF,
1563 (*color_d
>> 24) & 0xFF);
1565 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1567 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1568 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1569 (*color_s
>> 16) & 0xFF,
1570 (*color_s
>> 8) & 0xFF,
1571 (*color_s
>> 0) & 0xFF,
1572 (*color_s
>> 24) & 0xFF);
1574 for (tex_index
= 0; tex_index
< ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
); tex_index
++) {
1575 D3DVALUE
*tex_coord
=
1576 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1577 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1578 TRACE_(ddraw_geom
)(" / %f %f", tex_coord
[0], tex_coord
[1]);
1580 TRACE_(ddraw_geom
)("\n");
1584 ERR(" matrix weighting not handled yet....\n");
1590 /* Whatever the case, disable the color material stuff */
1591 glDisable(GL_COLOR_MATERIAL
);
1596 LeaveCriticalSection(&(This
->crit
));
1600 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface
,
1601 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1602 DWORD d3dvtVertexType
,
1604 DWORD dwVertexCount
,
1607 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1608 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1610 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1611 if (TRACE_ON(ddraw
)) {
1612 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1615 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1616 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1622 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface
,
1623 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1624 DWORD d3dvtVertexType
,
1626 DWORD dwVertexCount
,
1631 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1632 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1634 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1635 if (TRACE_ON(ddraw
)) {
1636 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1639 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1640 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1646 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1647 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1649 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1650 DWORD dwVertexCount
,
1653 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1655 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, dwFlags
);
1656 if (TRACE_ON(ddraw
)) {
1657 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1659 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1665 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1666 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1668 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1669 DWORD dwVertexCount
,
1674 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1676 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1677 if (TRACE_ON(ddraw
)) {
1678 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1681 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1687 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1688 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1689 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1690 DWORD dwStartVertex
,
1691 DWORD dwNumVertices
,
1694 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1695 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1696 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1698 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, dwFlags
);
1699 if (TRACE_ON(ddraw
)) {
1700 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1703 if (vb_impl
->processed
) {
1704 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1705 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1707 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1708 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1709 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1711 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1712 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1715 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1716 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1723 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1724 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1725 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1726 DWORD dwStartVertex
,
1727 DWORD dwNumVertices
,
1732 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1733 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1734 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1736 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1737 if (TRACE_ON(ddraw
)) {
1738 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1741 if (vb_impl
->processed
) {
1742 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1743 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1745 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1746 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1747 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1749 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1750 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1753 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1754 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1760 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1762 handle_color_alpha_args(IDirect3DDeviceImpl
*This
, DWORD dwStage
, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
, DWORD dwState
, D3DTEXTUREOP tex_op
)
1764 BOOLEAN is_complement
= FALSE
;
1765 BOOLEAN is_alpha_replicate
= FALSE
;
1766 BOOLEAN handled
= TRUE
;
1768 BOOLEAN is_color
= ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
));
1772 if (d3dTexStageStateType
== D3DTSS_COLORARG1
) num
= 0;
1773 else if (d3dTexStageStateType
== D3DTSS_COLORARG2
) num
= 1;
1778 if (tex_op
== D3DTOP_SELECTARG2
) {
1782 if (d3dTexStageStateType
== D3DTSS_ALPHAARG1
) num
= 0;
1783 else if (d3dTexStageStateType
== D3DTSS_ALPHAARG2
) num
= 1;
1788 if (tex_op
== D3DTOP_SELECTARG2
) {
1793 if (dwState
& D3DTA_COMPLEMENT
) {
1794 is_complement
= TRUE
;
1796 if (dwState
& D3DTA_ALPHAREPLICATE
) {
1797 is_alpha_replicate
= TRUE
;
1799 dwState
&= D3DTA_SELECTMASK
;
1800 if ((dwStage
== 0) && (dwState
== D3DTA_CURRENT
)) {
1801 dwState
= D3DTA_DIFFUSE
;
1805 case D3DTA_CURRENT
: src
= GL_PREVIOUS_EXT
; break;
1806 case D3DTA_DIFFUSE
: src
= GL_PRIMARY_COLOR_EXT
; break;
1807 case D3DTA_TEXTURE
: src
= GL_TEXTURE
; break;
1808 case D3DTA_TFACTOR
: {
1809 /* Get the constant value from the current rendering state */
1811 DWORD col
= This
->state_block
.render_state
[D3DRENDERSTATE_TEXTUREFACTOR
- 1];
1813 color
[0] = ((col
>> 16) & 0xFF) / 255.0f
;
1814 color
[1] = ((col
>> 8) & 0xFF) / 255.0f
;
1815 color
[2] = ((col
>> 0) & 0xFF) / 255.0f
;
1816 color
[3] = ((col
>> 24) & 0xFF) / 255.0f
;
1817 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, color
);
1819 src
= GL_CONSTANT_EXT
;
1821 default: src
= GL_TEXTURE
; handled
= FALSE
; break;
1825 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
+ num
, src
);
1826 if (is_alpha_replicate
) {
1827 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1829 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_COLOR
: GL_SRC_COLOR
);
1832 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
+ num
, src
);
1833 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1840 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface
,
1842 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
,
1845 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1846 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1851 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This
, iface
, dwStage
, d3dTexStageStateType
, dwState
);
1853 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
1854 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
1858 unit
= GL_TEXTURE0_WINE
+ dwStage
;
1859 if (unit
!= glThis
->current_active_tex_unit
) {
1860 GL_extensions
.glActiveTexture(unit
);
1861 glThis
->current_active_tex_unit
= unit
;
1864 switch (d3dTexStageStateType
) {
1865 #define GEN_CASE(a) case a: type = #a; break
1866 GEN_CASE(D3DTSS_COLOROP
);
1867 GEN_CASE(D3DTSS_COLORARG1
);
1868 GEN_CASE(D3DTSS_COLORARG2
);
1869 GEN_CASE(D3DTSS_ALPHAOP
);
1870 GEN_CASE(D3DTSS_ALPHAARG1
);
1871 GEN_CASE(D3DTSS_ALPHAARG2
);
1872 GEN_CASE(D3DTSS_BUMPENVMAT00
);
1873 GEN_CASE(D3DTSS_BUMPENVMAT01
);
1874 GEN_CASE(D3DTSS_BUMPENVMAT10
);
1875 GEN_CASE(D3DTSS_BUMPENVMAT11
);
1876 GEN_CASE(D3DTSS_TEXCOORDINDEX
);
1877 GEN_CASE(D3DTSS_ADDRESS
);
1878 GEN_CASE(D3DTSS_ADDRESSU
);
1879 GEN_CASE(D3DTSS_ADDRESSV
);
1880 GEN_CASE(D3DTSS_BORDERCOLOR
);
1881 GEN_CASE(D3DTSS_MAGFILTER
);
1882 GEN_CASE(D3DTSS_MINFILTER
);
1883 GEN_CASE(D3DTSS_MIPFILTER
);
1884 GEN_CASE(D3DTSS_MIPMAPLODBIAS
);
1885 GEN_CASE(D3DTSS_MAXMIPLEVEL
);
1886 GEN_CASE(D3DTSS_MAXANISOTROPY
);
1887 GEN_CASE(D3DTSS_BUMPENVLSCALE
);
1888 GEN_CASE(D3DTSS_BUMPENVLOFFSET
);
1889 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS
);
1891 default: type
= "UNKNOWN";
1894 /* Store the values in the state array */
1895 prev_state
= This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1];
1896 This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1] = dwState
;
1897 /* Some special cases when one state modifies more than one... */
1898 if (d3dTexStageStateType
== D3DTSS_ADDRESS
) {
1899 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSU
- 1] = dwState
;
1900 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSV
- 1] = dwState
;
1905 switch (d3dTexStageStateType
) {
1906 case D3DTSS_MINFILTER
:
1907 case D3DTSS_MIPFILTER
:
1908 if (TRACE_ON(ddraw
)) {
1909 if (d3dTexStageStateType
== D3DTSS_MINFILTER
) {
1910 switch ((D3DTEXTUREMINFILTER
) dwState
) {
1911 case D3DTFN_POINT
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1912 case D3DTFN_LINEAR
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1913 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState
); break;
1916 switch ((D3DTEXTUREMIPFILTER
) dwState
) {
1917 case D3DTFP_NONE
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1918 case D3DTFP_POINT
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1919 case D3DTFP_LINEAR
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1920 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState
); break;
1926 case D3DTSS_MAGFILTER
:
1927 if (TRACE_ON(ddraw
)) {
1928 switch ((D3DTEXTUREMAGFILTER
) dwState
) {
1929 case D3DTFG_POINT
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1930 case D3DTFG_LINEAR
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1931 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState
); break;
1936 case D3DTSS_ADDRESS
:
1937 case D3DTSS_ADDRESSU
:
1938 case D3DTSS_ADDRESSV
: {
1939 switch ((D3DTEXTUREADDRESS
) dwState
) {
1940 case D3DTADDRESS_WRAP
: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type
); break;
1941 case D3DTADDRESS_CLAMP
: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type
); break;
1942 case D3DTADDRESS_BORDER
: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type
); break;
1943 case D3DTADDRESS_MIRROR
:
1944 if (GL_extensions
.mirrored_repeat
) {
1945 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type
);
1947 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type
);
1950 default: FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
); break;
1954 case D3DTSS_ALPHAOP
:
1955 case D3DTSS_COLOROP
: {
1957 GLenum parm
= (d3dTexStageStateType
== D3DTSS_ALPHAOP
) ? GL_COMBINE_ALPHA_EXT
: GL_COMBINE_RGB_EXT
;
1962 #define GEN_CASE(a) case a: value = #a; break
1963 GEN_CASE(D3DTOP_DISABLE
);
1964 GEN_CASE(D3DTOP_SELECTARG1
);
1965 GEN_CASE(D3DTOP_SELECTARG2
);
1966 GEN_CASE(D3DTOP_MODULATE
);
1967 GEN_CASE(D3DTOP_MODULATE2X
);
1968 GEN_CASE(D3DTOP_MODULATE4X
);
1969 GEN_CASE(D3DTOP_ADD
);
1970 GEN_CASE(D3DTOP_ADDSIGNED
);
1971 GEN_CASE(D3DTOP_ADDSIGNED2X
);
1972 GEN_CASE(D3DTOP_SUBTRACT
);
1973 GEN_CASE(D3DTOP_ADDSMOOTH
);
1974 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA
);
1975 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA
);
1976 GEN_CASE(D3DTOP_BLENDFACTORALPHA
);
1977 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM
);
1978 GEN_CASE(D3DTOP_BLENDCURRENTALPHA
);
1979 GEN_CASE(D3DTOP_PREMODULATE
);
1980 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR
);
1981 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA
);
1982 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR
);
1983 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA
);
1984 GEN_CASE(D3DTOP_BUMPENVMAP
);
1985 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE
);
1986 GEN_CASE(D3DTOP_DOTPRODUCT3
);
1987 GEN_CASE(D3DTOP_FORCE_DWORD
);
1989 default: value
= "UNKNOWN";
1992 if ((d3dTexStageStateType
== D3DTSS_COLOROP
) && (dwState
== D3DTOP_DISABLE
)) {
1993 glDisable(GL_TEXTURE_2D
);
1994 TRACE(" disabling 2D texturing.\n");
1996 /* Re-enable texturing only if COLOROP was not already disabled... */
1997 if ((glThis
->current_bound_texture
[dwStage
] != NULL
) &&
1998 (This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
1999 glEnable(GL_TEXTURE_2D
);
2000 TRACE(" enabling 2D texturing.\n");
2003 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
2004 if ((dwState
!= D3DTOP_DISABLE
) &&
2005 (This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
)) {
2006 if (glThis
->current_tex_env
!= GL_COMBINE_EXT
) {
2007 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
2008 glThis
->current_tex_env
= GL_COMBINE_EXT
;
2012 /* Now set up the operand correctly */
2014 case D3DTOP_DISABLE
:
2015 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2016 and it works, so ignore this op */
2017 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2020 case D3DTOP_SELECTARG1
:
2021 case D3DTOP_SELECTARG2
:
2022 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_REPLACE
);
2025 case D3DTOP_MODULATE4X
:
2026 scale
= scale
* 2; /* Drop through */
2027 case D3DTOP_MODULATE2X
:
2028 scale
= scale
* 2; /* Drop through */
2029 case D3DTOP_MODULATE
:
2030 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_MODULATE
);
2034 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD
);
2037 case D3DTOP_ADDSIGNED2X
:
2038 scale
= scale
* 2; /* Drop through */
2039 case D3DTOP_ADDSIGNED
:
2040 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD_SIGNED_EXT
);
2043 /* For the four blending modes, use the Arg2 parameter */
2044 case D3DTOP_BLENDDIFFUSEALPHA
:
2045 case D3DTOP_BLENDTEXTUREALPHA
:
2046 case D3DTOP_BLENDFACTORALPHA
:
2047 case D3DTOP_BLENDCURRENTALPHA
: {
2048 GLenum src
= GL_PRIMARY_COLOR_EXT
; /* Just to prevent a compiler warning.. */
2051 case D3DTOP_BLENDDIFFUSEALPHA
: src
= GL_PRIMARY_COLOR_EXT
;
2052 case D3DTOP_BLENDTEXTUREALPHA
: src
= GL_TEXTURE
;
2053 case D3DTOP_BLENDFACTORALPHA
: src
= GL_CONSTANT_EXT
;
2054 case D3DTOP_BLENDCURRENTALPHA
: src
= GL_PREVIOUS_EXT
;
2057 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_INTERPOLATE_EXT
);
2058 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, src
);
2059 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_ALPHA
);
2060 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, src
);
2061 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
2070 if (((prev_state
== D3DTOP_SELECTARG2
) && (dwState
!= D3DTOP_SELECTARG2
)) ||
2071 ((dwState
== D3DTOP_SELECTARG2
) && (prev_state
!= D3DTOP_SELECTARG2
))) {
2072 /* Switch the arguments if needed... */
2073 if (d3dTexStageStateType
== D3DTSS_COLOROP
) {
2074 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG1
,
2075 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG1
- 1],
2077 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG2
,
2078 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG2
- 1],
2081 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG1
,
2082 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG1
- 1],
2084 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG2
,
2085 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG2
- 1],
2091 if (d3dTexStageStateType
== D3DTSS_ALPHAOP
) {
2092 glTexEnvi(GL_TEXTURE_ENV
, GL_ALPHA_SCALE
, scale
);
2094 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, scale
);
2096 TRACE(" Stage type is : %s => %s\n", type
, value
);
2098 FIXME(" Unhandled stage type is : %s => %s\n", type
, value
);
2102 case D3DTSS_COLORARG1
:
2103 case D3DTSS_COLORARG2
:
2104 case D3DTSS_ALPHAARG1
:
2105 case D3DTSS_ALPHAARG2
: {
2106 const char *value
, *value_comp
= "", *value_alpha
= "";
2108 D3DTEXTUREOP tex_op
;
2110 switch (dwState
& D3DTA_SELECTMASK
) {
2111 #define GEN_CASE(a) case a: value = #a; break
2112 GEN_CASE(D3DTA_DIFFUSE
);
2113 GEN_CASE(D3DTA_CURRENT
);
2114 GEN_CASE(D3DTA_TEXTURE
);
2115 GEN_CASE(D3DTA_TFACTOR
);
2116 GEN_CASE(D3DTA_SPECULAR
);
2118 default: value
= "UNKNOWN";
2120 if (dwState
& D3DTA_COMPLEMENT
) {
2121 value_comp
= " | D3DTA_COMPLEMENT";
2123 if (dwState
& D3DTA_ALPHAREPLICATE
) {
2124 value_alpha
= " | D3DTA_ALPHAREPLICATE";
2127 if ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
)) {
2128 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1];
2130 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAOP
- 1];
2133 handled
= handle_color_alpha_args(This
, dwStage
, d3dTexStageStateType
, dwState
, tex_op
);
2136 TRACE(" Stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2138 FIXME(" Unhandled stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2142 case D3DTSS_MIPMAPLODBIAS
: {
2143 D3DVALUE value
= *((D3DVALUE
*) &dwState
);
2144 BOOLEAN handled
= TRUE
;
2146 if ((value
!= 0.0) && (GL_extensions
.mipmap_lodbias
== FALSE
))
2150 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2151 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE
, GL_TEXTURE_LOD_BIAS_WINE
, value
);
2153 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2157 case D3DTSS_MAXMIPLEVEL
:
2158 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState
);
2161 case D3DTSS_BORDERCOLOR
:
2162 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2163 ((dwState
>> 16) & 0xFF),
2164 ((dwState
>> 8) & 0xFF),
2165 ((dwState
>> 0) & 0xFF),
2166 ((dwState
>> 24) & 0xFF));
2169 case D3DTSS_TEXCOORDINDEX
: {
2170 BOOLEAN handled
= TRUE
;
2173 switch (dwState
& 0xFFFF0000) {
2174 #define GEN_CASE(a) case a: value = #a; break
2175 GEN_CASE(D3DTSS_TCI_PASSTHRU
);
2176 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL
);
2177 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION
);
2178 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
);
2180 default: value
= "UNKNOWN";
2182 if ((dwState
& 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
)
2186 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2188 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2192 case D3DTSS_TEXTURETRANSFORMFLAGS
: {
2193 const char *projected
= "", *value
;
2194 BOOLEAN handled
= TRUE
;
2195 switch (dwState
& 0xFF) {
2196 #define GEN_CASE(a) case a: value = #a; break
2197 GEN_CASE(D3DTTFF_DISABLE
);
2198 GEN_CASE(D3DTTFF_COUNT1
);
2199 GEN_CASE(D3DTTFF_COUNT2
);
2200 GEN_CASE(D3DTTFF_COUNT3
);
2201 GEN_CASE(D3DTTFF_COUNT4
);
2203 default: value
= "UNKNOWN";
2205 if (dwState
& D3DTTFF_PROJECTED
) {
2206 projected
= " | D3DTTFF_PROJECTED";
2210 if ((dwState
& 0xFF) != D3DTTFF_DISABLE
) {
2211 This
->matrices_updated(This
, TEXMAT0_CHANGED
<< dwStage
);
2215 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2217 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2222 FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
);
2232 draw_primitive_handle_textures(IDirect3DDeviceImpl
*This
)
2234 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2236 BOOLEAN enable_colorkey
= FALSE
;
2238 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
2239 IDirectDrawSurfaceImpl
*surf_ptr
= This
->current_texture
[stage
];
2242 /* If this stage is disabled, no need to go further... */
2243 if (This
->state_block
.texture_stage_state
[stage
][D3DTSS_COLOROP
- 1] == D3DTOP_DISABLE
)
2246 /* First check if we need to bind any other texture for this stage */
2247 if (This
->current_texture
[stage
] != glThis
->current_bound_texture
[stage
]) {
2248 if (This
->current_texture
[stage
] == NULL
) {
2249 TRACE(" disabling 2D texturing for stage %ld.\n", stage
);
2251 unit
= GL_TEXTURE0_WINE
+ stage
;
2252 if (unit
!= glThis
->current_active_tex_unit
) {
2253 GL_extensions
.glActiveTexture(unit
);
2254 glThis
->current_active_tex_unit
= unit
;
2256 glBindTexture(GL_TEXTURE_2D
, 0);
2257 glDisable(GL_TEXTURE_2D
);
2259 GLenum tex_name
= ((IDirect3DTextureGLImpl
*) surf_ptr
->tex_private
)->tex_name
;
2261 unit
= GL_TEXTURE0_WINE
+ stage
;
2262 if (unit
!= glThis
->current_active_tex_unit
) {
2263 GL_extensions
.glActiveTexture(unit
);
2264 glThis
->current_active_tex_unit
= unit
;
2267 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2268 if (This
->state_block
.texture_stage_state
[stage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
) {
2269 TRACE(" enabling 2D texturing and");
2270 glEnable(GL_TEXTURE_2D
);
2273 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name
, stage
);
2274 glBindTexture(GL_TEXTURE_2D
, tex_name
);
2277 glThis
->current_bound_texture
[stage
] = This
->current_texture
[stage
];
2279 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2280 TRACE(" displaying without texturing activated for stage %ld.\n", stage
);
2282 TRACE(" using already bound texture id %d for stage %ld.\n",
2283 ((IDirect3DTextureGLImpl
*) (glThis
->current_bound_texture
[stage
])->tex_private
)->tex_name
, stage
);
2287 /* If no texure valid for this stage, go out of the loop */
2288 if (This
->current_texture
[stage
] == NULL
) break;
2290 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2291 This will also update the various texture parameters if needed.
2293 gltex_upload_texture(surf_ptr
, This
, stage
);
2295 /* And finally check for color-keying (only on first stage) */
2296 if (This
->current_texture
[stage
]->surface_desc
.dwFlags
& DDSD_CKSRCBLT
) {
2298 enable_colorkey
= TRUE
;
2300 static BOOL warn
= FALSE
;
2301 if (warn
== FALSE
) {
2303 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage
);
2308 enable_colorkey
= FALSE
;
2313 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2314 if (((This
->state_block
.render_state
[D3DRENDERSTATE_COLORKEYENABLE
- 1]) ||
2315 (glThis
->version
== 1)) &&
2316 (enable_colorkey
)) {
2317 TRACE(" colorkey activated.\n");
2319 if (glThis
->alpha_test
== FALSE
) {
2320 glEnable(GL_ALPHA_TEST
);
2321 glThis
->alpha_test
= TRUE
;
2323 if ((glThis
->current_alpha_test_func
!= GL_NOTEQUAL
) || (glThis
->current_alpha_test_ref
!= 0.0)) {
2324 if (This
->state_block
.render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1]) {
2325 static BOOL warn
= FALSE
;
2326 if (warn
== FALSE
) {
2328 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2331 glThis
->current_alpha_test_func
= GL_NOTEQUAL
;
2332 glThis
->current_alpha_test_ref
= 0.0;
2333 glAlphaFunc(GL_NOTEQUAL
, 0.0);
2335 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2336 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2338 if (This
->state_block
.render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] == FALSE
) {
2339 glDisable(GL_ALPHA_TEST
);
2340 glThis
->alpha_test
= FALSE
;
2342 /* Maybe we should restore here the application-given alpha test states ? */
2349 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface
,
2351 LPDIRECTDRAWSURFACE7 lpTexture2
)
2353 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2355 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwStage
, lpTexture2
);
2357 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
2358 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
2359 if (lpTexture2
!= NULL
) {
2360 WARN(" setting a texture to a non-supported texture stage !\n");
2365 if (This
->current_texture
[dwStage
] != NULL
) {
2366 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[dwStage
], IDirectDrawSurface7
));
2369 if (lpTexture2
== NULL
) {
2370 This
->current_texture
[dwStage
] = NULL
;
2372 IDirectDrawSurfaceImpl
*tex_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, lpTexture2
);
2373 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl
, IDirectDrawSurface7
));
2374 This
->current_texture
[dwStage
] = tex_impl
;
2381 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface
,
2382 LPD3DDEVICEDESC7 lpD3DHELDevDesc
)
2384 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2385 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpD3DHELDevDesc
);
2387 fill_opengl_caps_7(lpD3DHELDevDesc
);
2389 TRACE(" returning caps : no dump function yet.\n");
2395 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface
,
2396 LPD3DMATERIAL7 lpMat
)
2398 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2399 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpMat
);
2401 if (TRACE_ON(ddraw
)) {
2402 TRACE(" material is : \n");
2403 dump_D3DMATERIAL7(lpMat
);
2406 This
->current_material
= *lpMat
;
2409 glMaterialfv(GL_FRONT_AND_BACK
,
2411 (float *) &(This
->current_material
.u
.diffuse
));
2412 glMaterialfv(GL_FRONT_AND_BACK
,
2414 (float *) &(This
->current_material
.u1
.ambient
));
2415 glMaterialfv(GL_FRONT_AND_BACK
,
2417 (float *) &(This
->current_material
.u2
.specular
));
2418 glMaterialfv(GL_FRONT_AND_BACK
,
2420 (float *) &(This
->current_material
.u3
.emissive
));
2421 glMaterialf(GL_FRONT_AND_BACK
,
2423 This
->current_material
.u4
.power
); /* Not sure about this... */
2431 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface
,
2433 LPD3DLIGHT7 lpLight
)
2435 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2436 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2437 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwLightIndex
, lpLight
);
2439 if (TRACE_ON(ddraw
)) {
2440 TRACE(" setting light : \n");
2441 dump_D3DLIGHT7(lpLight
);
2444 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2445 This
->set_lights
|= 0x00000001 << dwLightIndex
;
2446 This
->light_parameters
[dwLightIndex
] = *lpLight
;
2448 /* Some checks to print out nice warnings :-) */
2449 switch (lpLight
->dltType
) {
2450 case D3DLIGHT_DIRECTIONAL
:
2451 case D3DLIGHT_POINT
:
2452 /* These are handled properly... */
2456 if ((lpLight
->dvTheta
!= 0.0) ||
2457 (lpLight
->dvTheta
!= lpLight
->dvPhi
)) {
2458 ERR("dvTheta not fully supported yet !\n");
2463 ERR("Light type not handled yet : %08x !\n", lpLight
->dltType
);
2466 /* This will force the Light setting on next drawing of primitives */
2467 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2473 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface
,
2477 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2478 TRACE("(%p/%p)->(%08lx,%d)\n", This
, iface
, dwLightIndex
, bEnable
);
2480 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2484 if (((0x00000001 << dwLightIndex
) & This
->set_lights
) == 0) {
2485 /* Set the default parameters.. */
2486 TRACE(" setting default light parameters...\n");
2487 GL_IDirect3DDeviceImpl_7_SetLight(iface
, dwLightIndex
, &(This
->light_parameters
[dwLightIndex
]));
2489 glEnable(GL_LIGHT0
+ dwLightIndex
);
2490 if ((This
->active_lights
& (0x00000001 << dwLightIndex
)) == 0) {
2491 /* This light gets active... Need to update its parameters to GL before the next drawing */
2492 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2494 This
->active_lights
|= 0x00000001 << dwLightIndex
;
2495 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2498 glDisable(GL_LIGHT0
+ dwLightIndex
);
2499 This
->active_lights
&= ~(0x00000001 << dwLightIndex
);
2507 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface
, DWORD dwIndex
, CONST D3DVALUE
* pPlaneEquation
)
2509 IDirect3DDeviceImpl
*This
= (IDirect3DDeviceImpl
*)iface
;
2510 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
2512 TRACE("(%p)->(%ld,%p)\n", This
, dwIndex
, pPlaneEquation
);
2514 if (dwIndex
>= This
->max_clipping_planes
) {
2515 return DDERR_INVALIDPARAMS
;
2518 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex
, pPlaneEquation
[0], pPlaneEquation
[1], pPlaneEquation
[2], pPlaneEquation
[3] );
2520 memcpy(This
->clipping_planes
[dwIndex
].plane
, pPlaneEquation
, sizeof(D3DVALUE
[4]));
2522 /* This is to force the reset of the transformation matrices on the next drawing.
2523 * This is needed to use the correct matrices for the various clipping planes.
2525 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2531 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface
,
2532 LPD3DVIEWPORT7 lpData
)
2534 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2535 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
2537 if (TRACE_ON(ddraw
)) {
2538 TRACE(" viewport is : \n");
2539 TRACE(" - dwX = %ld dwY = %ld\n",
2540 lpData
->dwX
, lpData
->dwY
);
2541 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2542 lpData
->dwWidth
, lpData
->dwHeight
);
2543 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2544 lpData
->dvMinZ
, lpData
->dvMaxZ
);
2548 /* Set the viewport */
2549 if ((lpData
->dvMinZ
!= This
->active_viewport
.dvMinZ
) ||
2550 (lpData
->dvMaxZ
!= This
->active_viewport
.dvMaxZ
)) {
2551 glDepthRange(lpData
->dvMinZ
, lpData
->dvMaxZ
);
2553 if ((lpData
->dwX
!= This
->active_viewport
.dwX
) ||
2554 (lpData
->dwY
!= This
->active_viewport
.dwY
) ||
2555 (lpData
->dwWidth
!= This
->active_viewport
.dwWidth
) ||
2556 (lpData
->dwHeight
!= This
->active_viewport
.dwHeight
)) {
2557 glViewport(lpData
->dwX
,
2558 This
->surface
->surface_desc
.dwHeight
- (lpData
->dwHeight
+ lpData
->dwY
),
2559 lpData
->dwWidth
, lpData
->dwHeight
);
2564 This
->active_viewport
= *lpData
;
2569 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2570 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2572 # define XCAST(fun) (void*)
2575 IDirect3DDevice7Vtbl VTABLE_IDirect3DDevice7
=
2577 XCAST(QueryInterface
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface
,
2578 XCAST(AddRef
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef
,
2579 XCAST(Release
) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release
,
2580 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_7_GetCaps
,
2581 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats
,
2582 XCAST(BeginScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene
,
2583 XCAST(EndScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene
,
2584 XCAST(GetDirect3D
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D
,
2585 XCAST(SetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget
,
2586 XCAST(GetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget
,
2587 XCAST(Clear
) Main_IDirect3DDeviceImpl_7_Clear
,
2588 XCAST(SetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform
,
2589 XCAST(GetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform
,
2590 XCAST(SetViewport
) GL_IDirect3DDeviceImpl_7_SetViewport
,
2591 XCAST(MultiplyTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform
,
2592 XCAST(GetViewport
) Main_IDirect3DDeviceImpl_7_GetViewport
,
2593 XCAST(SetMaterial
) GL_IDirect3DDeviceImpl_7_SetMaterial
,
2594 XCAST(GetMaterial
) Main_IDirect3DDeviceImpl_7_GetMaterial
,
2595 XCAST(SetLight
) GL_IDirect3DDeviceImpl_7_SetLight
,
2596 XCAST(GetLight
) Main_IDirect3DDeviceImpl_7_GetLight
,
2597 XCAST(SetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState
,
2598 XCAST(GetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState
,
2599 XCAST(BeginStateBlock
) Main_IDirect3DDeviceImpl_7_BeginStateBlock
,
2600 XCAST(EndStateBlock
) Main_IDirect3DDeviceImpl_7_EndStateBlock
,
2601 XCAST(PreLoad
) Main_IDirect3DDeviceImpl_7_PreLoad
,
2602 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive
,
2603 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive
,
2604 XCAST(SetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus
,
2605 XCAST(GetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus
,
2606 XCAST(DrawPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided
,
2607 XCAST(DrawIndexedPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided
,
2608 XCAST(DrawPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB
,
2609 XCAST(DrawIndexedPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB
,
2610 XCAST(ComputeSphereVisibility
) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility
,
2611 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_7_3T_GetTexture
,
2612 XCAST(SetTexture
) GL_IDirect3DDeviceImpl_7_3T_SetTexture
,
2613 XCAST(GetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState
,
2614 XCAST(SetTextureStageState
) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState
,
2615 XCAST(ValidateDevice
) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice
,
2616 XCAST(ApplyStateBlock
) Main_IDirect3DDeviceImpl_7_ApplyStateBlock
,
2617 XCAST(CaptureStateBlock
) Main_IDirect3DDeviceImpl_7_CaptureStateBlock
,
2618 XCAST(DeleteStateBlock
) Main_IDirect3DDeviceImpl_7_DeleteStateBlock
,
2619 XCAST(CreateStateBlock
) Main_IDirect3DDeviceImpl_7_CreateStateBlock
,
2620 XCAST(Load
) Main_IDirect3DDeviceImpl_7_Load
,
2621 XCAST(LightEnable
) GL_IDirect3DDeviceImpl_7_LightEnable
,
2622 XCAST(GetLightEnable
) Main_IDirect3DDeviceImpl_7_GetLightEnable
,
2623 XCAST(SetClipPlane
) GL_IDirect3DDeviceImpl_7_SetClipPlane
,
2624 XCAST(GetClipPlane
) Main_IDirect3DDeviceImpl_7_GetClipPlane
,
2625 XCAST(GetInfo
) Main_IDirect3DDeviceImpl_7_GetInfo
,
2628 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2633 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2634 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2636 # define XCAST(fun) (void*)
2639 IDirect3DDevice3Vtbl VTABLE_IDirect3DDevice3
=
2641 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_3_QueryInterface
,
2642 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_3_AddRef
,
2643 XCAST(Release
) Thunk_IDirect3DDeviceImpl_3_Release
,
2644 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps
,
2645 XCAST(GetStats
) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats
,
2646 XCAST(AddViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport
,
2647 XCAST(DeleteViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport
,
2648 XCAST(NextViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport
,
2649 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats
,
2650 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_3_BeginScene
,
2651 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_3_EndScene
,
2652 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_3_GetDirect3D
,
2653 XCAST(SetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport
,
2654 XCAST(GetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport
,
2655 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget
,
2656 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget
,
2657 XCAST(Begin
) Main_IDirect3DDeviceImpl_3_Begin
,
2658 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_3_BeginIndexed
,
2659 XCAST(Vertex
) Main_IDirect3DDeviceImpl_3_2T_Vertex
,
2660 XCAST(Index
) Main_IDirect3DDeviceImpl_3_2T_Index
,
2661 XCAST(End
) Main_IDirect3DDeviceImpl_3_2T_End
,
2662 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_3_GetRenderState
,
2663 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_3_SetRenderState
,
2664 XCAST(GetLightState
) GL_IDirect3DDeviceImpl_3_2T_GetLightState
,
2665 XCAST(SetLightState
) GL_IDirect3DDeviceImpl_3_2T_SetLightState
,
2666 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_3_SetTransform
,
2667 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_3_GetTransform
,
2668 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform
,
2669 XCAST(DrawPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive
,
2670 XCAST(DrawIndexedPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive
,
2671 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_3_SetClipStatus
,
2672 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_3_GetClipStatus
,
2673 XCAST(DrawPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided
,
2674 XCAST(DrawIndexedPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided
,
2675 XCAST(DrawPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB
,
2676 XCAST(DrawIndexedPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB
,
2677 XCAST(ComputeSphereVisibility
) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility
,
2678 XCAST(GetTexture
) Thunk_IDirect3DDeviceImpl_3_GetTexture
,
2679 XCAST(SetTexture
) Thunk_IDirect3DDeviceImpl_3_SetTexture
,
2680 XCAST(GetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState
,
2681 XCAST(SetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState
,
2682 XCAST(ValidateDevice
) Thunk_IDirect3DDeviceImpl_3_ValidateDevice
,
2685 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2690 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2691 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2693 # define XCAST(fun) (void*)
2696 IDirect3DDevice2Vtbl VTABLE_IDirect3DDevice2
=
2698 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_2_QueryInterface
,
2699 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_2_AddRef
,
2700 XCAST(Release
) Thunk_IDirect3DDeviceImpl_2_Release
,
2701 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_2_GetCaps
,
2702 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles
,
2703 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_2_GetStats
,
2704 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_2_AddViewport
,
2705 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_2_DeleteViewport
,
2706 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_2_NextViewport
,
2707 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats
,
2708 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_2_BeginScene
,
2709 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_2_EndScene
,
2710 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_2_GetDirect3D
,
2711 XCAST(SetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport
,
2712 XCAST(GetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport
,
2713 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget
,
2714 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget
,
2715 XCAST(Begin
) Main_IDirect3DDeviceImpl_2_Begin
,
2716 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_2_BeginIndexed
,
2717 XCAST(Vertex
) Thunk_IDirect3DDeviceImpl_2_Vertex
,
2718 XCAST(Index
) Thunk_IDirect3DDeviceImpl_2_Index
,
2719 XCAST(End
) Thunk_IDirect3DDeviceImpl_2_End
,
2720 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_2_GetRenderState
,
2721 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_2_SetRenderState
,
2722 XCAST(GetLightState
) Thunk_IDirect3DDeviceImpl_2_GetLightState
,
2723 XCAST(SetLightState
) Thunk_IDirect3DDeviceImpl_2_SetLightState
,
2724 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_2_SetTransform
,
2725 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_2_GetTransform
,
2726 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform
,
2727 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_2_DrawPrimitive
,
2728 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive
,
2729 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_2_SetClipStatus
,
2730 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_2_GetClipStatus
,
2733 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2738 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2739 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2741 # define XCAST(fun) (void*)
2744 IDirect3DDeviceVtbl VTABLE_IDirect3DDevice
=
2746 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_1_QueryInterface
,
2747 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_1_AddRef
,
2748 XCAST(Release
) Thunk_IDirect3DDeviceImpl_1_Release
,
2749 XCAST(Initialize
) Main_IDirect3DDeviceImpl_1_Initialize
,
2750 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_1_GetCaps
,
2751 XCAST(SwapTextureHandles
) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles
,
2752 XCAST(CreateExecuteBuffer
) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer
,
2753 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_1_GetStats
,
2754 XCAST(Execute
) Main_IDirect3DDeviceImpl_1_Execute
,
2755 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_1_AddViewport
,
2756 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_1_DeleteViewport
,
2757 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_1_NextViewport
,
2758 XCAST(Pick
) Main_IDirect3DDeviceImpl_1_Pick
,
2759 XCAST(GetPickRecords
) Main_IDirect3DDeviceImpl_1_GetPickRecords
,
2760 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats
,
2761 XCAST(CreateMatrix
) Main_IDirect3DDeviceImpl_1_CreateMatrix
,
2762 XCAST(SetMatrix
) Main_IDirect3DDeviceImpl_1_SetMatrix
,
2763 XCAST(GetMatrix
) Main_IDirect3DDeviceImpl_1_GetMatrix
,
2764 XCAST(DeleteMatrix
) Main_IDirect3DDeviceImpl_1_DeleteMatrix
,
2765 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_1_BeginScene
,
2766 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_1_EndScene
,
2767 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_1_GetDirect3D
,
2770 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2774 static HRESULT
d3ddevice_clear(IDirect3DDeviceImpl
*This
,
2775 WINE_GL_BUFFER_TYPE buffer_type
,
2783 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2784 GLbitfield bitfield
= 0;
2788 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2789 if (TRACE_ON(ddraw
)) {
2792 TRACE(" rectangles : \n");
2793 for (i
= 0; i
< dwCount
; i
++) {
2794 TRACE(" - %ld x %ld %ld x %ld\n", lpRects
[i
].u1
.x1
, lpRects
[i
].u2
.y1
, lpRects
[i
].u3
.x2
, lpRects
[i
].u4
.y2
);
2803 rect
.u3
.x2
= This
->surface
->surface_desc
.dwWidth
;
2804 rect
.u4
.y2
= This
->surface
->surface_desc
.dwHeight
;
2808 /* Clears the screen */
2811 if (dwFlags
& D3DCLEAR_TARGET
) {
2812 if (glThis
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
2813 /* TODO: optimize here the case where Clear changes all the screen... */
2814 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[buffer_type
]), glThis
->lock_surf
[buffer_type
]);
2816 glThis
->state
[buffer_type
] = SURFACE_GL
;
2819 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2820 bitfield
|= GL_DEPTH_BUFFER_BIT
;
2821 if (glThis
->depth_mask
== FALSE
) {
2822 glDepthMask(GL_TRUE
); /* Enables Z writing to be sure to delete also the Z buffer */
2824 if (dvZ
!= glThis
->prev_clear_Z
) {
2826 glThis
->prev_clear_Z
= dvZ
;
2828 TRACE(" depth value : %f\n", dvZ
);
2830 if (dwFlags
& D3DCLEAR_STENCIL
) {
2831 bitfield
|= GL_STENCIL_BUFFER_BIT
;
2832 if (dwStencil
!= glThis
->prev_clear_stencil
) {
2833 glClearStencil(dwStencil
);
2834 glThis
->prev_clear_stencil
= dwStencil
;
2836 TRACE(" stencil value : %ld\n", dwStencil
);
2838 if (dwFlags
& D3DCLEAR_TARGET
) {
2839 bitfield
|= GL_COLOR_BUFFER_BIT
;
2840 if (dwColor
!= glThis
->prev_clear_color
) {
2841 glClearColor(((dwColor
>> 16) & 0xFF) / 255.0,
2842 ((dwColor
>> 8) & 0xFF) / 255.0,
2843 ((dwColor
>> 0) & 0xFF) / 255.0,
2844 ((dwColor
>> 24) & 0xFF) / 255.0);
2845 glThis
->prev_clear_color
= dwColor
;
2847 TRACE(" color value (ARGB) : %08lx\n", dwColor
);
2850 glEnable(GL_SCISSOR_TEST
);
2851 for (i
= 0; i
< dwCount
; i
++) {
2852 glScissor(lpRects
[i
].u1
.x1
, This
->surface
->surface_desc
.dwHeight
- lpRects
[i
].u4
.y2
,
2853 lpRects
[i
].u3
.x2
- lpRects
[i
].u1
.x1
, lpRects
[i
].u4
.y2
- lpRects
[i
].u2
.y1
);
2856 glDisable(GL_SCISSOR_TEST
);
2858 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2859 if (glThis
->depth_mask
== FALSE
) glDepthMask(GL_FALSE
);
2867 static HRESULT
d3ddevice_clear_back(IDirect3DDeviceImpl
*This
,
2875 return d3ddevice_clear(This
, WINE_GL_BUFFER_BACK
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2879 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl
*This
,
2880 WINE_GL_BUFFER_TYPE
*buffer_type_p
, D3DRECT
*rect
)
2882 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
2883 WINE_GL_BUFFER_TYPE buffer_type
;
2885 /* First check if we BLT to the backbuffer... */
2886 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
2887 buffer_type
= WINE_GL_BUFFER_BACK
;
2888 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
2889 buffer_type
= WINE_GL_BUFFER_FRONT
;
2891 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2892 return DDERR_INVALIDPARAMS
;
2895 if ((gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) &&
2896 (rect
->u1
.x1
>= gl_d3d_dev
->lock_rect
[buffer_type
].left
) &&
2897 (rect
->u2
.y1
>= gl_d3d_dev
->lock_rect
[buffer_type
].top
) &&
2898 (rect
->u3
.x2
<= gl_d3d_dev
->lock_rect
[buffer_type
].right
) &&
2899 (rect
->u4
.y2
<= gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
2900 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2903 return DDERR_INVALIDPARAMS
;
2905 *buffer_type_p
= buffer_type
;
2911 d3ddevice_blt(IDirectDrawSurfaceImpl
*This
, LPRECT rdst
,
2912 LPDIRECTDRAWSURFACE7 src
, LPRECT rsrc
,
2913 DWORD dwFlags
, LPDDBLTFX lpbltfx
)
2915 WINE_GL_BUFFER_TYPE buffer_type
;
2919 rect
.u1
.x1
= rdst
->left
;
2920 rect
.u2
.y1
= rdst
->top
;
2921 rect
.u3
.x2
= rdst
->right
;
2922 rect
.u4
.y2
= rdst
->bottom
;
2926 rect
.u3
.x2
= This
->surface_desc
.dwWidth
;
2927 rect
.u4
.y2
= This
->surface_desc
.dwHeight
;
2930 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, &rect
) != DD_OK
) return DDERR_INVALIDPARAMS
;
2932 if (dwFlags
& DDBLT_COLORFILL
) {
2933 /* This is easy to handle for the D3D Device... */
2937 /* The color as given in the Blt function is in the format of the frame-buffer...
2938 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2940 if (This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
2941 if (This
->palette
) {
2942 color
= ((0xFF000000) |
2943 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peRed
<< 16) |
2944 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peGreen
<< 8) |
2945 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peBlue
));
2949 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) &&
2950 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
2951 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
2952 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
2953 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
2954 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
2955 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
2956 if (lpbltfx
->u5
.dwFillColor
== 0xFFFF) {
2959 color
= ((0xFF000000) |
2960 ((lpbltfx
->u5
.dwFillColor
& 0xF800) << 8) |
2961 ((lpbltfx
->u5
.dwFillColor
& 0x07E0) << 5) |
2962 ((lpbltfx
->u5
.dwFillColor
& 0x001F) << 3));
2964 } else if (((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) ||
2965 (This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24)) &&
2966 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
2967 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
2968 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
2969 color
= 0xFF000000 | lpbltfx
->u5
.dwFillColor
;
2971 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2972 return DDERR_INVALIDPARAMS
;
2975 ERR("Wrong surface type for BLT override !\n");
2976 return DDERR_INVALIDPARAMS
;
2979 TRACE(" executing D3D Device override.\n");
2983 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
2984 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
2985 glDrawBuffer(GL_FRONT
);
2987 glDrawBuffer(GL_BACK
);
2989 d3ddevice_clear(This
->d3ddevice
, buffer_type
, 1, &rect
, D3DCLEAR_TARGET
, color
, 0.0, 0x00000000);
2991 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
2992 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
2993 glDrawBuffer(prev_draw
);
2998 } else if ((dwFlags
& (~(DDBLT_KEYSRC
|DDBLT_WAIT
|DDBLT_ASYNC
))) == 0) {
2999 /* Normal blit without any special case... */
3001 /* And which has a SRC surface */
3002 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
3004 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
) &&
3005 (src_impl
->d3ddevice
== This
->d3ddevice
) &&
3006 ((dwFlags
& DDBLT_KEYSRC
) == 0)) {
3007 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
3011 WINE_GL_BUFFER_TYPE src_buffer_type
;
3012 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3018 src_rect
.u1
.x1
= rsrc
->left
;
3019 src_rect
.u2
.y1
= rsrc
->top
;
3020 src_rect
.u3
.x2
= rsrc
->right
;
3021 src_rect
.u4
.y2
= rsrc
->bottom
;
3025 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
3026 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
3029 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
3030 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
3032 if ((width
!= (rect
.u3
.x2
- rect
.u1
.x1
)) ||
3033 (height
!= (rect
.u4
.y2
- rect
.u2
.y1
))) {
3034 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
3035 return DDERR_INVALIDPARAMS
;
3038 /* First check if we BLT from the backbuffer... */
3039 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
3040 src_buffer_type
= WINE_GL_BUFFER_BACK
;
3041 } else if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3042 src_buffer_type
= WINE_GL_BUFFER_FRONT
;
3044 ERR("Unexpected case in direct buffer to buffer copy !\n");
3045 return DDERR_INVALIDPARAMS
;
3048 TRACE(" using direct buffer to buffer copy.\n");
3052 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, FALSE
, &initial
);
3054 if (upload_surface_to_tex_memory_init(This
, 0, &gl_d3d_dev
->current_internal_format
,
3055 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3056 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3058 return DDERR_INVALIDPARAMS
;
3061 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3062 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3063 glDrawBuffer(GL_FRONT
);
3065 glDrawBuffer(GL_BACK
);
3067 if (src_buffer_type
== WINE_GL_BUFFER_FRONT
)
3068 glReadBuffer(GL_FRONT
);
3070 glReadBuffer(GL_BACK
);
3072 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3073 And directly re-draws this on the destination buffer. */
3074 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3077 if ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwHeight
)
3078 get_height
= src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
);
3080 get_height
= UNLOCK_TEX_SIZE
;
3082 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3085 if ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwWidth
)
3086 get_width
= src_impl
->surface_desc
.dwWidth
- (src_rect
.u1
.x1
+ x
);
3088 get_width
= UNLOCK_TEX_SIZE
;
3090 glCopyTexSubImage2D(GL_TEXTURE_2D
, 0,
3091 0, UNLOCK_TEX_SIZE
- get_height
,
3092 src_rect
.u1
.x1
+ x
, src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
+ get_height
),
3093 get_width
, get_height
);
3096 glTexCoord2f(0.0, 0.0);
3097 glVertex3d(rect
.u1
.x1
+ x
,
3098 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
3100 glTexCoord2f(1.0, 0.0);
3101 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
3102 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
3104 glTexCoord2f(1.0, 1.0);
3105 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
3108 glTexCoord2f(0.0, 1.0);
3109 glVertex3d(rect
.u1
.x1
+ x
,
3116 upload_surface_to_tex_memory_release();
3117 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, FALSE
);
3119 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3120 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3121 glDrawBuffer(prev_draw
);
3127 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3128 (this prevents calling glReadPixels) */
3132 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3136 double x_stretch
, y_stretch
;
3139 src_rect
.u1
.x1
= rsrc
->left
;
3140 src_rect
.u2
.y1
= rsrc
->top
;
3141 src_rect
.u3
.x2
= rsrc
->right
;
3142 src_rect
.u4
.y2
= rsrc
->bottom
;
3146 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
3147 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
3150 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
3151 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
3153 x_stretch
= (double) (rect
.u3
.x2
- rect
.u1
.x1
) / (double) width
;
3154 y_stretch
= (double) (rect
.u4
.y2
- rect
.u2
.y1
) / (double) height
;
3156 TRACE(" using memory to buffer Blt override.\n");
3160 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, ((dwFlags
& DDBLT_KEYSRC
) != 0), &initial
);
3162 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3163 initial
, ((dwFlags
& DDBLT_KEYSRC
) != 0), UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3164 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3166 return DDERR_INVALIDPARAMS
;
3169 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3170 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3171 glDrawBuffer(GL_FRONT
);
3173 glDrawBuffer(GL_BACK
);
3175 /* Now the serious stuff happens. This is basically the same code as for the memory
3176 flush to frame buffer ... with stretching and different rectangles added :-) */
3177 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3180 flush_rect
.top
= src_rect
.u2
.y1
+ y
;
3181 flush_rect
.bottom
= ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
> src_rect
.u4
.y2
) ?
3183 (src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
));
3185 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3186 flush_rect
.left
= src_rect
.u1
.x1
+ x
;
3187 flush_rect
.right
= ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
> src_rect
.u3
.x2
) ?
3189 (src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
));
3191 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3194 glTexCoord2f(0.0, 0.0);
3195 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3196 rect
.u2
.y1
+ (y
* y_stretch
),
3198 glTexCoord2f(1.0, 0.0);
3199 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3200 rect
.u2
.y1
+ (y
* y_stretch
),
3202 glTexCoord2f(1.0, 1.0);
3203 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3204 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3206 glTexCoord2f(0.0, 1.0);
3207 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3208 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3214 upload_surface_to_tex_memory_release();
3215 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, ((dwFlags
& DDBLT_KEYSRC
) != 0));
3217 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3218 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3219 glDrawBuffer(prev_draw
);
3227 return DDERR_INVALIDPARAMS
;
3231 d3ddevice_bltfast(IDirectDrawSurfaceImpl
*This
, DWORD dstx
,
3232 DWORD dsty
, LPDIRECTDRAWSURFACE7 src
,
3233 LPRECT rsrc
, DWORD trans
)
3237 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
3238 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3239 WINE_GL_BUFFER_TYPE buffer_type
;
3243 int width
, height
, x
, y
;
3245 /* Cannot support DSTCOLORKEY blitting... */
3246 if ((trans
& DDBLTFAST_DESTCOLORKEY
) != 0) return DDERR_INVALIDPARAMS
;
3249 WARN("rsrc is NULL - getting the whole surface !!\n");
3251 rsrc
->left
= rsrc
->top
= 0;
3252 rsrc
->right
= src_impl
->surface_desc
.dwWidth
;
3253 rsrc
->bottom
= src_impl
->surface_desc
.dwHeight
;
3261 rdst
.right
= dstx
+ (rsrc
->right
- rsrc
->left
);
3262 if (rdst
.right
> This
->surface_desc
.dwWidth
) {
3263 rsrc
->right
-= (This
->surface_desc
.dwWidth
- rdst
.right
);
3264 rdst
.right
= This
->surface_desc
.dwWidth
;
3266 rdst
.bottom
= dsty
+ (rsrc
->bottom
- rsrc
->top
);
3267 if (rdst
.bottom
> This
->surface_desc
.dwHeight
) {
3268 rsrc
->bottom
-= (This
->surface_desc
.dwHeight
- rdst
.bottom
);
3269 rdst
.bottom
= This
->surface_desc
.dwHeight
;
3272 width
= rsrc
->right
- rsrc
->left
;
3273 height
= rsrc
->bottom
- rsrc
->top
;
3275 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, (D3DRECT
*) &rdst
) != DD_OK
) return DDERR_INVALIDPARAMS
;
3277 TRACE(" using BltFast memory to frame buffer override.\n");
3281 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, &rdst
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0, &initial
);
3283 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3284 initial
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0,
3285 UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3286 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
3288 return DDERR_INVALIDPARAMS
;
3291 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3292 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3293 glDrawBuffer(GL_FRONT
);
3295 glDrawBuffer(GL_BACK
);
3297 /* Now the serious stuff happens. This is basically the same code that for the memory
3298 flush to frame buffer but with different rectangles for source and destination :-) */
3299 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3302 flush_rect
.top
= rsrc
->top
+ y
;
3303 flush_rect
.bottom
= ((rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
> rsrc
->bottom
) ?
3305 (rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
));
3307 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3308 flush_rect
.left
= rsrc
->left
+ x
;
3309 flush_rect
.right
= ((rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
> rsrc
->right
) ?
3311 (rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
));
3313 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3316 glTexCoord2f(0.0, 0.0);
3317 glVertex3d(rdst
.left
+ x
,
3320 glTexCoord2f(1.0, 0.0);
3321 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3324 glTexCoord2f(1.0, 1.0);
3325 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3326 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3328 glTexCoord2f(0.0, 1.0);
3329 glVertex3d(rdst
.left
+ x
,
3330 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3336 upload_surface_to_tex_memory_release();
3337 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0);
3339 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3340 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3341 glDrawBuffer(prev_draw
);
3349 d3ddevice_set_ortho(IDirect3DDeviceImpl
*This
)
3351 GLfloat height
, width
;
3352 GLfloat trans_mat
[16];
3354 TRACE("(%p)\n", This
);
3356 width
= This
->surface
->surface_desc
.dwWidth
;
3357 height
= This
->surface
->surface_desc
.dwHeight
;
3359 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3360 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3362 trans_mat
[ 0] = 2.0 / width
; trans_mat
[ 4] = 0.0; trans_mat
[ 8] = 0.0; trans_mat
[12] = -1.0;
3363 trans_mat
[ 1] = 0.0; trans_mat
[ 5] = -2.0 / height
; trans_mat
[ 9] = 0.0; trans_mat
[13] = 1.0;
3365 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3366 * that the Z coordinate needs to be given to GL unchanged.
3368 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 2.0; trans_mat
[14] = -1.0;
3370 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 1.0; trans_mat
[14] = 0.0;
3371 trans_mat
[ 3] = 0.0; trans_mat
[ 7] = 0.0; trans_mat
[11] = 0.0; trans_mat
[15] = 1.0;
3374 glMatrixMode(GL_MODELVIEW
);
3376 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3377 Correctness Tips section).
3379 Basically, from what I understood, if the game does not filter the font texture,
3380 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3381 one and we will have strange artifacts (as the rounding and stuff may give different results
3382 for different pixels, ie sometimes take the left pixel, sometimes the right).
3384 glTranslatef(0.375, 0.375, 0);
3385 glMatrixMode(GL_PROJECTION
);
3386 glLoadMatrixf(trans_mat
);
3391 d3ddevice_set_matrices(IDirect3DDeviceImpl
*This
, DWORD matrices
,
3392 D3DMATRIX
*world_mat
, D3DMATRIX
*view_mat
, D3DMATRIX
*proj_mat
)
3394 TRACE("(%p,%08lx,%p,%p,%p)\n", This
, matrices
, world_mat
, view_mat
, proj_mat
);
3397 if ((matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
)) != 0) {
3398 glMatrixMode(GL_MODELVIEW
);
3399 glLoadMatrixf((float *) view_mat
);
3401 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3402 if (This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPING
- 1] != FALSE
) {
3405 for (i
= 0, runner
= 0x00000001; i
< This
->max_clipping_planes
; i
++, runner
<<= 1) {
3406 if (runner
& This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPLANEENABLE
- 1]) {
3409 plane
[0] = This
->clipping_planes
[i
].plane
[0];
3410 plane
[1] = This
->clipping_planes
[i
].plane
[1];
3411 plane
[2] = This
->clipping_planes
[i
].plane
[2];
3412 plane
[3] = This
->clipping_planes
[i
].plane
[3];
3414 glClipPlane( GL_CLIP_PLANE0
+ i
, (const GLdouble
*) (&plane
) );
3418 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] != FALSE
) {
3422 for (i
= 0, runner
= 0x00000001; i
< MAX_LIGHTS
; i
++, runner
<<= 1) {
3423 if (runner
& This
->active_lights
) {
3424 switch (This
->light_parameters
[i
].dltType
) {
3425 case D3DLIGHT_DIRECTIONAL
: {
3427 float cut_off
= 180.0;
3429 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3430 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3431 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3432 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3434 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3435 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3436 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3438 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) direction
);
3441 case D3DLIGHT_POINT
: {
3443 float cut_off
= 180.0;
3445 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3446 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3447 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3448 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3449 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3450 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3452 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3453 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3454 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3455 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3456 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3459 case D3DLIGHT_SPOT
: {
3462 float cut_off
= 90.0 * (This
->light_parameters
[i
].dvPhi
/ M_PI
);
3464 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3465 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3466 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3468 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3469 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3470 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3472 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_DIRECTION
, (float *) direction
);
3473 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3474 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3475 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3477 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3478 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3479 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3480 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3481 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3482 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_EXPONENT
, &(This
->light_parameters
[i
].dvFalloff
));
3486 /* No warning here as it's already done at light setting */
3493 glMultMatrixf((float *) world_mat
);
3495 if ((matrices
& PROJMAT_CHANGED
) != 0) {
3496 glMatrixMode(GL_PROJECTION
);
3497 glLoadMatrixf((float *) proj_mat
);
3503 d3ddevice_matrices_updated(IDirect3DDeviceImpl
*This
, DWORD matrices
)
3505 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
3506 DWORD tex_mat
, tex_stage
;
3508 TRACE("(%p,%08lx)\n", This
, matrices
);
3510 if (matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
)) {
3511 if (glThis
->transform_state
== GL_TRANSFORM_NORMAL
) {
3512 /* This will force an update of the transform state at the next drawing. */
3513 glThis
->transform_state
= GL_TRANSFORM_NONE
;
3516 if (matrices
& (TEXMAT0_CHANGED
|TEXMAT1_CHANGED
|TEXMAT2_CHANGED
|TEXMAT3_CHANGED
|
3517 TEXMAT4_CHANGED
|TEXMAT5_CHANGED
|TEXMAT6_CHANGED
|TEXMAT7_CHANGED
))
3520 for (tex_mat
= TEXMAT0_CHANGED
, tex_stage
= 0; tex_mat
<= TEXMAT7_CHANGED
; tex_mat
<<= 1, tex_stage
++) {
3521 GLenum unit
= GL_TEXTURE0_WINE
+ tex_stage
;
3522 if (matrices
& tex_mat
) {
3523 if (This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXTURETRANSFORMFLAGS
- 1] != D3DTTFF_DISABLE
) {
3524 int is_identity
= (memcmp(This
->tex_mat
[tex_stage
], id_mat
, 16 * sizeof(D3DVALUE
)) != 0);
3526 if (This
->tex_mat_is_identity
[tex_stage
] != is_identity
) {
3527 if (glThis
->current_active_tex_unit
!= unit
) {
3528 GL_extensions
.glActiveTexture(unit
);
3529 glThis
->current_active_tex_unit
= unit
;
3531 glMatrixMode(GL_TEXTURE
);
3532 glLoadMatrixf((float *) This
->tex_mat
[tex_stage
]);
3534 This
->tex_mat_is_identity
[tex_stage
] = is_identity
;
3536 if (This
->tex_mat_is_identity
[tex_stage
] == FALSE
) {
3537 if (glThis
->current_active_tex_unit
!= unit
) {
3538 GL_extensions
.glActiveTexture(unit
);
3539 glThis
->current_active_tex_unit
= unit
;
3541 glMatrixMode(GL_TEXTURE
);
3543 This
->tex_mat_is_identity
[tex_stage
] = TRUE
;
3552 /* TODO for both these functions :
3553 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3554 by other OpenGL code in D3D
3555 - handle the case where no 'Begin / EndScene' was done between two locks
3556 - handle the rectangles in the unlock too
3557 - handle pitch correctly...
3559 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
3561 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3562 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3563 WINE_GL_BUFFER_TYPE buffer_type
;
3566 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3567 buffer_type
= WINE_GL_BUFFER_FRONT
;
3568 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_FRONT
] != SURFACE_GL
) &&
3569 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] != This
)) {
3570 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3572 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] = This
;
3573 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3574 buffer_type
= WINE_GL_BUFFER_BACK
;
3575 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] != SURFACE_GL
) &&
3576 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] != This
)) {
3577 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3579 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] = This
;
3581 ERR("Wrong surface type for locking !\n");
3585 if (pRect
== NULL
) {
3588 loc_rect
.bottom
= This
->surface_desc
.dwHeight
;
3589 loc_rect
.right
= This
->surface_desc
.dwWidth
;
3593 /* Try to acquire the device critical section */
3594 EnterCriticalSection(&(d3d_dev
->crit
));
3596 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
]) {
3597 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3598 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3600 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = TRUE
;
3602 if (gl_d3d_dev
->state
[buffer_type
] != SURFACE_GL
) {
3603 /* Check if the new rectangle is in the previous one or not.
3604 If it is not, flush first the previous locks on screen.
3606 if ((pRect
->top
< gl_d3d_dev
->lock_rect
[buffer_type
].top
) ||
3607 (pRect
->left
< gl_d3d_dev
->lock_rect
[buffer_type
].left
) ||
3608 (pRect
->right
> gl_d3d_dev
->lock_rect
[buffer_type
].right
) ||
3609 (pRect
->bottom
> gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
3610 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
3611 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3612 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3613 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
,
3614 gl_d3d_dev
->lock_rect
[buffer_type
].left
, gl_d3d_dev
->lock_rect
[buffer_type
].top
,
3615 gl_d3d_dev
->lock_rect
[buffer_type
].right
, gl_d3d_dev
->lock_rect
[buffer_type
].bottom
);
3616 d3d_dev
->flush_to_framebuffer(d3d_dev
, &(gl_d3d_dev
->lock_rect
[buffer_type
]), gl_d3d_dev
->lock_surf
[buffer_type
]);
3618 gl_d3d_dev
->state
[buffer_type
] = SURFACE_GL
;
3619 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3621 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3623 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3626 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_GL
) {
3627 /* If the surface is already in memory, no need to do anything here... */
3628 GLenum buffer_format
;
3629 GLenum buffer_color
;
3633 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3634 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3636 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3637 may only write to the device... But when we will blit it back to the screen, we need
3638 also to blit correctly the parts the application did not overwrite... */
3640 if (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) != 0) &&
3641 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
3642 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
3643 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
3644 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
3645 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
3646 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
3647 buffer_format
= GL_UNSIGNED_SHORT_5_6_5
;
3648 buffer_color
= GL_RGB
;
3649 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24) &&
3650 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xFF0000) &&
3651 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x00FF00) &&
3652 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x0000FF)) {
3653 buffer_format
= GL_UNSIGNED_BYTE
;
3654 buffer_color
= GL_RGB
;
3655 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) &&
3656 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
3657 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
3658 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
3659 buffer_format
= GL_UNSIGNED_INT_8_8_8_8_REV
;
3660 buffer_color
= GL_BGRA
;
3662 ERR(" unsupported pixel format at device locking.\n");
3666 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3672 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3673 /* Application wants to lock the front buffer */
3674 glReadBuffer(GL_FRONT
);
3676 /* Application wants to lock the back buffer */
3677 glReadBuffer(GL_BACK
);
3679 dst
= ((char *)This
->surface_desc
.lpSurface
) +
3680 (pRect
->top
* This
->surface_desc
.u1
.lPitch
) + (pRect
->left
* GET_BPP(This
->surface_desc
));
3682 if (This
->surface_desc
.u1
.lPitch
!= (GET_BPP(This
->surface_desc
) * This
->surface_desc
.dwWidth
)) {
3683 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3684 * could not be bothered considering the rare cases where it may be useful :-)
3686 for (y
= (This
->surface_desc
.dwHeight
- pRect
->top
- 1);
3687 y
>= ((int) This
->surface_desc
.dwHeight
- (int) pRect
->bottom
);
3689 glReadPixels(pRect
->left
, y
,
3690 pRect
->right
- pRect
->left
, 1,
3691 buffer_color
, buffer_format
, dst
);
3692 dst
+= This
->surface_desc
.u1
.lPitch
;
3695 /* Faster path for surface copy. Note that I can use static variables here as I am
3696 * protected by the OpenGL critical section so this function won't be called by
3697 * two threads at the same time.
3699 static char *buffer
= NULL
;
3700 static int buffer_width
= 0;
3701 char *dst2
= dst
+ ((pRect
->bottom
- pRect
->top
) - 1) * This
->surface_desc
.u1
.lPitch
;
3702 int current_width
= (pRect
->right
- pRect
->left
) * GET_BPP(This
->surface_desc
);
3704 glReadPixels(pRect
->left
, ((int) This
->surface_desc
.dwHeight
- (int) pRect
->bottom
),
3705 pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
,
3706 buffer_color
, buffer_format
, dst
);
3708 if (current_width
> buffer_width
) {
3709 if (buffer
!= NULL
) HeapFree(GetProcessHeap(), 0, buffer
);
3710 buffer_width
= current_width
;
3711 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_width
);
3713 for (y
= 0; y
< ((pRect
->bottom
- pRect
->top
) / 2); y
++) {
3714 memcpy(buffer
, dst
, current_width
);
3715 memcpy(dst
, dst2
, current_width
);
3716 memcpy(dst2
, buffer
, current_width
);
3717 dst
+= This
->surface_desc
.u1
.lPitch
;
3718 dst2
-= This
->surface_desc
.u1
.lPitch
;
3722 gl_d3d_dev
->state
[buffer_type
] = SURFACE_MEMORY
;
3725 /* I keep this code here as it's very useful to debug :-) */
3727 static int flush_count
= 0;
3731 if ((++flush_count
% 50) == 0) {
3732 sprintf(buf
, "lock_%06d.pnm", flush_count
);
3733 f
= fopen(buf
, "wb");
3734 DDRAW_dump_surface_to_disk(This
, f
);
3743 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
3745 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3750 /* Note : no need here to lock the 'device critical section' as we are already protected by
3751 the GL critical section. */
3753 if (pRect
== NULL
) {
3756 loc_rect
.bottom
= d3d_dev
->surface
->surface_desc
.dwHeight
;
3757 loc_rect
.right
= d3d_dev
->surface
->surface_desc
.dwWidth
;
3761 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect
->top
, pRect
->left
, pRect
->right
, pRect
->bottom
);
3763 opt_bitmap
= d3ddevice_set_state_for_flush(d3d_dev
, pRect
, FALSE
, &initial
);
3765 if (upload_surface_to_tex_memory_init(surf
, 0, &gl_d3d_dev
->current_internal_format
,
3766 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3767 ERR(" unsupported pixel format at frame buffer flush.\n");
3771 for (y
= pRect
->top
; y
< pRect
->bottom
; y
+= UNLOCK_TEX_SIZE
) {
3775 flush_rect
.bottom
= (y
+ UNLOCK_TEX_SIZE
> pRect
->bottom
) ? pRect
->bottom
: (y
+ UNLOCK_TEX_SIZE
);
3777 for (x
= pRect
->left
; x
< pRect
->right
; x
+= UNLOCK_TEX_SIZE
) {
3778 /* First, upload the texture... */
3779 flush_rect
.left
= x
;
3780 flush_rect
.right
= (x
+ UNLOCK_TEX_SIZE
> pRect
->right
) ? pRect
->right
: (x
+ UNLOCK_TEX_SIZE
);
3782 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3785 glTexCoord2f(0.0, 0.0);
3786 glVertex3d(x
, y
, 0.5);
3787 glTexCoord2f(1.0, 0.0);
3788 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
, 0.5);
3789 glTexCoord2f(1.0, 1.0);
3790 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3791 glTexCoord2f(0.0, 1.0);
3792 glVertex3d(x
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3797 upload_surface_to_tex_memory_release();
3798 d3ddevice_restore_state_after_flush(d3d_dev
, opt_bitmap
, FALSE
);
3801 /* I keep this code here as it's very useful to debug :-) */
3803 static int flush_count
= 0;
3807 if ((++flush_count
% 50) == 0) {
3808 sprintf(buf
, "flush_%06d.pnm", flush_count
);
3809 f
= fopen(buf
, "wb");
3810 DDRAW_dump_surface_to_disk(surf
, f
);
3816 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
3818 WINE_GL_BUFFER_TYPE buffer_type
;
3819 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3820 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3822 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3823 buffer_type
= WINE_GL_BUFFER_FRONT
;
3824 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3825 buffer_type
= WINE_GL_BUFFER_BACK
;
3827 ERR("Wrong surface type for locking !\n");
3831 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
] == FALSE
) {
3832 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3833 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3835 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = FALSE
;
3837 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3838 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0) {
3839 if (buffer_type
== WINE_GL_BUFFER_FRONT
) {
3842 TRACE(" flushing front buffer immediately on screen.\n");
3845 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3846 glDrawBuffer(GL_FRONT
);
3847 /* Note: we do not use the application provided lock rectangle but our own stored at
3848 lock time. This is because in old D3D versions, the 'lock' parameter did not
3851 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
]);
3852 glDrawBuffer(prev_draw
);
3855 gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_MEMORY_DIRTY
;
3859 /* And 'frees' the device critical section */
3860 LeaveCriticalSection(&(d3d_dev
->crit
));
3864 apply_texture_state(IDirect3DDeviceImpl
*This
)
3868 /* Initialize texture stages states */
3869 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
3870 for (state
= 0; state
< HIGHEST_TEXTURE_STAGE_STATE
; state
+= 1) {
3871 if (This
->state_block
.set_flags
.texture_stage_state
[stage
][state
]) {
3872 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
3873 stage
, state
+ 1, This
->state_block
.texture_stage_state
[stage
][state
]);
3880 d3ddevice_create(IDirect3DDeviceImpl
**obj
, IDirectDrawImpl
*d3d
, IDirectDrawSurfaceImpl
*surface
, BOOLEAN from_surface
)
3882 IDirect3DDeviceImpl
*object
;
3883 IDirect3DDeviceGLImpl
*gl_object
;
3884 IDirectDrawSurfaceImpl
*surf
;
3889 XVisualInfo
template;
3890 GLenum buffer
= GL_FRONT
;
3893 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DDeviceGLImpl
));
3894 if (object
== NULL
) return DDERR_OUTOFMEMORY
;
3896 gl_object
= (IDirect3DDeviceGLImpl
*) object
;
3900 object
->surface
= surface
;
3901 object
->set_context
= set_context
;
3902 object
->clear
= d3ddevice_clear_back
;
3903 object
->set_matrices
= d3ddevice_set_matrices
;
3904 object
->matrices_updated
= d3ddevice_matrices_updated
;
3905 object
->flush_to_framebuffer
= d3ddevice_flush_to_frame_buffer
;
3907 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface
, d3d
);
3909 InitializeCriticalSection(&(object
->crit
));
3911 TRACE(" device critical section : %p\n", &(object
->crit
));
3913 /* This is just a hack for some badly done games :-/ */
3915 gl_object
->version
= 1;
3916 TRACE(" using D3D1 special hacks.\n");
3918 gl_object
->version
= 7;
3920 device_context
= GetDC(surface
->ddraw_owner
->window
);
3921 gl_object
->display
= get_display(device_context
);
3922 gl_object
->drawable
= get_drawable(device_context
);
3923 ReleaseDC(surface
->ddraw_owner
->window
,device_context
);
3926 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3927 vis
= XGetVisualInfo(gl_object
->display
, VisualIDMask
, &template, &num
);
3929 HeapFree(GetProcessHeap(), 0, object
);
3930 ERR("No visual found !\n");
3932 return DDERR_INVALIDPARAMS
;
3934 TRACE(" visual found\n");
3937 gl_object
->gl_context
= glXCreateContext(gl_object
->display
, vis
,
3940 if (gl_object
->gl_context
== NULL
) {
3941 HeapFree(GetProcessHeap(), 0, object
);
3942 ERR("Error in context creation !\n");
3944 return DDERR_INVALIDPARAMS
;
3946 TRACE(" context created (%p)\n", gl_object
->gl_context
);
3949 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3950 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3951 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
3952 surf
->aux_ctx
= (LPVOID
) object
;
3953 surf
->aux_data
= (LPVOID
) gl_object
->drawable
;
3954 surf
->aux_flip
= opengl_flip
;
3959 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3961 TRACE(" no double buffering : drawing on the front buffer\n");
3965 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3966 IDirectDrawSurfaceImpl
*surf2
;
3967 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
3968 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
3969 TRACE(" checking surface %p :", surf2
);
3970 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
3971 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
3972 /* Override the Lock / Unlock function for all these surfaces */
3973 surf2
->lock_update_prev
= surf2
->lock_update
;
3974 surf2
->lock_update
= d3ddevice_lock_update
;
3975 surf2
->unlock_update_prev
= surf2
->unlock_update
;
3976 surf2
->unlock_update
= d3ddevice_unlock_update
;
3977 /* And install also the blt / bltfast overrides */
3978 surf2
->aux_blt
= d3ddevice_blt
;
3979 surf2
->aux_bltfast
= d3ddevice_bltfast
;
3981 TRACE(" overriding direct surface access.\n");
3983 TRACE(" no override.\n");
3985 surf2
->d3ddevice
= object
;
3989 /* Set the various light parameters */
3990 for (light
= 0; light
< MAX_LIGHTS
; light
++) {
3991 /* Only set the fields that are not zero-created */
3992 object
->light_parameters
[light
].dltType
= D3DLIGHT_DIRECTIONAL
;
3993 object
->light_parameters
[light
].dcvDiffuse
.u1
.r
= 1.0;
3994 object
->light_parameters
[light
].dcvDiffuse
.u2
.g
= 1.0;
3995 object
->light_parameters
[light
].dcvDiffuse
.u3
.b
= 1.0;
3996 object
->light_parameters
[light
].dvDirection
.u3
.z
= 1.0;
3999 /* Allocate memory for the matrices */
4000 object
->world_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
4001 object
->view_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
4002 object
->proj_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
4003 memcpy(object
->world_mat
, id_mat
, 16 * sizeof(float));
4004 memcpy(object
->view_mat
, id_mat
, 16 * sizeof(float));
4005 memcpy(object
->proj_mat
, id_mat
, 16 * sizeof(float));
4006 for (tex_num
= 0; tex_num
< MAX_TEXTURES
; tex_num
++) {
4007 object
->tex_mat
[tex_num
] = (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
4008 memcpy(object
->tex_mat
[tex_num
], id_mat
, 16 * sizeof(float));
4009 object
->tex_mat_is_identity
[tex_num
] = TRUE
;
4012 /* Initialisation */
4013 TRACE(" setting current context\n");
4014 object
->set_context(object
);
4015 TRACE(" current context set\n");
4017 /* allocate the clipping planes */
4018 object
->max_clipping_planes
= opengl_device_caps
.wMaxUserClipPlanes
;
4019 object
->clipping_planes
= (d3d7clippingplane
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->max_clipping_planes
* sizeof(d3d7clippingplane
));
4021 glHint(GL_FOG_HINT
,GL_NICEST
);
4023 /* Initialize the various GL contexts to be in sync with what we store locally */
4026 glClearColor(0.0, 0.0, 0.0, 0.0);
4027 glDepthMask(GL_TRUE
);
4028 gl_object
->depth_mask
= TRUE
;
4029 glEnable(GL_DEPTH_TEST
);
4030 gl_object
->depth_test
= TRUE
;
4031 glDisable(GL_ALPHA_TEST
);
4032 glDisable(GL_STENCIL_TEST
);
4033 glDisable(GL_CULL_FACE
);
4034 glDisable(GL_LIGHTING
);
4035 glDisable(GL_BLEND
);
4037 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
4038 gl_object
->current_tex_env
= GL_REPLACE
;
4039 gl_object
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
4040 if (GL_extensions
.glActiveTexture
!= NULL
) {
4041 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
4043 gl_object
->current_alpha_test_ref
= 0.0;
4044 gl_object
->current_alpha_test_func
= GL_ALWAYS
;
4045 glAlphaFunc(GL_ALWAYS
, 0.0);
4047 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4048 glDrawBuffer(buffer
);
4049 glReadBuffer(buffer
);
4050 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
4053 gl_object
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
4054 gl_object
->state
[WINE_GL_BUFFER_FRONT
] = SURFACE_GL
;
4056 /* fill_device_capabilities(d3d->ddraw); */
4058 ICOM_INIT_INTERFACE(object
, IDirect3DDevice
, VTABLE_IDirect3DDevice
);
4059 ICOM_INIT_INTERFACE(object
, IDirect3DDevice2
, VTABLE_IDirect3DDevice2
);
4060 ICOM_INIT_INTERFACE(object
, IDirect3DDevice3
, VTABLE_IDirect3DDevice3
);
4061 ICOM_INIT_INTERFACE(object
, IDirect3DDevice7
, VTABLE_IDirect3DDevice7
);
4065 TRACE(" creating implementation at %p.\n", *obj
);
4067 /* And finally warn D3D that this device is now present */
4068 object
->d3d
->d3d_added_device(object
->d3d
, object
);
4070 /* FIXME: Should handle other versions than just 7 */
4071 InitDefaultStateBlock(&object
->state_block
, 7);
4072 /* Apply default render state and texture stage state values */
4073 apply_render_state(object
, &object
->state_block
);
4074 apply_texture_state(object
);
4076 /* And fill the fog table with the default fog value */
4077 build_fog_table(gl_object
->fog_table
, object
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
4082 static void fill_opengl_primcaps(D3DPRIMCAPS
*pc
)
4084 pc
->dwSize
= sizeof(*pc
);
4085 pc
->dwMiscCaps
= D3DPMISCCAPS_CONFORMANT
| D3DPMISCCAPS_CULLCCW
| D3DPMISCCAPS_CULLCW
|
4086 D3DPMISCCAPS_LINEPATTERNREP
| D3DPMISCCAPS_MASKPLANES
| D3DPMISCCAPS_MASKZ
;
4087 pc
->dwRasterCaps
= D3DPRASTERCAPS_DITHER
| D3DPRASTERCAPS_FOGRANGE
| D3DPRASTERCAPS_FOGTABLE
|
4088 D3DPRASTERCAPS_FOGVERTEX
| D3DPRASTERCAPS_STIPPLE
| D3DPRASTERCAPS_ZBIAS
| D3DPRASTERCAPS_ZTEST
| D3DPRASTERCAPS_SUBPIXEL
|
4089 D3DPRASTERCAPS_ZFOG
;
4090 if (GL_extensions
.mipmap_lodbias
) {
4091 pc
->dwRasterCaps
|= D3DPRASTERCAPS_MIPMAPLODBIAS
;
4093 pc
->dwZCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
4094 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
4095 pc
->dwSrcBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_DESTCOLOR
| D3DPBLENDCAPS_INVDESTCOLOR
|
4096 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
4097 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
4098 pc
->dwDestBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_SRCCOLOR
| D3DPBLENDCAPS_INVSRCCOLOR
|
4099 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
4100 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
4101 pc
->dwAlphaCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
4102 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
4103 pc
->dwShadeCaps
= D3DPSHADECAPS_ALPHAFLATBLEND
| D3DPSHADECAPS_ALPHAGOURAUDBLEND
| D3DPSHADECAPS_COLORFLATRGB
| D3DPSHADECAPS_COLORGOURAUDRGB
|
4104 D3DPSHADECAPS_FOGFLAT
| D3DPSHADECAPS_FOGGOURAUD
| D3DPSHADECAPS_SPECULARFLATRGB
| D3DPSHADECAPS_SPECULARGOURAUDRGB
;
4105 pc
->dwTextureCaps
= D3DPTEXTURECAPS_ALPHA
| D3DPTEXTURECAPS_ALPHAPALETTE
| D3DPTEXTURECAPS_BORDER
| D3DPTEXTURECAPS_PERSPECTIVE
|
4106 D3DPTEXTURECAPS_POW2
| D3DPTEXTURECAPS_TRANSPARENCY
;
4107 pc
->dwTextureFilterCaps
= D3DPTFILTERCAPS_LINEAR
| D3DPTFILTERCAPS_LINEARMIPLINEAR
| D3DPTFILTERCAPS_LINEARMIPNEAREST
|
4108 D3DPTFILTERCAPS_MIPLINEAR
| D3DPTFILTERCAPS_MIPNEAREST
| D3DPTFILTERCAPS_NEAREST
| D3DPTFILTERCAPS_MAGFLINEAR
|
4109 D3DPTFILTERCAPS_MAGFPOINT
| D3DPTFILTERCAPS_MINFLINEAR
| D3DPTFILTERCAPS_MINFPOINT
| D3DPTFILTERCAPS_MIPFLINEAR
|
4110 D3DPTFILTERCAPS_MIPFPOINT
;
4111 pc
->dwTextureBlendCaps
= D3DPTBLENDCAPS_ADD
| D3DPTBLENDCAPS_COPY
| D3DPTBLENDCAPS_DECAL
| D3DPTBLENDCAPS_DECALALPHA
| D3DPTBLENDCAPS_DECALMASK
|
4112 D3DPTBLENDCAPS_MODULATE
| D3DPTBLENDCAPS_MODULATEALPHA
| D3DPTBLENDCAPS_MODULATEMASK
;
4113 pc
->dwTextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
| D3DPTADDRESSCAPS_CLAMP
| D3DPTADDRESSCAPS_WRAP
| D3DPTADDRESSCAPS_INDEPENDENTUV
;
4114 if (GL_extensions
.mirrored_repeat
) {
4115 pc
->dwTextureAddressCaps
|= D3DPTADDRESSCAPS_MIRROR
;
4117 pc
->dwStippleWidth
= 32;
4118 pc
->dwStippleHeight
= 32;
4121 static void fill_caps(void)
4123 GLint max_clip_planes
;
4126 /* Fill first all the fields with default values which will be overriden later on with
4127 correct ones from the GL code
4129 opengl_device_caps
.dwDevCaps
= D3DDEVCAPS_CANRENDERAFTERFLIP
| D3DDEVCAPS_DRAWPRIMTLVERTEX
| D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
4130 D3DDEVCAPS_EXECUTEVIDEOMEMORY
| D3DDEVCAPS_FLOATTLVERTEX
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
| D3DDEVCAPS_TEXTURESYSTEMMEMORY
|
4131 D3DDEVCAPS_TEXTUREVIDEOMEMORY
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
4132 /* D3D 7 capabilities */
4133 D3DDEVCAPS_DRAWPRIMITIVES2
/*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION
| D3DDEVCAPS_DRAWPRIMITIVES2EX
;
4134 fill_opengl_primcaps(&(opengl_device_caps
.dpcLineCaps
));
4135 fill_opengl_primcaps(&(opengl_device_caps
.dpcTriCaps
));
4136 opengl_device_caps
.dwDeviceRenderBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
;
4137 opengl_device_caps
.dwMinTextureWidth
= 1;
4138 opengl_device_caps
.dwMinTextureHeight
= 1;
4139 opengl_device_caps
.dwMaxTextureWidth
= 1024;
4140 opengl_device_caps
.dwMaxTextureHeight
= 1024;
4141 opengl_device_caps
.dwMaxTextureRepeat
= 16;
4142 opengl_device_caps
.dwMaxTextureAspectRatio
= 1024;
4143 opengl_device_caps
.dwMaxAnisotropy
= 0;
4144 opengl_device_caps
.dvGuardBandLeft
= 0.0;
4145 opengl_device_caps
.dvGuardBandRight
= 0.0;
4146 opengl_device_caps
.dvGuardBandTop
= 0.0;
4147 opengl_device_caps
.dvGuardBandBottom
= 0.0;
4148 opengl_device_caps
.dvExtentsAdjust
= 0.0;
4149 opengl_device_caps
.dwStencilCaps
= D3DSTENCILCAPS_DECRSAT
| D3DSTENCILCAPS_INCRSAT
| D3DSTENCILCAPS_INVERT
| D3DSTENCILCAPS_KEEP
|
4150 D3DSTENCILCAPS_REPLACE
| D3DSTENCILCAPS_ZERO
;
4151 opengl_device_caps
.dwTextureOpCaps
= D3DTEXOPCAPS_DISABLE
| D3DTEXOPCAPS_SELECTARG1
| D3DTEXOPCAPS_SELECTARG2
| D3DTEXOPCAPS_MODULATE4X
|
4152 D3DTEXOPCAPS_MODULATE2X
| D3DTEXOPCAPS_MODULATE
| D3DTEXOPCAPS_ADD
| D3DTEXOPCAPS_ADDSIGNED2X
| D3DTEXOPCAPS_ADDSIGNED
|
4153 D3DTEXOPCAPS_BLENDDIFFUSEALPHA
| D3DTEXOPCAPS_BLENDTEXTUREALPHA
| D3DTEXOPCAPS_BLENDFACTORALPHA
| D3DTEXOPCAPS_BLENDCURRENTALPHA
;
4154 if (GL_extensions
.max_texture_units
!= 0) {
4155 opengl_device_caps
.wMaxTextureBlendStages
= GL_extensions
.max_texture_units
;
4156 opengl_device_caps
.wMaxSimultaneousTextures
= GL_extensions
.max_texture_units
;
4157 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| GL_extensions
.max_texture_units
;
4159 opengl_device_caps
.wMaxTextureBlendStages
= 1;
4160 opengl_device_caps
.wMaxSimultaneousTextures
= 1;
4161 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| 1;
4163 opengl_device_caps
.dwMaxActiveLights
= 16;
4164 opengl_device_caps
.dvMaxVertexW
= 100000000.0; /* No idea exactly what to put here... */
4165 opengl_device_caps
.deviceGUID
= IID_IDirect3DTnLHalDevice
;
4166 opengl_device_caps
.wMaxUserClipPlanes
= 1;
4167 opengl_device_caps
.wMaxVertexBlendMatrices
= 0;
4168 opengl_device_caps
.dwVertexProcessingCaps
= D3DVTXPCAPS_TEXGEN
| D3DVTXPCAPS_MATERIALSOURCE7
| D3DVTXPCAPS_VERTEXFOG
|
4169 D3DVTXPCAPS_DIRECTIONALLIGHTS
| D3DVTXPCAPS_POSITIONALLIGHTS
| D3DVTXPCAPS_LOCALVIEWER
;
4170 opengl_device_caps
.dwReserved1
= 0;
4171 opengl_device_caps
.dwReserved2
= 0;
4172 opengl_device_caps
.dwReserved3
= 0;
4173 opengl_device_caps
.dwReserved4
= 0;
4175 /* And now some GL overrides :-) */
4176 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (GLint
*) &opengl_device_caps
.dwMaxTextureWidth
);
4177 opengl_device_caps
.dwMaxTextureHeight
= opengl_device_caps
.dwMaxTextureWidth
;
4178 opengl_device_caps
.dwMaxTextureAspectRatio
= opengl_device_caps
.dwMaxTextureWidth
;
4179 TRACE(": max texture size = %ld\n", opengl_device_caps
.dwMaxTextureWidth
);
4181 glGetIntegerv(GL_MAX_LIGHTS
, (GLint
*) &opengl_device_caps
.dwMaxActiveLights
);
4182 TRACE(": max active lights = %ld\n", opengl_device_caps
.dwMaxActiveLights
);
4184 glGetIntegerv(GL_MAX_CLIP_PLANES
, &max_clip_planes
);
4185 opengl_device_caps
.wMaxUserClipPlanes
= max_clip_planes
;
4186 TRACE(": max clipping planes = %d\n", opengl_device_caps
.wMaxUserClipPlanes
);
4188 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
4189 TRACE(": Z bits = %d\n", depth_bits
);
4190 switch (depth_bits
) {
4191 case 16: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
; break;
4192 case 24: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
; break;
4194 default: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
; break;
4199 d3ddevice_init_at_startup(void *gl_handle
)
4201 XVisualInfo
template;
4206 Drawable drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4207 XWindowAttributes win_attr
;
4208 GLXContext gl_context
;
4210 const char *glExtensions
;
4211 const char *glVersion
;
4212 const char *glXExtensions
= NULL
;
4213 const void *(*pglXGetProcAddressARB
)(const GLubyte
*) = NULL
;
4214 int major
, minor
, patch
, num_parsed
;
4216 TRACE("Initializing GL...\n");
4220 WARN("x11drv not loaded - D3D support disabled!\n");
4224 /* Get a default rendering context to have the 'caps' function query some info from GL */
4225 device_context
= GetDC(0);
4226 display
= get_display(device_context
);
4227 ReleaseDC(0, device_context
);
4230 if (XGetWindowAttributes(display
, drawable
, &win_attr
)) {
4231 visual
= win_attr
.visual
;
4233 visual
= DefaultVisual(display
, DefaultScreen(display
));
4235 template.visualid
= XVisualIDFromVisual(visual
);
4236 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
4239 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4242 gl_context
= glXCreateContext(display
, vis
, NULL
, GL_TRUE
);
4244 if (gl_context
== NULL
) {
4246 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4249 if (glXMakeCurrent(display
, drawable
, gl_context
) == False
) {
4250 glXDestroyContext(display
, gl_context
);
4252 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4256 /* Then, query all extensions */
4257 glXExtensions
= glXQueryExtensionsString(display
, DefaultScreen(display
)); /* Note: not used right now but will for PBuffers */
4258 glExtensions
= (const char *) glGetString(GL_EXTENSIONS
);
4259 glVersion
= (const char *) glGetString(GL_VERSION
);
4260 if (gl_handle
!= NULL
) {
4261 pglXGetProcAddressARB
= wine_dlsym(gl_handle
, "glXGetProcAddressARB", NULL
, 0);
4264 /* Parse the GL version string */
4265 num_parsed
= sscanf(glVersion
, "%d.%d.%d", &major
, &minor
, &patch
);
4266 if (num_parsed
== 1) {
4269 } else if (num_parsed
== 2) {
4272 TRACE("GL version %d.%d.%d\n", major
, minor
, patch
);
4274 /* And starts to fill the extension context properly */
4275 memset(&GL_extensions
, 0, sizeof(GL_extensions
));
4276 TRACE("GL supports following extensions used by Wine :\n");
4278 /* Mirrored Repeat extension :
4279 - GL_ARB_texture_mirrored_repeat
4280 - GL_IBM_texture_mirrored_repeat
4283 if ((strstr(glExtensions
, "GL_ARB_texture_mirrored_repeat")) ||
4284 (strstr(glExtensions
, "GL_IBM_texture_mirrored_repeat")) ||
4286 ((major
== 1) && (minor
>= 4))) {
4287 TRACE(" - mirrored repeat\n");
4288 GL_extensions
.mirrored_repeat
= TRUE
;
4291 /* Texture LOD Bias :
4292 - GL_EXT_texture_lod_bias
4294 if (strstr(glExtensions
, "GL_EXT_texture_lod_bias")) {
4295 TRACE(" - texture lod bias\n");
4296 GL_extensions
.mipmap_lodbias
= TRUE
;
4299 /* For all subsequent extensions, we need glXGetProcAddress */
4300 if (pglXGetProcAddressARB
!= NULL
) {
4301 /* Multi-texturing :
4302 - GL_ARB_multitexture
4305 if ((strstr(glExtensions
, "GL_ARB_multitexture")) ||
4307 ((major
== 1) && (minor
> 2)) ||
4308 ((major
== 1) && (minor
== 2) && (patch
>= 1))) {
4309 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE
, &(GL_extensions
.max_texture_units
));
4310 TRACE(" - multi-texturing (%d stages)\n", GL_extensions
.max_texture_units
);
4311 /* We query the ARB version to be the most portable we can... */
4312 GL_extensions
.glActiveTexture
= pglXGetProcAddressARB("glActiveTextureARB");
4313 GL_extensions
.glMultiTexCoord2fv
= pglXGetProcAddressARB("glMultiTexCoord2fv");
4314 GL_extensions
.glClientActiveTexture
= pglXGetProcAddressARB("glClientActiveTextureARB");
4317 if (strstr(glExtensions
, "GL_EXT_texture_compression_s3tc")) {
4318 TRACE(" - S3TC compression supported\n");
4319 GL_extensions
.s3tc_compressed_texture
= TRUE
;
4320 GL_extensions
.glCompressedTexImage2D
= pglXGetProcAddressARB("glCompressedTexImage2D");
4321 GL_extensions
.glCompressedTexSubImage2D
= pglXGetProcAddressARB("glCompressedTexSubImage2D");
4325 /* Fill the D3D capabilities according to what GL tells us... */
4328 /* And frees this now-useless context */
4329 glXMakeCurrent(display
, None
, NULL
);
4330 glXDestroyContext(display
, gl_context
);