Added Finnish keyboard layout.
[wine/hacks.git] / graphics / d3ddevices.c
blob4626a179d3d9ba5d1d6ee21f0f7aec2854c48aca
1 /* Direct3D Device
2 (c) 1998 Lionel ULMER
4 This files contains all the D3D devices that Wine supports. For the moment
5 only the 'OpenGL' target is supported. */
7 #include <string.h>
8 #include "config.h"
9 #include "windef.h"
10 #include "winerror.h"
11 #include "wine/obj_base.h"
12 #include "heap.h"
13 #include "ddraw.h"
14 #include "d3d.h"
15 #include "debug.h"
17 #include "d3d_private.h"
19 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
20 on Mesa's home page) or version 3.1b.
22 Version 3.2b should correct this bug */
23 #undef HAVE_BUGGY_MESAGL
25 #ifdef HAVE_MESAGL
27 static GUID IID_D3DDEVICE2_OpenGL = {
28 0x39a0da38,
29 0x7e57,
30 0x11d2,
31 { 0x8b,0x7c,0x0e,0x4e,0xd8,0x3c,0x2b,0x3c }
34 static GUID IID_D3DDEVICE_OpenGL = {
35 0x31416d44,
36 0x86ae,
37 0x11d2,
38 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
42 static IDirect3DDevice2_VTable OpenGL_vtable;
43 static IDirect3DDevice_VTable OpenGL_vtable_dx3;
45 /*******************************************************************************
46 * OpenGL static functions
48 static void set_context(LPDIRECT3DDEVICE2 this) {
49 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
51 OSMesaMakeCurrent(odev->ctx, odev->buffer,
52 GL_UNSIGNED_BYTE,
53 this->surface->s.surface_desc.dwWidth,
54 this->surface->s.surface_desc.dwHeight);
57 static void set_context_dx3(LPDIRECT3DDEVICE this) {
58 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) this;
60 OSMesaMakeCurrent(odev->ctx, odev->buffer,
61 GL_UNSIGNED_BYTE,
62 this->surface->s.surface_desc.dwWidth,
63 this->surface->s.surface_desc.dwHeight);
66 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
68 pc->dwSize = sizeof(*pc);
69 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
70 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
71 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
72 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
73 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
74 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
75 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
76 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
77 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
78 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
79 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
80 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
81 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
82 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
83 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
84 pc->dwStippleWidth = 32;
85 pc->dwStippleHeight = 32;
88 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
90 /* GLint maxlight; */
92 d1->dwSize = sizeof(*d1);
93 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
94 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
95 d1->dcmColorModel = D3DCOLOR_RGB;
96 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
97 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
98 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
99 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
100 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
101 d1->bClipping = TRUE;
102 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
103 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
104 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
105 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
106 fill_opengl_primcaps(&(d1->dpcLineCaps));
107 fill_opengl_primcaps(&(d1->dpcTriCaps));
108 d1->dwDeviceRenderBitDepth = DDBD_16;
109 d1->dwDeviceZBufferBitDepth = DDBD_16;
110 d1->dwMaxBufferSize = 0;
111 d1->dwMaxVertexCount = 65536;
112 d1->dwMinTextureWidth = 1;
113 d1->dwMinTextureHeight = 1;
114 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
115 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
116 d1->dwMinStippleWidth = 1;
117 d1->dwMinStippleHeight = 1;
118 d1->dwMaxStippleWidth = 32;
119 d1->dwMaxStippleHeight = 32;
121 d2->dwSize = sizeof(*d2);
122 d2->dwFlags = 0;
125 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
126 D3DDEVICEDESC d1,d2;
128 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
130 fill_opengl_caps(&d1, &d2);
132 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
135 int is_OpenGL(REFCLSID rguid, LPDIRECTDRAWSURFACE surface, LPDIRECT3DDEVICE2 *device, LPDIRECT3D2 d3d)
137 if (/* Default device */
138 (rguid == NULL) ||
139 /* HAL Device */
140 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
141 /* OpenGL Device */
142 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
143 OpenGL_IDirect3DDevice2 *odev;
145 const float id_mat[16] = {
146 1.0, 0.0, 0.0, 0.0,
147 0.0, 1.0, 0.0, 0.0,
148 0.0, 0.0, 1.0, 0.0,
149 0.0, 0.0, 0.0, 1.0
152 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
153 odev = (OpenGL_IDirect3DDevice2 *) (*device);
154 (*device)->ref = 1;
155 (*device)->lpvtbl = &OpenGL_vtable;
156 (*device)->d3d = d3d;
157 (*device)->surface = surface;
159 (*device)->viewport_list = NULL;
160 (*device)->current_viewport = NULL;
162 (*device)->set_context = set_context;
164 TRACE(ddraw, "OpenGL device created \n");
166 /* Create the OpenGL context */
167 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
168 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
169 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
170 odev->rs.src = GL_ONE;
171 odev->rs.dst = GL_ZERO;
172 odev->rs.mag = GL_NEAREST;
173 odev->rs.min = GL_NEAREST;
174 odev->vt = 0;
176 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
177 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
178 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
180 /* Initialisation */
181 (*device)->set_context(*device);
182 glClearColor(0.0, 0.0, 0.0, 0.0);
183 glColor3f(1.0, 1.0, 1.0);
185 return 1;
188 /* This is not the OpenGL UID */
189 return 0;
192 /*******************************************************************************
193 * Common IDirect3DDevice2
196 static HRESULT WINAPI IDirect3DDevice2_QueryInterface(LPDIRECT3DDEVICE2 this,
197 REFIID riid,
198 LPVOID* ppvObj)
200 char xrefiid[50];
202 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
203 FIXME(ddraw, "(%p)->(%s,%p): stub\n", this, xrefiid,ppvObj);
205 return S_OK;
210 static ULONG WINAPI IDirect3DDevice2_AddRef(LPDIRECT3DDEVICE2 this)
212 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", this, this->ref );
214 return ++(this->ref);
219 static ULONG WINAPI IDirect3DDevice2_Release(LPDIRECT3DDEVICE2 this)
221 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
223 if (!--(this->ref)) {
224 HeapFree(GetProcessHeap(),0,this);
225 return 0;
228 return this->ref;
232 /*** IDirect3DDevice2 methods ***/
233 static HRESULT WINAPI IDirect3DDevice2_GetCaps(LPDIRECT3DDEVICE2 this,
234 LPD3DDEVICEDESC lpdescsoft,
235 LPD3DDEVICEDESC lpdeschard)
237 FIXME(ddraw, "(%p)->(%p,%p): stub\n", this, lpdescsoft, lpdeschard);
239 fill_opengl_caps(lpdescsoft, lpdeschard);
241 return DD_OK;
246 static HRESULT WINAPI IDirect3DDevice2_SwapTextureHandles(LPDIRECT3DDEVICE2 this,
247 LPDIRECT3DTEXTURE2 lptex1,
248 LPDIRECT3DTEXTURE2 lptex2)
250 FIXME(ddraw, "(%p)->(%p,%p): stub\n", this, lptex1, lptex2);
252 return DD_OK;
257 static HRESULT WINAPI IDirect3DDevice2_GetStats(LPDIRECT3DDEVICE2 this,
258 LPD3DSTATS lpstats)
260 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpstats);
262 return DD_OK;
267 static HRESULT WINAPI IDirect3DDevice2_AddViewport(LPDIRECT3DDEVICE2 this,
268 LPDIRECT3DVIEWPORT2 lpvp)
270 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvp);
272 /* Adds this viewport to the viewport list */
273 lpvp->next = this->viewport_list;
274 this->viewport_list = lpvp;
276 return DD_OK;
281 static HRESULT WINAPI IDirect3DDevice2_DeleteViewport(LPDIRECT3DDEVICE2 this,
282 LPDIRECT3DVIEWPORT2 lpvp)
284 LPDIRECT3DVIEWPORT2 cur, prev;
285 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvp);
287 /* Finds this viewport in the list */
288 prev = NULL;
289 cur = this->viewport_list;
290 while ((cur != NULL) && (cur != lpvp)) {
291 prev = cur;
292 cur = cur->next;
294 if (cur == NULL)
295 return DDERR_INVALIDOBJECT;
297 /* And remove it */
298 if (prev == NULL)
299 this->viewport_list = cur->next;
300 else
301 prev->next = cur->next;
303 return DD_OK;
308 static HRESULT WINAPI IDirect3DDevice2_NextViewport(LPDIRECT3DDEVICE2 this,
309 LPDIRECT3DVIEWPORT2 lpvp,
310 LPDIRECT3DVIEWPORT2* lplpvp,
311 DWORD dwFlags)
313 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", this, lpvp, lpvp, dwFlags);
315 switch (dwFlags) {
316 case D3DNEXT_NEXT:
317 *lplpvp = lpvp->next;
318 break;
320 case D3DNEXT_HEAD:
321 *lplpvp = this->viewport_list;
322 break;
324 case D3DNEXT_TAIL:
325 lpvp = this->viewport_list;
326 while (lpvp->next != NULL)
327 lpvp = lpvp->next;
329 *lplpvp = lpvp;
330 break;
332 default:
333 return DDERR_INVALIDPARAMS;
336 return DD_OK;
339 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
340 LPVOID context) {
341 DDSURFACEDESC sdesc;
342 LPDDPIXELFORMAT pformat;
344 /* Do the texture enumeration */
345 sdesc.dwSize = sizeof(DDSURFACEDESC);
346 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
347 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
348 pformat = &(sdesc.ddpfPixelFormat);
349 pformat->dwSize = sizeof(DDPIXELFORMAT);
350 pformat->dwFourCC = 0;
352 TRACE(ddraw, "Enumerating GL_RGBA unpacked (32)\n");
353 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
354 pformat->x.dwRGBBitCount = 32;
355 pformat->y.dwRBitMask = 0xFF000000;
356 pformat->z.dwGBitMask = 0x00FF0000;
357 pformat->xx.dwBBitMask = 0x0000FF00;
358 pformat->xy.dwRGBAlphaBitMask = 0x000000FF;
359 if (cb(&sdesc, context) == 0)
360 return DD_OK;
362 TRACE(ddraw, "Enumerating GL_RGB unpacked (24)\n");
363 pformat->dwFlags = DDPF_RGB;
364 pformat->x.dwRGBBitCount = 24;
365 pformat->y.dwRBitMask = 0x00FF0000;
366 pformat->z.dwGBitMask = 0x0000FF00;
367 pformat->xx.dwBBitMask = 0x000000FF;
368 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
369 if (cb(&sdesc, context) == 0)
370 return DD_OK;
372 #ifndef HAVE_BUGGY_MESAGL
373 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
374 so that future version will work great. */
375 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
376 pformat->dwFlags = DDPF_RGB;
377 pformat->x.dwRGBBitCount = 16;
378 pformat->y.dwRBitMask = 0x0000F800;
379 pformat->z.dwGBitMask = 0x000007E0;
380 pformat->xx.dwBBitMask = 0x0000001F;
381 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
382 if (cb(&sdesc, context) == 0)
383 return DD_OK;
385 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
386 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
387 pformat->x.dwRGBBitCount = 16;
388 pformat->y.dwRBitMask = 0x0000F800;
389 pformat->z.dwGBitMask = 0x000007C0;
390 pformat->xx.dwBBitMask = 0x0000003E;
391 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
392 if (cb(&sdesc, context) == 0)
393 return DD_OK;
395 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
396 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
397 pformat->x.dwRGBBitCount = 16;
398 pformat->y.dwRBitMask = 0x0000F000;
399 pformat->z.dwGBitMask = 0x00000F00;
400 pformat->xx.dwBBitMask = 0x000000F0;
401 pformat->xy.dwRGBAlphaBitMask = 0x0000000F;
402 if (cb(&sdesc, context) == 0)
403 return DD_OK;
405 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
406 pformat->dwFlags = DDPF_RGB;
407 pformat->x.dwRGBBitCount = 8;
408 pformat->y.dwRBitMask = 0x0000F800;
409 pformat->z.dwGBitMask = 0x000007C0;
410 pformat->xx.dwBBitMask = 0x0000003E;
411 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
412 if (cb(&sdesc, context) == 0)
413 return DD_OK;
414 #endif
416 TRACE(ddraw, "Enumerating Paletted (8)\n");
417 pformat->dwFlags = DDPF_PALETTEINDEXED8;
418 pformat->x.dwRGBBitCount = 8;
419 pformat->y.dwRBitMask = 0x00000000;
420 pformat->z.dwGBitMask = 0x00000000;
421 pformat->xx.dwBBitMask = 0x00000000;
422 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
423 if (cb(&sdesc, context) == 0)
424 return DD_OK;
426 TRACE(ddraw, "End of enumeration\n");
428 return DD_OK;
431 static HRESULT WINAPI IDirect3DDevice2_EnumTextureFormats(LPDIRECT3DDEVICE2 this,
432 LPD3DENUMTEXTUREFORMATSCALLBACK cb,
433 LPVOID context)
435 FIXME(ddraw, "(%p)->(%p,%p): stub\n", this, cb, context);
437 return enum_texture_format_OpenGL(cb, context);
442 static HRESULT WINAPI IDirect3DDevice2_BeginScene(LPDIRECT3DDEVICE2 this)
444 /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this; */
446 FIXME(ddraw, "(%p)->(): stub\n", this);
448 /* Here, we should get the DDraw surface and 'copy it' to the
449 OpenGL surface.... */
451 return DD_OK;
456 static HRESULT WINAPI IDirect3DDevice2_EndScene(LPDIRECT3DDEVICE2 this)
458 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
459 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) this->surface;
460 DDSURFACEDESC sdesc;
461 int x,y;
462 unsigned char *src;
463 unsigned short *dest;
465 FIXME(ddraw, "(%p)->(): stub\n", this);
467 /* Here we copy back the OpenGL scene to the the DDraw surface */
468 /* First, lock the surface */
469 surf->lpvtbl->fnLock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
471 /* The copy the OpenGL buffer to this surface */
473 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
474 I am currently working on a set of patches for Mesa to have OSMesa support
475 16 bpp surfaces => we will able to render directly onto the surface, no
476 need to do a bpp conversion */
477 dest = (unsigned short *) sdesc.y.lpSurface;
478 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
479 for (y = 0; y < sdesc.dwHeight; y++) {
480 unsigned char *lsrc = src;
482 for (x = 0; x < sdesc.dwWidth ; x++) {
483 unsigned char r = *lsrc++;
484 unsigned char g = *lsrc++;
485 unsigned char b = *lsrc++;
486 lsrc++; /* Alpha */
487 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
489 dest++;
492 src -= 4 * sdesc.dwWidth;
495 /* Unlock the surface */
496 surf->lpvtbl->fnUnlock(surf,sdesc.y.lpSurface);
498 return DD_OK;
503 static HRESULT WINAPI IDirect3DDevice2_GetDirect3D(LPDIRECT3DDEVICE2 this, LPDIRECT3D2 *lpd3d2)
505 TRACE(ddraw, "(%p)->(%p): stub\n", this, lpd3d2);
507 *lpd3d2 = this->d3d;
509 return DD_OK;
514 /*** DrawPrimitive API ***/
515 static HRESULT WINAPI IDirect3DDevice2_SetCurrentViewport(LPDIRECT3DDEVICE2 this,
516 LPDIRECT3DVIEWPORT2 lpvp)
518 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvp);
520 /* Should check if the viewport was added or not */
522 /* Set this viewport as the current viewport */
523 this->current_viewport = lpvp;
525 /* Activate this viewport */
526 lpvp->device.active_device2 = this;
527 lpvp->activate(lpvp);
529 return DD_OK;
534 static HRESULT WINAPI IDirect3DDevice2_GetCurrentViewport(LPDIRECT3DDEVICE2 this,
535 LPDIRECT3DVIEWPORT2 *lplpvp)
537 FIXME(ddraw, "(%p)->(%p): stub\n", this, lplpvp);
539 /* Returns the current viewport */
540 *lplpvp = this->current_viewport;
542 return DD_OK;
547 static HRESULT WINAPI IDirect3DDevice2_SetRenderTarget(LPDIRECT3DDEVICE2 this,
548 LPDIRECTDRAWSURFACE lpdds,
549 DWORD dwFlags)
551 FIXME(ddraw, "(%p)->(%p,%08lx): stub\n", this, lpdds, dwFlags);
553 return DD_OK;
558 static HRESULT WINAPI IDirect3DDevice2_GetRenderTarget(LPDIRECT3DDEVICE2 this,
559 LPDIRECTDRAWSURFACE *lplpdds)
561 FIXME(ddraw, "(%p)->(%p): stub\n", this, lplpdds);
563 /* Returns the current rendering target (the surface on wich we render) */
564 *lplpdds = this->surface;
566 return DD_OK;
571 static HRESULT WINAPI IDirect3DDevice2_Begin(LPDIRECT3DDEVICE2 this,
572 D3DPRIMITIVETYPE d3dp,
573 D3DVERTEXTYPE d3dv,
574 DWORD dwFlags)
576 FIXME(ddraw, "(%p)->(%d,%d,%08lx): stub\n", this, d3dp, d3dv, dwFlags);
578 return DD_OK;
583 static HRESULT WINAPI IDirect3DDevice2_BeginIndexed(LPDIRECT3DDEVICE2 this,
584 D3DPRIMITIVETYPE d3dp,
585 D3DVERTEXTYPE d3dv,
586 LPVOID lpvert,
587 DWORD numvert,
588 DWORD dwFlags)
590 FIXME(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", this, d3dp, d3dv, lpvert, numvert, dwFlags);
592 return DD_OK;
597 static HRESULT WINAPI IDirect3DDevice2_Vertex(LPDIRECT3DDEVICE2 this,
598 LPVOID lpvert)
600 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvert);
602 return DD_OK;
607 static HRESULT WINAPI IDirect3DDevice2_Index(LPDIRECT3DDEVICE2 this,
608 WORD index)
610 FIXME(ddraw, "(%p)->(%d): stub\n", this, index);
612 return DD_OK;
617 static HRESULT WINAPI IDirect3DDevice2_End(LPDIRECT3DDEVICE2 this,
618 DWORD dwFlags)
620 FIXME(ddraw, "(%p)->(%08lx): stub\n", this, dwFlags);
622 return DD_OK;
628 static HRESULT WINAPI IDirect3DDevice2_GetRenderState(LPDIRECT3DDEVICE2 this,
629 D3DRENDERSTATETYPE d3drs,
630 LPDWORD lprstate)
632 FIXME(ddraw, "(%p)->(%d,%p): stub\n", this, d3drs, lprstate);
634 return DD_OK;
639 static HRESULT WINAPI IDirect3DDevice2_SetRenderState(LPDIRECT3DDEVICE2 this,
640 D3DRENDERSTATETYPE dwRenderStateType,
641 DWORD dwRenderState)
643 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
645 TRACE(ddraw, "(%p)->(%d,%ld)\n", this, dwRenderStateType, dwRenderState);
647 /* Call the render state functions */
648 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
650 return DD_OK;
655 static HRESULT WINAPI IDirect3DDevice2_GetLightState(LPDIRECT3DDEVICE2 this,
656 D3DLIGHTSTATETYPE d3dls,
657 LPDWORD lplstate)
659 FIXME(ddraw, "(%p)->(%d,%p): stub\n", this, d3dls, lplstate);
661 return DD_OK;
666 static HRESULT WINAPI IDirect3DDevice2_SetLightState(LPDIRECT3DDEVICE2 this,
667 D3DLIGHTSTATETYPE dwLightStateType,
668 DWORD dwLightState)
670 FIXME(ddraw, "(%p)->(%d,%08lx): stub\n", this, dwLightStateType, dwLightState);
672 switch (dwLightStateType) {
673 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
674 LPDIRECT3DMATERIAL2 mat = (LPDIRECT3DMATERIAL2) dwLightState;
676 if (mat != NULL) {
677 mat->activate(mat);
678 } else {
679 TRACE(ddraw, "Zoups !!!\n");
681 } break;
683 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
684 float light[4];
686 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
687 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
688 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
689 light[3] = 1.0;
690 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
691 } break;
693 case D3DLIGHTSTATE_COLORMODEL: /* 3 */
694 break;
696 case D3DLIGHTSTATE_FOGMODE: /* 4 */
697 break;
699 case D3DLIGHTSTATE_FOGSTART: /* 5 */
700 break;
702 case D3DLIGHTSTATE_FOGEND: /* 6 */
703 break;
705 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
706 break;
708 default:
709 TRACE(ddraw, "Unexpected Light State Type\n");
710 return DDERR_INVALIDPARAMS;
713 return DD_OK;
718 static HRESULT WINAPI IDirect3DDevice2_SetTransform(LPDIRECT3DDEVICE2 this,
719 D3DTRANSFORMSTATETYPE d3dts,
720 LPD3DMATRIX lpmatrix)
722 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
724 FIXME(ddraw, "(%p)->(%d,%p): stub\n", this, d3dts, lpmatrix);
726 /* Using a trial and failure approach, I found that the order of
727 Direct3D transformations that works best is :
729 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
731 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
732 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
734 If anyone has a good explanation of the three different matrices in
735 the SDK online documentation, feel free to point it to me. For example,
736 which matrices transform lights ? In OpenGL only the PROJECTION matrix
737 transform the lights, not the MODELVIEW. Using the matrix names, I
738 supposed that PROJECTION and VIEW (all 'camera' related names) do
739 transform lights, but WORLD do not. It may be wrong though... */
741 /* After reading through both OpenGL and Direct3D documentations, I
742 thought that D3D matrices were written in 'line major mode' transposed
743 from OpenGL's 'column major mode'. But I found out that a simple memcpy
744 works fine to transfer one matrix format to the other (it did not work
745 when transposing)....
747 So :
748 1) are the documentations wrong
749 2) does the matrix work even if they are not read correctly
750 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
751 loading using glLoadMatrix ?
753 Anyway, I always use 'conv_mat' to transfer the matrices from one format
754 to the other so that if I ever find out that I need to transpose them, I
755 will able to do it quickly, only by changing the macro conv_mat. */
757 switch (d3dts) {
758 case D3DTRANSFORMSTATE_WORLD: {
759 conv_mat(lpmatrix, odev->world_mat);
760 glMatrixMode(GL_MODELVIEW);
761 glLoadMatrixf((float *) &(odev->world_mat));
762 } break;
764 case D3DTRANSFORMSTATE_VIEW: {
765 conv_mat(lpmatrix, odev->view_mat);
766 glMatrixMode(GL_PROJECTION);
767 glLoadMatrixf((float *) &(odev->proj_mat));
768 glMultMatrixf((float *) &(odev->view_mat));
769 } break;
771 case D3DTRANSFORMSTATE_PROJECTION: {
772 conv_mat(lpmatrix, odev->proj_mat);
773 glMatrixMode(GL_PROJECTION);
774 glLoadMatrixf((float *) &(odev->proj_mat));
775 glMultMatrixf((float *) &(odev->view_mat));
776 } break;
778 default:
779 break;
782 return DD_OK;
787 static HRESULT WINAPI IDirect3DDevice2_GetTransform(LPDIRECT3DDEVICE2 this,
788 D3DTRANSFORMSTATETYPE d3dts,
789 LPD3DMATRIX lpmatrix)
791 FIXME(ddraw, "(%p)->(%d,%p): stub\n", this, d3dts, lpmatrix);
793 return DD_OK;
798 static HRESULT WINAPI IDirect3DDevice2_MultiplyTransform(LPDIRECT3DDEVICE2 this,
799 D3DTRANSFORMSTATETYPE d3dts,
800 LPD3DMATRIX lpmatrix)
802 FIXME(ddraw, "(%p)->(%d,%p): stub\n", this, d3dts, lpmatrix);
804 return DD_OK;
807 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
808 /* Puts GL in the correct lighting mode */ \
809 if (odev->vt != d3dv) { \
810 if (odev->vt == D3DVT_TLVERTEX) { \
811 /* Need to put the correct transformation again */ \
812 glMatrixMode(GL_MODELVIEW); \
813 glLoadMatrixf((float *) &(odev->world_mat)); \
814 glMatrixMode(GL_PROJECTION); \
815 glLoadMatrixf((float *) &(odev->proj_mat)); \
816 glMultMatrixf((float *) &(odev->view_mat)); \
819 switch (d3dv) { \
820 case D3DVT_VERTEX: \
821 TRACE(ddraw, "Standard Vertex\n"); \
822 glEnable(GL_LIGHTING); \
823 break; \
825 case D3DVT_LVERTEX: \
826 TRACE(ddraw, "Lighted Vertex\n"); \
827 glDisable(GL_LIGHTING); \
828 break; \
830 case D3DVT_TLVERTEX: { \
831 GLdouble height, width, minZ, maxZ; \
833 TRACE(ddraw, "Transformed - Lighted Vertex\n"); \
834 /* First, disable lighting */ \
835 glDisable(GL_LIGHTING); \
837 /* Then do not put any transformation matrixes */ \
838 glMatrixMode(GL_MODELVIEW); \
839 glLoadIdentity(); \
840 glMatrixMode(GL_PROJECTION); \
841 glLoadIdentity(); \
843 if (this->current_viewport == NULL) { \
844 ERR(ddraw, "No current viewport !\n"); \
845 /* Using standard values */ \
846 height = 640.0; \
847 width = 480.0; \
848 minZ = -10.0; \
849 maxZ = 10.0; \
850 } else { \
851 if (this->current_viewport->use_vp2) { \
852 height = (GLdouble) this->current_viewport->viewport.vp2.dwHeight; \
853 width = (GLdouble) this->current_viewport->viewport.vp2.dwWidth; \
854 minZ = (GLdouble) this->current_viewport->viewport.vp2.dvMinZ; \
855 maxZ = (GLdouble) this->current_viewport->viewport.vp2.dvMaxZ; \
856 } else { \
857 height = (GLdouble) this->current_viewport->viewport.vp1.dwHeight; \
858 width = (GLdouble) this->current_viewport->viewport.vp1.dwWidth; \
859 minZ = (GLdouble) this->current_viewport->viewport.vp1.dvMinZ; \
860 maxZ = (GLdouble) this->current_viewport->viewport.vp1.dvMaxZ; \
864 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
865 } break; \
867 default: \
868 ERR(ddraw, "Unhandled vertex type\n"); \
869 break; \
872 odev->vt = d3dv; \
875 switch (d3dp) { \
876 case D3DPT_POINTLIST: \
877 TRACE(ddraw, "Start POINTS\n"); \
878 glBegin(GL_POINTS); \
879 break; \
881 case D3DPT_LINELIST: \
882 TRACE(ddraw, "Start LINES\n"); \
883 glBegin(GL_LINES); \
884 break; \
886 case D3DPT_LINESTRIP: \
887 TRACE(ddraw, "Start LINE_STRIP\n"); \
888 glBegin(GL_LINE_STRIP); \
889 break; \
891 case D3DPT_TRIANGLELIST: \
892 TRACE(ddraw, "Start TRIANGLES\n"); \
893 glBegin(GL_TRIANGLES); \
894 break; \
896 case D3DPT_TRIANGLESTRIP: \
897 TRACE(ddraw, "Start TRIANGLE_STRIP\n"); \
898 glBegin(GL_TRIANGLE_STRIP); \
899 break; \
901 case D3DPT_TRIANGLEFAN: \
902 TRACE(ddraw, "Start TRIANGLE_FAN\n"); \
903 glBegin(GL_TRIANGLE_FAN); \
904 break; \
906 default: \
907 TRACE(ddraw, "Unhandled primitive\n"); \
908 break; \
911 /* Draw the primitives */ \
912 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
913 switch (d3dv) { \
914 case D3DVT_VERTEX: { \
915 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
917 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
918 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
919 TRACE(ddraw, " V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
920 } break; \
922 case D3DVT_LVERTEX: { \
923 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
924 DWORD col = vx->c.color; \
926 glColor3f(((col >> 16) & 0xFF) / 255.0, \
927 ((col >> 8) & 0xFF) / 255.0, \
928 ((col >> 0) & 0xFF) / 255.0); \
929 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
930 TRACE(ddraw, " LV: %f %f %f (%02lx %02lx %02lx)\n", \
931 vx->x.x, vx->y.y, vx->z.z, \
932 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
933 } break; \
935 case D3DVT_TLVERTEX: { \
936 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
937 DWORD col = vx->c.color; \
939 glColor3f(((col >> 16) & 0xFF) / 255.0, \
940 ((col >> 8) & 0xFF) / 255.0, \
941 ((col >> 0) & 0xFF) / 255.0); \
942 glTexCoord2f(vx->u.tu, vx->v.tv); \
943 if (vx->r.rhw < 0.01) \
944 glVertex3f(vx->x.sx, \
945 vx->y.sy, \
946 vx->z.sz); \
947 else \
948 glVertex4f(vx->x.sx / vx->r.rhw, \
949 vx->y.sy / vx->r.rhw, \
950 vx->z.sz / vx->r.rhw, \
951 1.0 / vx->r.rhw); \
952 TRACE(ddraw, " TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
953 vx->x.sx, vx->y.sy, vx->z.sz, \
954 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
955 vx->u.tu, vx->v.tv, vx->r.rhw); \
956 } break; \
958 default: \
959 TRACE(ddraw, "Unhandled vertex type\n"); \
960 break; \
964 glEnd(); \
965 TRACE(ddraw, "End\n");
968 static HRESULT WINAPI IDirect3DDevice2_DrawPrimitive(LPDIRECT3DDEVICE2 this,
969 D3DPRIMITIVETYPE d3dp,
970 D3DVERTEXTYPE d3dv,
971 LPVOID lpvertex,
972 DWORD vertcount,
973 DWORD dwFlags)
975 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
976 int vx_index;
978 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", this, d3dp, d3dv, lpvertex, vertcount, dwFlags);
980 DRAW_PRIMITIVE(vertcount, vx_index);
982 return D3D_OK;
987 static HRESULT WINAPI IDirect3DDevice2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 this,
988 D3DPRIMITIVETYPE d3dp,
989 D3DVERTEXTYPE d3dv,
990 LPVOID lpvertex,
991 DWORD vertcount,
992 LPWORD lpindexes,
993 DWORD indexcount,
994 DWORD dwFlags)
996 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) this;
997 int vx_index;
999 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", this, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1001 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1003 return D3D_OK;
1008 static HRESULT WINAPI IDirect3DDevice2_SetClipStatus(LPDIRECT3DDEVICE2 this,
1009 LPD3DCLIPSTATUS lpcs)
1011 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpcs);
1013 return DD_OK;
1018 static HRESULT WINAPI IDirect3DDevice2_GetClipStatus(LPDIRECT3DDEVICE2 this,
1019 LPD3DCLIPSTATUS lpcs)
1021 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpcs);
1023 return DD_OK;
1028 /*******************************************************************************
1029 * OpenGL-specific IDirect3DDevice2
1032 /*******************************************************************************
1033 * OpenGL-specific VTable
1036 static IDirect3DDevice2_VTable OpenGL_vtable = {
1037 IDirect3DDevice2_QueryInterface,
1038 IDirect3DDevice2_AddRef,
1039 IDirect3DDevice2_Release,
1040 /*** IDirect3DDevice2 methods ***/
1041 IDirect3DDevice2_GetCaps,
1042 IDirect3DDevice2_SwapTextureHandles,
1043 IDirect3DDevice2_GetStats,
1044 IDirect3DDevice2_AddViewport,
1045 IDirect3DDevice2_DeleteViewport,
1046 IDirect3DDevice2_NextViewport,
1047 IDirect3DDevice2_EnumTextureFormats,
1048 IDirect3DDevice2_BeginScene,
1049 IDirect3DDevice2_EndScene,
1050 IDirect3DDevice2_GetDirect3D,
1052 /*** DrawPrimitive API ***/
1053 IDirect3DDevice2_SetCurrentViewport,
1054 IDirect3DDevice2_GetCurrentViewport,
1056 IDirect3DDevice2_SetRenderTarget,
1057 IDirect3DDevice2_GetRenderTarget,
1059 IDirect3DDevice2_Begin,
1060 IDirect3DDevice2_BeginIndexed,
1061 IDirect3DDevice2_Vertex,
1062 IDirect3DDevice2_Index,
1063 IDirect3DDevice2_End,
1065 IDirect3DDevice2_GetRenderState,
1066 IDirect3DDevice2_SetRenderState,
1067 IDirect3DDevice2_GetLightState,
1068 IDirect3DDevice2_SetLightState,
1069 IDirect3DDevice2_SetTransform,
1070 IDirect3DDevice2_GetTransform,
1071 IDirect3DDevice2_MultiplyTransform,
1073 IDirect3DDevice2_DrawPrimitive,
1074 IDirect3DDevice2_DrawIndexedPrimitive,
1076 IDirect3DDevice2_SetClipStatus,
1077 IDirect3DDevice2_GetClipStatus,
1080 /*******************************************************************************
1081 * Direct3DDevice
1083 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1084 D3DDEVICEDESC d1,d2;
1086 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
1088 fill_opengl_caps(&d1, &d2);
1090 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1093 float id_mat[16] = {
1094 1.0, 0.0, 0.0, 0.0,
1095 0.0, 1.0, 0.0, 0.0,
1096 0.0, 0.0, 1.0, 0.0,
1097 0.0, 0.0, 0.0, 1.0
1100 int is_OpenGL_dx3(REFCLSID rguid, LPDIRECTDRAWSURFACE surface, LPDIRECT3DDEVICE *device)
1102 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1103 OpenGL_IDirect3DDevice *odev;
1105 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1106 odev = (OpenGL_IDirect3DDevice *) (*device);
1107 (*device)->ref = 1;
1108 (*device)->lpvtbl = &OpenGL_vtable_dx3;
1109 (*device)->d3d = NULL;
1110 (*device)->surface = surface;
1112 (*device)->viewport_list = NULL;
1113 (*device)->current_viewport = NULL;
1115 (*device)->set_context = set_context_dx3;
1117 TRACE(ddraw, "OpenGL device created \n");
1119 /* Create the OpenGL context */
1120 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1121 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1122 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1123 odev->rs.src = GL_ONE;
1124 odev->rs.dst = GL_ZERO;
1125 odev->rs.mag = GL_NEAREST;
1126 odev->rs.min = GL_NEAREST;
1128 odev->world_mat = (LPD3DMATRIX) &id_mat;
1129 odev->view_mat = (LPD3DMATRIX) &id_mat;
1130 odev->proj_mat = (LPD3DMATRIX) &id_mat;
1132 /* Initialisation */
1133 (*device)->set_context(*device);
1134 glClearColor(0.0, 0.0, 0.0, 0.0);
1135 glColor3f(1.0, 1.0, 1.0);
1137 return 1;
1140 /* This is not the OpenGL UID */
1141 return DD_OK;
1145 /*******************************************************************************
1146 * Direct3DDevice
1148 static HRESULT WINAPI IDirect3DDevice_QueryInterface(LPDIRECT3DDEVICE this,
1149 REFIID riid,
1150 LPVOID* ppvObj)
1152 char xrefiid[50];
1154 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1155 FIXME(ddraw, "(%p)->(%s,%p): stub\n", this, xrefiid,ppvObj);
1157 return S_OK;
1162 static ULONG WINAPI IDirect3DDevice_AddRef(LPDIRECT3DDEVICE this)
1164 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", this, this->ref );
1166 return ++(this->ref);
1171 static ULONG WINAPI IDirect3DDevice_Release(LPDIRECT3DDEVICE this)
1173 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
1175 if (!--(this->ref)) {
1176 HeapFree(GetProcessHeap(),0,this);
1177 return 0;
1180 return this->ref;
1183 static HRESULT WINAPI IDirect3DDevice_Initialize(LPDIRECT3DDEVICE this,
1184 LPDIRECT3D lpd3d,
1185 LPGUID lpGUID,
1186 LPD3DDEVICEDESC lpd3ddvdesc)
1188 TRACE(ddraw, "(%p)->(%p,%p,%p): stub\n", this, lpd3d,lpGUID, lpd3ddvdesc);
1190 return DDERR_ALREADYINITIALIZED;
1194 static HRESULT WINAPI IDirect3DDevice_GetCaps(LPDIRECT3DDEVICE this,
1195 LPD3DDEVICEDESC lpD3DHWDevDesc,
1196 LPD3DDEVICEDESC lpD3DSWDevDesc)
1198 TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpD3DHWDevDesc, lpD3DSWDevDesc);
1200 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1202 return DD_OK;
1206 static HRESULT WINAPI IDirect3DDevice_SwapTextureHandles(LPDIRECT3DDEVICE this,
1207 LPDIRECT3DTEXTURE lpD3DTex1,
1208 LPDIRECT3DTEXTURE lpD3DTex2)
1210 TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpD3DTex1, lpD3DTex2);
1212 return DD_OK;
1215 static HRESULT WINAPI IDirect3DDevice_CreateExecuteBuffer(LPDIRECT3DDEVICE this,
1216 LPD3DEXECUTEBUFFERDESC lpDesc,
1217 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1218 IUnknown *pUnkOuter)
1220 TRACE(ddraw, "(%p)->(%p,%p,%p)\n", this, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1222 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(this, lpDesc);
1224 return DD_OK;
1228 static HRESULT WINAPI IDirect3DDevice_GetStats(LPDIRECT3DDEVICE this,
1229 LPD3DSTATS lpD3DStats)
1231 TRACE(ddraw, "(%p)->(%p): stub\n", this, lpD3DStats);
1233 return DD_OK;
1237 static HRESULT WINAPI IDirect3DDevice_Execute(LPDIRECT3DDEVICE this,
1238 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1239 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1240 DWORD dwFlags)
1242 TRACE(ddraw, "(%p)->(%p,%p,%08ld): stub\n", this, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1244 /* Put this as the default context */
1246 /* Execute... */
1247 lpDirect3DExecuteBuffer->execute(lpDirect3DExecuteBuffer, this, lpDirect3DViewport);
1249 return DD_OK;
1252 static HRESULT WINAPI IDirect3DDevice_AddViewport(LPDIRECT3DDEVICE this,
1253 LPDIRECT3DVIEWPORT lpvp)
1255 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvp);
1257 /* Adds this viewport to the viewport list */
1258 lpvp->next = this->viewport_list;
1259 this->viewport_list = lpvp;
1261 return DD_OK;
1266 static HRESULT WINAPI IDirect3DDevice_DeleteViewport(LPDIRECT3DDEVICE this,
1267 LPDIRECT3DVIEWPORT lpvp)
1269 LPDIRECT3DVIEWPORT cur, prev;
1270 FIXME(ddraw, "(%p)->(%p): stub\n", this, lpvp);
1272 /* Finds this viewport in the list */
1273 prev = NULL;
1274 cur = this->viewport_list;
1275 while ((cur != NULL) && (cur != lpvp)) {
1276 prev = cur;
1277 cur = cur->next;
1279 if (cur == NULL)
1280 return DDERR_INVALIDOBJECT;
1282 /* And remove it */
1283 if (prev == NULL)
1284 this->viewport_list = cur->next;
1285 else
1286 prev->next = cur->next;
1288 return DD_OK;
1293 static HRESULT WINAPI IDirect3DDevice_NextViewport(LPDIRECT3DDEVICE this,
1294 LPDIRECT3DVIEWPORT lpvp,
1295 LPDIRECT3DVIEWPORT* lplpvp,
1296 DWORD dwFlags)
1298 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", this, lpvp, lpvp, dwFlags);
1300 switch (dwFlags) {
1301 case D3DNEXT_NEXT:
1302 *lplpvp = lpvp->next;
1303 break;
1305 case D3DNEXT_HEAD:
1306 *lplpvp = this->viewport_list;
1307 break;
1309 case D3DNEXT_TAIL:
1310 lpvp = this->viewport_list;
1311 while (lpvp->next != NULL)
1312 lpvp = lpvp->next;
1314 *lplpvp = lpvp;
1315 break;
1317 default:
1318 return DDERR_INVALIDPARAMS;
1321 return DD_OK;
1324 static HRESULT WINAPI IDirect3DDevice_Pick(LPDIRECT3DDEVICE this,
1325 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1326 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1327 DWORD dwFlags,
1328 LPD3DRECT lpRect)
1330 TRACE(ddraw, "(%p)->(%p,%p,%08lx,%p): stub\n", this, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1331 dwFlags, lpRect);
1333 return DD_OK;
1337 static HRESULT WINAPI IDirect3DDevice_GetPickRecords(LPDIRECT3DDEVICE this,
1338 LPDWORD lpCount,
1339 LPD3DPICKRECORD lpD3DPickRec)
1341 TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpCount, lpD3DPickRec);
1343 return DD_OK;
1347 static HRESULT WINAPI IDirect3DDevice_EnumTextureFormats(LPDIRECT3DDEVICE this,
1348 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1349 LPVOID lpArg)
1351 TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpd3dEnumTextureProc, lpArg);
1353 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1357 static HRESULT WINAPI IDirect3DDevice_CreateMatrix(LPDIRECT3DDEVICE this,
1358 LPD3DMATRIXHANDLE lpD3DMatHandle)
1360 TRACE(ddraw, "(%p)->(%p)\n", this, lpD3DMatHandle);
1362 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1364 return DD_OK;
1368 static HRESULT WINAPI IDirect3DDevice_SetMatrix(LPDIRECT3DDEVICE this,
1369 D3DMATRIXHANDLE d3dMatHandle,
1370 const LPD3DMATRIX lpD3DMatrix)
1372 TRACE(ddraw, "(%p)->(%08lx,%p)\n", this, d3dMatHandle, lpD3DMatrix);
1374 dump_mat(lpD3DMatrix);
1376 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1378 return DD_OK;
1382 static HRESULT WINAPI IDirect3DDevice_GetMatrix(LPDIRECT3DDEVICE this,
1383 D3DMATRIXHANDLE D3DMatHandle,
1384 LPD3DMATRIX lpD3DMatrix)
1386 TRACE(ddraw, "(%p)->(%08lx,%p)\n", this, D3DMatHandle, lpD3DMatrix);
1388 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1390 return DD_OK;
1394 static HRESULT WINAPI IDirect3DDevice_DeleteMatrix(LPDIRECT3DDEVICE this,
1395 D3DMATRIXHANDLE d3dMatHandle)
1397 TRACE(ddraw, "(%p)->(%08lx)\n", this, d3dMatHandle);
1399 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1401 return DD_OK;
1405 static HRESULT WINAPI IDirect3DDevice_BeginScene(LPDIRECT3DDEVICE this)
1407 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) this; */
1409 FIXME(ddraw, "(%p)->(): stub\n", this);
1411 /* We get the pointer to the surface (should be done on flip) */
1412 /* odev->zb->pbuf = this->surface->s.surface_desc.y.lpSurface; */
1414 return DD_OK;
1418 /* This is for the moment copy-pasted from IDirect3DDevice2...
1419 Will make a common function ... */
1420 static HRESULT WINAPI IDirect3DDevice_EndScene(LPDIRECT3DDEVICE this)
1422 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) this;
1423 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) this->surface;
1424 DDSURFACEDESC sdesc;
1425 int x,y;
1426 unsigned char *src;
1427 unsigned short *dest;
1429 FIXME(ddraw, "(%p)->(): stub\n", this);
1431 /* Here we copy back the OpenGL scene to the the DDraw surface */
1432 /* First, lock the surface */
1433 surf->lpvtbl->fnLock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1435 /* The copy the OpenGL buffer to this surface */
1437 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1438 I am currently working on a set of patches for Mesa to have OSMesa support
1439 16 bpp surfaces => we will able to render directly onto the surface, no
1440 need to do a bpp conversion */
1441 dest = (unsigned short *) sdesc.y.lpSurface;
1442 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1443 for (y = 0; y < sdesc.dwHeight; y++) {
1444 unsigned char *lsrc = src;
1446 for (x = 0; x < sdesc.dwWidth ; x++) {
1447 unsigned char r = *lsrc++;
1448 unsigned char g = *lsrc++;
1449 unsigned char b = *lsrc++;
1450 lsrc++; /* Alpha */
1452 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1454 dest++;
1457 src -= 4 * sdesc.dwWidth;
1460 /* Unlock the surface */
1461 surf->lpvtbl->fnUnlock(surf,sdesc.y.lpSurface);
1463 return DD_OK;
1467 static HRESULT WINAPI IDirect3DDevice_GetDirect3D(LPDIRECT3DDEVICE this,
1468 LPDIRECT3D *lpDirect3D)
1470 TRACE(ddraw, "(%p)->(%p): stub\n", this, lpDirect3D);
1472 return DD_OK;
1477 /*******************************************************************************
1478 * Direct3DDevice VTable
1480 static IDirect3DDevice_VTable OpenGL_vtable_dx3 = {
1481 IDirect3DDevice_QueryInterface,
1482 IDirect3DDevice_AddRef,
1483 IDirect3DDevice_Release,
1484 IDirect3DDevice_Initialize,
1485 IDirect3DDevice_GetCaps,
1486 IDirect3DDevice_SwapTextureHandles,
1487 IDirect3DDevice_CreateExecuteBuffer,
1488 IDirect3DDevice_GetStats,
1489 IDirect3DDevice_Execute,
1490 IDirect3DDevice_AddViewport,
1491 IDirect3DDevice_DeleteViewport,
1492 IDirect3DDevice_NextViewport,
1493 IDirect3DDevice_Pick,
1494 IDirect3DDevice_GetPickRecords,
1495 IDirect3DDevice_EnumTextureFormats,
1496 IDirect3DDevice_CreateMatrix,
1497 IDirect3DDevice_SetMatrix,
1498 IDirect3DDevice_GetMatrix,
1499 IDirect3DDevice_DeleteMatrix,
1500 IDirect3DDevice_BeginScene,
1501 IDirect3DDevice_EndScene,
1502 IDirect3DDevice_GetDirect3D,
1505 #else /* HAVE_MESAGL */
1507 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1508 return 0;
1511 int is_OpenGL(REFCLSID rguid, LPDIRECTDRAWSURFACE surface, LPDIRECT3DDEVICE2 *device, LPDIRECT3D2 d3d)
1513 return 0;
1516 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1517 return 0;
1520 int is_OpenGL_dx3(REFCLSID rguid, LPDIRECTDRAWSURFACE surface, LPDIRECT3DDEVICE *device)
1522 return 0;
1525 #endif /* HAVE_MESAGL */