[PATCH v2 2/6] wined3d: Add a real implementation of wined3d_check_device_multisample_type().

Matteo Bruni mbruni at codeweavers.com
Wed Jan 13 17:00:05 CST 2016


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
Barring any mistakes, the behavior with WINED3D_MULTISAMPLE_NON_MASKABLE
should be essentially unchanged if ARB_internalformat_query2 is not
supported.

v2: Just store a bitmask of the available multisampling types in struct
wined3d_format. A few small cleanups.

 dlls/wined3d/directx.c         | 35 +++++++++++++++++++----------------
 dlls/wined3d/surface.c         | 26 +++++++++++++++++++++++++-
 dlls/wined3d/utils.c           | 18 +++++++++++++++++-
 dlls/wined3d/wined3d_private.h |  9 +++++++++
 4 files changed, 70 insertions(+), 18 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 7c681a2..75a1e40 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -4400,7 +4400,9 @@ HRESULT CDECL wined3d_check_device_multisample_type(const struct wined3d *wined3
         enum wined3d_device_type device_type, enum wined3d_format_id surface_format_id, BOOL windowed,
         enum wined3d_multisample_type multisample_type, DWORD *quality_levels)
 {
-    const struct wined3d_gl_info *gl_info;
+    const struct wined3d_gl_info *gl_info = &wined3d->adapters[adapter_idx].gl_info;
+    const struct wined3d_format *format = wined3d_get_format(gl_info, surface_format_id);
+    HRESULT hr = WINED3D_OK;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, surface_format %s,\n"
             "windowed %#x, multisample_type %#x, quality_levels %p.\n",
@@ -4409,27 +4411,28 @@ HRESULT CDECL wined3d_check_device_multisample_type(const struct wined3d *wined3
 
     if (adapter_idx >= wined3d->adapter_count)
         return WINED3DERR_INVALIDCALL;
+    if (surface_format_id == WINED3DFMT_UNKNOWN)
+        return WINED3DERR_INVALIDCALL;
+    if (multisample_type < WINED3D_MULTISAMPLE_NONE || multisample_type > WINED3D_MULTISAMPLE_16_SAMPLES)
+        return WINED3DERR_INVALIDCALL;
 
-    gl_info = &wined3d->adapters[adapter_idx].gl_info;
+    if (multisample_type && !(format->multisample_types & 1u << (multisample_type - 1)))
+        hr = WINED3DERR_NOTAVAILABLE;
 
-    if (multisample_type > gl_info->limits.samples)
+    if (SUCCEEDED(hr) || (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE && format->multisample_types))
     {
-        TRACE("Returning not supported.\n");
         if (quality_levels)
-            *quality_levels = 0;
-
-        return WINED3DERR_NOTAVAILABLE;
-    }
-
-    if (quality_levels)
-    {
-        if (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
-            *quality_levels = wined3d_log2i(gl_info->limits.samples);
-        else
-            *quality_levels = 1;
+        {
+            if (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
+                *quality_levels = popcount(format->multisample_types);
+            else
+                *quality_levels = 1;
+        }
+        return WINED3D_OK;
     }
 
-    return WINED3D_OK;
+    TRACE("Returning not supported.\n");
+    return hr;
 }
 
 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index b5c2d7e..7df7994 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2856,10 +2856,34 @@ static void surface_prepare_rb(struct wined3d_surface *surface, const struct win
          *
          * AMD has a similar feature called Enhanced Quality Anti-Aliasing (EQAA),
          * but it does not have an equivalent OpenGL extension. */
+
+        /* We advertise as many WINED3D_MULTISAMPLE_NON_MASKABLE quality levels
+         * as the count of advertised multisample types for the surface format. */
         if (surface->resource.multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
-            samples = 1u << (surface->resource.multisample_quality + 1);
+        {
+            const struct wined3d_format *format = surface->resource.format;
+            unsigned int i, count = 0;
+
+            for (i = 0; i < sizeof(format->multisample_types) * 8; ++i)
+            {
+                if (format->multisample_types & 1u << i)
+                {
+                    if (surface->resource.multisample_quality == count++)
+                        break;
+                }
+            }
+            if (i == sizeof(format->multisample_types) * 8)
+            {
+                WARN("Unsupported quality level %u requested for WINED3D_MULTISAMPLE_NON_MASKABLE.\n",
+                        surface->resource.multisample_quality);
+                i = 1;
+            }
+            samples = i + 1;
+        }
         else
+        {
             samples = surface->resource.multisample_type;
+        }
 
         gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_multisample);
         gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_multisample);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index f06affd..a015f4c 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2150,10 +2150,11 @@ static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx)
 
 static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
 {
+    GLint count, multisample_types[MAX_MULTISAMPLE_TYPES];
     struct fragment_caps fragment_caps;
     struct shader_caps shader_caps;
     BOOL srgb_write;
-    unsigned int i;
+    unsigned int i, j, max_log2;
 
     adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
     adapter->shader_backend->shader_get_caps(gl_info, &shader_caps);
@@ -2233,6 +2234,17 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
                 else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
                     format->glInternal = format->glGammaInternal;
             }
+
+            GL_EXTCALL(glGetInternalformativ(GL_TEXTURE_2D, format->glInternal, GL_NUM_SAMPLE_COUNTS, 1, &count));
+            count = min(count, MAX_MULTISAMPLE_TYPES);
+            GL_EXTCALL(glGetInternalformativ(GL_TEXTURE_2D, format->glInternal, GL_SAMPLES,
+                    count, multisample_types));
+            for (j = 0; j < count; ++j)
+            {
+                if (multisample_types[j] > sizeof(format->multisample_types) * 8)
+                    continue;
+                format->multisample_types |= 1u << (multisample_types[j] - 1);
+            }
         }
         else
         {
@@ -2270,6 +2282,10 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
                 format->flags[WINED3D_GL_RES_TYPE_TEX_CUBE] &= ~WINED3DFMT_FLAG_TEXTURE;
                 format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] &= ~WINED3DFMT_FLAG_TEXTURE;
             }
+
+            max_log2 = wined3d_log2i(min(gl_info->limits.samples, sizeof(format->multisample_types) * 8));
+            for (j = 1; j <= max_log2; ++j)
+                format->multisample_types |= 1u << ((1u << j) - 1);
         }
 
         /* Texture conversion stuff */
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 07007c0..4ae3bdf 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -185,6 +185,7 @@ void wined3d_rb_free(void *ptr) DECLSPEC_HIDDEN;
 #define MAX_SAMPLER_OBJECTS         16
 #define MAX_SHADER_RESOURCE_VIEWS   128
 #define MAX_VERTEX_BLENDS           4
+#define MAX_MULTISAMPLE_TYPES       8
 
 struct min_lookup
 {
@@ -257,6 +258,13 @@ static inline float float_24_to_32(DWORD in)
     }
 }
 
+static inline unsigned int popcount(unsigned int v)
+{
+    v -= v >> 1 & 0x55555555;
+    v = (v & 0x33333333) + (v >> 2 & 0x33333333);
+    return ((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101 >> 24;
+}
+
 #define ORM_BACKBUFFER  0
 #define ORM_FBO         1
 
@@ -3254,6 +3262,7 @@ struct wined3d_format
     GLint glFormat;
     GLint glType;
     UINT  conv_byte_count;
+    DWORD multisample_types;
     unsigned int flags[WINED3D_GL_RES_TYPE_COUNT];
     struct wined3d_rational height_scale;
     struct color_fixup_desc color_fixup;
-- 
2.4.10




More information about the wine-patches mailing list