[PATCH] Add D3D8/9 multisampling support. It works fine in D3D sdk samples.

Roderick Colenbrander thunderbird2k at gmx.net
Mon Apr 28 16:44:21 CDT 2008


---
 dlls/wined3d/context.c         |   29 +++++++++----
 dlls/wined3d/directx.c         |   86 ++++++++++++++++++++++++++++++++++-----
 dlls/wined3d/wined3d_private.h |    1 +
 3 files changed, 96 insertions(+), 20 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index d80ef06..c91153c 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -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);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 29f451c..5d770b1 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -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;
+    /* 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;
         }
-        *pQualityLevels = 1; /* Guess at a value! */
     }
+    else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
+        short redSize, greenSize, blueSize, alphaSize, colorBits;
+        int i, nCfgs;
+        WineD3D_PixelFormat *cfgs;
 
-    if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
+        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++;
         }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 73570fa..17a8fb0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -686,6 +686,7 @@ typedef struct WineD3D_PixelFormat
     BOOL pbufferDrawable;
     BOOL doubleBuffer;
     int auxBuffers;
+    int numSamples;
 } WineD3D_PixelFormat;
 
 /* The adapter structure */
-- 
1.5.3.4


--========GMX187151209411891758870--



More information about the wine-patches mailing list