directx.c revision b955672b950093ff7416d1269dd4d3b69983bd8f
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * IWineD3D implementation
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * Copyright 2002-2004 Jason Edmeades
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * Copyright 2003-2004 Raphael Junqueira
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * Copyright 2004 Christian Costa
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * Copyright 2005 Oliver Stieber
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * This library is free software; you can redistribute it and/or
8e4512841edf17d9e35762ebbd140a76c01c15c5houz * modify it under the terms of the GNU Lesser General Public
#ifndef DEBUG_SINGLE_MODE
#define DEBUG_SINGLE_MODE 0
#include "config.h"
#include <assert.h>
#include "wined3d_private.h"
static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
const char *extension_string;
} EXTENSION_MAP[] = {
static int numAdapters = 0;
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
static int wined3d_fake_gl_context_ref = 0;
0, 0, &wined3d_fake_gl_context_cs,
static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
static void WineD3D_ReleaseFakeGLContext(void) {
if (0 == (--wined3d_fake_gl_context_ref) ) {
if (!glCtx) {
int iPixelFormat;
wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
if(!wined3d_fake_gl_context_hwnd) {
goto fail;
if(!wined3d_fake_gl_context_hdc) {
goto fail;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
if(!iPixelFormat) {
goto fail;
if (!glCtx) {
goto fail;
goto fail;
ret:
return TRUE;
fail:
return FALSE;
return S_OK;
return E_NOINTERFACE;
return refCount;
if (ref == 0) {
return ref;
static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
static void select_shader_max_constants(
int ps_selected_mode,
int vs_selected_mode,
switch (vs_selected_mode) {
case SHADER_GLSL:
/* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
case SHADER_ARB:
switch (ps_selected_mode) {
case SHADER_GLSL:
/* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
case SHADER_ARB:
* a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
const char *testcode =
while(glGetError());
if(!prog) {
if(glGetError() != 0) {
return ret;
unsigned int vidmem=0;
ENTER_GL();
if(major <= 0) {
case VENDOR_NVIDIA:
if (!gl_string_cursor) {
if (!gl_string_cursor) {
if (!*gl_string_cursor) {
case VENDOR_ATI:
if (gl_string_cursor) {
int error = 0;
if (error)
gl_string_cursor = 0;
if (!gl_string_cursor)
case VENDOR_INTEL:
case VENDOR_MESA:
if (*gl_string_cursor) {
int cursor = 0;
if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
cursor = 0;
major = 0;
TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
const char *Start;
LEAVE_GL();
ENTER_GL();
/* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
* loading the functions, otherwise the code above will load the extension entry points instead of the
GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
/* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
/* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
* features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
* rendering. Various games use this information to get a rough estimation of the features of the card
* games might even use it to work around bugs which happen on certain videocards/driver combinations.
* The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
* Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
* the renderer string and translate this to the right PCI id. This is a lot of work because there are more
* than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
* Another way would be to query the PCI id from the operating system (assuming this is the videocard which
* is used for rendering which is not always the case). This would work but it is not very portable. Second
* it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
* The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
* Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
* is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
* won't pass we return a default card. This way is better than maintaining a full card database as even
* without a full database we can return a card with similar features. Second the size of the database
* can be made quite small because when you know what type of 3d functionality a card has, you know to which
* GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
* The code also selects a default amount of video memory which we will use for an estimation of the amount
* of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
* memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
* system memory can be addressed by the system but we can make a reasonable estimation about the amount of
* video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
* makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
case VENDOR_NVIDIA:
vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
case VENDOR_ATI:
case VENDOR_INTEL:
case VENDOR_MESA:
case VENDOR_WINE:
TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
if(vidmem)
for (i = 0; i < MAX_LOOKUPS; i++) {
stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
if (hdc) {
const char *Start;
LEAVE_GL();
return return_value;
return numAdapters;
static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
return WINED3D_OK;
return NULL;
static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
if (!DEBUG_SINGLE_MODE) {
switch (Format)
case WINED3DFMT_UNKNOWN:
case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_P8:
static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
return WINED3DERR_INVALIDCALL;
int ModeIdx = 0;
UINT i = 0;
switch (Format)
case WINED3DFMT_UNKNOWN:
case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_P8:
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
} else if (DEBUG_SINGLE_MODE) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
return WINED3DERR_INVALIDCALL;
int bpp = 0;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
return WINED3D_OK;
static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
if(!cfg)
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
} else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
return FALSE;
return FALSE;
static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
if(!cfg)
return FALSE;
return FALSE;
/* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
* We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
* a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
return FALSE;
/* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
return FALSE;
return TRUE;
static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
int nCfgs;
int it;
WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
return WINED3DERR_NOTAVAILABLE;
static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
This,
return WINED3DERR_INVALIDCALL;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_INVALIDCALL;
int i, nCfgs;
for(i=0; i<nCfgs; i++) {
TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
if(pQualityLevels)
return WINED3D_OK;
int i, nCfgs;
return WINED3DERR_NOTAVAILABLE;
for(i=0; i<nCfgs; i++) {
TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
if(pQualityLevels)
return WINED3D_OK;
return WINED3DERR_NOTAVAILABLE;
static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This,
Windowed);
return WINED3DERR_INVALIDCALL;
return WINED3DERR_NOTAVAILABLE;
if(!nmodes) {
return WINED3DERR_NOTAVAILABLE;
/* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
return WINED3DERR_NOTAVAILABLE;
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
/* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return hr;
static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
switch(CheckFormat) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_Q8W8V8U8:
return TRUE;
return FALSE;
return FALSE;
static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
int it=0;
const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc);
return FALSE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return FALSE;
int it;
getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
* The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
return FALSE;
* drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
return TRUE;
/* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
int it;
/* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
return TRUE;
return TRUE;
return FALSE;
return FALSE;
switch (CheckFormat) {
case WINED3DFMT_A8R8G8B8:
case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_A4R4G4B4:
case WINED3DFMT_L8:
case WINED3DFMT_A8L8:
case WINED3DFMT_DXT1:
case WINED3DFMT_DXT2:
case WINED3DFMT_DXT3:
case WINED3DFMT_DXT4:
case WINED3DFMT_DXT5:
return TRUE;
TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
return FALSE;
return FALSE;
static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
int vs_selected_mode;
int ps_selected_mode;
return TRUE;
TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
return FALSE;
return FALSE;
return TRUE;
return FALSE;
return TRUE;
static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
switch (CheckFormat) {
case WINED3DFMT_A8R8G8B8:
case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_A4R4G4B4:
case WINED3DFMT_A8:
case WINED3DFMT_X4R4G4B4:
case WINED3DFMT_A8B8G8R8:
case WINED3DFMT_X8B8G8R8:
case WINED3DFMT_A2R10G10B10:
case WINED3DFMT_A2B10G10R10:
case WINED3DFMT_G16R16:
return TRUE;
case WINED3DFMT_R3G3B2:
return FALSE;
case WINED3DFMT_P8:
return TRUE;
case WINED3DFMT_A8P8:
return FALSE;
case WINED3DFMT_L8:
case WINED3DFMT_A8L8:
case WINED3DFMT_L16:
return TRUE;
case WINED3DFMT_A4L4:
return FALSE;
case WINED3DFMT_D16_LOCKABLE:
case WINED3DFMT_D16:
case WINED3DFMT_D15S1:
case WINED3DFMT_D24X8:
case WINED3DFMT_D24X4S4:
case WINED3DFMT_D24S8:
case WINED3DFMT_D24FS8:
case WINED3DFMT_D32:
case WINED3DFMT_D32F_LOCKABLE:
return TRUE;
case WINED3DFMT_V8U8:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_Q8W8V8U8:
case WINED3DFMT_V16U16:
return TRUE;
return FALSE;
case WINED3DFMT_DXT1:
case WINED3DFMT_DXT2:
case WINED3DFMT_DXT3:
case WINED3DFMT_DXT4:
case WINED3DFMT_DXT5:
return TRUE;
return FALSE;
case WINED3DFMT_VERTEXDATA:
case WINED3DFMT_INDEX16:
case WINED3DFMT_INDEX32:
case WINED3DFMT_Q16W16V16U16:
case WINED3DFMT_A2W10V10U10:
case WINED3DFMT_W11V11U10:
return FALSE;
case WINED3DFMT_CxV8U8:
return FALSE;
case WINED3DFMT_UYVY:
case WINED3DFMT_YUY2:
return TRUE;
return FALSE;
case WINED3DFMT_YV12:
return FALSE;
case WINED3DFMT_A16B16G16R16:
case WINED3DFMT_A8R3G3B2:
return FALSE;
case WINED3DFMT_R16F:
case WINED3DFMT_A16B16G16R16F:
return TRUE;
return FALSE;
case WINED3DFMT_R32F:
case WINED3DFMT_A32B32G32R32F:
return TRUE;
return FALSE;
case WINED3DFMT_G16R16F:
case WINED3DFMT_G32R32F:
return FALSE;
* MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
* Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
return TRUE;
return FALSE;
case WINED3DFMT_R8G8_B8G8:
case WINED3DFMT_G8R8_G8B8:
case WINED3DFMT_MULTI2_ARGB8:
return FALSE;
case WINED3DFMT_ATI2N:
return TRUE;
return TRUE;
return FALSE;
case WINED3DFMT_NVHU:
case WINED3DFMT_NVHS:
return FALSE;
case WINED3DFMT_UNKNOWN:
return FALSE;
return FALSE;
static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) {
switch(CheckFormat) {
case WINED3DFMT_R8G8B8:
case WINED3DFMT_A8R8G8B8:
case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_R5G6B5:
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_A4R4G4B4:
case WINED3DFMT_R3G3B2:
case WINED3DFMT_A8:
case WINED3DFMT_A8R3G3B2:
case WINED3DFMT_X4R4G4B4:
case WINED3DFMT_A2B10G10R10:
case WINED3DFMT_A8B8G8R8:
case WINED3DFMT_X8B8G8R8:
case WINED3DFMT_G16R16:
case WINED3DFMT_A2R10G10B10:
case WINED3DFMT_A16B16G16R16:
case WINED3DFMT_P8:
return TRUE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
switch (CheckFormat) {
case WINED3DFMT_A32B32G32R32F:
return FALSE;
return TRUE;
return FALSE;
return FALSE;
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
This,
return WINED3DERR_INVALIDCALL;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
switch(CheckFormat) {
case WINED3DFMT_P8:
case WINED3DFMT_A4L4:
case WINED3DFMT_R32F:
case WINED3DFMT_R16F:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_G16R16:
return WINED3DERR_NOTAVAILABLE;
case WINED3DFMT_Q8W8V8U8:
case WINED3DFMT_V16U16:
return WINED3DERR_NOTAVAILABLE;
case WINED3DFMT_V8U8:
return WINED3DERR_NOTAVAILABLE;
case WINED3DFMT_DXT1:
case WINED3DFMT_DXT2:
case WINED3DFMT_DXT3:
case WINED3DFMT_DXT4:
case WINED3DFMT_DXT5:
return WINED3DERR_NOTAVAILABLE;
/* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
return WINED3DERR_NOTAVAILABLE;
return WINED3DERR_NOTAVAILABLE;
return WINED3D_OK;
} else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
return WINED3DOK_NOAUTOGEN;
TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
return WINED3DERR_NOTAVAILABLE;
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
This,
return WINED3D_OK;
int vs_selected_mode;
int ps_selected_mode;
return ret;
static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
int vs_selected_mode;
int ps_selected_mode;
if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
return &arbfp_fragment_pipeline;
return &atifs_fragment_pipeline;
return &nvts_fragment_pipeline;
return &nvrc_fragment_pipeline;
return &ffp_fragment_pipeline;
static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
int vs_selected_mode;
int ps_selected_mode;
if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
return &arbfp_blit;
return &ffp_blit;
static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
int vs_selected_mode;
int ps_selected_mode;
return WINED3DERR_INVALIDCALL;
pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
/* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
/* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
/* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
/* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
/* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */
pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
return WINED3D_OK;
static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
return WINED3DERR_INVALIDCALL;
return WINED3DERR_OUTOFVIDEOMEMORY;
TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
for(i = 0; i < PATCHMAP_SIZE; i++) {
return WINED3D_OK;
return WINED3D_OK;
TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
return TRUE;
return FALSE;
static const unsigned int pattern[] = {
while(glGetError());
GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
struct driver_version_information {
if(apple) {
/* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
/* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
* and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
* We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
* ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
/* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
* This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
* within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
* Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
DebugBreak();
DebugBreak();
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
if(!mod_gl) {
#ifdef USE_WIN32_OPENGL
if(!mod_gl) {
goto nogl_adapter;
/* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
if(!mod_win32gl) {
goto nogl_adapter;
if(!pwglGetProcAddress) {
goto nogl_adapter;
int iPixelFormat;
int nAttribs = 0;
int res;
int attribute;
if (!WineD3D_CreateFakeGLContext()) {
goto nogl_adapter;
if(!ret) {
goto nogl_adapter;
if(!ret) {
goto nogl_adapter;
if(!hdc) {
goto nogl_adapter;
Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
if(!res)
/* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
int value;
if(value[0])
TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
cfgs++;
/* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
* mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
* Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
* that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
/* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
return TRUE;
return FALSE;