summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2013-09-04 11:25:39 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2013-09-04 11:25:39 +0200
commite3b4e7b421df902dd062a44ef3e39d2477ad1dc2 (patch)
tree6a9e998833a46150e98ec291640e2167ae372561
parent78fc50ed7a172e39fc51c6c82fb4abc3fee1a715 (diff)
driver: implement MSAA
For now, use ETNA_DEBUG="msaa4x" or ETNA_DEBUG="msaa2x" to force usage of MSAA for screen surface (MESA may have its own way for this...).
-rw-r--r--native/Makefile.inc2
-rw-r--r--native/driver/etna_debug.h2
-rw-r--r--native/driver/etna_internal.h9
-rw-r--r--native/driver/etna_pipe.c121
-rw-r--r--native/driver/etna_resource.c27
-rw-r--r--native/driver/etna_screen.c35
-rw-r--r--native/driver/etna_shader.c12
-rw-r--r--native/driver/etna_surface.c5
-rw-r--r--native/driver/etna_translate.h37
-rw-r--r--native/etnaviv/etna_rs.h9
-rw-r--r--native/fb/alpha_blend.c2
-rw-r--r--native/fb_old/.gitignore2
-rw-r--r--native/lib/fbdemos.c18
-rw-r--r--tools/data/viv_gallium_state.txt3
14 files changed, 234 insertions, 50 deletions
diff --git a/native/Makefile.inc b/native/Makefile.inc
index 47547fc..4fbefd2 100644
--- a/native/Makefile.inc
+++ b/native/Makefile.inc
@@ -7,7 +7,7 @@ LD = $(GCCPREFIX)ld
AR = $(GCCPREFIX)ar
GCC_CFLAGS = -D_POSIX_C_SOURCE=200809 -D_GNU_SOURCE
-COMMON_FLAGS = -O2 -g -Wall -Wmissing-prototypes -DGCABI_${GCABI} $(GCC_CFLAGS) -I$(TOP)/lib -I$(TOP)/include_$(GCABI) -g -fPIC \
+COMMON_FLAGS = -O2 -g3 -Wall -Wmissing-prototypes -DGCABI_${GCABI} $(GCC_CFLAGS) -I$(TOP)/lib -I$(TOP)/include_$(GCABI) -g -fPIC \
-I$(TOP)/gallium/include -I$(TOP)/gallium/auxiliary -I$(TOP) \
-fdiagnostics-show-option \
-Werror=missing-prototypes -Werror=missing-declarations -Werror=implicit-function-declaration \
diff --git a/native/driver/etna_debug.h b/native/driver/etna_debug.h
index 9a714e2..22b8691 100644
--- a/native/driver/etna_debug.h
+++ b/native/driver/etna_debug.h
@@ -40,6 +40,8 @@
/* Bypasses */
#define ETNA_DBG_NO_TS 0x1000 /* Disable TS */
#define ETNA_DBG_CFLUSH_ALL 0x2000 /* Flush before every state update + draw call */
+#define ETNA_DBG_MSAA_2X 0x4000 /* Force 2X MSAA for screen */
+#define ETNA_DBG_MSAA_4X 0x8000 /* Force 4X MSAA for screen */
extern uint32_t etna_mesa_debug; /* set in etna_screen.c from ETNA_DEBUG */
diff --git a/native/driver/etna_internal.h b/native/driver/etna_internal.h
index 75313a3..4b9a674 100644
--- a/native/driver/etna_internal.h
+++ b/native/driver/etna_internal.h
@@ -206,6 +206,9 @@ struct compiled_framebuffer_state
uint32_t SE_SCISSOR_TOP; // fixp
uint32_t SE_SCISSOR_RIGHT; // fixp
uint32_t SE_SCISSOR_BOTTOM; // fixp
+ uint32_t RA_MULTISAMPLE_UNK00E04;
+ uint32_t RA_MULTISAMPLE_UNK00E10[VIVS_RA_MULTISAMPLE_UNK00E10__LEN];
+ uint32_t RA_CENTROID_TABLE[VIVS_RA_CENTROID_TABLE__LEN];
uint32_t TS_MEM_CONFIG;
uint32_t TS_DEPTH_CLEAR_VALUE;
uint32_t TS_DEPTH_STATUS_BASE;
@@ -213,6 +216,7 @@ struct compiled_framebuffer_state
uint32_t TS_COLOR_CLEAR_VALUE;
uint32_t TS_COLOR_STATUS_BASE;
uint32_t TS_COLOR_SURFACE_BASE;
+ bool msaa_mode; // adds input (and possible temp) to PS
};
/* Compiled context->create_vertex_elements_state */
@@ -255,7 +259,9 @@ struct compiled_shader_state
uint32_t PS_END_PC;
uint32_t PS_OUTPUT_REG;
uint32_t PS_INPUT_COUNT;
+ uint32_t PS_INPUT_COUNT_MSAA; /* Adds an input */
uint32_t PS_TEMP_REGISTER_CONTROL;
+ uint32_t PS_TEMP_REGISTER_CONTROL_MSAA; /* Adds a temporary if needed to make space for extra input */
uint32_t PS_CONTROL;
uint32_t PS_START_PC;
uint32_t GL_VARYING_TOTAL_COMPONENTS;
@@ -321,6 +327,9 @@ struct etna_3d_state
uint32_t /*00C18*/ SE_CONFIG;
uint32_t /*00E00*/ RA_CONTROL;
+ uint32_t /*00E04*/ RA_MULTISAMPLE_UNK00E04;
+ uint32_t /*00E10*/ RA_MULTISAMPLE_UNK00E10[VIVS_RA_MULTISAMPLE_UNK00E10__LEN];
+ uint32_t /*00E40*/ RA_CENTROID_TABLE[VIVS_RA_CENTROID_TABLE__LEN];
uint32_t /*01000*/ PS_END_PC;
uint32_t /*01004*/ PS_OUTPUT_REG;
diff --git a/native/driver/etna_pipe.c b/native/driver/etna_pipe.c
index 14c6bb4..ac74f6d 100644
--- a/native/driver/etna_pipe.c
+++ b/native/driver/etna_pipe.c
@@ -89,8 +89,8 @@ static uint32_t active_samplers_bits(struct pipe_context *pipe)
*
* This pushes the current register state in pipe->gpu3d to the GPU.
* The function is used to initialize the GPU in a predictable state
- * at the beginning of the rendering, as well as to create a context
- * buffer for the kernel driver before flush.
+ * at the beginning of rendering, as well as to create a context
+ * buffer for the kernel driver.
*/
static void reset_context(struct pipe_context *restrict pipe)
{
@@ -166,6 +166,15 @@ static void reset_context(struct pipe_context *restrict pipe)
/*00C14*/ EMIT_STATE(SE_DEPTH_BIAS, SE_DEPTH_BIAS);
/*00C18*/ EMIT_STATE(SE_CONFIG, SE_CONFIG);
/*00E00*/ EMIT_STATE(RA_CONTROL, RA_CONTROL);
+ /*00E04*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E04, RA_MULTISAMPLE_UNK00E04);
+ for(int x=0; x<4; ++x)
+ {
+ /*00E10*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E10(x), RA_MULTISAMPLE_UNK00E10[x]);
+ }
+ for(int x=0; x<16; ++x)
+ {
+ /*00E40*/ EMIT_STATE(RA_CENTROID_TABLE(x), RA_CENTROID_TABLE[x]);
+ }
/*01000*/ EMIT_STATE(PS_END_PC, PS_END_PC);
/*01004*/ EMIT_STATE(PS_OUTPUT_REG, PS_OUTPUT_REG);
/*01008*/ EMIT_STATE(PS_INPUT_COUNT, PS_INPUT_COUNT);
@@ -340,7 +349,7 @@ static void sync_context(struct pipe_context *restrict pipe)
* emit state in increasing order of address (this makes it possible to merge
* consecutive register updates into one SET_STATE command)
*
- * There have been some manual changes, where the weving operation is not
+ * There have been some manual changes, where the weaving operation is not
* simply bitwise or:
* - scissor fixp
* - num vertex elements
@@ -349,6 +358,7 @@ static void sync_context(struct pipe_context *restrict pipe)
* - texture lod
* - ETNA_STATE_TS
* - removed ETNA_STATE_BASE_SETUP statements -- these are guaranteed to not change anyway
+ * - PS / framebuffer interaction for MSAA
*/
uint32_t last_reg, last_fixp, span_start;
ETNA_COALESCE_STATE_OPEN(ETNA_3D_CONTEXT_SIZE);
@@ -465,11 +475,31 @@ static void sync_context(struct pipe_context *restrict pipe)
if(dirty & (ETNA_STATE_SHADER))
{
/*00E00*/ EMIT_STATE(RA_CONTROL, RA_CONTROL, e->shader_state.RA_CONTROL);
+ }
+ if(dirty & (ETNA_STATE_FRAMEBUFFER))
+ {
+ /*00E04*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E04, RA_MULTISAMPLE_UNK00E04, e->framebuffer.RA_MULTISAMPLE_UNK00E04);
+ for(int x=0; x<4; ++x)
+ {
+ /*00E10*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E10(x), RA_MULTISAMPLE_UNK00E10[x], e->framebuffer.RA_MULTISAMPLE_UNK00E10[x]);
+ }
+ for(int x=0; x<16; ++x)
+ {
+ /*00E40*/ EMIT_STATE(RA_CENTROID_TABLE(x), RA_CENTROID_TABLE[x], e->framebuffer.RA_CENTROID_TABLE[x]);
+ }
+ }
+ if(dirty & (ETNA_STATE_SHADER | ETNA_STATE_FRAMEBUFFER))
+ {
/*01000*/ EMIT_STATE(PS_END_PC, PS_END_PC, e->shader_state.PS_END_PC);
/*01004*/ EMIT_STATE(PS_OUTPUT_REG, PS_OUTPUT_REG, e->shader_state.PS_OUTPUT_REG);
- /* XXX affected by supersampling as well (supersampling adds a PS input, and thus a temp when that makes #inputs>#temps) */
- /*01008*/ EMIT_STATE(PS_INPUT_COUNT, PS_INPUT_COUNT, e->shader_state.PS_INPUT_COUNT);
- /*0100C*/ EMIT_STATE(PS_TEMP_REGISTER_CONTROL, PS_TEMP_REGISTER_CONTROL, e->shader_state.PS_TEMP_REGISTER_CONTROL);
+ /*01008*/ EMIT_STATE(PS_INPUT_COUNT, PS_INPUT_COUNT,
+ e->framebuffer.msaa_mode ?
+ e->shader_state.PS_INPUT_COUNT_MSAA :
+ e->shader_state.PS_INPUT_COUNT);
+ /*0100C*/ EMIT_STATE(PS_TEMP_REGISTER_CONTROL, PS_TEMP_REGISTER_CONTROL,
+ e->framebuffer.msaa_mode ?
+ e->shader_state.PS_TEMP_REGISTER_CONTROL_MSAA :
+ e->shader_state.PS_TEMP_REGISTER_CONTROL);
/*01010*/ EMIT_STATE(PS_CONTROL, PS_CONTROL, e->shader_state.PS_CONTROL);
/*01018*/ EMIT_STATE(PS_START_PC, PS_START_PC, e->shader_state.PS_START_PC);
if (e->specs.has_shader_range_registers)
@@ -871,16 +901,9 @@ static void etna_pipe_set_framebuffer_state(struct pipe_context *pipe,
{
struct etna_pipe_context *priv = etna_pipe_context(pipe);
struct compiled_framebuffer_state *cs = &priv->framebuffer;
+ int nr_samples_color = -1;
+ int nr_samples_depth = -1;
- /* XXX support multisample 2X/4X, take care that required width/height is doubled
- * for both depth and color surfaces.
- */
- cs->GL_MULTI_SAMPLE_CONFIG =
- VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
- /* VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(0xf)
- VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12 |
- VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16 */
- /* merged with sample_mask */
/* Set up TS as well. Warning: this state is used by both the RS and PE */
uint32_t ts_mem_config = 0;
@@ -912,7 +935,10 @@ static void etna_pipe_set_framebuffer_state(struct pipe_context *pipe,
cs->TS_COLOR_STATUS_BASE = cbuf->surf.ts_address;
cs->TS_COLOR_SURFACE_BASE = cbuf->surf.address;
}
- /* XXX ts_mem_config |= VIVS_TS_MEM_CONFIG_MSAA | translate_msaa_format(cbuf->format) */
+ /* MSAA */
+ if(cbuf->base.texture->nr_samples > 1)
+ ts_mem_config |= VIVS_TS_MEM_CONFIG_MSAA | translate_msaa_format(cbuf->base.format, false);
+ nr_samples_color = cbuf->base.texture->nr_samples;
} else {
pipe_surface_reference(&cs->cbuf, NULL);
cs->PE_COLOR_FORMAT = 0; /* Is this enough to render without color? */
@@ -928,8 +954,8 @@ static void etna_pipe_set_framebuffer_state(struct pipe_context *pipe,
bool depth_supertiled = (zsbuf->layout & 2)!=0;
cs->PE_DEPTH_CONFIG =
depth_format |
- (depth_supertiled ? VIVS_PE_DEPTH_CONFIG_SUPER_TILED : 0) | /* XXX depends on layout */
- VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z; /* XXX set to NONE if no Z buffer */
+ (depth_supertiled ? VIVS_PE_DEPTH_CONFIG_SUPER_TILED : 0) |
+ VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z;
/* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */
/* merged with depth_stencil_alpha */
if (priv->ctx->conn->chip.pixel_pipes == 1)
@@ -946,19 +972,70 @@ static void etna_pipe_set_framebuffer_state(struct pipe_context *pipe,
cs->PE_DEPTH_NORMALIZE = etna_f32_to_u32(exp2f(depth_bits) - 1.0f);
if(zsbuf->surf.ts_address)
{
- ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR |
- (depth_bits == 16 ? VIVS_TS_MEM_CONFIG_DEPTH_16BPP : 0);
- /* XXX VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION;
- * Disable for now, as it causes corruption in glquake. */
+ ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR;
cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value;
cs->TS_DEPTH_STATUS_BASE = zsbuf->surf.ts_address;
cs->TS_DEPTH_SURFACE_BASE = zsbuf->surf.address;
}
+ ts_mem_config |= (depth_bits == 16 ? VIVS_TS_MEM_CONFIG_DEPTH_16BPP : 0);
+ /* MSAA */
+ if(zsbuf->base.texture->nr_samples > 1)
+ /* XXX VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION;
+ * Disable without MSAA for now, as it causes corruption in glquake. */
+ ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION;
+ nr_samples_depth = zsbuf->base.texture->nr_samples;
} else {
pipe_surface_reference(&cs->zsbuf, NULL);
cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE;
}
+ /* MSAA setup */
+ if(nr_samples_depth != -1 && nr_samples_color != -1 &&
+ nr_samples_depth != nr_samples_color)
+ {
+ printf("%s: Number of samples in color and depth texture must match (%i and %i respectively)\n", __func__,
+ nr_samples_color, nr_samples_depth);
+ }
+ switch(MAX2(nr_samples_depth, nr_samples_color))
+ {
+ case 0:
+ case 1: /* Are 0 and 1 samples allowed? */
+ cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
+ cs->msaa_mode = false;
+ break;
+ case 2:
+ cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
+ cs->msaa_mode = true; /* Add input to PS */
+ cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
+ cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22;
+ cs->RA_CENTROID_TABLE[0] = 0x66aa2288;
+ cs->RA_CENTROID_TABLE[1] = 0x88558800;
+ cs->RA_CENTROID_TABLE[2] = 0x88881100;
+ cs->RA_CENTROID_TABLE[3] = 0x33888800;
+ break;
+ case 4:
+ cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
+ cs->msaa_mode = true; /* Add input to PS */
+ cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
+ cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26;
+ cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a;
+ cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22;
+ cs->RA_CENTROID_TABLE[0] = 0x4a6e2688;
+ cs->RA_CENTROID_TABLE[1] = 0x888888a2;
+ cs->RA_CENTROID_TABLE[2] = 0x888888ea;
+ cs->RA_CENTROID_TABLE[3] = 0x888888c6;
+ cs->RA_CENTROID_TABLE[4] = 0x46622a88;
+ cs->RA_CENTROID_TABLE[5] = 0x888888ae;
+ cs->RA_CENTROID_TABLE[6] = 0x888888e6;
+ cs->RA_CENTROID_TABLE[7] = 0x888888ca;
+ cs->RA_CENTROID_TABLE[8] = 0x262a2288;
+ cs->RA_CENTROID_TABLE[9] = 0x886688a2;
+ cs->RA_CENTROID_TABLE[10] = 0x888866aa;
+ cs->RA_CENTROID_TABLE[11] = 0x668888a6;
+ break;
+ }
+
+ /* Scissor setup */
cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */
cs->SE_SCISSOR_TOP = 0;
cs->SE_SCISSOR_RIGHT = (sv->width << 16)-1;
diff --git a/native/driver/etna_resource.c b/native/driver/etna_resource.c
index 072bd6b..e6b0ba8 100644
--- a/native/driver/etna_resource.c
+++ b/native/driver/etna_resource.c
@@ -81,7 +81,7 @@ static boolean etna_screen_can_create_resource(struct pipe_screen *pscreen,
const struct pipe_resource *templat)
{
struct etna_screen *screen = etna_screen(pscreen);
- if(templat->nr_samples > 1)
+ if(!translate_samples_to_xyscale(templat->nr_samples, NULL, NULL, NULL))
return false;
if(templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW))
{
@@ -129,7 +129,6 @@ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *sc
{
assert(templat->array_size == 1);
}
- assert(templat->nr_samples <= 1);
assert(templat->width0 != 0);
assert(templat->height0 != 0);
assert(templat->depth0 != 0);
@@ -150,6 +149,23 @@ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *sc
}
/* XXX multi tiled formats */
+ /* Determine scaling for antialiasing, allow override using debug flag */
+ int nr_samples = templat->nr_samples;
+ if((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) &&
+ !(templat->bind & PIPE_BIND_SAMPLER_VIEW))
+ {
+ if(DBG_ENABLED(ETNA_DBG_MSAA_2X))
+ nr_samples = 2;
+ if(DBG_ENABLED(ETNA_DBG_MSAA_4X))
+ nr_samples = 4;
+ }
+ int msaa_xscale = 1, msaa_yscale = 1;
+ if(!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale, NULL))
+ {
+ /* Number of samples not supported */
+ assert(0);
+ }
+
/* Determine needed padding (alignment of height/width) */
unsigned paddingX = 0, paddingY = 0;
unsigned halign = TEXTURE_HALIGN_FOUR;
@@ -179,9 +195,9 @@ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *sc
struct etna_resource_level *mip = &resource->levels[ix];
mip->width = x;
mip->height = y;
- mip->padded_width = align(x, paddingX);
- mip->padded_height = align(y, paddingY);
- mip->stride = align(resource->levels[ix].padded_width, divSizeX)/divSizeX * element_size;
+ mip->padded_width = align(x * msaa_xscale, paddingX);
+ mip->padded_height = align(y * msaa_yscale, paddingY);
+ mip->stride = align(mip->padded_width, divSizeX)/divSizeX * element_size;
mip->offset = offset;
mip->layer_stride = align(mip->padded_width, divSizeX)/divSizeX *
align(mip->padded_height, divSizeY)/divSizeY * element_size;
@@ -225,6 +241,7 @@ static struct pipe_resource * etna_screen_resource_create(struct pipe_screen *sc
resource->base = *templat;
resource->base.last_level = ix; /* real last mipmap level */
resource->base.screen = screen;
+ resource->base.nr_samples = nr_samples;
resource->layout = layout;
resource->halign = halign;
resource->surface = rt;
diff --git a/native/driver/etna_screen.c b/native/driver/etna_screen.c
index c929514..f8882b7 100644
--- a/native/driver/etna_screen.c
+++ b/native/driver/etna_screen.c
@@ -43,7 +43,7 @@
uint32_t etna_mesa_debug = 0;
-/* Set debug flags from environment variable */
+/* Set debug flags from ETNA_DEBUG environment variable */
static void etna_set_debug_flags(const char *str)
{
struct option {
@@ -58,7 +58,9 @@ static void etna_set_debug_flags(const char *str)
{ "linker_msgs", ETNA_DBG_LINKER_MSGS },
{ "dump_shaders", ETNA_DBG_DUMP_SHADERS },
{ "no_ts", ETNA_DBG_NO_TS },
- { "cflush_all", ETNA_DBG_CFLUSH_ALL }
+ { "cflush_all", ETNA_DBG_CFLUSH_ALL },
+ { "msaa2x", ETNA_DBG_MSAA_2X },
+ { "msaa4x", ETNA_DBG_MSAA_4X }
};
int i;
@@ -343,8 +345,7 @@ static boolean etna_screen_is_format_supported( struct pipe_screen *screen,
{
struct etna_screen *priv = etna_screen(screen);
unsigned allowed = 0;
- if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
- (sample_count > 1) /* TODO add MSAA */)
+ if (target >= PIPE_MAX_TEXTURE_TYPES)
{
return FALSE;
}
@@ -354,7 +355,19 @@ static boolean etna_screen_is_format_supported( struct pipe_screen *screen,
/* if render target, must be RS-supported format */
if(translate_rt_format(format, true) != ETNA_NO_MATCH)
{
- allowed |= PIPE_BIND_RENDER_TARGET;
+ /* Validate MSAA; number of samples must be allowed, and render target must have
+ * MSAA'able format.
+ */
+ if(sample_count > 1)
+ {
+ if(translate_samples_to_xyscale(sample_count, NULL, NULL, NULL) &&
+ translate_msaa_format(format, true) != ETNA_NO_MATCH)
+ {
+ allowed |= PIPE_BIND_RENDER_TARGET;
+ }
+ } else {
+ allowed |= PIPE_BIND_RENDER_TARGET;
+ }
}
}
if (usage & PIPE_BIND_DEPTH_STENCIL)
@@ -368,7 +381,7 @@ static boolean etna_screen_is_format_supported( struct pipe_screen *screen,
if (usage & PIPE_BIND_SAMPLER_VIEW)
{
/* must be supported texture format */
- if(translate_texture_format(format, true) != ETNA_NO_MATCH)
+ if(sample_count < 2 && translate_texture_format(format, true) != ETNA_NO_MATCH)
{
allowed |= PIPE_BIND_SAMPLER_VIEW;
}
@@ -448,6 +461,10 @@ static void etna_screen_flush_frontbuffer( struct pipe_screen *screen,
ectx->dirty_bits |= ETNA_STATE_TS;
}
+ int msaa_xscale=1, msaa_yscale=1;
+ if(!translate_samples_to_xyscale(resource->nr_samples, &msaa_xscale, &msaa_yscale, NULL))
+ return;
+
/* Kick off RS here */
struct compiled_rs_state copy_to_screen;
etna_compile_rs_state(&copy_to_screen, &(struct rs_state){
@@ -459,11 +476,13 @@ static void etna_screen_flush_frontbuffer( struct pipe_screen *screen,
.dest_tiling = ETNA_LAYOUT_LINEAR,
.dest_addr = drawable->addr,
.dest_stride = drawable->stride,
+ .downsample_x = msaa_xscale > 1,
+ .downsample_y = msaa_yscale > 1,
.swap_rb = drawable->swap_rb,
.dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit?
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED,
- .width = drawable->width,
- .height = drawable->height
+ .width = drawable->width * msaa_xscale,
+ .height = drawable->height * msaa_yscale
});
etna_submit_rs_state(ctx, &copy_to_screen);
DBG_F(ETNA_DBG_FRAME_MSGS,
diff --git a/native/driver/etna_shader.c b/native/driver/etna_shader.c
index 65fad67..efe7425 100644
--- a/native/driver/etna_shader.c
+++ b/native/driver/etna_shader.c
@@ -111,13 +111,21 @@ void etna_link_shaders(struct pipe_context *pipe,
cs->PS_END_PC = fs->code_size / 4;
cs->PS_OUTPUT_REG = fs->ps_color_out_reg;
- cs->PS_INPUT_COUNT = VIVS_PS_INPUT_COUNT_COUNT(fs->num_inputs + 1) | /* XXX MSAA adds another input */
+ cs->PS_INPUT_COUNT = VIVS_PS_INPUT_COUNT_COUNT(fs->num_inputs + 1) | /* Number of inputs plus position */
VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8);
cs->PS_TEMP_REGISTER_CONTROL =
- VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(fs->num_temps);
+ VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, fs->num_inputs + 1));
cs->PS_CONTROL = VIVS_PS_CONTROL_UNK1; /* XXX when can we set BYPASS? */
cs->PS_START_PC = 0;
+ /* Precompute PS_INPUT_COUNT and TEMP_REGISTER_CONTROL in the case of MSAA mode, avoids
+ * some fumbling in sync_context.
+ */
+ cs->PS_INPUT_COUNT_MSAA = VIVS_PS_INPUT_COUNT_COUNT(fs->num_inputs + 2) | /* MSAA adds another input */
+ VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8);
+ cs->PS_TEMP_REGISTER_CONTROL_MSAA =
+ VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, fs->num_inputs + 2));
+
uint32_t total_components = 0;
uint32_t num_components = 0;
uint32_t component_use[2] = {0};
diff --git a/native/driver/etna_surface.c b/native/driver/etna_surface.c
index 446a6f8..cb110cc 100644
--- a/native/driver/etna_surface.c
+++ b/native/driver/etna_surface.c
@@ -77,9 +77,10 @@ static struct pipe_surface *etna_pipe_create_surface(struct pipe_context *pipe,
surf->base.u = templat->u;
surf->layout = resource->layout;
- surf->level = &resource->levels[level]; /* Keep pointer to actual level to set clear color */
+ surf->level = &resource->levels[level]; /* Keep pointer to actual level to set clear color on */
+ /* underlying resource instead of surface */
surf->surf = resource->levels[level]; /* Make copy of level to narrow down address to layer */
- /* XXX we don't really need a copy */
+ /* XXX we don't really need a copy but it's convenient */
surf->surf.address += layer * surf->surf.layer_stride;
surf->surf.logical += layer * surf->surf.layer_stride;
diff --git a/native/driver/etna_translate.h b/native/driver/etna_translate.h
index adf5415..2ef2f2c 100644
--- a/native/driver/etna_translate.h
+++ b/native/driver/etna_translate.h
@@ -513,5 +513,42 @@ static inline uint32_t translate_clear_depth_stencil(enum pipe_format format, fl
return clear_value;
}
+/* Convert MSAA number of samples to x and y scaling factor and VIVS_GL_MULTI_SAMPLE_CONFIG value.
+ * Return true if supported and false otherwise.
+ */
+static inline bool translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out, uint32_t *config_out)
+{
+ int xscale, yscale;
+ uint32_t config;
+ switch(num_samples)
+ {
+ case 0:
+ case 1:
+ xscale = 1;
+ yscale = 1;
+ config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
+ break;
+ case 2:
+ xscale = 2;
+ yscale = 1;
+ config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
+ break;
+ case 4:
+ xscale = 2;
+ yscale = 2;
+ config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
+ break;
+ default:
+ return false;
+ }
+ if(xscale_out)
+ *xscale_out = xscale;
+ if(yscale_out)
+ *yscale_out = yscale;
+ if(config_out)
+ *config_out = config;
+ return true;
+}
+
#endif
diff --git a/native/etnaviv/etna_rs.h b/native/etnaviv/etna_rs.h
index 85c52c3..3593548 100644
--- a/native/etnaviv/etna_rs.h
+++ b/native/etnaviv/etna_rs.h
@@ -27,9 +27,10 @@
struct rs_state
{
+ uint8_t downsample_x:1; // Downsample in x direction
+ uint8_t downsample_y:1; // Downsample in y direction
+
uint8_t source_format; // RS_FORMAT_XXX
- uint8_t downsample_x; // Downsample in x direction
- uint8_t downsample_y; // Downsample in y direction
uint8_t source_tiling; // ETNA_LAYOUT_XXX
uint8_t dest_tiling; // ETNA_LAYOUT_XXX
uint8_t dest_format; // RS_FORMAT_XXX
@@ -39,8 +40,8 @@ struct rs_state
uint32_t source_stride;
uint32_t dest_addr;
uint32_t dest_stride;
- uint16_t width;
- uint16_t height;
+ uint16_t width; // source width
+ uint16_t height; // source height
uint32_t dither[2];
uint32_t clear_bits;
uint32_t clear_mode; // VIVS_RS_CLEAR_CONTROL_MODE_XXX
diff --git a/native/fb/alpha_blend.c b/native/fb/alpha_blend.c
index 439751f..3d0a553 100644
--- a/native/fb/alpha_blend.c
+++ b/native/fb/alpha_blend.c
@@ -110,7 +110,7 @@ int main(int argc, char **argv)
struct pipe_resource *rt_resource = fbdemo_create_2d(fbs->screen, PIPE_BIND_RENDER_TARGET, PIPE_FORMAT_B8G8R8X8_UNORM, width, height, 0);
struct pipe_resource *z_resource = fbdemo_create_2d(fbs->screen, PIPE_BIND_RENDER_TARGET, PIPE_FORMAT_Z16_UNORM, width, height, 0);
struct pipe_resource *vtx_resource = pipe_buffer_create(fbs->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_IMMUTABLE, VERTEX_BUFFER_SIZE);
-
+
/* bind render target to framebuffer */
etna_fb_bind_resource(&fbs->fb, rt_resource);
diff --git a/native/fb_old/.gitignore b/native/fb_old/.gitignore
index d987658..c870aed 100644
--- a/native/fb_old/.gitignore
+++ b/native/fb_old/.gitignore
@@ -1,7 +1,7 @@
fbtest
etna_test
rotate_cube
-cube_companion
+cube_companion_msaa
mip_cube
rstests
mip_cube_raw
diff --git a/native/lib/fbdemos.c b/native/lib/fbdemos.c
index 0dc0e32..208e425 100644
--- a/native/lib/fbdemos.c
+++ b/native/lib/fbdemos.c
@@ -47,6 +47,7 @@
#define FBDEV_DEV "/dev/fb%i"
#endif
struct fbdemos_scaffold *_fbs; /* for gdb */
+int fbdemos_msaa_samples = 0;
void fbdemo_init(struct fbdemos_scaffold **out)
{
@@ -61,6 +62,9 @@ void fbdemo_init(struct fbdemos_scaffold **out)
fbs->width = fbs->fb.fb_var.xres;
fbs->height = fbs->fb.fb_var.yres;
+ if(getenv("ETNA_MSAA_SAMPLES"))
+ fbdemos_msaa_samples = atoi(getenv("ETNA_MSAA_SAMPLES"));
+
rv = viv_open(VIV_HW_3D, &fbs->conn);
if(rv!=0)
{
@@ -82,7 +86,7 @@ void fbdemo_init(struct fbdemos_scaffold **out)
exit(1);
}
fbs->ctx = etna_pipe_context(fbs->pipe)->ctx;
-
+
if(etna_bswap_create(fbs->ctx, &fbs->buffers, fbs->fb.num_buffers, (etna_set_buffer_cb_t)&fb_set_buffer, (etna_copy_buffer_cb_t)&etna_fb_copy_buffer, &fbs->fb) != ETNA_OK)
{
printf("Unable to create buffer swapper\n");
@@ -110,7 +114,7 @@ struct pipe_resource *fbdemo_create_2d(struct pipe_screen *screen, unsigned bind
.depth0 = 1,
.array_size = 1,
.last_level = max_mip_level,
- .nr_samples = 1,
+ .nr_samples = ((bind == PIPE_BIND_DEPTH_STENCIL || bind == PIPE_BIND_RENDER_TARGET) ? fbdemos_msaa_samples : 1),
.usage = PIPE_USAGE_IMMUTABLE,
.bind = bind,
.flags = 0,
@@ -272,6 +276,10 @@ int etna_fb_bind_resource(struct fb_info *fb, struct pipe_resource *rt_resource_
struct etna_resource *rt_resource = etna_resource(rt_resource_);
fb->resource = rt_resource;
assert(rt_resource->base.width0 <= fb->fb_var.xres && rt_resource->base.height0 <= fb->fb_var.yres);
+ int msaa_xscale=1, msaa_yscale=1;
+ if(!translate_samples_to_xyscale(rt_resource_->nr_samples, &msaa_xscale, &msaa_yscale, NULL))
+ abort();
+
for(int bi=0; bi<ETNA_FB_MAX_BUFFERS; ++bi)
{
etna_compile_rs_state(&fb->copy_to_screen[bi], &(struct rs_state){
@@ -283,11 +291,13 @@ int etna_fb_bind_resource(struct fb_info *fb, struct pipe_resource *rt_resource_
.dest_tiling = ETNA_LAYOUT_LINEAR,
.dest_addr = fb->physical[bi],
.dest_stride = fb->fb_fix.line_length,
+ .downsample_x = msaa_xscale > 1,
+ .downsample_y = msaa_yscale > 1,
.swap_rb = fb->swap_rb,
.dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit?
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED,
- .width = fb->fb_var.xres,
- .height = fb->fb_var.yres
+ .width = fb->fb_var.xres * msaa_xscale,
+ .height = fb->fb_var.yres * msaa_yscale
});
}
return 0;
diff --git a/tools/data/viv_gallium_state.txt b/tools/data/viv_gallium_state.txt
index be2e008..c545ccc 100644
--- a/tools/data/viv_gallium_state.txt
+++ b/tools/data/viv_gallium_state.txt
@@ -91,6 +91,9 @@ framebuffer_state framebuffer. ETNA_STATE_FRAMEBUFFER
SE.SCISSOR_TOP
SE.SCISSOR_RIGHT
SE.SCISSOR_BOTTOM
+ RA.MULTISAMPLE_UNK00E04
+ RA.MULTISAMPLE_UNK00E10
+ RA.CENTROID_TABLE
TS.MEM_CONFIG
TS.DEPTH_CLEAR_VALUE
TS.DEPTH_STATUS_BASE