diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2013-09-04 11:25:39 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2013-09-04 11:25:39 +0200 |
commit | e3b4e7b421df902dd062a44ef3e39d2477ad1dc2 (patch) | |
tree | 6a9e998833a46150e98ec291640e2167ae372561 | |
parent | 78fc50ed7a172e39fc51c6c82fb4abc3fee1a715 (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.inc | 2 | ||||
-rw-r--r-- | native/driver/etna_debug.h | 2 | ||||
-rw-r--r-- | native/driver/etna_internal.h | 9 | ||||
-rw-r--r-- | native/driver/etna_pipe.c | 121 | ||||
-rw-r--r-- | native/driver/etna_resource.c | 27 | ||||
-rw-r--r-- | native/driver/etna_screen.c | 35 | ||||
-rw-r--r-- | native/driver/etna_shader.c | 12 | ||||
-rw-r--r-- | native/driver/etna_surface.c | 5 | ||||
-rw-r--r-- | native/driver/etna_translate.h | 37 | ||||
-rw-r--r-- | native/etnaviv/etna_rs.h | 9 | ||||
-rw-r--r-- | native/fb/alpha_blend.c | 2 | ||||
-rw-r--r-- | native/fb_old/.gitignore | 2 | ||||
-rw-r--r-- | native/lib/fbdemos.c | 18 | ||||
-rw-r--r-- | tools/data/viv_gallium_state.txt | 3 |
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(©_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, ©_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 |