wine/dlls/d3d8/directx.c
Jason Edmeades ae5a436873 - Make d3d8 know about the wined3d device and start using it.
- Move some of the screen mode related functions into wined3d and add
  untested support for the new d3d9 options of providing the format to
  some of the calls.
- Move other functions from the directx interface into the common
  library and implement the calls from d3d9 as well.
- Copy across the first of the functions used to make traces more readable,
  creating utils.c to store them in. Eventually the ones in d3d8 will be
  removed but for now just duplicate the code.
2004-09-28 02:12:12 +00:00

1368 lines
51 KiB
C

/*
* IDirect3D8 implementation
*
* Copyright 2002-2004 Jason Edmeades
* Copyright 2003-2004 Raphael Junqueira
* Copyright 2004 Christian Costa
*
* 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 <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "d3d8_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
/* x11drv GDI escapes */
#define X11DRV_ESCAPE 6789
enum x11drv_escape_codes
{
X11DRV_GET_DISPLAY, /* get X11 display for a DC */
X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
X11DRV_GET_FONT, /* get current X font for a DC */
};
#define NUM_FORMATS 7
static const D3DFORMAT device_formats[NUM_FORMATS] = {
D3DFMT_P8,
D3DFMT_R3G3B2,
D3DFMT_R5G6B5,
D3DFMT_X1R5G5B5,
D3DFMT_X4R4G4B4,
D3DFMT_R8G8B8,
D3DFMT_X8R8G8B8
};
static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display);
/* retrieve the X display to use on a given DC */
inline static Display *get_display( HDC hdc )
{
Display *display;
enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
sizeof(display), (LPSTR)&display )) display = NULL;
return display;
}
/**
* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
* ie there is no GL Context - Get a default rendering context to enable the
* function query some info from GL
*/
static
WineD3D_Context* WineD3DCreateFakeGLContext(void) {
static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
WineD3D_Context* ret = NULL;
if (glXGetCurrentContext() == NULL) {
BOOL gotContext = FALSE;
BOOL created = FALSE;
XVisualInfo template;
HDC device_context;
Visual* visual;
BOOL failed = FALSE;
int num;
XWindowAttributes win_attr;
TRACE_(d3d_caps)("Creating Fake GL Context\n");
ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
/* Get the display */
device_context = GetDC(0);
ctx.display = get_display(device_context);
ReleaseDC(0, device_context);
/* Get the X visual */
ENTER_GL();
if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
visual = win_attr.visual;
} else {
visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
}
template.visualid = XVisualIDFromVisual(visual);
ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
if (ctx.visInfo == NULL) {
LEAVE_GL();
WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
failed = TRUE;
}
/* Create a GL context */
if (!failed) {
ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
if (ctx.glCtx == NULL) {
LEAVE_GL();
WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
failed = TRUE;
}
}
/* Make it the current GL context */
if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
glXDestroyContext(ctx.display, ctx.glCtx);
LEAVE_GL();
WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
failed = TRUE;
}
/* It worked! Wow... */
if (!failed) {
gotContext = TRUE;
created = TRUE;
ret = &ctx;
} else {
ret = NULL;
}
} else {
if (ctx.ref > 0) ret = &ctx;
}
if (NULL != ret) ++ret->ref;
return ret;
}
static
void WineD3DReleaseFakeGLContext(WineD3D_Context* ctx) {
/* If we created a dummy context, throw it away */
if (NULL != ctx) {
--ctx->ref;
if (0 == ctx->ref) {
glXMakeCurrent(ctx->display, None, NULL);
glXDestroyContext(ctx->display, ctx->glCtx);
ctx->display = NULL;
ctx->glCtx = NULL;
LEAVE_GL();
}
}
}
/* IDirect3D IUnknown parts follow: */
HRESULT WINAPI IDirect3D8Impl_QueryInterface(LPDIRECT3D8 iface,REFIID riid,LPVOID *ppobj)
{
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IDirect3D8)) {
IDirect3D8Impl_AddRef(iface);
*ppobj = This;
return D3D_OK;
}
WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
ULONG WINAPI IDirect3D8Impl_AddRef(LPDIRECT3D8 iface) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE("(%p) : AddRef from %ld\n", This, This->ref);
return ++(This->ref);
}
ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
ULONG ref = --This->ref;
TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
if (ref == 0) {
IWineD3D_Release(This->WineD3D);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
/* IDirect3D Interface follow: */
HRESULT WINAPI IDirect3D8Impl_RegisterSoftwareDevice (LPDIRECT3D8 iface, void* pInitializeFunction) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_RegisterSoftwareDevice(This->WineD3D, pInitializeFunction);
}
UINT WINAPI IDirect3D8Impl_GetAdapterCount (LPDIRECT3D8 iface) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_GetAdapterCount(This->WineD3D);
}
HRESULT WINAPI IDirect3D8Impl_GetAdapterIdentifier (LPDIRECT3D8 iface,
UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
if (Adapter == 0) { /* Display */
/* If we don't know the device settings, go query them now */
if (This->isGLInfoValid == FALSE) {
WineD3D_Context* ctx = WineD3DCreateFakeGLContext();
if (NULL != ctx) IDirect3D8Impl_FillGLCaps(iface, ctx->display);
WineD3DReleaseFakeGLContext(ctx);
}
if (This->isGLInfoValid == TRUE) {
TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
strcpy(pIdentifier->Driver, "Display");
strcpy(pIdentifier->Description, "Direct3D HAL");
pIdentifier->DriverVersion.u.HighPart = 0xa;
pIdentifier->DriverVersion.u.LowPart = This->gl_info.gl_driver_version;
pIdentifier->VendorId = This->gl_info.gl_vendor;
pIdentifier->DeviceId = This->gl_info.gl_card;
pIdentifier->SubSysId = 0;
pIdentifier->Revision = 0;
} else {
WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
strcpy(pIdentifier->Driver, "Display");
strcpy(pIdentifier->Description, "Direct3D HAL");
pIdentifier->DriverVersion.u.HighPart = 0xa;
pIdentifier->DriverVersion.u.LowPart = MAKEDWORD_VERSION(53, 96); /* last Linux Nvidia drivers */
pIdentifier->VendorId = VENDOR_NVIDIA;
pIdentifier->DeviceId = CARD_NVIDIA_GEFORCE4_TI4600;
pIdentifier->SubSysId = 0;
pIdentifier->Revision = 0;
}
/*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
if (Flags & D3DENUM_NO_WHQL_LEVEL) {
pIdentifier->WHQLLevel = 0;
} else {
pIdentifier->WHQLLevel = 1;
}
} else {
FIXME_(d3d_caps)("Adapter not primary display\n");
}
return D3D_OK;
}
UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface,UINT Adapter) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_GetAdapterModeCount(This->WineD3D, Adapter, D3DFMT_UNKNOWN);
}
HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface, UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, D3DFMT_UNKNOWN, Mode, pMode);
}
HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface, UINT Adapter, D3DDISPLAYMODE* pMode) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, pMode);
}
HRESULT WINAPI IDirect3D8Impl_CheckDeviceType (LPDIRECT3D8 iface,
UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat,
D3DFORMAT BackBufferFormat, BOOL Windowed) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This,
Adapter,
CheckType, debug_d3ddevicetype(CheckType),
DisplayFormat, debug_d3dformat(DisplayFormat),
BackBufferFormat, debug_d3dformat(BackBufferFormat),
Windowed);
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
/*
switch (DisplayFormat) {
case D3DFMT_A8R8G8B8:
return D3DERR_NOTAVAILABLE;
default:
break;
}
*/
switch (DisplayFormat) {
/*case D3DFMT_R5G6B5:*/
case D3DFMT_R3G3B2:
return D3DERR_NOTAVAILABLE;
default:
break;
}
return D3D_OK;
}
HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 iface,
UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
AdapterFormat, debug_d3dformat(AdapterFormat),
Usage, debug_d3dusage(Usage),
RType, debug_d3dressourcetype(RType),
CheckFormat, debug_d3dformat(CheckFormat));
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
switch (CheckFormat) {
case D3DFMT_DXT1:
case D3DFMT_DXT3:
case D3DFMT_DXT5:
TRACE_(d3d_caps)("[OK]\n");
return D3D_OK;
default:
break; /* Avoid compiler warnings */
}
}
switch (CheckFormat) {
/*****
* check supported using GL_SUPPORT
*/
case D3DFMT_DXT1:
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
/*****
* supported
*/
/*case D3DFMT_R5G6B5: */
/*case D3DFMT_X1R5G5B5:*/
/*case D3DFMT_A1R5G5B5: */
/*case D3DFMT_A4R4G4B4:*/
/*****
* unsupported
*/
/* color buffer */
/*case D3DFMT_X8R8G8B8:*/
case D3DFMT_A8R3G3B2:
/* Paletted */
case D3DFMT_P8:
case D3DFMT_A8P8:
/* Luminance */
case D3DFMT_L8:
case D3DFMT_A8L8:
case D3DFMT_A4L4:
/* Bump */
#if 0
case D3DFMT_V8U8:
case D3DFMT_V16U16:
#endif
case D3DFMT_L6V5U5:
case D3DFMT_X8L8V8U8:
case D3DFMT_Q8W8V8U8:
case D3DFMT_W11V11U10:
/****
* currently hard to support
*/
case D3DFMT_UYVY:
case D3DFMT_YUY2:
/* Since we do not support these formats right now, don't pretend to. */
TRACE_(d3d_caps)("[FAILED]\n");
return D3DERR_NOTAVAILABLE;
default:
break;
}
TRACE_(d3d_caps)("[OK]\n");
return D3D_OK;
}
HRESULT WINAPI IDirect3D8Impl_CheckDeviceMultiSampleType(LPDIRECT3D8 iface,
UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x)\n",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
SurfaceFormat, debug_d3dformat(SurfaceFormat),
Windowed,
MultiSampleType);
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
if (D3DMULTISAMPLE_NONE == MultiSampleType)
return D3D_OK;
return D3DERR_NOTAVAILABLE;
}
HRESULT WINAPI IDirect3D8Impl_CheckDepthStencilMatch(LPDIRECT3D8 iface,
UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
AdapterFormat, debug_d3dformat(AdapterFormat),
RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
#if 0
switch (DepthStencilFormat) {
case D3DFMT_D24X4S4:
case D3DFMT_D24X8:
case D3DFMT_D24S8:
case D3DFMT_D32:
/**
* as i don't know how to really check hard caps of graphics cards
* i prefer to not permit 32bit zbuffers enumeration (as few cards can do it)
*/
return D3DERR_NOTAVAILABLE;
default:
break;
}
#endif
return D3D_OK;
}
HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
BOOL gotContext = FALSE;
GLint gl_tex_size = 0;
WineD3D_Context* fake_ctx = NULL;
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
/* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
ie there is no GL Context - Get a default rendering context to enable the
function query some info from GL */
if (glXGetCurrentContext() == NULL) {
fake_ctx = WineD3DCreateFakeGLContext();
if (NULL != fake_ctx) gotContext = TRUE;
} else {
gotContext = TRUE;
}
if (gotContext == FALSE) {
FIXME_(d3d_caps)("GetDeviceCaps called but no GL Context - Returning dummy values\n");
gl_tex_size=65535;
pCaps->MaxTextureBlendStages = 2;
pCaps->MaxSimultaneousTextures = 2;
pCaps->MaxUserClipPlanes = 8;
pCaps->MaxActiveLights = 8;
pCaps->MaxVertexBlendMatrices = 0;
pCaps->MaxVertexBlendMatrixIndex = 1;
pCaps->MaxAnisotropy = 0;
pCaps->MaxPointSize = 255.0;
} else {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
}
/* If we don't know the device settings, go query them now */
if (This->isGLInfoValid == FALSE) IDirect3D8Impl_FillGLCaps(iface, NULL);
pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
pCaps->AdapterOrdinal = Adapter;
pCaps->Caps = 0;
pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
pCaps->Caps3 = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
pCaps->CursorCaps = 0;
pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX |
D3DDEVCAPS_HWTRANSFORMANDLIGHT |
D3DDEVCAPS_PUREDEVICE;
pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW |
D3DPMISCCAPS_CULLCW |
D3DPMISCCAPS_COLORWRITEENABLE |
D3DPMISCCAPS_CLIPTLVERTS |
D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
D3DPMISCCAPS_MASKZ;
/*NOT: D3DPMISCCAPS_TSSARGTEMP*/
pCaps->RasterCaps = D3DPRASTERCAPS_DITHER |
D3DPRASTERCAPS_PAT |
D3DPRASTERCAPS_WFOG |
D3DPRASTERCAPS_ZFOG |
D3DPRASTERCAPS_FOGVERTEX |
D3DPRASTERCAPS_FOGTABLE |
D3DPRASTERCAPS_FOGRANGE;
if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
pCaps->RasterCaps |= D3DPRASTERCAPS_ANISOTROPY;
}
/* FIXME Add:
D3DPRASTERCAPS_MIPMAPLODBIAS
D3DPRASTERCAPS_ZBIAS
D3DPRASTERCAPS_COLORPERSPECTIVE
D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
D3DPRASTERCAPS_ANTIALIASEDGES
D3DPRASTERCAPS_ZBUFFERLESSHSR
D3DPRASTERCAPS_WBUFFER */
pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
D3DPCMPCAPS_EQUAL |
D3DPCMPCAPS_GREATER |
D3DPCMPCAPS_GREATEREQUAL |
D3DPCMPCAPS_LESS |
D3DPCMPCAPS_LESSEQUAL |
D3DPCMPCAPS_NEVER |
D3DPCMPCAPS_NOTEQUAL;
pCaps->SrcBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
pCaps->DestBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
pCaps->AlphaCmpCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB |
D3DPSHADECAPS_COLORGOURAUDRGB;
pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA |
D3DPTEXTURECAPS_ALPHAPALETTE |
D3DPTEXTURECAPS_POW2 |
D3DPTEXTURECAPS_VOLUMEMAP |
D3DPTEXTURECAPS_MIPMAP |
D3DPTEXTURECAPS_PROJECTED;
if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
pCaps->TextureCaps |= D3DPTEXTURECAPS_CUBEMAP |
D3DPTEXTURECAPS_MIPCUBEMAP |
D3DPTEXTURECAPS_CUBEMAP_POW2;
}
pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR |
D3DPTFILTERCAPS_MAGFPOINT |
D3DPTFILTERCAPS_MINFLINEAR |
D3DPTFILTERCAPS_MINFPOINT |
D3DPTFILTERCAPS_MIPFLINEAR |
D3DPTFILTERCAPS_MIPFPOINT;
pCaps->CubeTextureFilterCaps = 0;
pCaps->VolumeTextureFilterCaps = 0;
pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER |
D3DPTADDRESSCAPS_CLAMP |
D3DPTADDRESSCAPS_WRAP;
if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
}
if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
}
if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
}
pCaps->VolumeTextureAddressCaps = 0;
pCaps->LineCaps = D3DLINECAPS_TEXTURE |
D3DLINECAPS_ZTEST;
/* FIXME: Add
D3DLINECAPS_BLEND
D3DLINECAPS_ALPHACMP
D3DLINECAPS_FOG */
pCaps->MaxTextureWidth = gl_tex_size;
pCaps->MaxTextureHeight = gl_tex_size;
pCaps->MaxVolumeExtent = 0;
pCaps->MaxTextureRepeat = 32768;
pCaps->MaxTextureAspectRatio = 32768;
pCaps->MaxVertexW = 1.0;
pCaps->GuardBandLeft = 0;
pCaps->GuardBandTop = 0;
pCaps->GuardBandRight = 0;
pCaps->GuardBandBottom = 0;
pCaps->ExtentsAdjust = 0;
pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
D3DSTENCILCAPS_INCRSAT |
D3DSTENCILCAPS_INVERT |
D3DSTENCILCAPS_KEEP |
D3DSTENCILCAPS_REPLACE |
D3DSTENCILCAPS_ZERO;
if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
D3DSTENCILCAPS_INCR;
}
pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
D3DTEXOPCAPS_ADDSIGNED |
D3DTEXOPCAPS_ADDSIGNED2X |
D3DTEXOPCAPS_MODULATE |
D3DTEXOPCAPS_MODULATE2X |
D3DTEXOPCAPS_MODULATE4X |
D3DTEXOPCAPS_SELECTARG1 |
D3DTEXOPCAPS_SELECTARG2 |
D3DTEXOPCAPS_DISABLE;
#if defined(GL_VERSION_1_3)
pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 |
D3DTEXOPCAPS_SUBTRACT;
#endif
if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
D3DTEXOPCAPS_BLENDTEXTUREALPHA |
D3DTEXOPCAPS_BLENDFACTORALPHA |
D3DTEXOPCAPS_BLENDCURRENTALPHA |
D3DTEXOPCAPS_LERP;
}
if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
D3DTEXOPCAPS_MULTIPLYADD |
D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
}
#if 0
pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
/* FIXME: Add
D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
D3DTEXOPCAPS_PREMODULATE */
#endif
if (gotContext) {
GLint gl_max;
GLfloat gl_float;
#if defined(GL_VERSION_1_3)
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
#else
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
#endif
TRACE_(d3d_caps)("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
pCaps->MaxTextureBlendStages = min(8, gl_max);
pCaps->MaxSimultaneousTextures = min(8, gl_max);
glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
pCaps->MaxUserClipPlanes = min(MAX_CLIPPLANES, gl_max);
TRACE_(d3d_caps)("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
pCaps->MaxActiveLights = gl_max;
TRACE_(d3d_caps)("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
pCaps->MaxVertexBlendMatrices = gl_max;
pCaps->MaxVertexBlendMatrixIndex = 1;
} else {
pCaps->MaxVertexBlendMatrices = 0;
pCaps->MaxVertexBlendMatrixIndex = 1;
}
if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
checkGLcall("glGetInterv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)");
pCaps->MaxAnisotropy = gl_max;
} else {
pCaps->MaxAnisotropy = 0;
}
glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
pCaps->MaxPointSize = gl_float;
}
pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS |
D3DVTXPCAPS_MATERIALSOURCE7 |
D3DVTXPCAPS_POSITIONALLIGHTS |
D3DVTXPCAPS_LOCALVIEWER |
D3DVTXPCAPS_TEXGEN;
/* FIXME: Add
D3DVTXPCAPS_TWEENING */
pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
pCaps->MaxVertexIndex = 0xFFFFFFFF;
pCaps->MaxStreams = MAX_STREAMS;
pCaps->MaxStreamStride = 1024;
if (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) || (vs_mode == VS_SW) || (DeviceType == D3DDEVTYPE_REF)) {
pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
if (This->gl_info.gl_vendor == VENDOR_MESA ||
This->gl_info.gl_vendor == VENDOR_WINE) {
pCaps->MaxVertexShaderConst = 95;
} else {
pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS;
}
} else {
pCaps->VertexShaderVersion = 0;
pCaps->MaxVertexShaderConst = 0;
}
if ((ps_mode == PS_HW) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && (DeviceType != D3DDEVTYPE_REF)) {
pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
pCaps->MaxPixelShaderValue = 1.0;
} else {
pCaps->PixelShaderVersion = 0;
pCaps->MaxPixelShaderValue = 0.0;
}
/* If we created a dummy context, throw it away */
WineD3DReleaseFakeGLContext(fake_ctx);
return D3D_OK;
}
HMONITOR WINAPI IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT Adapter) {
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
return IWineD3D_GetAdapterMonitor(This->WineD3D, Adapter);
}
static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) {
const char *GL_Extensions = NULL;
const char *GLX_Extensions = NULL;
GLint gl_max;
const char* gl_string = NULL;
const char* gl_string_cursor = NULL;
Bool test = 0;
int major, minor;
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
if (This->gl_info.bIsFilled) return;
This->gl_info.bIsFilled = 1;
TRACE_(d3d_caps)("(%p, %p)\n", This, display);
if (NULL != display) {
test = glXQueryVersion(display, &major, &minor);
This->gl_info.glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
gl_string = glXGetClientString(display, GLX_VENDOR);
} else {
gl_string = glGetString(GL_VENDOR);
}
if (strstr(gl_string, "NVIDIA")) {
This->gl_info.gl_vendor = VENDOR_NVIDIA;
} else if (strstr(gl_string, "ATI")) {
This->gl_info.gl_vendor = VENDOR_ATI;
} else {
This->gl_info.gl_vendor = VENDOR_WINE;
}
TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), This->gl_info.gl_vendor);
gl_string = glGetString(GL_VERSION);
switch (This->gl_info.gl_vendor) {
case VENDOR_NVIDIA:
gl_string_cursor = strstr(gl_string, "NVIDIA");
gl_string_cursor = strstr(gl_string_cursor, " ");
while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
if (*gl_string_cursor) {
char tmp[16];
int cursor = 0;
while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
tmp[cursor++] = *gl_string_cursor;
++gl_string_cursor;
}
tmp[cursor] = 0;
major = atoi(tmp);
if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
++gl_string_cursor;
while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
tmp[cursor++] = *gl_string_cursor;
++gl_string_cursor;
}
tmp[cursor] = 0;
minor = atoi(tmp);
break;
}
case VENDOR_ATI:
major = minor = 0;
gl_string_cursor = strchr(gl_string, '-');
if (gl_string_cursor++) {
int error = 0;
/* Check if version number is of the form x.y.z */
if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
error = 1;
if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
error = 1;
if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
error = 1;
if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
error = 1;
/* Mark version number as malformed */
if (error)
gl_string_cursor = 0;
}
if (!gl_string_cursor)
WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
else {
major = *gl_string_cursor - '0';
minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
}
break;
default:
major = 0;
minor = 9;
}
This->gl_info.gl_driver_version = MAKEDWORD_VERSION(major, minor);
FIXME_(d3d_caps)("found GL_VERSION (%s)->(0x%08lx)\n", debugstr_a(gl_string), This->gl_info.gl_driver_version);
gl_string = glGetString(GL_RENDERER);
strcpy(This->gl_info.gl_renderer, gl_string);
switch (This->gl_info.gl_vendor) {
case VENDOR_NVIDIA:
if (strstr(This->gl_info.gl_renderer, "GeForce4 Ti")) {
This->gl_info.gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
} else if (strstr(This->gl_info.gl_renderer, "GeForceFX")) {
This->gl_info.gl_card = CARD_NVIDIA_GEFORCEFX_5900ULTRA;
} else {
This->gl_info.gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
}
break;
case VENDOR_ATI:
if (strstr(This->gl_info.gl_renderer, "RADEON 9800 PRO")) {
This->gl_info.gl_card = CARD_ATI_RADEON_9800PRO;
} else if (strstr(This->gl_info.gl_renderer, "RADEON 9700 PRO")) {
This->gl_info.gl_card = CARD_ATI_RADEON_9700PRO;
} else {
This->gl_info.gl_card = CARD_ATI_RADEON_8500;
}
break;
default:
This->gl_info.gl_card = CARD_WINE;
break;
}
FIXME_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(This->gl_info.gl_renderer), This->gl_info.gl_card);
/*
* Initialize openGL extension related variables
* with Default values
*/
memset(&This->gl_info.supported, 0, sizeof(This->gl_info.supported));
This->gl_info.max_textures = 1;
This->gl_info.ps_arb_version = PS_VERSION_NOT_SUPPORTED;
This->gl_info.vs_arb_version = VS_VERSION_NOT_SUPPORTED;
This->gl_info.vs_nv_version = VS_VERSION_NOT_SUPPORTED;
This->gl_info.vs_ati_version = VS_VERSION_NOT_SUPPORTED;
#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = NULL;
GL_EXT_FUNCS_GEN;
#undef USE_GL_FUNC
/* Retrieve opengl defaults */
glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
This->gl_info.max_clipplanes = min(MAX_CLIPPLANES, gl_max);
TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
This->gl_info.max_lights = gl_max;
TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
/* Parse the gl supported features, in theory enabling parts of our code appropriately */
GL_Extensions = glGetString(GL_EXTENSIONS);
TRACE_(d3d_caps)("GL_Extensions reported:\n");
if (NULL == GL_Extensions) {
ERR(" GL_Extensions returns NULL\n");
} else {
while (*GL_Extensions != 0x00) {
const char *Start = GL_Extensions;
char ThisExtn[256];
memset(ThisExtn, 0x00, sizeof(ThisExtn));
while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
GL_Extensions++;
}
memcpy(ThisExtn, Start, (GL_Extensions - Start));
TRACE_(d3d_caps)("- %s\n", ThisExtn);
/**
* ARB
*/
if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
This->gl_info.ps_arb_version = PS_VERSION_11;
TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", This->gl_info.ps_arb_version);
This->gl_info.supported[ARB_FRAGMENT_PROGRAM] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
This->gl_info.supported[ARB_MULTISAMPLE] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
This->gl_info.supported[ARB_MULTITEXTURE] = TRUE;
This->gl_info.max_textures = min(8, gl_max);
} else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
This->gl_info.supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
This->gl_info.supported[NV_TEXGEN_REFLECTION] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
This->gl_info.supported[ARB_TEXTURE_COMPRESSION] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
This->gl_info.supported[ARB_TEXTURE_ENV_ADD] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
This->gl_info.supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
This->gl_info.supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
This->gl_info.supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
} else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
This->gl_info.supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
} else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
This->gl_info.vs_arb_version = VS_VERSION_11;
TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", This->gl_info.vs_arb_version);
This->gl_info.supported[ARB_VERTEX_PROGRAM] = TRUE;
/**
* EXT
*/
} else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
This->gl_info.supported[EXT_FOG_COORD] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
This->gl_info.supported[EXT_PALETTED_TEXTURE] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
This->gl_info.supported[EXT_POINT_PARAMETERS] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
This->gl_info.supported[EXT_SECONDARY_COLOR] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
This->gl_info.supported[EXT_STENCIL_WRAP] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
This->gl_info.supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
This->gl_info.supported[EXT_TEXTURE_ENV_ADD] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
This->gl_info.supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
This->gl_info.supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support\n");
This->gl_info.supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
This->gl_info.supported[EXT_TEXTURE_LOD] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
This->gl_info.supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
This->gl_info.supported[EXT_VERTEX_WEIGHTING] = TRUE;
/**
* NVIDIA
*/
} else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
This->gl_info.supported[NV_FOG_DISTANCE] = TRUE;
} else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
This->gl_info.ps_nv_version = PS_VERSION_11;
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", This->gl_info.ps_nv_version);
} else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support\n");
This->gl_info.supported[NV_REGISTER_COMBINERS] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
This->gl_info.supported[NV_REGISTER_COMBINERS2] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
This->gl_info.supported[NV_TEXGEN_REFLECTION] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
This->gl_info.supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
This->gl_info.supported[NV_TEXTURE_SHADER] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
This->gl_info.supported[NV_TEXTURE_SHADER2] = TRUE;
} else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
This->gl_info.supported[NV_TEXTURE_SHADER3] = TRUE;
} else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program1_1")) ? VS_VERSION_11 : VS_VERSION_10);
This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program2")) ? VS_VERSION_20 : VS_VERSION_10);
TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", This->gl_info.vs_nv_version);
This->gl_info.supported[NV_VERTEX_PROGRAM] = TRUE;
/**
* ATI
*/
/** TODO */
} else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
This->gl_info.supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
} else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
This->gl_info.supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
} else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
This->gl_info.vs_ati_version = VS_VERSION_11;
TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", This->gl_info.vs_ati_version);
This->gl_info.supported[EXT_VERTEX_SHADER] = TRUE;
}
if (*GL_Extensions == ' ') GL_Extensions++;
}
}
#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
GL_EXT_FUNCS_GEN;
#undef USE_GL_FUNC
if (display != NULL) {
GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
TRACE_(d3d_caps)("GLX_Extensions reported:\n");
if (NULL == GLX_Extensions) {
ERR(" GLX_Extensions returns NULL\n");
} else {
while (*GLX_Extensions != 0x00) {
const char *Start = GLX_Extensions;
char ThisExtn[256];
memset(ThisExtn, 0x00, sizeof(ThisExtn));
while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
GLX_Extensions++;
}
memcpy(ThisExtn, Start, (GLX_Extensions - Start));
TRACE_(d3d_caps)("- %s\n", ThisExtn);
if (*GLX_Extensions == ' ') GLX_Extensions++;
}
}
}
#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
GLX_EXT_FUNCS_GEN;
#undef USE_GL_FUNC
/* Only save the values obtained when a display is provided */
if (display != NULL) This->isGLInfoValid = TRUE;
}
HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DDevice8** ppReturnedDeviceInterface) {
IDirect3DDevice8Impl *object;
HWND whichHWND;
int num;
XVisualInfo template;
HDC hDc;
IDirect3D8Impl *This = (IDirect3D8Impl *)iface;
TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);
if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
return D3DERR_INVALIDCALL;
}
/* Allocate the storage for the device */
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
if (NULL == object) {
return D3DERR_OUTOFVIDEOMEMORY;
}
object->lpVtbl = &Direct3DDevice8_Vtbl;
object->ref = 1;
object->direct3d8 = This;
/** The device AddRef the direct3d8 Interface else crash in propers clients codes */
IDirect3D8_AddRef((LPDIRECT3D8) object->direct3d8);
/** use StateBlock Factory here, for creating the startup stateBlock */
object->StateBlock = NULL;
IDirect3DDeviceImpl_CreateStateBlock(object, D3DSBT_ALL, NULL);
object->UpdateStateBlock = object->StateBlock;
/* Save the creation parameters */
object->CreateParms.AdapterOrdinal = Adapter;
object->CreateParms.DeviceType = DeviceType;
object->CreateParms.hFocusWindow = hFocusWindow;
object->CreateParms.BehaviorFlags = BehaviourFlags;
*ppReturnedDeviceInterface = (LPDIRECT3DDEVICE8) object;
/* Initialize settings */
object->PresentParms.BackBufferCount = 1; /* Opengl only supports one? */
object->adapterNo = Adapter;
object->devType = DeviceType;
/* Initialize openGl - Note the visual is chosen as the window is created and the glcontext cannot
use different properties after that point in time. FIXME: How to handle when requested format
doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
it chooses is identical to the one already being used! */
/* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
/* Which hwnd are we using? */
whichHWND = pPresentationParameters->hDeviceWindow;
if (!whichHWND) {
whichHWND = hFocusWindow;
}
object->win_handle = whichHWND;
object->win = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
hDc = GetDC(whichHWND);
object->display = get_display(hDc);
TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
ENTER_GL();
/* Create a context based off the properties of the existing visual */
template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
if (NULL == object->visInfo) {
ERR("cannot really get XVisual\n");
LEAVE_GL();
return D3DERR_NOTAVAILABLE;
}
object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
if (NULL == object->glCtx) {
ERR("cannot create glxContext\n");
LEAVE_GL();
return D3DERR_NOTAVAILABLE;
}
LEAVE_GL();
ReleaseDC(whichHWND, hDc);
if (object->glCtx == NULL) {
ERR("Error in context creation !\n");
return D3DERR_INVALIDCALL;
} else {
TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
whichHWND, object->glCtx, object->win, object->visInfo);
}
/* If not windowed, need to go fullscreen, and resize the HWND to the appropriate */
/* dimensions */
if (!pPresentationParameters->Windowed) {
#if 1
DEVMODEW devmode;
HDC hdc;
int bpp = 0;
memset(&devmode, 0, sizeof(DEVMODEW));
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
bpp = GetDeviceCaps(hdc, BITSPIXEL);
DeleteDC(hdc);
devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp;/*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/
devmode.dmPelsWidth = pPresentationParameters->BackBufferWidth;
devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
#else
FIXME("Requested full screen support not implemented, expect windowed operation\n");
#endif
/* Make popup window */
SetWindowLongA(whichHWND, GWL_STYLE, WS_POPUP);
SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
pPresentationParameters->BackBufferWidth,
pPresentationParameters->BackBufferHeight, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
}
TRACE("Creating back buffer\n");
/* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
then the corresponding dimension of the client area of the hDeviceWindow
(or the focus window, if hDeviceWindow is NULL) is taken. */
if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
(pPresentationParameters->BackBufferHeight == 0))) {
RECT Rect;
GetClientRect(whichHWND, &Rect);
if (pPresentationParameters->BackBufferWidth == 0) {
pPresentationParameters->BackBufferWidth = Rect.right;
TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
}
if (pPresentationParameters->BackBufferHeight == 0) {
pPresentationParameters->BackBufferHeight = Rect.bottom;
TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
}
}
/* Save the presentation parms now filled in correctly */
memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
pPresentationParameters->BackBufferWidth,
pPresentationParameters->BackBufferHeight,
pPresentationParameters->BackBufferFormat,
pPresentationParameters->MultiSampleType,
TRUE,
(LPDIRECT3DSURFACE8*) &object->frontBuffer);
IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
pPresentationParameters->BackBufferWidth,
pPresentationParameters->BackBufferHeight,
pPresentationParameters->BackBufferFormat,
pPresentationParameters->MultiSampleType,
TRUE,
(LPDIRECT3DSURFACE8*) &object->backBuffer);
if (pPresentationParameters->EnableAutoDepthStencil) {
IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
pPresentationParameters->BackBufferWidth,
pPresentationParameters->BackBufferHeight,
pPresentationParameters->AutoDepthStencilFormat,
D3DMULTISAMPLE_NONE,
(LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
} else {
object->depthStencilBuffer = NULL;
}
TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer);
/* init the default renderTarget management */
object->drawable = object->win;
object->render_ctx = object->glCtx;
object->renderTarget = object->backBuffer;
IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->renderTarget);
object->stencilBufferTarget = object->depthStencilBuffer;
if (NULL != object->stencilBufferTarget) {
IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget);
}
ENTER_GL();
if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
}
checkGLcall("glXMakeCurrent");
/* Clear the screen */
glClearColor(1.0, 0.0, 0.0, 0.0);
checkGLcall("glClearColor");
glColor3f(1.0, 1.0, 1.0);
checkGLcall("glColor3f");
glEnable(GL_LIGHTING);
checkGLcall("glEnable");
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
/*
* Initialize openGL extension related variables
* with Default values
*/
IDirect3D8Impl_FillGLCaps(iface, object->display);
/* Setup all the devices defaults */
IDirect3DDeviceImpl_InitStartupStateBlock(object);
LEAVE_GL();
{ /* Set a default viewport */
D3DVIEWPORT8 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = pPresentationParameters->BackBufferWidth;
vp.Height = pPresentationParameters->BackBufferHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
}
/* Initialize the current view state */
object->modelview_valid = 1;
object->proj_valid = 0;
object->view_ident = 1;
object->last_was_rhw = 0;
glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
/* Clear the screen */
IDirect3DDevice8Impl_Clear((LPDIRECT3DDEVICE8) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
return D3D_OK;
}
IDirect3D8Vtbl Direct3D8_Vtbl =
{
IDirect3D8Impl_QueryInterface,
IDirect3D8Impl_AddRef,
IDirect3D8Impl_Release,
IDirect3D8Impl_RegisterSoftwareDevice,
IDirect3D8Impl_GetAdapterCount,
IDirect3D8Impl_GetAdapterIdentifier,
IDirect3D8Impl_GetAdapterModeCount,
IDirect3D8Impl_EnumAdapterModes,
IDirect3D8Impl_GetAdapterDisplayMode,
IDirect3D8Impl_CheckDeviceType,
IDirect3D8Impl_CheckDeviceFormat,
IDirect3D8Impl_CheckDeviceMultiSampleType,
IDirect3D8Impl_CheckDepthStencilMatch,
IDirect3D8Impl_GetDeviceCaps,
IDirect3D8Impl_GetAdapterMonitor,
IDirect3D8Impl_CreateDevice
};