+static boolean r300_is_simple_msaa_resolve(const struct pipe_blit_info *info)
+{
+ unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level);
+ unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level);
+
+ return info->src.resource->nr_samples > 1 &&
+ info->dst.resource->nr_samples <= 1 &&
+ info->dst.resource->format == info->src.resource->format &&
+ info->dst.resource->format == info->dst.format &&
+ info->src.resource->format == info->src.format &&
+ !info->scissor_enable &&
+ info->mask == PIPE_MASK_RGBA &&
+ dst_width == info->src.resource->width0 &&
+ dst_height == info->src.resource->height0 &&
+ info->dst.box.x == 0 &&
+ info->dst.box.y == 0 &&
+ info->dst.box.width == dst_width &&
+ info->dst.box.height == dst_height &&
+ info->src.box.x == 0 &&
+ info->src.box.y == 0 &&
+ info->src.box.width == dst_width &&
+ info->src.box.height == dst_height &&
+ (r300_resource(info->dst.resource)->tex.microtile != RADEON_LAYOUT_LINEAR ||
+ r300_resource(info->dst.resource)->tex.macrotile[info->dst.level] != RADEON_LAYOUT_LINEAR);
+}
+
+static void r300_simple_msaa_resolve(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ unsigned dst_level,
+ unsigned dst_layer,
+ struct pipe_resource *src,
+ enum pipe_format format)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_surface *srcsurf, *dstsurf;
+ struct pipe_surface surf_tmpl;
+ struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
+
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ surf_tmpl.format = format;
+ srcsurf = r300_surface(pipe->create_surface(pipe, src, &surf_tmpl));
+
+ surf_tmpl.format = format;
+ surf_tmpl.u.tex.level = dst_level;
+ surf_tmpl.u.tex.first_layer =
+ surf_tmpl.u.tex.last_layer = dst_layer;
+ dstsurf = r300_surface(pipe->create_surface(pipe, dst, &surf_tmpl));
+
+ /* COLORPITCH should contain the tiling info of the resolve buffer.
+ * The tiling of the AA buffer isn't programmable anyway. */
+ srcsurf->pitch &= ~(R300_COLOR_TILE(1) | R300_COLOR_MICROTILE(3));
+ srcsurf->pitch |= dstsurf->pitch & (R300_COLOR_TILE(1) | R300_COLOR_MICROTILE(3));
+
+ /* Enable AA resolve. */
+ aa->dest = dstsurf;
+ r300->aa_state.size = 8;
+ r300_mark_atom_dirty(r300, &r300->aa_state);
+
+ /* Resolve the surface. */
+ r300_blitter_begin(r300, R300_CLEAR_SURFACE);
+ util_blitter_custom_color(r300->blitter, &srcsurf->base, NULL);
+ r300_blitter_end(r300);
+
+ /* Disable AA resolve. */
+ aa->dest = NULL;
+ r300->aa_state.size = 4;
+ r300_mark_atom_dirty(r300, &r300->aa_state);
+
+ pipe_surface_reference((struct pipe_surface**)&srcsurf, NULL);
+ pipe_surface_reference((struct pipe_surface**)&dstsurf, NULL);
+}
+
+static void r300_msaa_resolve(struct pipe_context *pipe,
+ const struct pipe_blit_info *info)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_resource *tmp, templ;
+ struct pipe_blit_info blit;
+
+ assert(info->src.level == 0);
+ assert(info->src.box.z == 0);
+ assert(info->src.box.depth == 1);
+ assert(info->dst.box.depth == 1);
+
+ if (r300_is_simple_msaa_resolve(info)) {
+ r300_simple_msaa_resolve(pipe, info->dst.resource, info->dst.level,
+ info->dst.box.z, info->src.resource,
+ info->src.format);
+ return;
+ }
+
+ /* resolve into a temporary texture, then blit */
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = info->src.resource->format;
+ templ.width0 = info->src.resource->width0;
+ templ.height0 = info->src.resource->height0;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+ templ.usage = PIPE_USAGE_DEFAULT;
+ templ.flags = R300_RESOURCE_FORCE_MICROTILING;
+
+ tmp = screen->resource_create(screen, &templ);
+
+ /* resolve */
+ r300_simple_msaa_resolve(pipe, tmp, 0, 0, info->src.resource,
+ info->src.format);
+
+ /* blit */
+ blit = *info;
+ blit.src.resource = tmp;
+ blit.src.box.z = 0;
+
+ r300_blitter_begin(r300, R300_BLIT | R300_IGNORE_RENDER_COND);
+ util_blitter_blit(r300->blitter, &blit);
+ r300_blitter_end(r300);
+
+ pipe_resource_reference(&tmp, NULL);
+}
+