wined3d: Add a real implementation of wined3d_check_device_multisample_type().
authorMatteo Bruni <mbruni@codeweavers.com>
Wed, 27 Jan 2016 23:15:43 +0000 (00:15 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 28 Jan 2016 15:42:25 +0000 (00:42 +0900)
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
dlls/wined3d/directx.c
dlls/wined3d/surface.c
dlls/wined3d/utils.c
dlls/wined3d/wined3d_private.h

index 9faf4ec18c575de12b32108184cf3ca10c56f95e..c7b63f1b24ff96d8f8d99dd6502f1c56db8b86a9 100644 (file)
@@ -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 */
index 48ff005d4f6df19af8415bedf3ab004d0812f513..145e2c11050c0dd23ff218a639e34e3117c56aef 100644 (file)
@@ -2863,10 +2863,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);
index 28a32163cede7301c5a369b3883276d28a9b011b..6c2d08b3f8192c3ccfba58aada6d82f8ec818c89 100644 (file)
@@ -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,34 @@ 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 | WINED3DFMT_FLAG_DEPTH | 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;
index 5f91dc41a7c4ecf1aef40c1e7e20e0535d30c6bb..028708899ec1810b4b8d44092d988f3bac299fe0 100644 (file)
@@ -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
 {
@@ -3271,6 +3272,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;