summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2012-12-03 05:36:08 +0100
committerMarek Olšák <maraeo@gmail.com>2012-12-07 14:19:29 +0100
commit35840ab189595b817fa8b1a1df8cc92474a7c38d (patch)
tree8c24773dedcfc0663c1388ed77ba30dc34212ed6
parent919f788b92362676fa368d9950532f82f762cdfb (diff)
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>
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.c61
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.h6
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.c6
-rw-r--r--src/gallium/state_trackers/dri/drm/dri2.c48
-rw-r--r--src/mesa/state_tracker/st_manager.c4
5 files changed, 112 insertions, 13 deletions
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c
index dca6def284c..ee4d11d1495 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.c
@@ -51,12 +51,15 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
(struct dri_drawable *) stfbi->st_manager_private;
struct dri_screen *screen = dri_screen(drawable->sPriv);
unsigned statt_mask, new_mask;
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++)
statt_mask |= (1 << statts[i]);
/* record newly allocated textures */
@@ -76,27 +79,28 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
drawable->update_drawable_info(drawable);
drawable->allocate_textures(drawable, statts, count);
/* add existing textures */
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
- if (drawable->textures[i])
+ if (textures[i])
statt_mask |= (1 << i);
}
drawable->texture_stamp = lastStamp;
drawable->texture_mask = statt_mask;
}
} while (lastStamp != drawable->dPriv->lastStamp);
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;
}
static boolean
@@ -163,12 +167,14 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
int i;
pipe_surface_reference(&drawable->drisw_surface, NULL);
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);
FREE(drawable);
}
@@ -349,12 +355,54 @@ swap_fences_unref(struct dri_drawable *draw)
screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
draw->tail &= DRI_SWAP_FENCES_MASK;
--draw->cur_fences;
}
}
+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.
*
* \param context the context
* \param drawable the drawable to flush
* \param flags a combination of _DRI2_FLUSH_xxx flags
@@ -378,16 +426,19 @@ dri_flush(__DRIcontext *cPriv,
if (!drawable) {
flags &= ~__DRI2_FLUSH_DRAWABLE;
}
/* 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;
if (flags & __DRI2_FLUSH_CONTEXT)
flush_flags |= ST_FLUSH_FRONT;
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h
index 6a769910fe6..caa1faa08f4 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.h
@@ -54,12 +54,13 @@ struct dri_drawable
__DRIbuffer old[8];
unsigned old_num;
unsigned old_w;
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];
unsigned int cur_fences;
unsigned int head;
unsigned int tail;
@@ -105,12 +106,17 @@ void
dri_drawable_get_format(struct dri_drawable *drawable,
enum st_attachment_type statt,
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,
unsigned flags,
enum __DRI2throttleReason reason);
extern const __DRItexBufferExtension driTexBufferExtension;
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index df2cd3f6b37..6d220f2ed7b 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -101,13 +101,13 @@ dri_fill_in_modes(struct dri_screen *screen)
};
depth_bits_array[0] = 0;
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,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_DEPTH_STENCIL);
pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
@@ -203,13 +203,15 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
{
memset(stvis, 0, sizeof(*stvis));
if (!mode)
return;
- stvis->samples = mode->samples;
+ if (mode->sampleBuffers) {
+ stvis->samples = mode->samples;
+ }
if (mode->redBits == 8) {
if (mode->alphaBits == 8)
stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
else
stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 5ebe18480d8..7f4f2f00c77 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -187,12 +187,14 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
drawable->old_h == dri_drawable->h &&
memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count) == 0)
return;
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;
templ.last_level = 0;
templ.width0 = dri_drawable->w;
templ.height0 = dri_drawable->h;
@@ -232,12 +234,31 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
whandle.handle = buf->name;
whandle.stride = buf->pitch;
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. */
for (i = 0; i < att_count; i++) {
if (atts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
alloc_depthstencil = TRUE;
@@ -253,14 +274,26 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
dri_drawable_get_format(drawable, ST_ATTACHMENT_DEPTH_STENCIL,
&format, &bind);
if (format) {
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]);
+ }
}
}
drawable->old_num = buffer_count;
drawable->old_w = dri_drawable->w;
drawable->old_h = dri_drawable->h;
@@ -377,16 +410,23 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
struct dri_drawable *drawable,
enum st_attachment_type statt)
{
__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);
}
}
static void
dri2_update_tex_buffer(struct dri_drawable *drawable,
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index da581861479..b065db0acdf 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -395,13 +395,13 @@ st_visual_to_context_mode(const struct st_visual *visual,
UTIL_FORMAT_COLORSPACE_RGB, 2);
mode->accumAlphaBits =
util_format_get_component_bits(visual->accum_format,
UTIL_FORMAT_COLORSPACE_RGB, 3);
}
- if (visual->samples) {
+ if (visual->samples > 1) {
mode->sampleBuffers = 1;
mode->samples = visual->samples;
}
}
/**
@@ -896,13 +896,13 @@ static const struct st_api st_gl_api = {
ST_PROFILE_OPENGL_ES1_MASK |
#endif
#if FEATURE_ES2
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,
st_api_make_current,
st_api_get_current,
};