1999-01-03 18:00:19 +01:00
|
|
|
/* Direct3D Device
|
|
|
|
(c) 1998 Lionel ULMER
|
|
|
|
|
|
|
|
This files contains all the D3D devices that Wine supports. For the moment
|
|
|
|
only the 'OpenGL' target is supported. */
|
|
|
|
|
1999-02-28 13:27:56 +01:00
|
|
|
#include <string.h>
|
1999-01-03 18:00:19 +01:00
|
|
|
#include "config.h"
|
1999-03-14 17:35:05 +01:00
|
|
|
#include "windef.h"
|
1999-01-03 18:00:19 +01:00
|
|
|
#include "winerror.h"
|
1999-02-02 17:14:23 +01:00
|
|
|
#include "wine/obj_base.h"
|
1999-01-03 18:00:19 +01:00
|
|
|
#include "heap.h"
|
|
|
|
#include "ddraw.h"
|
|
|
|
#include "d3d.h"
|
1999-06-26 21:09:08 +02:00
|
|
|
#include "debugtools.h"
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
#include "d3d_private.h"
|
|
|
|
|
1999-04-19 16:56:29 +02:00
|
|
|
DEFAULT_DEBUG_CHANNEL(ddraw)
|
|
|
|
|
1999-01-23 13:32:46 +01:00
|
|
|
/* Define this variable if you have an unpatched Mesa 3.0 (patches are available
|
|
|
|
on Mesa's home page) or version 3.1b.
|
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
Version 3.1b2 should correct this bug */
|
1999-01-23 13:32:46 +01:00
|
|
|
#undef HAVE_BUGGY_MESAGL
|
|
|
|
|
1999-01-03 18:00:19 +01:00
|
|
|
#ifdef HAVE_MESAGL
|
|
|
|
|
|
|
|
static GUID IID_D3DDEVICE2_OpenGL = {
|
|
|
|
0x39a0da38,
|
|
|
|
0x7e57,
|
|
|
|
0x11d2,
|
|
|
|
{ 0x8b,0x7c,0x0e,0x4e,0xd8,0x3c,0x2b,0x3c }
|
|
|
|
};
|
|
|
|
|
|
|
|
static GUID IID_D3DDEVICE_OpenGL = {
|
|
|
|
0x31416d44,
|
|
|
|
0x86ae,
|
|
|
|
0x11d2,
|
|
|
|
{ 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
|
|
|
|
static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* OpenGL static functions
|
|
|
|
*/
|
1999-03-27 17:56:13 +01:00
|
|
|
static void set_context(IDirect3DDevice2Impl* This) {
|
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
OSMesaMakeCurrent(odev->ctx, odev->buffer,
|
|
|
|
GL_UNSIGNED_BYTE,
|
1999-03-27 17:56:13 +01:00
|
|
|
This->surface->s.surface_desc.dwWidth,
|
|
|
|
This->surface->s.surface_desc.dwHeight);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
if (glXMakeCurrent(display,
|
|
|
|
odev->common.surface->s.ddraw->d.drawable,
|
|
|
|
odev->ctx) == False) {
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("Error in setting current context (context %p drawable %ld)!\n",
|
1999-05-13 20:53:05 +02:00
|
|
|
odev->ctx, odev->common.surface->s.ddraw->d.drawable);
|
|
|
|
}
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static void set_context_dx3(IDirect3DDeviceImpl* This) {
|
|
|
|
OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
OSMesaMakeCurrent(odev->ctx, odev->buffer,
|
|
|
|
GL_UNSIGNED_BYTE,
|
1999-03-27 17:56:13 +01:00
|
|
|
This->surface->s.surface_desc.dwWidth,
|
|
|
|
This->surface->s.surface_desc.dwHeight);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
if (glXMakeCurrent(display,
|
|
|
|
odev->common.surface->s.ddraw->d.drawable,
|
|
|
|
odev->ctx) == False) {
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("Error in setting current context !\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
}
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
|
|
|
|
{
|
|
|
|
pc->dwSize = sizeof(*pc);
|
|
|
|
pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
|
|
|
|
D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
|
|
|
|
pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
|
|
|
|
D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
|
|
|
|
pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
|
|
|
|
pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
|
|
|
|
pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
|
|
|
|
pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
|
|
|
|
pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
|
|
|
|
pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
|
|
|
|
D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
|
|
|
|
pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
|
|
|
|
D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
|
|
|
|
pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
|
|
|
|
pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
|
|
|
|
pc->dwStippleWidth = 32;
|
|
|
|
pc->dwStippleHeight = 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
|
|
|
|
{
|
1999-01-23 13:32:46 +01:00
|
|
|
/* GLint maxlight; */
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
d1->dwSize = sizeof(*d1);
|
|
|
|
d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
|
1999-01-23 13:32:46 +01:00
|
|
|
| D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
|
1999-01-03 18:00:19 +01:00
|
|
|
d1->dcmColorModel = D3DCOLOR_RGB;
|
|
|
|
d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
|
|
|
|
D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
|
|
|
|
D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
|
|
|
|
d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
|
|
|
|
d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
|
|
|
|
d1->bClipping = TRUE;
|
|
|
|
d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
|
|
|
|
d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
|
|
|
|
d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
|
1999-01-17 17:55:11 +01:00
|
|
|
d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
|
1999-01-03 18:00:19 +01:00
|
|
|
fill_opengl_primcaps(&(d1->dpcLineCaps));
|
|
|
|
fill_opengl_primcaps(&(d1->dpcTriCaps));
|
|
|
|
d1->dwDeviceRenderBitDepth = DDBD_16;
|
|
|
|
d1->dwDeviceZBufferBitDepth = DDBD_16;
|
|
|
|
d1->dwMaxBufferSize = 0;
|
1999-01-23 13:32:46 +01:00
|
|
|
d1->dwMaxVertexCount = 65536;
|
1999-01-03 18:00:19 +01:00
|
|
|
d1->dwMinTextureWidth = 1;
|
|
|
|
d1->dwMinTextureHeight = 1;
|
|
|
|
d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
|
|
|
|
d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
|
|
|
|
d1->dwMinStippleWidth = 1;
|
|
|
|
d1->dwMinStippleHeight = 1;
|
|
|
|
d1->dwMaxStippleWidth = 32;
|
|
|
|
d1->dwMaxStippleHeight = 32;
|
|
|
|
|
|
|
|
d2->dwSize = sizeof(*d2);
|
|
|
|
d2->dwFlags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
|
|
|
|
D3DDEVICEDESC d1,d2;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE(" Enumerating OpenGL D3D device.\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
fill_opengl_caps(&d1, &d2);
|
|
|
|
|
|
|
|
return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
|
|
|
if (/* Default device */
|
|
|
|
(rguid == NULL) ||
|
|
|
|
/* HAL Device */
|
|
|
|
(!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
|
|
|
|
/* OpenGL Device */
|
|
|
|
(!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
|
|
|
|
OpenGL_IDirect3DDevice2 *odev;
|
|
|
|
|
|
|
|
const float id_mat[16] = {
|
|
|
|
1.0, 0.0, 0.0, 0.0,
|
|
|
|
0.0, 1.0, 0.0, 0.0,
|
|
|
|
0.0, 0.0, 1.0, 0.0,
|
|
|
|
0.0, 0.0, 0.0, 1.0
|
|
|
|
};
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifndef USE_OSMESA
|
|
|
|
int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
|
|
|
|
XVisualInfo *xvis;
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
*device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
|
|
|
|
odev = (OpenGL_IDirect3DDevice2 *) (*device);
|
|
|
|
(*device)->ref = 1;
|
|
|
|
(*device)->lpvtbl = &OpenGL_vtable;
|
|
|
|
(*device)->d3d = d3d;
|
|
|
|
(*device)->surface = surface;
|
|
|
|
|
|
|
|
(*device)->viewport_list = NULL;
|
|
|
|
(*device)->current_viewport = NULL;
|
|
|
|
|
|
|
|
(*device)->set_context = set_context;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Creating OpenGL device for surface %p\n", surface);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Create the OpenGL context */
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
|
|
|
|
odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
|
|
|
|
surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
/* First get the correct visual */
|
|
|
|
/* if (surface->s.backbuffer == NULL)
|
|
|
|
attributeList[3] = None; */
|
|
|
|
ENTER_GL();
|
|
|
|
xvis = glXChooseVisual(display,
|
|
|
|
DefaultScreen(display),
|
|
|
|
attributeList);
|
|
|
|
if (xvis == NULL)
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("No visual found !\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
else
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Visual found\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
/* Create the context */
|
|
|
|
odev->ctx = glXCreateContext(display,
|
|
|
|
xvis,
|
|
|
|
NULL,
|
|
|
|
GL_TRUE);
|
|
|
|
if (odev->ctx == NULL)
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("Error in context creation !\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
else
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Context created (%p)\n", odev->ctx);
|
1999-05-13 20:53:05 +02:00
|
|
|
|
|
|
|
/* Now override the surface's Flip method (if in double buffering) */
|
|
|
|
surface->s.d3d_device = (void *) odev;
|
1999-07-03 13:57:29 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct _surface_chain *chain = surface->s.chain;
|
|
|
|
for (i=0;i<chain->nrofsurfaces;i++)
|
|
|
|
if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
|
|
|
|
chain->surfaces[i]->s.d3d_device = (void *) odev;
|
|
|
|
}
|
1999-05-13 20:53:05 +02:00
|
|
|
#endif
|
1999-01-17 17:55:11 +01:00
|
|
|
odev->rs.src = GL_ONE;
|
|
|
|
odev->rs.dst = GL_ZERO;
|
|
|
|
odev->rs.mag = GL_NEAREST;
|
|
|
|
odev->rs.min = GL_NEAREST;
|
|
|
|
odev->vt = 0;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
|
|
|
|
memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
|
|
|
|
memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
|
|
|
|
|
|
|
|
/* Initialisation */
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Setting current context\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
(*device)->set_context(*device);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Current context set\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glColor3f(1.0, 1.0, 1.0);
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("OpenGL device created \n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is not the OpenGL UID */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Common IDirect3DDevice2
|
|
|
|
*/
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_QueryInterface(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
REFIID riid,
|
|
|
|
LPVOID* ppvObj)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-01-03 18:00:19 +01:00
|
|
|
char xrefiid[50];
|
|
|
|
|
|
|
|
WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
return ++(This->ref);
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
if (!--(This->ref)) {
|
1999-05-13 20:53:05 +02:00
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
|
|
|
|
|
|
|
#ifdef USE_OSMESA
|
|
|
|
OSMesaDestroyContext(odev->ctx);
|
|
|
|
#else
|
|
|
|
ENTER_GL();
|
|
|
|
glXDestroyContext(display,
|
|
|
|
odev->ctx);
|
|
|
|
LEAVE_GL();
|
|
|
|
#endif
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
HeapFree(GetProcessHeap(),0,This);
|
1999-01-03 18:00:19 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
return This->ref;
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** IDirect3DDevice2 methods ***/
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DDEVICEDESC lpdescsoft,
|
|
|
|
LPD3DDEVICEDESC lpdeschard)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
fill_opengl_caps(lpdescsoft, lpdeschard);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DTEXTURE2 lptex1,
|
|
|
|
LPDIRECT3DTEXTURE2 lptex2)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DSTATS lpstats)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpstats);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT2 lpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, ilpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Adds this viewport to the viewport list */
|
1999-03-27 17:56:13 +01:00
|
|
|
ilpvp->next = This->viewport_list;
|
|
|
|
This->viewport_list = ilpvp;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT2 lpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
|
|
|
IDirect3DViewport2Impl *cur, *prev;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Finds this viewport in the list */
|
|
|
|
prev = NULL;
|
1999-03-27 17:56:13 +01:00
|
|
|
cur = This->viewport_list;
|
|
|
|
while ((cur != NULL) && (cur != ilpvp)) {
|
1999-01-03 18:00:19 +01:00
|
|
|
prev = cur;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
if (cur == NULL)
|
|
|
|
return DDERR_INVALIDOBJECT;
|
|
|
|
|
|
|
|
/* And remove it */
|
|
|
|
if (prev == NULL)
|
1999-03-27 17:56:13 +01:00
|
|
|
This->viewport_list = cur->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
else
|
|
|
|
prev->next = cur->next;
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT2 lpvp,
|
|
|
|
LPDIRECT3DVIEWPORT2* lplpvp,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
|
|
|
IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
switch (dwFlags) {
|
|
|
|
case D3DNEXT_NEXT:
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = ilpvp->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DNEXT_HEAD:
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = This->viewport_list;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DNEXT_TAIL:
|
1999-03-27 17:56:13 +01:00
|
|
|
ilpvp = This->viewport_list;
|
|
|
|
while (ilpvp->next != NULL)
|
|
|
|
ilpvp = ilpvp->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = ilpvp;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
|
|
|
|
LPVOID context) {
|
|
|
|
DDSURFACEDESC sdesc;
|
|
|
|
LPDDPIXELFORMAT pformat;
|
|
|
|
|
|
|
|
/* Do the texture enumeration */
|
|
|
|
sdesc.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
|
|
|
|
sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
|
|
|
pformat = &(sdesc.ddpfPixelFormat);
|
|
|
|
pformat->dwSize = sizeof(DDPIXELFORMAT);
|
|
|
|
pformat->dwFourCC = 0;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGBA unpacked (32)\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
|
|
|
pformat->x.dwRGBBitCount = 32;
|
1999-01-23 13:32:46 +01:00
|
|
|
pformat->y.dwRBitMask = 0xFF000000;
|
|
|
|
pformat->z.dwGBitMask = 0x00FF0000;
|
|
|
|
pformat->xx.dwBBitMask = 0x0000FF00;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x000000FF;
|
1999-01-03 18:00:19 +01:00
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGB unpacked (24)\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB;
|
|
|
|
pformat->x.dwRGBBitCount = 24;
|
|
|
|
pformat->y.dwRBitMask = 0x00FF0000;
|
|
|
|
pformat->z.dwGBitMask = 0x0000FF00;
|
|
|
|
pformat->xx.dwBBitMask = 0x000000FF;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x00000000;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-01-23 13:32:46 +01:00
|
|
|
#ifndef HAVE_BUGGY_MESAGL
|
|
|
|
/* The packed texture format are buggy in Mesa. The bug was reported and corrected,
|
|
|
|
so that future version will work great. */
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB;
|
|
|
|
pformat->x.dwRGBBitCount = 16;
|
|
|
|
pformat->y.dwRBitMask = 0x0000F800;
|
|
|
|
pformat->z.dwGBitMask = 0x000007E0;
|
|
|
|
pformat->xx.dwBBitMask = 0x0000001F;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x00000000;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
|
1999-01-23 13:32:46 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
|
|
|
pformat->x.dwRGBBitCount = 16;
|
|
|
|
pformat->y.dwRBitMask = 0x0000F800;
|
|
|
|
pformat->z.dwGBitMask = 0x000007C0;
|
|
|
|
pformat->xx.dwBBitMask = 0x0000003E;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x00000001;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
|
1999-01-23 13:32:46 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
|
|
|
pformat->x.dwRGBBitCount = 16;
|
|
|
|
pformat->y.dwRBitMask = 0x0000F000;
|
|
|
|
pformat->z.dwGBitMask = 0x00000F00;
|
|
|
|
pformat->xx.dwBBitMask = 0x000000F0;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x0000000F;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
|
1999-01-23 13:32:46 +01:00
|
|
|
pformat->dwFlags = DDPF_RGB;
|
|
|
|
pformat->x.dwRGBBitCount = 8;
|
|
|
|
pformat->y.dwRBitMask = 0x0000F800;
|
|
|
|
pformat->z.dwGBitMask = 0x000007C0;
|
|
|
|
pformat->xx.dwBBitMask = 0x0000003E;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x00000001;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
#endif
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Enumerating Paletted (8)\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
pformat->dwFlags = DDPF_PALETTEINDEXED8;
|
|
|
|
pformat->x.dwRGBBitCount = 8;
|
|
|
|
pformat->y.dwRBitMask = 0x00000000;
|
|
|
|
pformat->z.dwGBitMask = 0x00000000;
|
|
|
|
pformat->xx.dwBBitMask = 0x00000000;
|
|
|
|
pformat->xy.dwRGBAlphaBitMask = 0x00000000;
|
|
|
|
if (cb(&sdesc, context) == 0)
|
|
|
|
return DD_OK;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("End of enumeration\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DENUMTEXTUREFORMATSCALLBACK cb,
|
|
|
|
LPVOID context)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return enum_texture_format_OpenGL(cb, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
/* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(): stub\n", This);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Here, we should get the DDraw surface and 'copy it' to the
|
|
|
|
OpenGL surface.... */
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-03-27 17:56:13 +01:00
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
|
|
|
LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
|
1999-01-03 18:00:19 +01:00
|
|
|
DDSURFACEDESC sdesc;
|
|
|
|
int x,y;
|
|
|
|
unsigned char *src;
|
|
|
|
unsigned short *dest;
|
1999-05-13 20:53:05 +02:00
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(): stub\n", This);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
/* Here we copy back the OpenGL scene to the the DDraw surface */
|
|
|
|
/* First, lock the surface */
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* The copy the OpenGL buffer to this surface */
|
|
|
|
|
|
|
|
/* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
|
|
|
|
I am currently working on a set of patches for Mesa to have OSMesa support
|
|
|
|
16 bpp surfaces => we will able to render directly onto the surface, no
|
|
|
|
need to do a bpp conversion */
|
|
|
|
dest = (unsigned short *) sdesc.y.lpSurface;
|
|
|
|
src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
|
|
|
|
for (y = 0; y < sdesc.dwHeight; y++) {
|
|
|
|
unsigned char *lsrc = src;
|
|
|
|
|
|
|
|
for (x = 0; x < sdesc.dwWidth ; x++) {
|
|
|
|
unsigned char r = *lsrc++;
|
|
|
|
unsigned char g = *lsrc++;
|
|
|
|
unsigned char b = *lsrc++;
|
|
|
|
lsrc++; /* Alpha */
|
|
|
|
*dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
|
|
|
|
|
|
|
dest++;
|
|
|
|
}
|
|
|
|
|
|
|
|
src -= 4 * sdesc.dwWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the surface */
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
/* No need to do anything here... */
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p): stub\n", This, lpd3d2);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
*lpd3d2 = (LPDIRECT3D2)This->d3d;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*** DrawPrimitive API ***/
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT2 lpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, ilpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Should check if the viewport was added or not */
|
|
|
|
|
|
|
|
/* Set this viewport as the current viewport */
|
1999-03-27 17:56:13 +01:00
|
|
|
This->current_viewport = ilpvp;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Activate this viewport */
|
1999-03-27 17:56:13 +01:00
|
|
|
ilpvp->device.active_device2 = This;
|
|
|
|
ilpvp->activate(ilpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT2 *lplpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lplpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Returns the current viewport */
|
1999-03-27 17:56:13 +01:00
|
|
|
*lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECTDRAWSURFACE lpdds,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECTDRAWSURFACE *lplpdds)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lplpdds);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Returns the current rendering target (the surface on wich we render) */
|
1999-03-27 17:56:13 +01:00
|
|
|
*lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DPRIMITIVETYPE d3dp,
|
|
|
|
D3DVERTEXTYPE d3dv,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DPRIMITIVETYPE d3dp,
|
|
|
|
D3DVERTEXTYPE d3dv,
|
|
|
|
LPVOID lpvert,
|
|
|
|
DWORD numvert,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPVOID lpvert)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpvert);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
WORD index)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d): stub\n", This, index);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%08lx): stub\n", This, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DRENDERSTATETYPE d3drs,
|
|
|
|
LPDWORD lprstate)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DRENDERSTATETYPE dwRenderStateType,
|
|
|
|
DWORD dwRenderState)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
1999-01-17 17:55:11 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Call the render state functions */
|
1999-01-17 17:55:11 +01:00
|
|
|
set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DLIGHTSTATETYPE d3dls,
|
|
|
|
LPDWORD lplstate)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DLIGHTSTATETYPE dwLightStateType,
|
|
|
|
DWORD dwLightState)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
switch (dwLightStateType) {
|
|
|
|
case D3DLIGHTSTATE_MATERIAL: { /* 1 */
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
if (mat != NULL) {
|
1999-05-13 20:53:05 +02:00
|
|
|
ENTER_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
mat->activate(mat);
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
} else {
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Zoups !!!\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_AMBIENT: { /* 2 */
|
|
|
|
float light[4];
|
|
|
|
|
|
|
|
light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
|
|
|
|
light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
|
|
|
|
light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
|
|
|
|
light[3] = 1.0;
|
1999-05-13 20:53:05 +02:00
|
|
|
ENTER_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_COLORMODEL: /* 3 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_FOGMODE: /* 4 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_FOGSTART: /* 5 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_FOGEND: /* 6 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Unexpected Light State Type\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DTRANSFORMSTATETYPE d3dts,
|
|
|
|
LPD3DMATRIX lpmatrix)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
ENTER_GL();
|
|
|
|
|
1999-01-03 18:00:19 +01:00
|
|
|
/* Using a trial and failure approach, I found that the order of
|
|
|
|
Direct3D transformations that works best is :
|
|
|
|
|
|
|
|
ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
|
|
|
|
|
|
|
|
As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
|
|
|
|
OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
|
|
|
|
|
|
|
|
If anyone has a good explanation of the three different matrices in
|
|
|
|
the SDK online documentation, feel free to point it to me. For example,
|
|
|
|
which matrices transform lights ? In OpenGL only the PROJECTION matrix
|
|
|
|
transform the lights, not the MODELVIEW. Using the matrix names, I
|
|
|
|
supposed that PROJECTION and VIEW (all 'camera' related names) do
|
|
|
|
transform lights, but WORLD do not. It may be wrong though... */
|
|
|
|
|
|
|
|
/* After reading through both OpenGL and Direct3D documentations, I
|
|
|
|
thought that D3D matrices were written in 'line major mode' transposed
|
|
|
|
from OpenGL's 'column major mode'. But I found out that a simple memcpy
|
|
|
|
works fine to transfer one matrix format to the other (it did not work
|
|
|
|
when transposing)....
|
|
|
|
|
|
|
|
So :
|
|
|
|
1) are the documentations wrong
|
|
|
|
2) does the matrix work even if they are not read correctly
|
|
|
|
3) is Mesa's implementation of OpenGL not compliant regarding Matrix
|
|
|
|
loading using glLoadMatrix ?
|
|
|
|
|
|
|
|
Anyway, I always use 'conv_mat' to transfer the matrices from one format
|
|
|
|
to the other so that if I ever find out that I need to transpose them, I
|
|
|
|
will able to do it quickly, only by changing the macro conv_mat. */
|
|
|
|
|
|
|
|
switch (d3dts) {
|
|
|
|
case D3DTRANSFORMSTATE_WORLD: {
|
|
|
|
conv_mat(lpmatrix, odev->world_mat);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadMatrixf((float *) &(odev->world_mat));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3DTRANSFORMSTATE_VIEW: {
|
|
|
|
conv_mat(lpmatrix, odev->view_mat);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadMatrixf((float *) &(odev->proj_mat));
|
|
|
|
glMultMatrixf((float *) &(odev->view_mat));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3DTRANSFORMSTATE_PROJECTION: {
|
|
|
|
conv_mat(lpmatrix, odev->proj_mat);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadMatrixf((float *) &(odev->proj_mat));
|
|
|
|
glMultMatrixf((float *) &(odev->view_mat));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
|
|
|
|
1999-01-03 18:00:19 +01:00
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DTRANSFORMSTATETYPE d3dts,
|
|
|
|
LPD3DMATRIX lpmatrix)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DTRANSFORMSTATETYPE d3dts,
|
|
|
|
LPD3DMATRIX lpmatrix)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
1999-01-17 17:55:11 +01:00
|
|
|
#define DRAW_PRIMITIVE(MAXVERT,INDEX) \
|
|
|
|
/* Puts GL in the correct lighting mode */ \
|
|
|
|
if (odev->vt != d3dv) { \
|
|
|
|
if (odev->vt == D3DVT_TLVERTEX) { \
|
|
|
|
/* Need to put the correct transformation again */ \
|
|
|
|
glMatrixMode(GL_MODELVIEW); \
|
|
|
|
glLoadMatrixf((float *) &(odev->world_mat)); \
|
|
|
|
glMatrixMode(GL_PROJECTION); \
|
|
|
|
glLoadMatrixf((float *) &(odev->proj_mat)); \
|
|
|
|
glMultMatrixf((float *) &(odev->view_mat)); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
switch (d3dv) { \
|
|
|
|
case D3DVT_VERTEX: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Standard Vertex\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glEnable(GL_LIGHTING); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DVT_LVERTEX: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Lighted Vertex\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glDisable(GL_LIGHTING); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DVT_TLVERTEX: { \
|
|
|
|
GLdouble height, width, minZ, maxZ; \
|
|
|
|
\
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Transformed - Lighted Vertex\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
/* First, disable lighting */ \
|
|
|
|
glDisable(GL_LIGHTING); \
|
|
|
|
\
|
|
|
|
/* Then do not put any transformation matrixes */ \
|
|
|
|
glMatrixMode(GL_MODELVIEW); \
|
|
|
|
glLoadIdentity(); \
|
|
|
|
glMatrixMode(GL_PROJECTION); \
|
|
|
|
glLoadIdentity(); \
|
|
|
|
\
|
1999-03-27 17:56:13 +01:00
|
|
|
if (This->current_viewport == NULL) { \
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("No current viewport !\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
/* Using standard values */ \
|
|
|
|
height = 640.0; \
|
|
|
|
width = 480.0; \
|
|
|
|
minZ = -10.0; \
|
|
|
|
maxZ = 10.0; \
|
|
|
|
} else { \
|
1999-03-27 17:56:13 +01:00
|
|
|
if (This->current_viewport->use_vp2) { \
|
|
|
|
height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight; \
|
|
|
|
width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth; \
|
|
|
|
minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ; \
|
|
|
|
maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ; \
|
1999-01-17 17:55:11 +01:00
|
|
|
} else { \
|
1999-03-27 17:56:13 +01:00
|
|
|
height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight; \
|
|
|
|
width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth; \
|
|
|
|
minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ; \
|
|
|
|
maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ; \
|
1999-01-17 17:55:11 +01:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
|
|
|
|
} break; \
|
|
|
|
\
|
|
|
|
default: \
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("Unhandled vertex type\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
odev->vt = d3dv; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
switch (d3dp) { \
|
|
|
|
case D3DPT_POINTLIST: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start POINTS\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_POINTS); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DPT_LINELIST: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start LINES\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_LINES); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DPT_LINESTRIP: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start LINE_STRIP\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_LINE_STRIP); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DPT_TRIANGLELIST: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start TRIANGLES\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_TRIANGLES); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DPT_TRIANGLESTRIP: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start TRIANGLE_STRIP\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_TRIANGLE_STRIP); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
case D3DPT_TRIANGLEFAN: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Start TRIANGLE_FAN\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
glBegin(GL_TRIANGLE_FAN); \
|
|
|
|
break; \
|
|
|
|
\
|
|
|
|
default: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Unhandled primitive\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* Draw the primitives */ \
|
|
|
|
for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
|
|
|
|
switch (d3dv) { \
|
|
|
|
case D3DVT_VERTEX: { \
|
|
|
|
D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
|
|
|
|
\
|
|
|
|
glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
|
|
|
|
glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
|
1999-01-17 17:55:11 +01:00
|
|
|
} break; \
|
|
|
|
\
|
|
|
|
case D3DVT_LVERTEX: { \
|
|
|
|
D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
|
|
|
|
DWORD col = vx->c.color; \
|
|
|
|
\
|
|
|
|
glColor3f(((col >> 16) & 0xFF) / 255.0, \
|
|
|
|
((col >> 8) & 0xFF) / 255.0, \
|
|
|
|
((col >> 0) & 0xFF) / 255.0); \
|
|
|
|
glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
|
1999-01-17 17:55:11 +01:00
|
|
|
vx->x.x, vx->y.y, vx->z.z, \
|
|
|
|
((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
|
|
|
|
} break; \
|
|
|
|
\
|
|
|
|
case D3DVT_TLVERTEX: { \
|
|
|
|
D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
|
|
|
|
DWORD col = vx->c.color; \
|
|
|
|
\
|
|
|
|
glColor3f(((col >> 16) & 0xFF) / 255.0, \
|
|
|
|
((col >> 8) & 0xFF) / 255.0, \
|
|
|
|
((col >> 0) & 0xFF) / 255.0); \
|
|
|
|
glTexCoord2f(vx->u.tu, vx->v.tv); \
|
|
|
|
if (vx->r.rhw < 0.01) \
|
|
|
|
glVertex3f(vx->x.sx, \
|
|
|
|
vx->y.sy, \
|
|
|
|
vx->z.sz); \
|
|
|
|
else \
|
|
|
|
glVertex4f(vx->x.sx / vx->r.rhw, \
|
|
|
|
vx->y.sy / vx->r.rhw, \
|
|
|
|
vx->z.sz / vx->r.rhw, \
|
|
|
|
1.0 / vx->r.rhw); \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
|
1999-01-17 17:55:11 +01:00
|
|
|
vx->x.sx, vx->y.sy, vx->z.sz, \
|
|
|
|
((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
|
|
|
|
vx->u.tu, vx->v.tv, vx->r.rhw); \
|
|
|
|
} break; \
|
|
|
|
\
|
|
|
|
default: \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Unhandled vertex type\n"); \
|
1999-01-17 17:55:11 +01:00
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
glEnd(); \
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("End\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DPRIMITIVETYPE d3dp,
|
|
|
|
D3DVERTEXTYPE d3dv,
|
|
|
|
LPVOID lpvertex,
|
|
|
|
DWORD vertcount,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
1999-01-03 18:00:19 +01:00
|
|
|
int vx_index;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
ENTER_GL();
|
1999-01-17 17:55:11 +01:00
|
|
|
DRAW_PRIMITIVE(vertcount, vx_index);
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-01-17 17:55:11 +01:00
|
|
|
return D3D_OK;
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DPRIMITIVETYPE d3dp,
|
|
|
|
D3DVERTEXTYPE d3dv,
|
|
|
|
LPVOID lpvertex,
|
|
|
|
DWORD vertcount,
|
|
|
|
LPWORD lpindexes,
|
|
|
|
DWORD indexcount,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
|
|
|
OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
|
1999-01-03 18:00:19 +01:00
|
|
|
int vx_index;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
ENTER_GL();
|
1999-01-17 17:55:11 +01:00
|
|
|
DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
|
1999-05-13 20:53:05 +02:00
|
|
|
LEAVE_GL();
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-01-17 17:55:11 +01:00
|
|
|
return D3D_OK;
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DCLIPSTATUS lpcs)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpcs);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DCLIPSTATUS lpcs)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDevice2Impl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpcs);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* OpenGL-specific IDirect3DDevice2
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* OpenGL-specific VTable
|
|
|
|
*/
|
|
|
|
|
1999-05-22 13:41:38 +02:00
|
|
|
static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
|
|
|
|
{
|
|
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirect3DDevice2Impl_QueryInterface,
|
|
|
|
IDirect3DDevice2Impl_AddRef,
|
|
|
|
IDirect3DDevice2Impl_Release,
|
1999-01-03 18:00:19 +01:00
|
|
|
/*** IDirect3DDevice2 methods ***/
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirect3DDevice2Impl_GetCaps,
|
|
|
|
IDirect3DDevice2Impl_SwapTextureHandles,
|
|
|
|
IDirect3DDevice2Impl_GetStats,
|
|
|
|
IDirect3DDevice2Impl_AddViewport,
|
|
|
|
IDirect3DDevice2Impl_DeleteViewport,
|
|
|
|
IDirect3DDevice2Impl_NextViewport,
|
|
|
|
IDirect3DDevice2Impl_EnumTextureFormats,
|
|
|
|
IDirect3DDevice2Impl_BeginScene,
|
|
|
|
IDirect3DDevice2Impl_EndScene,
|
|
|
|
IDirect3DDevice2Impl_GetDirect3D,
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/*** DrawPrimitive API ***/
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirect3DDevice2Impl_SetCurrentViewport,
|
|
|
|
IDirect3DDevice2Impl_GetCurrentViewport,
|
|
|
|
|
|
|
|
IDirect3DDevice2Impl_SetRenderTarget,
|
|
|
|
IDirect3DDevice2Impl_GetRenderTarget,
|
|
|
|
|
|
|
|
IDirect3DDevice2Impl_Begin,
|
|
|
|
IDirect3DDevice2Impl_BeginIndexed,
|
|
|
|
IDirect3DDevice2Impl_Vertex,
|
|
|
|
IDirect3DDevice2Impl_Index,
|
|
|
|
IDirect3DDevice2Impl_End,
|
|
|
|
|
|
|
|
IDirect3DDevice2Impl_GetRenderState,
|
|
|
|
IDirect3DDevice2Impl_SetRenderState,
|
|
|
|
IDirect3DDevice2Impl_GetLightState,
|
|
|
|
IDirect3DDevice2Impl_SetLightState,
|
|
|
|
IDirect3DDevice2Impl_SetTransform,
|
|
|
|
IDirect3DDevice2Impl_GetTransform,
|
|
|
|
IDirect3DDevice2Impl_MultiplyTransform,
|
|
|
|
|
|
|
|
IDirect3DDevice2Impl_DrawPrimitive,
|
|
|
|
IDirect3DDevice2Impl_DrawIndexedPrimitive,
|
|
|
|
|
|
|
|
IDirect3DDevice2Impl_SetClipStatus,
|
|
|
|
IDirect3DDevice2Impl_GetClipStatus,
|
1999-01-03 18:00:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Direct3DDevice
|
|
|
|
*/
|
|
|
|
int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
|
|
|
|
D3DDEVICEDESC d1,d2;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE(" Enumerating OpenGL D3D device.\n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
fill_opengl_caps(&d1, &d2);
|
|
|
|
|
|
|
|
return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
|
|
|
|
}
|
|
|
|
|
|
|
|
float id_mat[16] = {
|
|
|
|
1.0, 0.0, 0.0, 0.0,
|
|
|
|
0.0, 1.0, 0.0, 0.0,
|
|
|
|
0.0, 0.0, 1.0, 0.0,
|
|
|
|
0.0, 0.0, 0.0, 1.0
|
|
|
|
};
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
|
|
|
if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
|
|
|
|
OpenGL_IDirect3DDevice *odev;
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifndef USE_OSMESA
|
|
|
|
int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
|
|
|
|
XVisualInfo *xvis;
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
*device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
|
|
|
|
odev = (OpenGL_IDirect3DDevice *) (*device);
|
|
|
|
(*device)->ref = 1;
|
|
|
|
(*device)->lpvtbl = &OpenGL_vtable_dx3;
|
|
|
|
(*device)->d3d = NULL;
|
|
|
|
(*device)->surface = surface;
|
|
|
|
|
|
|
|
(*device)->viewport_list = NULL;
|
|
|
|
(*device)->current_viewport = NULL;
|
|
|
|
|
|
|
|
(*device)->set_context = set_context_dx3;
|
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("OpenGL device created \n");
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Create the OpenGL context */
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
|
|
|
|
odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
|
|
|
|
surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
/* First get the correct visual */
|
|
|
|
/* if (surface->s.backbuffer == NULL)
|
|
|
|
attributeList[3] = None; */
|
|
|
|
ENTER_GL();
|
|
|
|
xvis = glXChooseVisual(display,
|
|
|
|
DefaultScreen(display),
|
|
|
|
attributeList);
|
|
|
|
if (xvis == NULL)
|
1999-06-26 21:09:08 +02:00
|
|
|
ERR("No visual found !\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
else
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Visual found\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
/* Create the context */
|
|
|
|
odev->ctx = glXCreateContext(display,
|
|
|
|
xvis,
|
|
|
|
NULL,
|
|
|
|
GL_TRUE);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("Context created\n");
|
1999-05-13 20:53:05 +02:00
|
|
|
|
|
|
|
/* Now override the surface's Flip method (if in double buffering) */
|
|
|
|
surface->s.d3d_device = (void *) odev;
|
1999-07-03 13:57:29 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct _surface_chain *chain = surface->s.chain;
|
|
|
|
for (i=0;i<chain->nrofsurfaces;i++)
|
|
|
|
if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
|
|
|
|
chain->surfaces[i]->s.d3d_device = (void *) odev;
|
|
|
|
}
|
1999-05-13 20:53:05 +02:00
|
|
|
#endif
|
1999-01-17 17:55:11 +01:00
|
|
|
odev->rs.src = GL_ONE;
|
|
|
|
odev->rs.dst = GL_ZERO;
|
|
|
|
odev->rs.mag = GL_NEAREST;
|
|
|
|
odev->rs.min = GL_NEAREST;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
odev->world_mat = (LPD3DMATRIX) &id_mat;
|
|
|
|
odev->view_mat = (LPD3DMATRIX) &id_mat;
|
|
|
|
odev->proj_mat = (LPD3DMATRIX) &id_mat;
|
|
|
|
|
|
|
|
/* Initialisation */
|
|
|
|
(*device)->set_context(*device);
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glColor3f(1.0, 1.0, 1.0);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is not the OpenGL UID */
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Direct3DDevice
|
|
|
|
*/
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
REFIID riid,
|
|
|
|
LPVOID* ppvObj)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-01-03 18:00:19 +01:00
|
|
|
char xrefiid[50];
|
|
|
|
|
|
|
|
WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
return ++(This->ref);
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
if (!--(This->ref)) {
|
1999-05-13 20:53:05 +02:00
|
|
|
OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
|
|
|
|
|
|
|
|
#ifdef USE_OSMESA
|
|
|
|
OSMesaDestroyContext(odev->ctx);
|
|
|
|
#else
|
|
|
|
ENTER_GL();
|
|
|
|
glXDestroyContext(display,
|
|
|
|
odev->ctx);
|
|
|
|
LEAVE_GL();
|
|
|
|
#endif
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
HeapFree(GetProcessHeap(),0,This);
|
1999-01-03 18:00:19 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
return This->ref;
|
1999-01-03 18:00:19 +01:00
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3D lpd3d,
|
|
|
|
LPGUID lpGUID,
|
|
|
|
LPD3DDEVICEDESC lpd3ddvdesc)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DDERR_ALREADYINITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DDEVICEDESC lpD3DHWDevDesc,
|
|
|
|
LPD3DDEVICEDESC lpD3DSWDevDesc)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DTEXTURE lpD3DTex1,
|
|
|
|
LPDIRECT3DTEXTURE lpD3DTex2)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DEXECUTEBUFFERDESC lpDesc,
|
|
|
|
LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
|
|
|
|
IUnknown *pUnkOuter)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
*lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DSTATS lpD3DStats)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
|
|
|
|
LPDIRECT3DVIEWPORT lpDirect3DViewport,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Put this as the default context */
|
|
|
|
|
|
|
|
/* Execute... */
|
1999-03-27 17:56:13 +01:00
|
|
|
((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT lpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, ilpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Adds this viewport to the viewport list */
|
1999-03-27 17:56:13 +01:00
|
|
|
ilpvp->next = This->viewport_list;
|
|
|
|
This->viewport_list = ilpvp;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT lpvp)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
|
|
|
IDirect3DViewport2Impl *cur, *prev;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p): stub\n", This, lpvp);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* Finds this viewport in the list */
|
|
|
|
prev = NULL;
|
1999-03-27 17:56:13 +01:00
|
|
|
cur = This->viewport_list;
|
|
|
|
while ((cur != NULL) && (cur != ilpvp)) {
|
1999-01-03 18:00:19 +01:00
|
|
|
prev = cur;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
if (cur == NULL)
|
|
|
|
return DDERR_INVALIDOBJECT;
|
|
|
|
|
|
|
|
/* And remove it */
|
|
|
|
if (prev == NULL)
|
1999-03-27 17:56:13 +01:00
|
|
|
This->viewport_list = cur->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
else
|
|
|
|
prev->next = cur->next;
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DVIEWPORT lpvp,
|
|
|
|
LPDIRECT3DVIEWPORT* lplpvp,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
|
|
|
IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
|
|
|
|
IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
switch (dwFlags) {
|
|
|
|
case D3DNEXT_NEXT:
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = ilpvp->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DNEXT_HEAD:
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = This->viewport_list;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3DNEXT_TAIL:
|
1999-03-27 17:56:13 +01:00
|
|
|
ilpvp = This->viewport_list;
|
|
|
|
while (ilpvp->next != NULL)
|
|
|
|
ilpvp = ilpvp->next;
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
*ilplpvp = ilpvp;
|
1999-01-03 18:00:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
|
|
|
|
LPDIRECT3DVIEWPORT lpDirect3DViewport,
|
|
|
|
DWORD dwFlags,
|
|
|
|
LPD3DRECT lpRect)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
|
1999-01-03 18:00:19 +01:00
|
|
|
dwFlags, lpRect);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDWORD lpCount,
|
|
|
|
LPD3DPICKRECORD lpD3DPickRec)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
|
|
|
|
LPVOID lpArg)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPD3DMATRIXHANDLE lpD3DMatHandle)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
*lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DMATRIXHANDLE d3dMatHandle,
|
|
|
|
const LPD3DMATRIX lpD3DMatrix)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
dump_mat(lpD3DMatrix);
|
1999-01-23 13:32:46 +01:00
|
|
|
|
1999-01-03 18:00:19 +01:00
|
|
|
*((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DMATRIXHANDLE D3DMatHandle,
|
|
|
|
LPD3DMATRIX lpD3DMatrix)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
*lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
D3DMATRIXHANDLE d3dMatHandle)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
|
|
|
/* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(): stub\n", This);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* We get the pointer to the surface (should be done on flip) */
|
1999-03-27 17:56:13 +01:00
|
|
|
/* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* This is for the moment copy-pasted from IDirect3DDevice2...
|
|
|
|
Will make a common function ... */
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-03-27 17:56:13 +01:00
|
|
|
OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
|
|
|
|
LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
|
1999-01-03 18:00:19 +01:00
|
|
|
DDSURFACEDESC sdesc;
|
|
|
|
int x,y;
|
|
|
|
unsigned char *src;
|
|
|
|
unsigned short *dest;
|
1999-05-13 20:53:05 +02:00
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-06-26 21:09:08 +02:00
|
|
|
FIXME("(%p)->(): stub\n", This);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
1999-05-13 20:53:05 +02:00
|
|
|
#ifdef USE_OSMESA
|
1999-01-03 18:00:19 +01:00
|
|
|
/* Here we copy back the OpenGL scene to the the DDraw surface */
|
|
|
|
/* First, lock the surface */
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
/* The copy the OpenGL buffer to this surface */
|
|
|
|
|
|
|
|
/* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
|
|
|
|
I am currently working on a set of patches for Mesa to have OSMesa support
|
|
|
|
16 bpp surfaces => we will able to render directly onto the surface, no
|
|
|
|
need to do a bpp conversion */
|
|
|
|
dest = (unsigned short *) sdesc.y.lpSurface;
|
|
|
|
src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
|
|
|
|
for (y = 0; y < sdesc.dwHeight; y++) {
|
|
|
|
unsigned char *lsrc = src;
|
|
|
|
|
|
|
|
for (x = 0; x < sdesc.dwWidth ; x++) {
|
|
|
|
unsigned char r = *lsrc++;
|
|
|
|
unsigned char g = *lsrc++;
|
|
|
|
unsigned char b = *lsrc++;
|
|
|
|
lsrc++; /* Alpha */
|
1999-01-23 13:32:46 +01:00
|
|
|
|
1999-01-03 18:00:19 +01:00
|
|
|
*dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
|
|
|
|
|
|
|
dest++;
|
|
|
|
}
|
|
|
|
|
|
|
|
src -= 4 * sdesc.dwWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the surface */
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
|
1999-05-13 20:53:05 +02:00
|
|
|
#else
|
|
|
|
/* No need to do anything here... */
|
|
|
|
#endif
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
|
1999-01-03 18:00:19 +01:00
|
|
|
LPDIRECT3D *lpDirect3D)
|
|
|
|
{
|
1999-03-27 17:56:13 +01:00
|
|
|
ICOM_THIS(IDirect3DDeviceImpl,iface);
|
1999-06-26 21:09:08 +02:00
|
|
|
TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
|
1999-01-03 18:00:19 +01:00
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Direct3DDevice VTable
|
|
|
|
*/
|
1999-05-22 13:41:38 +02:00
|
|
|
static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
|
|
|
|
{
|
|
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
1999-03-27 17:56:13 +01:00
|
|
|
IDirect3DDeviceImpl_QueryInterface,
|
|
|
|
IDirect3DDeviceImpl_AddRef,
|
|
|
|
IDirect3DDeviceImpl_Release,
|
|
|
|
IDirect3DDeviceImpl_Initialize,
|
|
|
|
IDirect3DDeviceImpl_GetCaps,
|
|
|
|
IDirect3DDeviceImpl_SwapTextureHandles,
|
|
|
|
IDirect3DDeviceImpl_CreateExecuteBuffer,
|
|
|
|
IDirect3DDeviceImpl_GetStats,
|
|
|
|
IDirect3DDeviceImpl_Execute,
|
|
|
|
IDirect3DDeviceImpl_AddViewport,
|
|
|
|
IDirect3DDeviceImpl_DeleteViewport,
|
|
|
|
IDirect3DDeviceImpl_NextViewport,
|
|
|
|
IDirect3DDeviceImpl_Pick,
|
|
|
|
IDirect3DDeviceImpl_GetPickRecords,
|
|
|
|
IDirect3DDeviceImpl_EnumTextureFormats,
|
|
|
|
IDirect3DDeviceImpl_CreateMatrix,
|
|
|
|
IDirect3DDeviceImpl_SetMatrix,
|
|
|
|
IDirect3DDeviceImpl_GetMatrix,
|
|
|
|
IDirect3DDeviceImpl_DeleteMatrix,
|
|
|
|
IDirect3DDeviceImpl_BeginScene,
|
|
|
|
IDirect3DDeviceImpl_EndScene,
|
|
|
|
IDirect3DDeviceImpl_GetDirect3D,
|
1999-01-03 18:00:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#else /* HAVE_MESAGL */
|
|
|
|
|
|
|
|
int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-03-27 17:56:13 +01:00
|
|
|
int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
|
1999-01-03 18:00:19 +01:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* HAVE_MESAGL */
|