|  | /* Direct3D Device | 
|  | * Copyright (c) 1998 Lionel ULMER | 
|  | * | 
|  | * This file contains the MESA implementation of all the D3D devices that | 
|  | * Wine supports. | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winerror.h" | 
|  | #include "wine/obj_base.h" | 
|  | #include "ddraw.h" | 
|  | #include "d3d.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | #include "mesa_private.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(ddraw); | 
|  |  | 
|  | ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable; | 
|  | ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3; | 
|  |  | 
|  | /* Define this variable if you have an unpatched Mesa 3.0 (patches are available | 
|  | on Mesa's home page) or version 3.1b. | 
|  |  | 
|  | Version 3.1b2 should correct this bug */ | 
|  | #undef HAVE_BUGGY_MESAGL | 
|  |  | 
|  | #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private) | 
|  |  | 
|  | #ifndef HAVE_GLEXT_PROTOTYPES | 
|  | /* This is for non-OpenGL ABI compliant glext.h headers :-) */ | 
|  | typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, | 
|  | GLsizei width, GLenum format, GLenum type, | 
|  | const GLvoid *table); | 
|  | #endif | 
|  |  | 
|  | static 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 | 
|  | }; | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				OpenGL static functions | 
|  | */ | 
|  | static void set_context(IDirect3DDevice2Impl* This) { | 
|  | #if COMPILABLE | 
|  | D3DDPRIVATE(This); | 
|  |  | 
|  | if (glXMakeCurrent(gdi_display,ddpriv->drawable, odev->ctx) == False) { | 
|  | ERR("Error in setting current context (context %p drawable %ld)!\n", | 
|  | odev->ctx, ddpriv->drawable); | 
|  | } | 
|  | #endif | 
|  | } | 
|  |  | 
|  | 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) | 
|  | { | 
|  | /* GLint maxlight; */ | 
|  |  | 
|  | d1->dwSize  = sizeof(*d1); | 
|  | d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH | 
|  | | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS; | 
|  | 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; | 
|  | d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */ | 
|  | fill_opengl_primcaps(&(d1->dpcLineCaps)); | 
|  | fill_opengl_primcaps(&(d1->dpcTriCaps)); | 
|  | d1->dwDeviceRenderBitDepth  = DDBD_16; | 
|  | d1->dwDeviceZBufferBitDepth = DDBD_16; | 
|  | d1->dwMaxBufferSize = 0; | 
|  | d1->dwMaxVertexCount = 65536; | 
|  | 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; | 
|  | } | 
|  |  | 
|  | static void fill_device_capabilities(IDirectDrawImpl* ddraw) { | 
|  | #if COMPILABLE | 
|  | x11_dd_private *private = (x11_dd_private *) ddraw->d->private; | 
|  | const char *ext_string; | 
|  | Mesa_DeviceCapabilities *devcap; | 
|  |  | 
|  | private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities)); | 
|  | devcap = (Mesa_DeviceCapabilities *) private->device_capabilities; | 
|  |  | 
|  | ENTER_GL(); | 
|  | ext_string = glGetString(GL_EXTENSIONS); | 
|  | /* Query for the ColorTable Extension */ | 
|  | if (strstr(ext_string, "GL_EXT_paletted_texture")) { | 
|  | devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT"); | 
|  | TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT); | 
|  | } else { | 
|  | TRACE("Color table extension not found.\n"); | 
|  | } | 
|  | LEAVE_GL(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) { | 
|  | D3DDEVICEDESC	d1,d2; | 
|  | TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL)); | 
|  | fill_opengl_caps(&d1, &d2); | 
|  | return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context); | 
|  | } | 
|  |  | 
|  | int | 
|  | is_OpenGL( | 
|  | REFCLSID rguid, IDirectDrawSurfaceImpl* surface, | 
|  | IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d | 
|  | ) { | 
|  | mesa_d3dd_private *odev = NULL; | 
|  |  | 
|  | 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)))) { | 
|  |  | 
|  | *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl)); | 
|  | (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private)); | 
|  | odev = (mesa_d3dd_private*)(*device)->private; | 
|  | (*device)->ref = 1; | 
|  | ICOM_VTBL(*device) = &OpenGL_vtable; | 
|  | (*device)->d3d = d3d; | 
|  | (*device)->surface = surface; | 
|  | (*device)->viewport_list = NULL; | 
|  | (*device)->current_viewport = NULL; | 
|  | (*device)->set_context = set_context; | 
|  |  | 
|  | TRACE("Creating OpenGL device for surface %p\n", surface); | 
|  | /* Create the OpenGL context */ | 
|  | #if COMPILABLE | 
|  | /* First get the correct visual */ | 
|  | ENTER_GL(); | 
|  | /* Create the context */ | 
|  | { | 
|  | XVisualInfo *vis; | 
|  | int num; | 
|  | XVisualInfo template; | 
|  |  | 
|  | template.visualid = XVisualIDFromVisual(visual); | 
|  | vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num); | 
|  |  | 
|  | odev->ctx = glXCreateContext(gdi_display, vis, | 
|  | NULL, GL_TRUE); | 
|  | } | 
|  |  | 
|  | if (odev->ctx == NULL) | 
|  | ERR("Error in context creation !\n"); | 
|  | else | 
|  | TRACE("Context created (%p)\n", odev->ctx); | 
|  |  | 
|  | /* Now override the surface's Flip method (if in double buffering) */ | 
|  | ((x11_ds_private *) surface->private)->opengl_flip = TRUE; | 
|  | { | 
|  | 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) | 
|  | ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | odev->rs.src = GL_ONE; | 
|  | odev->rs.dst = GL_ZERO; | 
|  | odev->rs.mag = GL_NEAREST; | 
|  | odev->rs.min = GL_NEAREST; | 
|  | odev->vt     = 0; | 
|  |  | 
|  | /* Allocate memory for the matrices */ | 
|  | odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float)); | 
|  | odev->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float)); | 
|  | odev->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float)); | 
|  |  | 
|  | 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 */ | 
|  | TRACE("Setting current context\n"); | 
|  | (*device)->set_context(*device); | 
|  | TRACE("Current context set\n"); | 
|  | glClearColor(0.0, 0.0, 0.0, 0.0); | 
|  | glColor3f(1.0, 1.0, 1.0); | 
|  | LEAVE_GL(); | 
|  |  | 
|  | fill_device_capabilities(d3d->ddraw); | 
|  |  | 
|  | TRACE("OpenGL device created \n"); | 
|  | return 1; | 
|  | } | 
|  | FIXME("bad IID %s\n",debugstr_guid(rguid)); | 
|  | /* This is not the OpenGL UID */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				MESA IDirect3DDevice2 | 
|  | */ | 
|  | static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface) | 
|  | { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | FIXME("(%p)->() decrementing from %lu.\n", This, This->ref ); | 
|  |  | 
|  | if (!--(This->ref)) { | 
|  | #if 0  /* broken for now */ | 
|  | D3DDPRIVATE(This); | 
|  | ENTER_GL(); | 
|  | glXDestroyContext(gdi_display, odev->ctx); | 
|  | LEAVE_GL(); | 
|  | #endif | 
|  | This->private = NULL; | 
|  | HeapFree(GetProcessHeap(),0,This); | 
|  | return 0; | 
|  | } | 
|  | return This->ref; | 
|  | } | 
|  |  | 
|  | /*** IDirect3DDevice2 methods ***/ | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps( | 
|  | LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft, | 
|  | LPD3DDEVICEDESC lpdeschard | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard); | 
|  | fill_opengl_caps(lpdescsoft, lpdeschard); | 
|  | 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; | 
|  |  | 
|  | TRACE("Enumerating GL_RGBA unpacked (32)\n"); | 
|  | pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; | 
|  | pformat->u1.dwRGBBitCount = 32; | 
|  | pformat->u2.dwRBitMask =         0xFF000000; | 
|  | pformat->u3.dwGBitMask =         0x00FF0000; | 
|  | pformat->u4.dwBBitMask =        0x0000FF00; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x000000FF; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("Enumerating GL_RGB unpacked (24)\n"); | 
|  | pformat->dwFlags = DDPF_RGB; | 
|  | pformat->u1.dwRGBBitCount = 24; | 
|  | pformat->u2.dwRBitMask =  0x00FF0000; | 
|  | pformat->u3.dwGBitMask =  0x0000FF00; | 
|  | pformat->u4.dwBBitMask = 0x000000FF; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x00000000; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | #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. */ | 
|  | TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n"); | 
|  | pformat->dwFlags = DDPF_RGB; | 
|  | pformat->u1.dwRGBBitCount = 16; | 
|  | pformat->u2.dwRBitMask =  0x0000F800; | 
|  | pformat->u3.dwGBitMask =  0x000007E0; | 
|  | pformat->u4.dwBBitMask = 0x0000001F; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x00000000; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n"); | 
|  | pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; | 
|  | pformat->u1.dwRGBBitCount = 16; | 
|  | pformat->u2.dwRBitMask =         0x0000F800; | 
|  | pformat->u3.dwGBitMask =         0x000007C0; | 
|  | pformat->u4.dwBBitMask =        0x0000003E; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x00000001; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n"); | 
|  | pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; | 
|  | pformat->u1.dwRGBBitCount = 16; | 
|  | pformat->u2.dwRBitMask =         0x0000F000; | 
|  | pformat->u3.dwGBitMask =         0x00000F00; | 
|  | pformat->u4.dwBBitMask =        0x000000F0; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x0000000F; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n"); | 
|  | pformat->dwFlags = DDPF_RGB; | 
|  | pformat->u1.dwRGBBitCount = 8; | 
|  | pformat->u2.dwRBitMask =         0x0000F800; | 
|  | pformat->u3.dwGBitMask =         0x000007C0; | 
|  | pformat->u4.dwBBitMask =        0x0000003E; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x00000001; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  | #endif | 
|  |  | 
|  | TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n"); | 
|  | pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; | 
|  | pformat->u1.dwRGBBitCount = 16; | 
|  | pformat->u2.dwRBitMask =         0x00007C00; | 
|  | pformat->u3.dwGBitMask =         0x000003E0; | 
|  | pformat->u4.dwBBitMask =         0x0000001F; | 
|  | pformat->u5.dwRGBAlphaBitMask =  0x00008000; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("Enumerating Paletted (8)\n"); | 
|  | pformat->dwFlags = DDPF_PALETTEINDEXED8; | 
|  | pformat->u1.dwRGBBitCount = 8; | 
|  | pformat->u2.dwRBitMask =  0x00000000; | 
|  | pformat->u3.dwGBitMask =  0x00000000; | 
|  | pformat->u4.dwBBitMask = 0x00000000; | 
|  | pformat->u5.dwRGBAlphaBitMask = 0x00000000; | 
|  | if (cb(&sdesc, context) == 0) | 
|  | return DD_OK; | 
|  |  | 
|  | TRACE("End of enumeration\n"); | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats( | 
|  | LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | FIXME("(%p)->(%p,%p): stub\n", This, cb, context); | 
|  |  | 
|  | return enum_texture_format_OpenGL(cb, context); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene( | 
|  | LPDIRECT3DDEVICE2 iface | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  |  | 
|  | FIXME("(%p)->(): stub\n", This); | 
|  |  | 
|  | /* Here, we should get the DDraw surface and 'copy it' to the | 
|  | OpenGL surface.... */ | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  |  | 
|  | FIXME("(%p)->(): stub\n", This); | 
|  |  | 
|  | /* No need to do anything here... */ | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState( | 
|  | LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType, | 
|  | DWORD dwRenderState | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | D3DDPRIVATE(This); | 
|  |  | 
|  | TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState); | 
|  |  | 
|  | /* Call the render state functions */ | 
|  | set_render_state(dwRenderStateType, dwRenderState, &(odev->rs)); | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState( | 
|  | LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType, | 
|  | DWORD dwLightState | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState); | 
|  |  | 
|  | switch (dwLightStateType) { | 
|  | case D3DLIGHTSTATE_MATERIAL: {  /* 1 */ | 
|  | IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState; | 
|  |  | 
|  | if (mat != NULL) { | 
|  | ENTER_GL(); | 
|  | mat->activate(mat); | 
|  | LEAVE_GL(); | 
|  | } else { | 
|  | TRACE("Zoups !!!\n"); | 
|  | } | 
|  | } 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; | 
|  | ENTER_GL(); | 
|  | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light); | 
|  | LEAVE_GL(); | 
|  | } break; | 
|  |  | 
|  | #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break; | 
|  | UNSUP(COLORMODEL); | 
|  | UNSUP(FOGMODE); | 
|  | UNSUP(FOGSTART); | 
|  | UNSUP(FOGEND); | 
|  | UNSUP(FOGDENSITY); | 
|  | #undef UNSUP | 
|  | default: | 
|  | TRACE("Unexpected Light State Type\n"); | 
|  | return DDERR_INVALIDPARAMS; | 
|  | } | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform( | 
|  | LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts, | 
|  | LPD3DMATRIX lpmatrix | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | D3DDPRIVATE(This); | 
|  |  | 
|  | FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix); | 
|  |  | 
|  | ENTER_GL(); | 
|  |  | 
|  | /* 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; | 
|  | } | 
|  | LEAVE_GL(); | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | #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:							\ | 
|  | TRACE("Standard Vertex\n");					\ | 
|  | glEnable(GL_LIGHTING);						\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DVT_LVERTEX:							\ | 
|  | TRACE("Lighted Vertex\n");					\ | 
|  | glDisable(GL_LIGHTING);						\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DVT_TLVERTEX: {						\ | 
|  | GLdouble height, width, minZ, maxZ;				\ | 
|  | \ | 
|  | TRACE("Transformed - Lighted Vertex\n");				\ | 
|  | /* First, disable lighting */					\ | 
|  | glDisable(GL_LIGHTING);						\ | 
|  | \ | 
|  | /* Then do not put any transformation matrixes */			\ | 
|  | glMatrixMode(GL_MODELVIEW);					\ | 
|  | glLoadIdentity();							\ | 
|  | glMatrixMode(GL_PROJECTION);					\ | 
|  | glLoadIdentity();							\ | 
|  | \ | 
|  | if (This->current_viewport == NULL) {				\ | 
|  | ERR("No current viewport !\n");					\ | 
|  | /* Using standard values */					\ | 
|  | height = 640.0;							\ | 
|  | width = 480.0;							\ | 
|  | minZ = -10.0;							\ | 
|  | maxZ = 10.0;							\ | 
|  | } else {								\ | 
|  | 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;\ | 
|  | } else {							\ | 
|  | 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;\ | 
|  | }								\ | 
|  | }									\ | 
|  | \ | 
|  | glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);			\ | 
|  | } break;								\ | 
|  | \ | 
|  | default:								\ | 
|  | ERR("Unhandled vertex type\n");					\ | 
|  | break;								\ | 
|  | }									\ | 
|  | \ | 
|  | odev->vt = d3dv;							\ | 
|  | }									\ | 
|  | \ | 
|  | switch (d3dp) {							\ | 
|  | case D3DPT_POINTLIST:							\ | 
|  | TRACE("Start POINTS\n");						\ | 
|  | glBegin(GL_POINTS);							\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DPT_LINELIST:							\ | 
|  | TRACE("Start LINES\n");						\ | 
|  | glBegin(GL_LINES);							\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DPT_LINESTRIP:							\ | 
|  | TRACE("Start LINE_STRIP\n");					\ | 
|  | glBegin(GL_LINE_STRIP);						\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DPT_TRIANGLELIST:						\ | 
|  | TRACE("Start TRIANGLES\n");						\ | 
|  | glBegin(GL_TRIANGLES);						\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DPT_TRIANGLESTRIP:						\ | 
|  | TRACE("Start TRIANGLE_STRIP\n");					\ | 
|  | glBegin(GL_TRIANGLE_STRIP);						\ | 
|  | break;								\ | 
|  | \ | 
|  | case D3DPT_TRIANGLEFAN:						\ | 
|  | TRACE("Start TRIANGLE_FAN\n");					\ | 
|  | glBegin(GL_TRIANGLE_FAN);						\ | 
|  | break;								\ | 
|  | \ | 
|  | default:								\ | 
|  | TRACE("Unhandled primitive\n");					\ | 
|  | 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->u4.nx, vx->u5.ny, vx->u6.nz);			\ | 
|  | glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);				\ | 
|  | TRACE("   V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);		\ | 
|  | } break;								\ | 
|  | \ | 
|  | case D3DVT_LVERTEX: {						\ | 
|  | D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX;		\ | 
|  | DWORD col = vx->u4.color;						\ | 
|  | \ | 
|  | glColor3f(((col >> 16) & 0xFF) / 255.0,				\ | 
|  | ((col >>  8) & 0xFF) / 255.0,				\ | 
|  | ((col >>  0) & 0xFF) / 255.0);				\ | 
|  | glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);				\ | 
|  | TRACE("  LV: %f %f %f (%02lx %02lx %02lx)\n",			\ | 
|  | vx->u1.x, vx->u2.y, vx->u3.z,				\ | 
|  | ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF));\ | 
|  | } break;								\ | 
|  | \ | 
|  | case D3DVT_TLVERTEX: {						\ | 
|  | D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX;		\ | 
|  | DWORD col = vx->u5.color;						\ | 
|  | \ | 
|  | glColor3f(((col >> 16) & 0xFF) / 255.0,				\ | 
|  | ((col >>  8) & 0xFF) / 255.0,				\ | 
|  | ((col >>  0) & 0xFF) / 255.0);				\ | 
|  | glTexCoord2f(vx->u7.tu, vx->u8.tv);				\ | 
|  | if (vx->u4.rhw < 0.01)						\ | 
|  | glVertex3f(vx->u1.sx,						\ | 
|  | vx->u2.sy,						\ | 
|  | vx->u3.sz);						\ | 
|  | else								\ | 
|  | glVertex4f(vx->u1.sx / vx->u4.rhw,				\ | 
|  | vx->u2.sy / vx->u4.rhw,				\ | 
|  | vx->u3.sz / vx->u4.rhw,				\ | 
|  | 1.0 / vx->u4.rhw);					\ | 
|  | TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",	\ | 
|  | vx->u1.sx, vx->u2.sy, vx->u3.sz,				\ | 
|  | ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),\ | 
|  | vx->u7.tu, vx->u8.tv, vx->u4.rhw);				\ | 
|  | } break;								\ | 
|  | \ | 
|  | default:								\ | 
|  | FIXME("Unhandled vertex type\n");					\ | 
|  | break;								\ | 
|  | }									\ | 
|  | }									\ | 
|  | \ | 
|  | glEnd();								\ | 
|  | TRACE("End\n"); | 
|  |  | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive( | 
|  | LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv, | 
|  | LPVOID lpvertex, DWORD vertcount, DWORD dwFlags | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | D3DDPRIVATE(This); | 
|  | int vx_index; | 
|  |  | 
|  | TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags); | 
|  |  | 
|  | ENTER_GL(); | 
|  | DRAW_PRIMITIVE(vertcount, vx_index); | 
|  | LEAVE_GL(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive( | 
|  | LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv, | 
|  | LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount, | 
|  | DWORD dwFlags | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDevice2Impl,iface); | 
|  | D3DDPRIVATE(This); | 
|  | int vx_index; | 
|  |  | 
|  | TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags); | 
|  |  | 
|  | ENTER_GL(); | 
|  | DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]); | 
|  | LEAVE_GL(); | 
|  |  | 
|  | return D3D_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer( | 
|  | LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc, | 
|  | LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter | 
|  | ) { | 
|  | ICOM_THIS(IDirect3DDeviceImpl,iface); | 
|  | TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter); | 
|  | *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc); | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				OpenGL-specific IDirect3DDevice2 | 
|  | */ | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				OpenGL-specific VTable | 
|  | */ | 
|  |  | 
|  | ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable = | 
|  | { | 
|  | ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE | 
|  | IDirect3DDevice2Impl_QueryInterface, | 
|  | IDirect3DDevice2Impl_AddRef, | 
|  | MESA_IDirect3DDevice2Impl_Release, | 
|  | /*** IDirect3DDevice2 methods ***/ | 
|  | MESA_IDirect3DDevice2Impl_GetCaps, | 
|  | IDirect3DDevice2Impl_SwapTextureHandles, | 
|  | IDirect3DDevice2Impl_GetStats, | 
|  | IDirect3DDevice2Impl_AddViewport, | 
|  | IDirect3DDevice2Impl_DeleteViewport, | 
|  | IDirect3DDevice2Impl_NextViewport, | 
|  | MESA_IDirect3DDevice2Impl_EnumTextureFormats, | 
|  | MESA_IDirect3DDevice2Impl_BeginScene, | 
|  | MESA_IDirect3DDevice2Impl_EndScene, | 
|  | IDirect3DDevice2Impl_GetDirect3D, | 
|  |  | 
|  | /*** DrawPrimitive API ***/ | 
|  | IDirect3DDevice2Impl_SetCurrentViewport, | 
|  | IDirect3DDevice2Impl_GetCurrentViewport, | 
|  |  | 
|  | IDirect3DDevice2Impl_SetRenderTarget, | 
|  | IDirect3DDevice2Impl_GetRenderTarget, | 
|  |  | 
|  | IDirect3DDevice2Impl_Begin, | 
|  | IDirect3DDevice2Impl_BeginIndexed, | 
|  | IDirect3DDevice2Impl_Vertex, | 
|  | IDirect3DDevice2Impl_Index, | 
|  | IDirect3DDevice2Impl_End, | 
|  |  | 
|  | IDirect3DDevice2Impl_GetRenderState, | 
|  | MESA_IDirect3DDevice2Impl_SetRenderState, | 
|  | IDirect3DDevice2Impl_GetLightState, | 
|  | MESA_IDirect3DDevice2Impl_SetLightState, | 
|  | MESA_IDirect3DDevice2Impl_SetTransform, | 
|  | IDirect3DDevice2Impl_GetTransform, | 
|  | IDirect3DDevice2Impl_MultiplyTransform, | 
|  |  | 
|  | MESA_IDirect3DDevice2Impl_DrawPrimitive, | 
|  | MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive, | 
|  |  | 
|  | IDirect3DDevice2Impl_SetClipStatus, | 
|  | IDirect3DDevice2Impl_GetClipStatus, | 
|  | }; | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				Direct3DDevice | 
|  | */ | 
|  | int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) { | 
|  | D3DDEVICEDESC	d1,d2; | 
|  |  | 
|  | TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL)); | 
|  |  | 
|  | fill_opengl_caps(&d1, &d2); | 
|  |  | 
|  | return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context); | 
|  | } | 
|  |  | 
|  | int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device) | 
|  | { | 
|  | if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) { | 
|  | mesa_d3dd_private *odev; | 
|  | #if 0 /* See below */ | 
|  | int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None }; | 
|  | XVisualInfo *xvis; | 
|  | #endif | 
|  |  | 
|  | *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl)); | 
|  | (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private)); | 
|  | odev = (mesa_d3dd_private*)(*device)->private; | 
|  | (*device)->ref = 1; | 
|  | ICOM_VTBL(*device) = &OpenGL_vtable_dx3; | 
|  | (*device)->d3d = NULL; | 
|  | (*device)->surface = surface; | 
|  |  | 
|  | (*device)->viewport_list = NULL; | 
|  | (*device)->current_viewport = NULL; | 
|  |  | 
|  | (*device)->set_context = (void*)set_context; | 
|  |  | 
|  | TRACE("OpenGL device created \n"); | 
|  |  | 
|  | /* Create the OpenGL context */ | 
|  | /* First get the correct visual */ | 
|  | /* if (surface->s.backbuffer == NULL) | 
|  | attributeList[3] = None; */ | 
|  | #if 0 /* non working currently */ | 
|  | ENTER_GL(); | 
|  | xvis = glXChooseVisual(gdi_display, | 
|  | DefaultScreen(gdi_display), | 
|  | attributeList); | 
|  | if (xvis == NULL) | 
|  | ERR("No visual found !\n"); | 
|  | else | 
|  | TRACE("Visual found\n"); | 
|  | /* Create the context */ | 
|  | odev->ctx = glXCreateContext(gdi_display, | 
|  | xvis, | 
|  | NULL, | 
|  | GL_TRUE); | 
|  | TRACE("Context created\n"); | 
|  |  | 
|  | /* Now override the surface's Flip method (if in double buffering) */ | 
|  | surface->s.d3d_device = (void *) odev; | 
|  | { | 
|  | 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; | 
|  | } | 
|  | #endif | 
|  | odev->rs.src = GL_ONE; | 
|  | odev->rs.dst = GL_ZERO; | 
|  | odev->rs.mag = GL_NEAREST; | 
|  | odev->rs.min = GL_NEAREST; | 
|  |  | 
|  | 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); | 
|  |  | 
|  | fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner); | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* This is not the OpenGL UID */ | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface) | 
|  | { | 
|  | ICOM_THIS(IDirect3DDeviceImpl,iface); | 
|  | FIXME("(%p)->() decrementing from %lu.\n", This, This->ref ); | 
|  |  | 
|  | if (!--(This->ref)) { | 
|  | #if 0  /* broken for now */ | 
|  | D3DDPRIVATE(This); | 
|  | ENTER_GL(); | 
|  | glXDestroyContext(gdi_display, odev->ctx); | 
|  | LEAVE_GL(); | 
|  | #endif | 
|  | This->private = NULL; | 
|  | HeapFree(GetProcessHeap(),0,This); | 
|  | return 0; | 
|  | } | 
|  | return This->ref; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats( | 
|  | LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc, | 
|  | LPVOID lpArg) | 
|  | { | 
|  | ICOM_THIS(IDirect3DDeviceImpl,iface); | 
|  | TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg); | 
|  |  | 
|  | return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg); | 
|  | } | 
|  |  | 
|  |  | 
|  | static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface) | 
|  | { | 
|  | ICOM_THIS(IDirect3DDeviceImpl,iface); | 
|  | /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */ | 
|  |  | 
|  | FIXME("(%p)->(): stub\n", This); | 
|  |  | 
|  | /* We get the pointer to the surface (should be done on flip) */ | 
|  | /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */ | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This is for the moment copy-pasted from IDirect3DDevice2... | 
|  | Will make a common function ... */ | 
|  | static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface) | 
|  | { | 
|  | ICOM_THIS(IDirect3DDeviceImpl,iface); | 
|  |  | 
|  | FIXME("(%p)->(): stub\n", This); | 
|  |  | 
|  | /* No need to do anything here... */ | 
|  |  | 
|  | return DD_OK; | 
|  | } | 
|  |  | 
|  | /******************************************************************************* | 
|  | *				Direct3DDevice VTable | 
|  | */ | 
|  | ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = | 
|  | { | 
|  | ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE | 
|  | IDirect3DDeviceImpl_QueryInterface, | 
|  | IDirect3DDeviceImpl_AddRef, | 
|  | MESA_IDirect3DDeviceImpl_Release, | 
|  | IDirect3DDeviceImpl_Initialize, | 
|  | IDirect3DDeviceImpl_GetCaps, | 
|  | IDirect3DDeviceImpl_SwapTextureHandles, | 
|  | MESA_IDirect3DDeviceImpl_CreateExecuteBuffer, | 
|  | IDirect3DDeviceImpl_GetStats, | 
|  | IDirect3DDeviceImpl_Execute, | 
|  | IDirect3DDeviceImpl_AddViewport, | 
|  | IDirect3DDeviceImpl_DeleteViewport, | 
|  | IDirect3DDeviceImpl_NextViewport, | 
|  | IDirect3DDeviceImpl_Pick, | 
|  | IDirect3DDeviceImpl_GetPickRecords, | 
|  | MESA_IDirect3DDeviceImpl_EnumTextureFormats, | 
|  | IDirect3DDeviceImpl_CreateMatrix, | 
|  | IDirect3DDeviceImpl_SetMatrix, | 
|  | IDirect3DDeviceImpl_GetMatrix, | 
|  | IDirect3DDeviceImpl_DeleteMatrix, | 
|  | MESA_IDirect3DDeviceImpl_BeginScene, | 
|  | MESA_IDirect3DDeviceImpl_EndScene, | 
|  | IDirect3DDeviceImpl_GetDirect3D, | 
|  | }; |