wined3d: Add multisampling support.

This commit is contained in:
Roderick Colenbrander 2008-04-28 21:44:21 +00:00 committed by Alexandre Julliard
parent 727eef4e4f
commit 628e4eece3
4 changed files with 102 additions and 21 deletions

View File

@ -111,7 +111,7 @@ static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_hand
}
/* This function takes care of WineD3D pixel format selection. */
static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, WINED3DFORMAT ColorFormat, WINED3DFORMAT DepthStencilFormat, BOOL auxBuffers, BOOL pbuffer, BOOL findCompatible)
static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, WINED3DFORMAT ColorFormat, WINED3DFORMAT DepthStencilFormat, BOOL auxBuffers, int numSamples, BOOL pbuffer, BOOL findCompatible)
{
int iPixelFormat=0;
short redBits, greenBits, blueBits, alphaBits, colorBits;
@ -173,6 +173,10 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, WINED3DF
if(!(cfgs->stencilSize == stencilBits))
continue;
/* Check multisampling support */
if(cfgs->numSamples != numSamples)
continue;
/* When we have passed all the checks then we have found a format which matches our
* requirements. Note that we only check for a limit number of capabilities right now,
* so there can easily be a dozen of pixel formats which appear to be the 'same' but
@ -245,8 +249,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
TRACE("(%p): Creating a %s context for render target %p\n", This, create_pbuffer ? "offscreen" : "onscreen", target);
#define PUSH1(att) attribs[nAttribs++] = (att);
#define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
if(create_pbuffer) {
HDC hdc_parent = GetDC(win_handle);
int iPixelFormat = 0;
@ -255,13 +257,13 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
/* Try to find a pixel format with pbuffer support. */
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffers */, TRUE /* PBUFFER */, FALSE /* findCompatible */);
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffers */, 0 /* numSamples */, TRUE /* PBUFFER */, FALSE /* findCompatible */);
if(!iPixelFormat) {
TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
/* For some reason we weren't able to find a format, try to find something instead of crashing.
* A reason for failure could have been wglChoosePixelFormatARB strictness. */
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffer */, TRUE /* PBUFFER */, TRUE /* findCompatible */);
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffer */, 0 /* numSamples */, TRUE /* PBUFFER */, TRUE /* findCompatible */);
}
/* This shouldn't happen as ChoosePixelFormat always returns something */
@ -295,6 +297,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
WINED3DFORMAT ColorFormat = target->resource.format;
WINED3DFORMAT DepthStencilFormat = 0;
BOOL auxBuffers = FALSE;
int numSamples = 0;
hdc = GetDC(win_handle);
if(hdc == NULL) {
@ -327,13 +330,23 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
DepthStencilFormat = pPresentParms->AutoDepthStencilFormat;
}
/* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD */
if(pPresentParms->MultiSampleType && (pPresentParms->SwapEffect == WINED3DSWAPEFFECT_DISCARD)) {
if(!GL_SUPPORT(ARB_MULTISAMPLE))
ERR("The program is requesting multisampling without support!\n");
else {
ERR("Requesting MultiSampleType=%d\n", pPresentParms->MultiSampleType);
numSamples = pPresentParms->MultiSampleType;
}
}
/* Try to find a pixel format which matches our requirements */
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, FALSE /* PBUFFER */, FALSE /* findCompatible */);
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, numSamples, FALSE /* PBUFFER */, FALSE /* findCompatible */);
/* Try to locate a compatible format if we weren't able to find anything */
if(!iPixelFormat) {
TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, FALSE /* PBUFFER */, TRUE /* findCompatible */ );
iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, 0 /* numSamples */, FALSE /* PBUFFER */, TRUE /* findCompatible */ );
}
/* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */
@ -370,8 +383,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
}
}
}
#undef PUSH1
#undef PUSH2
ctx = pwglCreateContext(hdc);
if(This->numContexts) pwglShareLists(This->contexts[0]->glCtx, ctx);

View File

@ -1753,7 +1753,10 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U
BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
const GlPixelFormatDesc *glDesc;
const StaticPixelFormatDesc *desc;
TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
@ -1766,17 +1769,66 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U
return WINED3DERR_INVALIDCALL;
}
/* TODO: Store in Adapter structure */
if (pQualityLevels != NULL) {
static int s_single_shot = 0;
if (!s_single_shot) {
FIXME("Quality levels unsupported at present\n");
s_single_shot = 1;
}
*pQualityLevels = 1; /* Guess at a value! */
}
/* TODO: handle Windowed, add more quality levels */
if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc);
if(!desc || !glDesc) {
return WINED3DERR_INVALIDCALL;
}
if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
int i, nCfgs;
WineD3D_PixelFormat *cfgs;
cfgs = Adapters[Adapter].cfgs;
nCfgs = Adapters[Adapter].nCfgs;
for(i=0; i<nCfgs; i++) {
if(cfgs[i].numSamples != MultiSampleType)
continue;
if(!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[i], SurfaceFormat))
continue;
TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
if(pQualityLevels)
*pQualityLevels = 1; /* Guess at a value! */
return WINED3D_OK;
}
}
else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
short redSize, greenSize, blueSize, alphaSize, colorBits;
int i, nCfgs;
WineD3D_PixelFormat *cfgs;
if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
return WINED3DERR_NOTAVAILABLE;
}
cfgs = Adapters[Adapter].cfgs;
nCfgs = Adapters[Adapter].nCfgs;
for(i=0; i<nCfgs; i++) {
if(cfgs[i].numSamples != MultiSampleType)
continue;
if(cfgs[i].redSize != redSize)
continue;
if(cfgs[i].greenSize != greenSize)
continue;
if(cfgs[i].blueSize != blueSize)
continue;
if(cfgs[i].alphaSize != alphaSize)
continue;
TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
if(pQualityLevels)
*pQualityLevels = 1; /* Guess at a value! */
return WINED3D_OK;
}
}
return WINED3DERR_NOTAVAILABLE;
}
@ -3876,8 +3928,7 @@ BOOL InitAdapters(void) {
cfgs->auxBuffers = values[9];
cfgs->pbufferDrawable = FALSE;
/* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown
attributes. */
/* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
int attrib = WGL_DRAW_TO_PBUFFER_ARB;
int value;
@ -3885,6 +3936,19 @@ attributes. */
cfgs->pbufferDrawable = value;
}
cfgs->numSamples = 0;
/* Check multisample support */
if(GL_SUPPORT(ARB_MULTISAMPLE)) {
int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
int value[2];
if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
/* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
* value[1] = number of multi sample buffers*/
if(value[0])
cfgs->numSamples = value[1];
}
}
TRACE("iPixelFormat=%d, iPixelType=%#x, RGBA=%d/%d/%d/%d, doubleBuffer=%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++;
}

View File

@ -686,6 +686,7 @@ typedef struct WineD3D_PixelFormat
BOOL pbufferDrawable;
BOOL doubleBuffer;
int auxBuffers;
int numSamples;
} WineD3D_PixelFormat;
/* The adapter structure */

View File

@ -3682,6 +3682,11 @@ typedef enum _GL_SupportedExt {
/* WGL_ARB_extensions_string */
typedef const char * (WINAPI * WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
/* WGL_ARB_multisample */
#ifndef WGL_ARB_multisample
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#endif
/* WGL_ARB_pixel_format */
#ifndef WGL_ARB_pixel_format
#define WGL_ARB_pixel_format 1