+ dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0);
+ src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0);
+
+ u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height),
+ abs(src_box->depth), &dstbox);
+
+ r300_blitter_begin(r300, R300_COPY);
+ util_blitter_blit_generic(r300->blitter, dst_view, &dstbox,
+ src_view, src_box, src_width0, src_height0,
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
+ r300_blitter_end(r300);
+
+ pipe_surface_reference(&dst_view, NULL);
+ pipe_sampler_view_reference(&src_view, NULL);
+}
+
+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);
+}
+
+static void r300_blit(struct pipe_context *pipe,
+ const struct pipe_blit_info *blit)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct pipe_blit_info info = *blit;
+
+ /* The driver supports sRGB textures but not framebuffers. Blitting
+ * from sRGB to sRGB should be the same as blitting from linear
+ * to linear, so use that, This avoids incorrect linearization.
+ */
+ if (util_format_is_srgb(info.src.format)) {
+ info.src.format = util_format_linear(info.src.format);
+ info.dst.format = util_format_linear(info.dst.format);
+ }
+
+ /* MSAA resolve. */
+ if (info.src.resource->nr_samples > 1 &&
+ !util_format_is_depth_or_stencil(info.src.resource->format)) {
+ r300_msaa_resolve(pipe, &info);
+ return;