summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300/r300_state.c
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 /src/gallium/drivers/r300/r300_state.c
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)
Diffstat (limited to 'src/gallium/drivers/r300/r300_state.c')
-rw-r--r--src/gallium/drivers/r300/r300_state.c91
1 files changed, 74 insertions, 17 deletions
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,