[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