summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2013-01-05 06:21:49 +0100
committerMarek Olšák <maraeo@gmail.com>2013-01-06 14:44:12 +0100
commit8ed6b1400bc8a78f46340f41aaf2e88b24c23267 (patch)
tree56cddcccd509040b3b38bed2b1929408bbe9f1b5
parentcc030da4284b6c965d2b72c68a875b3210a4b286 (diff)
r300g: implement MSAA
This is not as optimized as r600g - the MSAA compression is missing, so r300g needs a lot of bandwidth (more than r600g to do the same thing). However, if the bandwidth is not an issue for you, you can enjoy this unoptimized MSAA support. The only other missing optimization for MSAA is the fast color clear. MSAA is enabled on r500 only, because that's the only GPU family I tested. That said, MSAA should work on r300 and r400 as well (but you must set RADEON_MSAA=1 to allow it, then turn MSAA on in your app or set GALLIUM_MSAA=n, n >= 2, n <= 6) I will enable the support by default on r300-r400 once someone (other than me) tests those chipsets with piglit. The supported modes are 2x, 4x, 6x. The supported MSAA formats are RGBA8, BGRA8, and RGBA16F (r500 only). Those 3 formats are used for all GL internal formats. Tested with piglit. (I have ported all MSAA tests to GL2.1)
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c3
-rw-r--r--src/gallium/drivers/r300/r300_blit.c171
-rw-r--r--src/gallium/drivers/r300/r300_context.c7
-rw-r--r--src/gallium/drivers/r300/r300_context.h7
-rw-r--r--src/gallium/drivers/r300/r300_emit.c165
-rw-r--r--src/gallium/drivers/r300/r300_emit.h3
-rw-r--r--src/gallium/drivers/r300/r300_flush.c8
-rw-r--r--src/gallium/drivers/r300/r300_fs.c2
-rw-r--r--src/gallium/drivers/r300/r300_render.c52
-rw-r--r--src/gallium/drivers/r300/r300_screen.c29
-rw-r--r--src/gallium/drivers/r300/r300_state.c91
-rw-r--r--src/gallium/drivers/r300/r300_texture.c4
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c37
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c28
14 files changed, 458 insertions, 149 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 1b9a3f438ac..95224020c79 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -1813,13 +1813,14 @@ void util_blitter_custom_color(struct blitter_context *blitter,
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
/* bind states */
- pipe->bind_blend_state(pipe, custom_blend);
+ pipe->bind_blend_state(pipe, custom_blend ? custom_blend
+ : ctx->blend[PIPE_MASK_RGBA]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1);
/* set a framebuffer state */
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 9fff3700ed3..46578318af2 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -20,12 +20,13 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "r300_context.h"
#include "r300_emit.h"
#include "r300_texture.h"
+#include "r300_reg.h"
#include "util/u_format.h"
#include "util/u_pack_color.h"
#include "util/u_surface.h"
enum r300_blitter_op /* bitmask */
@@ -63,12 +64,13 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o
util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref));
util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state);
util_blitter_save_fragment_shader(r300->blitter, r300->fs.state);
util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
util_blitter_save_viewport(r300->blitter, &r300->viewport);
util_blitter_save_scissor(r300->blitter, r300->scissor_state.state);
+ util_blitter_save_sample_mask(r300->blitter, *(unsigned*)r300->sample_mask.state);
util_blitter_save_vertex_buffer_slot(r300->blitter, r300->vertex_buffer);
util_blitter_save_vertex_elements(r300->blitter, r300->velems);
if (op & R300_SAVE_FRAMEBUFFER) {
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
}
@@ -475,12 +477,17 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
!r300_is_blit_supported(dst->format)) {
util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box);
return;
}
+ /* Can't read MSAA textures. */
+ if (src->nr_samples > 1 || dst->nr_samples > 1) {
+ return;
+ }
+
/* The code below changes the texture format so that the copy can be done
* on hardware. E.g. depth-stencil surfaces are copied as RGBA
* colorbuffers. */
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
util_blitter_default_src_texture(&src_templ, src, src_level);
@@ -592,39 +599,177 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
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->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;
+}
+
+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_STATIC;
+
+ 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);
+ 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_info)
+ 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_info;
+ struct pipe_blit_info info = *blit;
- /* Decompress ZMASK. */
- if (r300->zmask_in_use && !r300->locked_zbuffer) {
- if (fb->zsbuf->texture == info.src.resource ||
- fb->zsbuf->texture == info.dst.resource) {
- r300_decompress_zmask(r300);
- }
+ /* MSAA resolve. */
+ if (info.src.resource->nr_samples > 1 &&
+ info.dst.resource->nr_samples <= 1 &&
+ !util_format_is_depth_or_stencil(info.src.resource->format)) {
+ r300_msaa_resolve(pipe, &info);
+ return;
+ }
+
+ /* Can't read MSAA textures. */
+ if (info.src.resource->nr_samples > 1) {
+ return;
}
/* Blit a combined depth-stencil resource as color.
* S8Z24 is the only supported stencil format. */
if ((info.mask & PIPE_MASK_S) &&
info.src.format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
info.dst.format == PIPE_FORMAT_S8_UINT_Z24_UNORM) {
- info.src.format = PIPE_FORMAT_B8G8R8A8_UNORM;
- info.dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
- if (info.mask & PIPE_MASK_Z) {
- info.mask = PIPE_MASK_RGBA; /* depth+stencil */
+ if (info.dst.resource->nr_samples > 1) {
+ /* Cannot do that with MSAA buffers. */
+ info.mask &= ~PIPE_MASK_S;
+ if (!(info.mask & PIPE_MASK_Z)) {
+ return;
+ }
} else {
- info.mask = PIPE_MASK_B; /* stencil only */
+ /* Single-sample buffer. */
+ info.src.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ info.dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ if (info.mask & PIPE_MASK_Z) {
+ info.mask = PIPE_MASK_RGBA; /* depth+stencil */
+ } else {
+ info.mask = PIPE_MASK_B; /* stencil only */
+ }
+ }
+ }
+
+ /* Decompress ZMASK. */
+ if (r300->zmask_in_use && !r300->locked_zbuffer) {
+ if (fb->zsbuf->texture == info.src.resource ||
+ fb->zsbuf->texture == info.dst.resource) {
+ r300_decompress_zmask(r300);
}
}
r300_blitter_begin(r300, R300_BLIT);
util_blitter_blit(r300->blitter, &info);
r300_blitter_end(r300);
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 8178c394d07..b498454561d 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -102,12 +102,13 @@ static void r300_destroy_context(struct pipe_context* context)
FREE(r300->clip_state.state);
FREE(r300->fb_state.state);
FREE(r300->gpu_flush.state);
FREE(r300->hyperz_state.state);
FREE(r300->invariant_state.state);
FREE(r300->rs_block_state.state);
+ FREE(r300->sample_mask.state);
FREE(r300->scissor_state.state);
FREE(r300->textures_state.state);
FREE(r300->vap_invariant_state.state);
FREE(r300->viewport_state.state);
FREE(r300->ztop_state.state);
FREE(r300->fs_constants.state);
@@ -172,15 +173,16 @@ static boolean r300_setup_atoms(struct r300_context* r300)
/* ZB, FG. */
R300_INIT_ATOM(dsa_state, is_r500 ? (drm_2_6_0 ? 10 : 8) : 6);
/* RB3D. */
R300_INIT_ATOM(blend_state, 8);
R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2);
/* SC. */
+ R300_INIT_ATOM(sample_mask, 2);
R300_INIT_ATOM(scissor_state, 3);
/* GB, FG, GA, SU, SC, RB3D. */
- R300_INIT_ATOM(invariant_state, 16 + (is_rv350 ? 4 : 0) + (is_r500 ? 4 : 0));
+ R300_INIT_ATOM(invariant_state, 14 + (is_rv350 ? 4 : 0) + (is_r500 ? 4 : 0));
/* VAP. */
R300_INIT_ATOM(viewport_state, 9);
R300_INIT_ATOM(pvs_flush, 2);
R300_INIT_ATOM(vap_invariant_state, is_r500 ? 11 : 9);
R300_INIT_ATOM(vertex_stream_state, 0);
R300_INIT_ATOM(vs_state, 0);
@@ -221,12 +223,13 @@ static boolean r300_setup_atoms(struct r300_context* r300)
R300_ALLOC_ATOM(textures_state, r300_textures_state);
R300_ALLOC_ATOM(vap_invariant_state, r300_vap_invariant_state);
R300_ALLOC_ATOM(viewport_state, r300_viewport_state);
R300_ALLOC_ATOM(ztop_state, r300_ztop_state);
R300_ALLOC_ATOM(fb_state, pipe_framebuffer_state);
R300_ALLOC_ATOM(gpu_flush, pipe_framebuffer_state);
+ r300->sample_mask.state = malloc(4);
R300_ALLOC_ATOM(scissor_state, pipe_scissor_state);
R300_ALLOC_ATOM(rs_block_state, r300_rs_block);
R300_ALLOC_ATOM(fs_constants, r300_constant_buffer);
R300_ALLOC_ATOM(vs_constants, r300_constant_buffer);
if (!r300->screen->caps.has_tcl) {
R300_ALLOC_ATOM(vertex_stream_state, r300_vertex_stream_state);
@@ -267,12 +270,13 @@ static void r300_init_states(struct pipe_context *pipe)
CB_LOCALS;
pipe->set_blend_color(pipe, &bc);
pipe->set_clip_state(pipe, &cs);
pipe->set_scissor_state(pipe, &ss);
+ pipe->set_sample_mask(pipe, ~0);
/* Initialize the GPU flush. */
{
BEGIN_CB(gpuflush->cb_flush_clean, 6);
/* Flush and free renderbuffer caches. */
@@ -314,13 +318,12 @@ static void r300_init_states(struct pipe_context *pipe)
OUT_CB_REG(R300_FG_FOG_BLEND, 0);
OUT_CB_REG(R300_GA_OFFSET, 0);
OUT_CB_REG(R300_SU_TEX_WRAP, 0);
OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0);
OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525);
- OUT_CB_REG(R300_SC_SCREENDOOR, 0xffffff);
if (r300->screen->caps.is_rv350) {
OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index cddd91d7ab8..1b912c3eeee 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -70,13 +70,12 @@ struct r300_atom {
};
struct r300_aa_state {
struct r300_surface *dest;
uint32_t aa_config;
- uint32_t aaresolve_ctl;
};
struct r300_blend_state {
struct pipe_blend_state state;
uint32_t cb_clamp[COLORMASK_NUM_SWIZZLES][8];
@@ -496,12 +495,14 @@ struct r300_context {
/* Blend state. */
struct r300_atom blend_state;
/* Blend color state. */
struct r300_atom blend_color_state;
/* Scissor state. */
struct r300_atom scissor_state;
+ /* Sample mask. */
+ struct r300_atom sample_mask;
/* Invariant state. This must be emitted to get the engine started. */
struct r300_atom invariant_state;
/* Viewport state. */
struct r300_atom viewport_state;
/* PVS flush. */
struct r300_atom pvs_flush;
@@ -570,12 +571,16 @@ struct r300_context {
/* Whether fast color clear is enabled. */
boolean cbzb_clear;
/* Whether fragment shader needs to be validated. */
enum r300_fs_validity_status fs_status;
/* Framebuffer multi-write. */
boolean fb_multiwrite;
+ unsigned num_samples;
+ boolean msaa_enable;
+ boolean alpha_to_one;
+ boolean alpha_to_coverage;
void *dsa_decompress_zmask;
struct pipe_index_buffer index_buffer;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
unsigned nr_vertex_buffers;
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 1b9de40afaa..1700cbb4667 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -90,12 +90,19 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state)
alpha_func |= R500_FG_ALPHA_FUNC_FP16_ENABLE;
} else {
alpha_func |= R500_FG_ALPHA_FUNC_8BIT;
}
}
+ /* Setup alpha-to-coverage. */
+ if (r300->alpha_to_coverage && r300->msaa_enable) {
+ /* Always set 3/6, it improves precision even for 2x and 4x MSAA. */
+ alpha_func |= R300_FG_ALPHA_FUNC_MASK_ENABLE |
+ R300_FG_ALPHA_FUNC_CFG_3_OF_6;
+ }
+
OUT_CS_REG(R300_FG_ALPHA_FUNC, alpha_func);
WRITE_CS_TABLE(fb->zsbuf ? &dsa->cb_begin : dsa->cb_zb_no_readwrite, size-2);
}
static void get_rc_constant_state(
float vec[4],
@@ -363,18 +370,22 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
CS_LOCALS(r300);
BEGIN_CS(size);
OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config);
if (aa->dest) {
- OUT_CS_REG(R300_RB3D_AARESOLVE_OFFSET, aa->dest->offset);
+ OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 3);
+ OUT_CS(aa->dest->offset);
+ OUT_CS(aa->dest->pitch & R300_RB3D_AARESOLVE_PITCH_MASK);
+ OUT_CS(R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
+ R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE);
OUT_CS_RELOC(aa->dest);
- OUT_CS_REG(R300_RB3D_AARESOLVE_PITCH, aa->dest->pitch);
+ } else {
+ OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0);
}
- OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl);
END_CS;
}
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
{
struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
@@ -472,18 +483,91 @@ void r300_emit_hyperz_end(struct r300_context *r300)
z.sc_hyperz = R300_SC_HYPERZ_ADJ_2;
z.gb_z_peq_config = 0;
r300_emit_hyperz_state(r300, r300->hyperz_state.size, &z);
}
+#define R300_NIBBLES(x0, y0, x1, y1, x2, y2, d0y, d0x) \
+ (((x0) & 0xf) | (((y0) & 0xf) << 4) | \
+ (((x1) & 0xf) << 8) | (((y1) & 0xf) << 12) | \
+ (((x2) & 0xf) << 16) | (((y2) & 0xf) << 20) | \
+ (((d0y) & 0xf) << 24) | (((d0x) & 0xf) << 28))
+
+static unsigned r300_get_mspos(int index, unsigned *p)
+{
+ unsigned reg, i, distx, disty, dist;
+
+ if (index == 0) {
+ /* MSPOS0 contains positions for samples 0,1,2 as (X,Y) pairs of nibbles,
+ * followed by a (Y,X) pair containing the minimum distance from the pixel
+ * edge:
+ * X0, Y0, X1, Y1, X2, Y2, D0_Y, D0_X
+ *
+ * There is a quirk when setting D0_X. The value represents the distance
+ * from the left edge of the pixel quad to the first sample in subpixels.
+ * All values less than eight should use the actual value, but „7‟ should
+ * be used for the distance „8‟. The hardware will convert 7 into 8 internally.
+ */
+ distx = 11;
+ for (i = 0; i < 12; i += 2) {
+ if (p[i] < distx)
+ distx = p[i];
+ }
+
+ disty = 11;
+ for (i = 1; i < 12; i += 2) {
+ if (p[i] < disty)
+ disty = p[i];
+ }
+
+ if (distx == 8)
+ distx = 7;
+
+ reg = R300_NIBBLES(p[0], p[1], p[2], p[3], p[4], p[5], disty, distx);
+ } else {
+ /* MSPOS1 contains positions for samples 3,4,5 as (X,Y) pairs of nibbles,
+ * followed by the minimum distance from the pixel edge (not sure if X or Y):
+ * X3, Y3, X4, Y4, X5, Y5, D1
+ */
+ dist = 11;
+ for (i = 0; i < 12; i++) {
+ if (p[i] < dist)
+ dist = p[i];
+ }
+
+ reg = R300_NIBBLES(p[6], p[7], p[8], p[9], p[10], p[11], dist, 0);
+ }
+ return reg;
+}
+
void r300_emit_fb_state_pipelined(struct r300_context *r300,
unsigned size, void *state)
{
+ /* The sample coordinates are in the range [0,11], because
+ * GB_TILE_CONFIG.SUBPIXEL is set to the 1/12 subpixel precision.
+ *
+ * Some sample coordinates reach to neighboring pixels and should not be used.
+ * (e.g. Y=11)
+ *
+ * The unused samples must be set to the positions of other valid samples. */
+ static unsigned sample_locs_1x[12] = {
+ 6,6, 6,6, 6,6, 6,6, 6,6, 6,6
+ };
+ static unsigned sample_locs_2x[12] = {
+ 3,9, 9,3, 9,3, 9,3, 9,3, 9,3
+ };
+ static unsigned sample_locs_4x[12] = {
+ 4,4, 8,8, 2,10, 10,2, 10,2, 10,2
+ };
+ static unsigned sample_locs_6x[12] = {
+ 3,1, 7,3, 11,5, 1,7, 5,9, 9,10
+ };
+
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- unsigned i, num_cbufs = fb->nr_cbufs;
+ unsigned i, num_samples, num_cbufs = fb->nr_cbufs;
unsigned mspos0, mspos1;
CS_LOCALS(r300);
/* If we use the multiwrite feature, the colorbuffers 2,3,4 must be
* marked as UNUSED in the US block. */
if (r300->fb_multiwrite) {
@@ -506,38 +590,34 @@ void r300_emit_fb_state_pipelined(struct r300_context *r300,
for (; i < 4; i++) {
OUT_CS(R300_US_OUT_FMT_UNUSED);
}
/* Multisampling. Depends on framebuffer sample count.
* These are pipelined regs and as such cannot be moved
- * to the AA state. */
- mspos0 = 0x66666666;
- mspos1 = 0x6666666;
-
- if (fb->nr_cbufs && fb->cbufs[0]->texture->nr_samples > 1) {
- /* Subsample placement. These may not be optimal. */
- switch (fb->cbufs[0]->texture->nr_samples) {
- case 2:
- mspos0 = 0x33996633;
- mspos1 = 0x6666663;
- break;
- case 3:
- mspos0 = 0x33936933;
- mspos1 = 0x6666663;
- break;
- case 4:
- mspos0 = 0x33939933;
- mspos1 = 0x3966663;
- break;
- case 6:
- mspos0 = 0x22a2aa22;
- mspos1 = 0x2a65672;
- break;
- default:
- debug_printf("r300: Bad number of multisamples!\n");
- }
+ * to the AA state.
+ */
+ num_samples = r300->msaa_enable ? r300->num_samples : 1;
+
+ /* Sample positions. */
+ switch (num_samples) {
+ default:
+ mspos0 = r300_get_mspos(0, sample_locs_1x);
+ mspos1 = r300_get_mspos(1, sample_locs_1x);
+ break;
+ case 2:
+ mspos0 = r300_get_mspos(0, sample_locs_2x);
+ mspos1 = r300_get_mspos(1, sample_locs_2x);
+ break;
+ case 4:
+ mspos0 = r300_get_mspos(0, sample_locs_4x);
+ mspos1 = r300_get_mspos(1, sample_locs_4x);
+ break;
+ case 6:
+ mspos0 = r300_get_mspos(0, sample_locs_6x);
+ mspos1 = r300_get_mspos(1, sample_locs_6x);
+ break;
}
OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
OUT_CS(mspos0);
OUT_CS(mspos1);
END_CS;
@@ -748,12 +828,24 @@ void r300_emit_rs_block_state(struct r300_context* r300,
OUT_CS_REG_SEQ(R300_RS_INST_0, count);
}
OUT_CS_TABLE(rs->inst, count);
END_CS;
}
+void r300_emit_sample_mask(struct r300_context *r300,
+ unsigned size, void *state)
+{
+ unsigned mask = (*(unsigned*)state) & ((1 << 6)-1);
+ CS_LOCALS(r300);
+
+ BEGIN_CS(size);
+ OUT_CS_REG(R300_SC_SCREENDOOR,
+ mask | (mask << 6) | (mask << 12) | (mask << 18));
+ END_CS;
+}
+
void r300_emit_scissor_state(struct r300_context* r300,
unsigned size, void* state)
{
struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
CS_LOCALS(r300);
@@ -1173,12 +1265,13 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi
boolean r300_emit_buffer_validate(struct r300_context *r300,
boolean do_validate_vertex_buffers,
struct pipe_resource *index_buffer)
{
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
struct r300_textures_state *texstate =
(struct r300_textures_state*)r300->textures_state.state;
struct r300_resource *tex;
unsigned i;
boolean flushed = FALSE;
@@ -1198,12 +1291,20 @@ validate:
assert(tex && tex->buf && "zsbuf is marked, but NULL!");
r300->rws->cs_add_reloc(r300->cs, tex->cs_buf,
RADEON_USAGE_READWRITE,
r300_surface(fb->zsbuf)->domain);
}
}
+ /* The AA resolve buffer. */
+ if (r300->aa_state.dirty) {
+ if (aa->dest) {
+ r300->rws->cs_add_reloc(r300->cs, aa->dest->cs_buf,
+ RADEON_USAGE_WRITE,
+ aa->dest->domain);
+ }
+ }
if (r300->textures_state.dirty) {
/* ...textures... */
for (i = 0; i < texstate->count; i++) {
if (!(texstate->tx_enable & (1 << i))) {
continue;
}
@@ -1279,13 +1380,15 @@ unsigned r300_get_num_cs_end_dwords(struct r300_context *r300)
unsigned dwords = 0;
/* Emitted in flush. */
dwords += 26; /* emit_query_end */
dwords += r300->hyperz_state.size + 2; /* emit_hyperz_end + zcache flush */
if (r300->screen->caps.is_r500)
- dwords += 2;
+ dwords += 2; /* emit_index_bias */
+ if (r300->screen->info.drm_minor >= 6)
+ dwords += 3; /* MSPOS */
return dwords;
}
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300)
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 234e043b071..a58ab857f56 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -77,12 +77,15 @@ void r300_emit_query_end(struct r300_context* r300);
void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state);
void r300_emit_rs_block_state(struct r300_context* r300,
unsigned size, void* state);
+void r300_emit_sample_mask(struct r300_context *r300,
+ unsigned size, void *state);
+
void r300_emit_scissor_state(struct r300_context* r300,
unsigned size, void* state);
void r300_emit_textures_state(struct r300_context *r300,
unsigned size, void *state);
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 365dc8c3c11..10c4a30f67f 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -40,12 +40,20 @@ static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags)
r300_emit_hyperz_end(r300);
r300_emit_query_end(r300);
if (r300->screen->caps.is_r500)
r500_emit_index_bias(r300, 0);
+ /* The DDX doesn't set these regs. */
+ if (r300->screen->info.drm_minor >= 6) {
+ CS_LOCALS(r300);
+ OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
+ OUT_CS(0x66666666);
+ OUT_CS(0x6666666);
+ }
+
r300->flush_counter++;
r300->rws->cs_flush(r300->cs, flags);
r300->dirty_hw = 0;
/* New kitchen sink, baby. */
foreach_atom(r300, atom) {
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index 0842f9ad5dc..6e1b4e44ad3 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -146,12 +146,14 @@ static void get_external_state(
struct r300_context* r300,
struct r300_fragment_program_external_state* state)
{
struct r300_textures_state *texstate = r300->textures_state.state;
unsigned i;
+ state->alpha_to_one = r300->alpha_to_one && r300->msaa_enable;
+
for (i = 0; i < texstate->sampler_state_count; i++) {
struct r300_sampler_state *s = texstate->sampler_states[i];
struct r300_sampler_view *v = texstate->sampler_views[i];
struct r300_resource *t;
if (!s || !v) {
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 683fc03d523..1e79970ed0d 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -1198,64 +1198,12 @@ done:
r300_mark_atom_dirty(r300, &r300->rs_state);
r300_mark_atom_dirty(r300, &r300->viewport_state);
r300->sprite_coord_enable = last_sprite_coord_enable;
}
-#if 0
-static void r300_resource_resolve(struct pipe_context *pipe,
- const struct pipe_resolve_info *info)
-{
- struct r300_context *r300 = r300_context(pipe);
- struct pipe_surface *srcsurf, *dstsurf, surf_tmpl;
- struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
- static const union pipe_color_union color;
-
- assert(0 && "Resource resolve is unsupported, invalid call.");
-
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = info->src.res->format;
- surf_tmpl.u.tex.first_layer =
- surf_tmpl.u.tex.last_layer = info->src.layer;
- srcsurf = pipe->create_surface(pipe, info->src.res, &surf_tmpl);
- /* XXX Offset both surfaces by x0,y1. */
-
- surf_tmpl.format = info->dst.res->format;
- surf_tmpl.u.tex.level = info->dst.level;
- surf_tmpl.u.tex.first_layer =
- surf_tmpl.u.tex.last_layer = info->dst.layer;
- dstsurf = pipe->create_surface(pipe, info->dst.res, &surf_tmpl);
-
- DBG(r300, DBG_DRAW, "r300: Resolving resource...\n");
-
- /* Enable AA resolve. */
- aa->dest = r300_surface(dstsurf);
- aa->aaresolve_ctl =
- R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
- R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE;
- r300->aa_state.size = 10;
- r300_mark_atom_dirty(r300, &r300->aa_state);
-
- /* Resolve the surface. */
- /* XXX: y1 < 0 ==> Y flip */
- r300->context.clear_render_target(pipe,
- srcsurf, &color, 0, 0,
- info->dst.x1 - info->dst.x0,
- info->dst.y1 - info->dst.y0);
-
- /* Disable AA resolve. */
- aa->dest = NULL;
- aa->aaresolve_ctl = 0;
- r300->aa_state.size = 4;
- r300_mark_atom_dirty(r300, &r300->aa_state);
-
- pipe_surface_reference(&srcsurf, NULL);
- pipe_surface_reference(&dstsurf, NULL);
-}
-#endif
-
void r300_init_render_functions(struct r300_context *r300)
{
/* Set draw functions based on presence of HW TCL. */
if (r300->screen->caps.has_tcl) {
r300->context.draw_vbo = r300_draw_vbo;
} else {
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index db8f171786d..762f6072e0c 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -389,23 +389,40 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
/* Check multisampling support. */
switch (sample_count) {
case 0:
case 1:
break;
case 2:
- case 3:
case 4:
case 6:
- return FALSE;
-#if 0
- if (usage != PIPE_BIND_RENDER_TARGET ||
+ /* We need DRM 2.8.0. */
+ if (!drm_2_8_0) {
+ return FALSE;
+ }
+ /* Only support R500, because I didn't test older chipsets,
+ * but MSAA should work there too. */
+ if (!is_r500 && !debug_get_bool_option("RADEON_MSAA", FALSE)) {
+ return FALSE;
+ }
+ /* No texturing and scanout. */
+ if (usage & (PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SCANOUT)) {
+ return FALSE;
+ }
+ /* Only allow depth/stencil, RGBA8, RGBA16F */
+ if (!util_format_is_depth_or_stencil(format) &&
!util_format_is_rgba8_variant(
- util_format_description(format))) {
+ util_format_description(format)) &&
+ format != PIPE_FORMAT_R16G16B16A16_FLOAT) {
+ return FALSE;
+ }
+ /* RGBA16F AA is only supported on R500. */
+ if (format == PIPE_FORMAT_R16G16B16A16_FLOAT && !is_r500) {
return FALSE;
}
-#endif
break;
default:
return FALSE;
}
/* Check sampler format support. */
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index a5f96831081..1e7cff91f9a 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -437,14 +437,33 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
/* Bind blend state. */
static void r300_bind_blend_state(struct pipe_context* pipe,
void* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_blend_state *blend = (struct r300_blend_state*)state;
+ boolean last_alpha_to_one = r300->alpha_to_one;
+ boolean last_alpha_to_coverage = r300->alpha_to_coverage;
UPDATE_STATE(state, r300->blend_state);
+
+ if (!blend)
+ return;
+
+ r300->alpha_to_one = blend->state.alpha_to_one;
+ r300->alpha_to_coverage = blend->state.alpha_to_coverage;
+
+ if (r300->alpha_to_one != last_alpha_to_one && r300->msaa_enable &&
+ r300->fs_status == FRAGMENT_SHADER_VALID) {
+ r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY;
+ }
+
+ if (r300->alpha_to_coverage != last_alpha_to_coverage &&
+ r300->msaa_enable) {
+ r300_mark_atom_dirty(r300, &r300->dsa_state);
+ }
}
/* Free blend state. */
static void r300_delete_blend_state(struct pipe_context* pipe,
void* state)
{
@@ -550,19 +569,12 @@ static void r300_set_clip_state(struct pipe_context* pipe,
r300_mark_atom_dirty(r300, &r300->clip_state);
} else {
draw_set_clip_state(r300->draw, state);
}
}
-static void
-r300_set_sample_mask(struct pipe_context *pipe,
- unsigned sample_mask)
-{
-}
-
-
/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
*
* This contains the depth buffer, stencil buffer, alpha test, and such.
* On the Radeon, depth and stencil buffer setup are intertwined, which is
* the reason for some of the strange-looking assignments across registers. */
static void* r300_create_dsa_state(struct pipe_context* pipe,
@@ -813,12 +825,31 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
r300->fb_state.size += 8;
}
/* The size of the rest of atoms stays the same. */
}
+static unsigned r300_get_num_samples(struct r300_context *r300)
+{
+ struct pipe_framebuffer_state* fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ unsigned num_samples;
+
+ if (fb->nr_cbufs)
+ num_samples = fb->cbufs[0]->texture->nr_samples;
+ else if (fb->zsbuf)
+ num_samples = fb->zsbuf->texture->nr_samples;
+ else
+ num_samples = 1;
+
+ if (!num_samples)
+ num_samples = 1;
+
+ return num_samples;
+}
+
static void
r300_set_framebuffer_state(struct pipe_context* pipe,
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
@@ -908,28 +939,28 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
if (r300->polygon_offset_enabled)
r300_mark_atom_dirty(r300, &r300->rs_state);
}
}
- /* Set up AA config. */
- if (state->nr_cbufs && state->cbufs[0]->texture->nr_samples > 1) {
- aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE;
+ r300->num_samples = r300_get_num_samples(r300);
- switch (state->cbufs[0]->texture->nr_samples) {
+ /* Set up AA config. */
+ if (r300->num_samples > 1) {
+ switch (r300->num_samples) {
case 2:
- aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2;
- break;
- case 3:
- aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3;
+ aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE |
+ R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2;
break;
case 4:
- aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4;
+ aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE |
+ R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4;
break;
case 6:
- aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6;
+ aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE |
+ R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6;
break;
}
} else {
aa->aa_config = 0;
}
@@ -1248,34 +1279,50 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_rs_state* rs = (struct r300_rs_state*)state;
int last_sprite_coord_enable = r300->sprite_coord_enable;
boolean last_two_sided_color = r300->two_sided_color;
+ boolean last_msaa_enable = r300->msaa_enable;
if (r300->draw && rs) {
draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
}
if (rs) {
r300->polygon_offset_enabled = rs->polygon_offset_enable;
r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
r300->two_sided_color = rs->rs.light_twoside;
+ r300->msaa_enable = rs->rs.multisample;
} else {
r300->polygon_offset_enabled = FALSE;
r300->sprite_coord_enable = 0;
r300->two_sided_color = FALSE;
+ r300->msaa_enable = FALSE;
}
UPDATE_STATE(state, r300->rs_state);
r300->rs_state.size = RS_STATE_MAIN_SIZE + (r300->polygon_offset_enabled ? 5 : 0);
if (last_sprite_coord_enable != r300->sprite_coord_enable ||
last_two_sided_color != r300->two_sided_color) {
r300_mark_atom_dirty(r300, &r300->rs_block_state);
}
+
+ if (last_msaa_enable != r300->msaa_enable) {
+ r300_mark_atom_dirty(r300, &r300->fb_state_pipelined);
+
+ if (r300->alpha_to_coverage) {
+ r300_mark_atom_dirty(r300, &r300->dsa_state);
+ }
+
+ if (r300->alpha_to_one &&
+ r300->fs_status == FRAGMENT_SHADER_VALID) {
+ r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY;
+ }
+ }
}
/* Free rasterizer state. */
static void r300_delete_rs_state(struct pipe_context* pipe, void* state)
{
FREE(state);
@@ -1539,12 +1586,22 @@ r300_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
+static void r300_set_sample_mask(struct pipe_context *pipe,
+ unsigned mask)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ *((unsigned*)r300->sample_mask.state) = mask;
+
+ r300_mark_atom_dirty(r300, &r300->sample_mask);
+}
+
static void r300_set_scissor_state(struct pipe_context* pipe,
const struct pipe_scissor_state* state)
{
struct r300_context* r300 = r300_context(pipe);
memcpy(r300->scissor_state.state, state,
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 568558f0adb..e18dcf8e1cc 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -952,16 +952,12 @@ r300_texture_create_object(struct r300_screen *rscreen,
unsigned stride_in_bytes_override,
struct pb_buffer *buffer)
{
struct radeon_winsys *rws = rscreen->rws;
struct r300_resource *tex = NULL;
- if (base->nr_samples > 1) {
- goto fail;
- }
-
tex = CALLOC_STRUCT(r300_resource);
if (!tex) {
goto fail;
}
pipe_reference_init(&tex->b.b.reference, 1);
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 04d439bcc1f..9493eb19c28 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -53,37 +53,28 @@ unsigned r300_get_pixel_alignment(enum pipe_format format,
{{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */
{{ 32, 8}, {16, 16}, { 0, 0}}, /* 64 bits per pixel */
{{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */
}
};
- static const unsigned aa_block[2] = {4, 8};
unsigned tile = 0;
unsigned pixsize = util_format_get_blocksize(format);
assert(macrotile <= RADEON_LAYOUT_TILED);
assert(microtile <= RADEON_LAYOUT_SQUARETILED);
assert(pixsize <= 16);
assert(dim <= DIM_HEIGHT);
- if (num_samples > 1) {
- /* Multisampled textures have their own alignment scheme. */
- if (pixsize == 4)
- tile = aa_block[dim];
- /* XXX FP16 AA. */
- } else {
- /* Standard alignment. */
- tile = table[macrotile][util_logbase2(pixsize)][microtile][dim];
- if (macrotile == 0 && is_rs690 && dim == DIM_WIDTH) {
- int align;
- int h_tile;
- h_tile = table[macrotile][util_logbase2(pixsize)][microtile][DIM_HEIGHT];
- align = 64 / (pixsize * h_tile);
- if (tile < align)
- tile = align;
- }
+ tile = table[macrotile][util_logbase2(pixsize)][microtile][dim];
+ if (macrotile == 0 && is_rs690 && dim == DIM_WIDTH) {
+ int align;
+ int h_tile;
+ h_tile = table[macrotile][util_logbase2(pixsize)][microtile][DIM_HEIGHT];
+ align = 64 / (pixsize * h_tile);
+ if (tile < align)
+ tile = align;
}
assert(tile);
return tile;
}
@@ -92,12 +83,16 @@ static boolean r300_texture_macro_switch(struct r300_resource *tex,
unsigned level,
boolean rv350_mode,
enum r300_dim dim)
{
unsigned tile, texdim;
+ if (tex->b.b.nr_samples > 1) {
+ return TRUE;
+ }
+
tile = r300_get_pixel_alignment(tex->b.b.format, tex->b.b.nr_samples,
tex->tex.microtile, RADEON_LAYOUT_TILED, dim, 0);
if (dim == DIM_WIDTH) {
texdim = u_minify(tex->tex.width0, level);
} else {
texdim = u_minify(tex->tex.height0, level);
@@ -245,13 +240,13 @@ static void r300_setup_miptree(struct r300_screen *screen,
nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb);
else
nblocksy = r300_texture_get_nblocksy(tex, i, NULL);
layer_size = stride * nblocksy;
- if (base->nr_samples) {
+ if (base->nr_samples > 1) {
layer_size *= base->nr_samples;
}
if (base->target == PIPE_TEXTURE_CUBE)
size = layer_size * 6;
else
@@ -420,12 +415,18 @@ static void r300_setup_tiling(struct r300_screen *screen,
{
enum pipe_format format = tex->b.b.format;
boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350;
boolean is_zb = util_format_is_depth_or_stencil(format);
boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING);
+ if (tex->b.b.nr_samples > 1) {
+ tex->tex.microtile = RADEON_LAYOUT_TILED;
+ tex->tex.macrotile[0] = RADEON_LAYOUT_TILED;
+ return;
+ }
+
tex->tex.microtile = RADEON_LAYOUT_LINEAR;
tex->tex.macrotile[0] = RADEON_LAYOUT_LINEAR;
if (!util_format_is_plain(format)) {
return;
}
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 6ad08c6740e..436b30445b2 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -49,17 +49,37 @@ r300_transfer(struct pipe_transfer* transfer)
/* Copy from a tiled texture to a detiled one. */
static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
struct r300_transfer *r300transfer)
{
struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
- struct pipe_resource *tex = transfer->resource;
+ struct pipe_resource *src = transfer->resource;
+ struct pipe_resource *dst = &r300transfer->linear_texture->b.b;
- ctx->resource_copy_region(ctx, &r300transfer->linear_texture->b.b, 0,
- 0, 0, 0,
- tex, transfer->level, &transfer->box);
+ if (src->nr_samples <= 1) {
+ ctx->resource_copy_region(ctx, dst, 0, 0, 0, 0,
+ src, transfer->level, &transfer->box);
+ } else {
+ /* Resolve the resource. */
+ struct pipe_blit_info blit;
+
+ memset(&blit, 0, sizeof(blit));
+ blit.src.resource = src;
+ blit.src.format = src->format;
+ blit.src.level = transfer->level;
+ blit.src.box = transfer->box;
+ blit.dst.resource = dst;
+ blit.dst.format = dst->format;
+ blit.dst.box.width = transfer->box.width;
+ blit.dst.box.height = transfer->box.height;
+ blit.dst.box.depth = transfer->box.depth;
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+ ctx->blit(ctx, &blit);
+ }
}
/* Copy a detiled texture to a tiled one. */
static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
struct r300_transfer *r300transfer)
{