st/dri: implement MSAA for GLX/DRI2 framebuffers
All MSAA buffers are allocated privately and resolved into the DRI-provided back and front buffers. If an MSAA visual is chosen, the buffers st/mesa receives are all multi-sample. st/mesa doesn't have access to the single-sample buffers in that case. This makes MSAA work in games like Nexuiz. Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
@@ -54,6 +54,9 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||
boolean new_stamp;
|
||||
int i;
|
||||
unsigned int lastStamp;
|
||||
struct pipe_resource **textures =
|
||||
drawable->stvis.samples > 1 ? drawable->msaa_textures
|
||||
: drawable->textures;
|
||||
|
||||
statt_mask = 0x0;
|
||||
for (i = 0; i < count; i++)
|
||||
@@ -79,7 +82,7 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||
|
||||
/* add existing textures */
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
|
||||
if (drawable->textures[i])
|
||||
if (textures[i])
|
||||
statt_mask |= (1 << i);
|
||||
}
|
||||
|
||||
@@ -91,9 +94,10 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
|
||||
if (!out)
|
||||
return TRUE;
|
||||
|
||||
/* Set the window-system buffers for the state tracker. */
|
||||
for (i = 0; i < count; i++) {
|
||||
out[i] = NULL;
|
||||
pipe_resource_reference(&out[i], drawable->textures[statts[i]]);
|
||||
pipe_resource_reference(&out[i], textures[statts[i]]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -166,6 +170,8 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
|
||||
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_resource_reference(&drawable->textures[i], NULL);
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_resource_reference(&drawable->msaa_textures[i], NULL);
|
||||
|
||||
swap_fences_unref(drawable);
|
||||
|
||||
@@ -352,6 +358,48 @@ swap_fences_unref(struct dri_drawable *draw)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dri_msaa_resolve(struct dri_context *ctx,
|
||||
struct dri_drawable *drawable,
|
||||
enum st_attachment_type att)
|
||||
{
|
||||
struct pipe_context *pipe = ctx->st->pipe;
|
||||
struct pipe_resource *dst = drawable->textures[att];
|
||||
struct pipe_resource *src = drawable->msaa_textures[att];
|
||||
struct pipe_blit_info blit;
|
||||
|
||||
if (!dst || !src)
|
||||
return;
|
||||
|
||||
memset(&blit, 0, sizeof(blit));
|
||||
blit.dst.resource = dst;
|
||||
blit.dst.box.width = dst->width0;
|
||||
blit.dst.box.height = dst->width0;
|
||||
blit.dst.box.depth = 1;
|
||||
blit.dst.format = util_format_linear(dst->format);
|
||||
blit.src.resource = src;
|
||||
blit.src.box.width = src->width0;
|
||||
blit.src.box.height = src->width0;
|
||||
blit.src.box.depth = 1;
|
||||
blit.src.format = util_format_linear(src->format);
|
||||
blit.mask = PIPE_MASK_RGBA;
|
||||
blit.filter = PIPE_TEX_FILTER_NEAREST;
|
||||
|
||||
pipe->blit(pipe, &blit);
|
||||
}
|
||||
|
||||
static void
|
||||
dri_postprocessing(struct dri_context *ctx,
|
||||
struct dri_drawable *drawable,
|
||||
enum st_attachment_type att)
|
||||
{
|
||||
struct pipe_resource *src = drawable->textures[att];
|
||||
struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL];
|
||||
|
||||
if (ctx->pp && src && zsbuf)
|
||||
pp_run(ctx->pp, src, src, zsbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* DRI2 flush extension, the flush_with_flags function.
|
||||
*
|
||||
@@ -381,10 +429,13 @@ dri_flush(__DRIcontext *cPriv,
|
||||
|
||||
/* Flush the drawable. */
|
||||
if (flags & __DRI2_FLUSH_DRAWABLE) {
|
||||
struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
|
||||
/* Resolve MSAA buffers. */
|
||||
if (drawable->stvis.samples > 1) {
|
||||
dri_msaa_resolve(ctx, drawable, ST_ATTACHMENT_BACK_LEFT);
|
||||
/* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */
|
||||
}
|
||||
|
||||
if (ptex && ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
|
||||
pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
|
||||
dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT);
|
||||
}
|
||||
|
||||
flush_flags = 0;
|
||||
|
||||
@@ -57,6 +57,7 @@ struct dri_drawable
|
||||
unsigned old_h;
|
||||
|
||||
struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
|
||||
struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT];
|
||||
unsigned int texture_mask, texture_stamp;
|
||||
|
||||
struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
|
||||
@@ -107,6 +108,11 @@ dri_drawable_get_format(struct dri_drawable *drawable,
|
||||
enum pipe_format *format,
|
||||
unsigned *bind);
|
||||
|
||||
void
|
||||
dri_msaa_resolve(struct dri_context *ctx,
|
||||
struct dri_drawable *drawable,
|
||||
enum st_attachment_type att);
|
||||
|
||||
void
|
||||
dri_flush(__DRIcontext *cPriv,
|
||||
__DRIdrawable *dPriv,
|
||||
|
||||
@@ -104,7 +104,7 @@ dri_fill_in_modes(struct dri_screen *screen)
|
||||
stencil_bits_array[0] = 0;
|
||||
depth_buffer_factor = 1;
|
||||
|
||||
msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS)
|
||||
msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK)
|
||||
? MSAA_VISUAL_MAX_SAMPLES : 1;
|
||||
|
||||
pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
|
||||
@@ -206,7 +206,9 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
stvis->samples = mode->samples;
|
||||
if (mode->sampleBuffers) {
|
||||
stvis->samples = mode->samples;
|
||||
}
|
||||
|
||||
if (mode->redBits == 8) {
|
||||
if (mode->alphaBits == 8)
|
||||
|
||||
@@ -190,6 +190,8 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
|
||||
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_resource_reference(&drawable->textures[i], NULL);
|
||||
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
|
||||
pipe_resource_reference(&drawable->msaa_textures[i], NULL);
|
||||
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.target = screen->target;
|
||||
@@ -235,6 +237,25 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
|
||||
drawable->textures[statt] =
|
||||
screen->base.screen->resource_from_handle(screen->base.screen,
|
||||
&templ, &whandle);
|
||||
assert(drawable->textures[statt]);
|
||||
}
|
||||
|
||||
/* Allocate private MSAA colorbuffers. */
|
||||
if (drawable->stvis.samples > 1) {
|
||||
for (i = 0; i < att_count; i++) {
|
||||
enum st_attachment_type att = atts[i];
|
||||
|
||||
if (drawable->textures[att]) {
|
||||
templ.format = drawable->textures[att]->format;
|
||||
templ.bind = drawable->textures[att]->bind;
|
||||
templ.nr_samples = drawable->stvis.samples;
|
||||
|
||||
drawable->msaa_textures[att] =
|
||||
screen->base.screen->resource_create(screen->base.screen,
|
||||
&templ);
|
||||
assert(drawable->msaa_textures[att]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we need a depth-stencil buffer. */
|
||||
@@ -256,8 +277,20 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
|
||||
templ.format = format;
|
||||
templ.bind = bind;
|
||||
|
||||
drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL] =
|
||||
screen->base.screen->resource_create(screen->base.screen, &templ);
|
||||
if (drawable->stvis.samples > 1) {
|
||||
templ.nr_samples = drawable->stvis.samples;
|
||||
drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL] =
|
||||
screen->base.screen->resource_create(screen->base.screen,
|
||||
&templ);
|
||||
assert(drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]);
|
||||
}
|
||||
else {
|
||||
templ.nr_samples = 0;
|
||||
drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL] =
|
||||
screen->base.screen->resource_create(screen->base.screen,
|
||||
&templ);
|
||||
assert(drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,10 +413,17 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
|
||||
__DRIdrawable *dri_drawable = drawable->dPriv;
|
||||
struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
|
||||
|
||||
if (loader->flushFrontBuffer == NULL)
|
||||
if (statt != ST_ATTACHMENT_FRONT_LEFT)
|
||||
return;
|
||||
|
||||
if (statt == ST_ATTACHMENT_FRONT_LEFT) {
|
||||
if (drawable->stvis.samples > 1) {
|
||||
struct pipe_context *pipe = ctx->st->pipe;
|
||||
|
||||
dri_msaa_resolve(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT);
|
||||
pipe->flush(pipe, NULL);
|
||||
}
|
||||
|
||||
if (loader->flushFrontBuffer) {
|
||||
loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ st_visual_to_context_mode(const struct st_visual *visual,
|
||||
UTIL_FORMAT_COLORSPACE_RGB, 3);
|
||||
}
|
||||
|
||||
if (visual->samples) {
|
||||
if (visual->samples > 1) {
|
||||
mode->sampleBuffers = 1;
|
||||
mode->samples = visual->samples;
|
||||
}
|
||||
@@ -899,7 +899,7 @@ static const struct st_api st_gl_api = {
|
||||
ST_PROFILE_OPENGL_ES2_MASK |
|
||||
#endif
|
||||
0,
|
||||
0,
|
||||
ST_API_FEATURE_MS_VISUALS_MASK,
|
||||
st_api_destroy,
|
||||
st_api_get_proc_address,
|
||||
st_api_create_context,
|
||||
|
||||
Reference in New Issue
Block a user