[PATCH v3 4/8] wined3d: Add a real implementation of wined3d_check_device_multisample_type().

Matteo Bruni mbruni at codeweavers.com
Tue Jan 26 15:51:31 CST 2016


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
It turns out that the ARB_internalformat_query spec is a bit more annoying
to use in that glGetInternalformativ() fails with GL_INVALID_ENUM if the
internal format is not color / depth / stencil renderable (while
ARB_internalformat_query2 helpfully specifies that it isn't an error and
glGetInternalformativ() just returns 0 for GL_NUM_SAMPLE_COUNTS).
Not a big problem though, also it made me realize the same limitation is
there in D3D so I added a test and rearranged the fallback code.

v2: Just store a bitmask of the available multisampling types in struct
wined3d_format. A few small cleanups.
v3: Use wined3d_popcount(). Also support ARB_internalformat_query.

 dlls/wined3d/directx.c         | 37 ++++++++++++++++++++-----------------
 dlls/wined3d/surface.c         | 26 +++++++++++++++++++++++++-
 dlls/wined3d/utils.c           | 33 ++++++++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |  2 ++
 4 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index cb920b2..f729e53 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -4408,36 +4408,39 @@ 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"
+    TRACE("wined3d %p, adapter_idx %u, device_type %s, surface_format %s, "
             "windowed %#x, multisample_type %#x, quality_levels %p.\n",
             wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(surface_format_id),
             windowed, multisample_type, quality_levels);
 
     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 = wined3d_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 fcde8d8..ebe4d0e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2862,10 +2862,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 6eb4508..4e40d98 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2162,10 +2162,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);
@@ -2284,6 +2285,36 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
             }
         }
 
+        if (format->glInternal
+                && (format->flags[WINED3D_GL_RES_TYPE_RB] & WINED3DFMT_FLAG_RENDERTARGET
+                || format->flags[WINED3D_GL_RES_TYPE_RB] & WINED3DFMT_FLAG_DEPTH
+                || format->flags[WINED3D_GL_RES_TYPE_RB] & WINED3DFMT_FLAG_STENCIL))
+        {
+            if (gl_info->supported[ARB_INTERNALFORMAT_QUERY])
+            {
+                GL_EXTCALL(glGetInternalformativ(GL_RENDERBUFFER, format->glInternal,
+                        GL_NUM_SAMPLE_COUNTS, 1, &count));
+                checkGLcall("glGetInternalformativ(GL_NUM_SAMPLE_COUNTS)");
+                count = min(count, MAX_MULTISAMPLE_TYPES);
+                GL_EXTCALL(glGetInternalformativ(GL_RENDERBUFFER, format->glInternal,
+                        GL_SAMPLES, count, multisample_types));
+                checkGLcall("glGetInternalformativ(GL_SAMPLES)");
+                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
+            {
+                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 */
         format->convert = format_texture_info[i].convert;
         format->conv_byte_count = format_texture_info[i].conv_byte_count;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3a83094..ea9c51e 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
 {
@@ -3269,6 +3270,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