2016-12-23 19:58:23 +00:00
/*
* Copyright ( c ) 2012 - 2015 Etnaviv Project
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sub license ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the
* next paragraph ) shall be included in all copies or substantial portions
* of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NON - INFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*
* Authors :
* Wladimir J . van der Laan < laanwj @ gmail . com >
* Christian Gmeiner < christian . gmeiner @ gmail . com >
*/
# include "etnaviv_state.h"
# include "hw/common.xml.h"
2017-06-04 20:06:32 +01:00
# include "etnaviv_blend.h"
2016-12-23 19:58:23 +00:00
# include "etnaviv_clear_blit.h"
# include "etnaviv_context.h"
# include "etnaviv_format.h"
2020-03-21 10:24:48 +00:00
# include "etnaviv_rasterizer.h"
2020-03-06 22:23:47 +00:00
# include "etnaviv_screen.h"
2016-12-23 19:58:23 +00:00
# include "etnaviv_shader.h"
# include "etnaviv_surface.h"
# include "etnaviv_translate.h"
# include "etnaviv_util.h"
2018-12-17 08:56:00 +00:00
# include "util/u_framebuffer.h"
2016-12-23 19:58:23 +00:00
# include "util/u_helpers.h"
# include "util/u_inlines.h"
# include "util/u_math.h"
# include "util/u_memory.h"
2019-06-28 03:02:45 +01:00
# include "util/u_upload_mgr.h"
2016-12-23 19:58:23 +00:00
static void
etna_set_stencil_ref ( struct pipe_context * pctx , const struct pipe_stencil_ref * sr )
{
struct etna_context * ctx = etna_context ( pctx ) ;
struct compiled_stencil_ref * cs = & ctx - > stencil_ref ;
ctx - > stencil_ref_s = * sr ;
2019-09-02 19:44:51 +01:00
for ( unsigned i = 0 ; i < 2 ; i + + ) {
cs - > PE_STENCIL_CONFIG [ i ] =
VIVS_PE_STENCIL_CONFIG_REF_FRONT ( sr - > ref_value [ i ] ) ;
cs - > PE_STENCIL_CONFIG_EXT [ i ] =
VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK ( sr - > ref_value [ ! i ] ) ;
}
2016-12-23 19:58:23 +00:00
ctx - > dirty | = ETNA_DIRTY_STENCIL_REF ;
}
static void
etna_set_clip_state ( struct pipe_context * pctx , const struct pipe_clip_state * pcs )
{
/* NOOP */
}
static void
etna_set_sample_mask ( struct pipe_context * pctx , unsigned sample_mask )
{
struct etna_context * ctx = etna_context ( pctx ) ;
ctx - > sample_mask = sample_mask ;
ctx - > dirty | = ETNA_DIRTY_SAMPLE_MASK ;
}
static void
2017-03-05 19:45:34 +00:00
etna_set_constant_buffer ( struct pipe_context * pctx ,
enum pipe_shader_type shader , uint index ,
2016-12-23 19:58:23 +00:00
const struct pipe_constant_buffer * cb )
{
struct etna_context * ctx = etna_context ( pctx ) ;
2020-02-14 18:55:24 +00:00
struct etna_constbuf_state * so = & ctx - > constant_buffer [ shader ] ;
2016-12-23 19:58:23 +00:00
2020-01-04 19:17:15 +00:00
assert ( index < ETNA_MAX_CONST_BUF ) ;
2016-12-23 19:58:23 +00:00
2020-02-14 18:55:24 +00:00
util_copy_constant_buffer ( & so - > cb [ index ] , cb ) ;
2016-12-23 19:58:23 +00:00
/* Note that the state tracker can unbind constant buffers by
* passing NULL here . */
2020-02-14 18:55:24 +00:00
if ( unlikely ( ! cb | | ( ! cb - > buffer & & ! cb - > user_buffer ) ) ) {
so - > enabled_mask & = ~ ( 1 < < index ) ;
2016-12-23 19:58:23 +00:00
return ;
2020-02-14 18:55:24 +00:00
}
2016-12-23 19:58:23 +00:00
2020-01-04 19:17:15 +00:00
assert ( index ! = 0 | | cb - > user_buffer ! = NULL ) ;
2016-12-23 19:58:23 +00:00
2019-06-28 03:02:45 +01:00
if ( ! cb - > buffer ) {
2020-02-14 18:55:24 +00:00
struct pipe_constant_buffer * cb = & so - > cb [ index ] ;
2019-06-28 03:02:45 +01:00
u_upload_data ( pctx - > const_uploader , 0 , cb - > buffer_size , 16 , cb - > user_buffer , & cb - > buffer_offset , & cb - > buffer ) ;
}
2020-02-14 18:55:24 +00:00
so - > enabled_mask | = 1 < < index ;
2016-12-23 19:58:23 +00:00
ctx - > dirty | = ETNA_DIRTY_CONSTBUF ;
}
static void
2019-08-10 22:00:32 +01:00
etna_update_render_resource ( struct pipe_context * pctx , struct etna_resource * base )
2016-12-23 19:58:23 +00:00
{
2019-08-10 22:00:32 +01:00
struct etna_resource * to = base , * from = base ;
2016-12-23 19:58:23 +00:00
2019-08-10 22:00:32 +01:00
if ( base - > texture & & etna_resource_newer ( etna_resource ( base - > texture ) , base ) )
from = etna_resource ( base - > texture ) ;
if ( base - > render )
to = etna_resource ( base - > render ) ;
if ( ( to ! = from ) & & etna_resource_older ( to , from ) ) {
etna_copy_resource ( pctx , & to - > base , & from - > base , 0 , base - > base . last_level ) ;
to - > seqno = from - > seqno ;
2016-12-23 19:58:23 +00:00
}
}
static void
etna_set_framebuffer_state ( struct pipe_context * pctx ,
2019-11-15 16:35:50 +00:00
const struct pipe_framebuffer_state * fb )
2016-12-23 19:58:23 +00:00
{
struct etna_context * ctx = etna_context ( pctx ) ;
2020-03-06 22:23:47 +00:00
struct etna_screen * screen = ctx - > screen ;
2016-12-23 19:58:23 +00:00
struct compiled_framebuffer_state * cs = & ctx - > framebuffer ;
int nr_samples_color = - 1 ;
int nr_samples_depth = - 1 ;
/* Set up TS as well. Warning: this state is used by both the RS and PE */
uint32_t ts_mem_config = 0 ;
2019-07-01 21:16:54 +01:00
uint32_t pe_mem_config = 0 ;
2019-10-20 07:21:43 +01:00
uint32_t pe_logic_op = 0 ;
2016-12-23 19:58:23 +00:00
2019-11-15 16:35:50 +00:00
if ( fb - > nr_cbufs > 0 ) { /* at least one color buffer? */
struct etna_surface * cbuf = etna_surface ( fb - > cbufs [ 0 ] ) ;
2016-12-23 19:58:23 +00:00
struct etna_resource * res = etna_resource ( cbuf - > base . texture ) ;
bool color_supertiled = ( res - > layout & ETNA_LAYOUT_BIT_SUPER ) ! = 0 ;
2019-06-14 07:22:07 +01:00
uint32_t fmt = translate_pe_format ( cbuf - > base . format ) ;
2016-12-23 19:58:23 +00:00
assert ( res - > layout & ETNA_LAYOUT_BIT_TILE ) ; /* Cannot render to linear surfaces */
2019-08-10 22:00:32 +01:00
etna_update_render_resource ( pctx , etna_resource ( cbuf - > prsc ) ) ;
2016-12-23 19:58:23 +00:00
2019-06-14 07:22:07 +01:00
if ( fmt > = PE_FORMAT_R16F )
cs - > PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT ( fmt ) |
VIVS_PE_COLOR_FORMAT_FORMAT_MASK ;
else
cs - > PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT ( fmt ) ;
cs - > PE_COLOR_FORMAT | =
2016-12-23 19:58:23 +00:00
VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
VIVS_PE_COLOR_FORMAT_OVERWRITE |
2017-11-29 12:19:45 +00:00
COND ( color_supertiled , VIVS_PE_COLOR_FORMAT_SUPER_TILED ) |
2020-03-06 22:23:47 +00:00
COND ( color_supertiled & & screen - > specs . halti > = 5 , VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW ) ;
2016-12-23 19:58:23 +00:00
/* VIVS_PE_COLOR_FORMAT_COMPONENTS() and
* VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
* but only if we set the bits above . */
/* merged with depth_stencil_alpha */
if ( ( cbuf - > surf . offset & 63 ) | |
( ( ( cbuf - > surf . stride * 4 ) & 63 ) & & cbuf - > surf . height > 4 ) ) {
/* XXX Must make temporary surface here.
* Need the same mechanism on gc2000 when we want to do mipmap
* generation by
* rendering to levels > 1 due to multitiled / tiled conversion . */
BUG ( " Alignment error, trying to render to offset %08x with tile "
" stride %i " ,
cbuf - > surf . offset , cbuf - > surf . stride * 4 ) ;
}
2020-03-06 22:23:47 +00:00
if ( screen - > specs . pixel_pipes = = 1 ) {
2016-12-23 19:58:23 +00:00
cs - > PE_COLOR_ADDR = cbuf - > reloc [ 0 ] ;
cs - > PE_COLOR_ADDR . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
} else {
2017-04-14 08:44:27 +01:00
/* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */
2020-03-06 22:23:47 +00:00
assert ( ( res - > layout & ETNA_LAYOUT_BIT_MULTI ) | | screen - > specs . single_buffer ) ;
for ( int i = 0 ; i < screen - > specs . pixel_pipes ; i + + ) {
2016-12-23 19:58:23 +00:00
cs - > PE_PIPE_COLOR_ADDR [ i ] = cbuf - > reloc [ i ] ;
cs - > PE_PIPE_COLOR_ADDR [ i ] . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
}
}
cs - > PE_COLOR_STRIDE = cbuf - > surf . stride ;
if ( cbuf - > surf . ts_size ) {
cs - > TS_COLOR_CLEAR_VALUE = cbuf - > level - > clear_value ;
2019-08-12 16:43:26 +01:00
cs - > TS_COLOR_CLEAR_VALUE_EXT = cbuf - > level - > clear_value > > 32 ;
2016-12-23 19:58:23 +00:00
cs - > TS_COLOR_STATUS_BASE = cbuf - > ts_reloc ;
cs - > TS_COLOR_STATUS_BASE . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
cs - > TS_COLOR_SURFACE_BASE = cbuf - > reloc [ 0 ] ;
cs - > TS_COLOR_SURFACE_BASE . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
2019-07-01 21:16:54 +01:00
pe_mem_config | = VIVS_PE_MEM_CONFIG_COLOR_TS_MODE ( cbuf - > level - > ts_mode ) ;
2016-12-23 19:58:23 +00:00
2019-07-01 23:41:20 +01:00
if ( cbuf - > level - > ts_compress_fmt > = 0 ) {
/* overwrite bit breaks v1/v2 compression */
2020-03-06 22:23:47 +00:00
if ( ! screen - > specs . v4_compression )
2019-07-01 23:41:20 +01:00
cs - > PE_COLOR_FORMAT & = ~ VIVS_PE_COLOR_FORMAT_OVERWRITE ;
ts_mem_config | =
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION |
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT ( cbuf - > level - > ts_compress_fmt ) ;
}
2019-07-01 21:29:40 +01:00
}
2016-12-23 19:58:23 +00:00
nr_samples_color = cbuf - > base . texture - > nr_samples ;
2019-10-20 07:21:43 +01:00
if ( util_format_is_srgb ( cbuf - > base . format ) )
pe_logic_op | = VIVS_PE_LOGIC_OP_SRGB ;
2019-08-12 19:19:59 +01:00
cs - > PS_CONTROL = COND ( util_format_is_unorm ( cbuf - > base . format ) , VIVS_PS_CONTROL_SATURATE_RT0 ) ;
cs - > PS_CONTROL_EXT =
2020-03-06 22:23:47 +00:00
VIVS_PS_CONTROL_EXT_OUTPUT_MODE0 ( translate_output_mode ( cbuf - > base . format , screen - > specs . halti > = 5 ) ) ;
2016-12-23 19:58:23 +00:00
} else {
/* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and
* VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the
* color target */
2017-11-15 16:33:17 +00:00
cs - > PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE ;
2016-12-23 19:58:23 +00:00
cs - > PE_COLOR_STRIDE = 0 ;
cs - > TS_COLOR_STATUS_BASE . bo = NULL ;
cs - > TS_COLOR_SURFACE_BASE . bo = NULL ;
2018-11-14 13:51:49 +00:00
cs - > PE_COLOR_ADDR = ctx - > dummy_rt_reloc ;
2020-03-06 22:23:47 +00:00
for ( int i = 0 ; i < screen - > specs . pixel_pipes ; i + + )
2018-11-14 13:51:49 +00:00
cs - > PE_PIPE_COLOR_ADDR [ i ] = ctx - > dummy_rt_reloc ;
2016-12-23 19:58:23 +00:00
}
2019-11-15 16:35:50 +00:00
if ( fb - > zsbuf ! = NULL ) {
struct etna_surface * zsbuf = etna_surface ( fb - > zsbuf ) ;
2016-12-23 19:58:23 +00:00
struct etna_resource * res = etna_resource ( zsbuf - > base . texture ) ;
2019-08-10 22:00:32 +01:00
etna_update_render_resource ( pctx , etna_resource ( zsbuf - > prsc ) ) ;
2016-12-23 19:58:23 +00:00
assert ( res - > layout & ETNA_LAYOUT_BIT_TILE ) ; /* Cannot render to linear surfaces */
uint32_t depth_format = translate_depth_format ( zsbuf - > base . format ) ;
unsigned depth_bits =
depth_format = = VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24 ;
bool depth_supertiled = ( res - > layout & ETNA_LAYOUT_BIT_SUPER ) ! = 0 ;
cs - > PE_DEPTH_CONFIG =
depth_format |
COND ( depth_supertiled , VIVS_PE_DEPTH_CONFIG_SUPER_TILED ) |
2017-11-29 12:19:45 +00:00
VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z |
2019-09-02 19:46:15 +01:00
VIVS_PE_DEPTH_CONFIG_UNK18 | /* something to do with clipping? */
2020-03-06 22:23:47 +00:00
COND ( screen - > specs . halti > = 5 , VIVS_PE_DEPTH_CONFIG_DISABLE_ZS ) /* Needs to be enabled on GC7000, otherwise depth writes hang w/ TS - apparently it does something else now */
2017-11-29 12:19:45 +00:00
;
2016-12-23 19:58:23 +00:00
/* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */
/* merged with depth_stencil_alpha */
2020-03-06 22:23:47 +00:00
if ( screen - > specs . pixel_pipes = = 1 ) {
2016-12-23 19:58:23 +00:00
cs - > PE_DEPTH_ADDR = zsbuf - > reloc [ 0 ] ;
cs - > PE_DEPTH_ADDR . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
} else {
2020-03-06 22:23:47 +00:00
for ( int i = 0 ; i < screen - > specs . pixel_pipes ; i + + ) {
2016-12-23 19:58:23 +00:00
cs - > PE_PIPE_DEPTH_ADDR [ i ] = zsbuf - > reloc [ i ] ;
cs - > PE_PIPE_DEPTH_ADDR [ i ] . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
}
}
cs - > PE_DEPTH_STRIDE = zsbuf - > surf . stride ;
cs - > PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED ;
cs - > PE_DEPTH_NORMALIZE = fui ( exp2f ( depth_bits ) - 1.0f ) ;
if ( zsbuf - > surf . ts_size ) {
cs - > TS_DEPTH_CLEAR_VALUE = zsbuf - > level - > clear_value ;
cs - > TS_DEPTH_STATUS_BASE = zsbuf - > ts_reloc ;
cs - > TS_DEPTH_STATUS_BASE . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
cs - > TS_DEPTH_SURFACE_BASE = zsbuf - > reloc [ 0 ] ;
cs - > TS_DEPTH_SURFACE_BASE . flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE ;
2019-07-01 21:16:54 +01:00
pe_mem_config | = VIVS_PE_MEM_CONFIG_DEPTH_TS_MODE ( zsbuf - > level - > ts_mode ) ;
2019-07-01 23:41:20 +01:00
if ( zsbuf - > level - > ts_compress_fmt > = 0 ) {
ts_mem_config | =
VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION |
COND ( zsbuf - > level - > ts_compress_fmt = = COMPRESSION_FORMAT_D24S8 ,
VIVS_TS_MEM_CONFIG_STENCIL_ENABLE ) ;
}
2016-12-23 19:58:23 +00:00
}
ts_mem_config | = COND ( depth_bits = = 16 , VIVS_TS_MEM_CONFIG_DEPTH_16BPP ) ;
nr_samples_depth = zsbuf - > base . texture - > nr_samples ;
} else {
cs - > PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE ;
cs - > PE_DEPTH_ADDR . bo = NULL ;
cs - > PE_DEPTH_STRIDE = 0 ;
cs - > TS_DEPTH_STATUS_BASE . bo = NULL ;
cs - > TS_DEPTH_SURFACE_BASE . bo = NULL ;
for ( int i = 0 ; i < ETNA_MAX_PIXELPIPES ; i + + )
cs - > PE_PIPE_DEPTH_ADDR [ i ] . bo = NULL ;
}
/* MSAA setup */
if ( nr_samples_depth ! = - 1 & & nr_samples_color ! = - 1 & &
nr_samples_depth ! = nr_samples_color ) {
BUG ( " Number of samples in color and depth texture must match (%i and %i respectively) " ,
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 ;
}
cs - > TS_MEM_CONFIG = ts_mem_config ;
2019-07-01 21:16:54 +01:00
cs - > PE_MEM_CONFIG = pe_mem_config ;
2016-12-23 19:58:23 +00:00
2017-04-14 08:44:27 +01:00
/* Single buffer setup. There is only one switch for this, not a separate
* one per color buffer / depth buffer . To keep the logic simple always use
* single buffer when this feature is available .
2019-10-20 07:21:43 +01:00
* note : the blob will use 2 in some situations , figure out why ?
2017-04-14 08:44:27 +01:00
*/
2020-03-06 22:23:47 +00:00
pe_logic_op | = VIVS_PE_LOGIC_OP_SINGLE_BUFFER ( screen - > specs . single_buffer ? 3 : 0 ) ;
2019-10-20 07:21:43 +01:00
cs - > PE_LOGIC_OP = pe_logic_op ;
2017-04-14 08:44:27 +01:00
2018-12-17 08:56:00 +00:00
/* keep copy of original structure */
2019-11-15 16:35:50 +00:00
util_copy_framebuffer_state ( & ctx - > framebuffer_s , fb ) ;
2017-10-12 15:07:48 +01:00
ctx - > dirty | = ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS ;
2016-12-23 19:58:23 +00:00
}
static void
etna_set_polygon_stipple ( struct pipe_context * pctx ,
const struct pipe_poly_stipple * stipple )
{
/* NOP */
}
static void
etna_set_scissor_states ( struct pipe_context * pctx , unsigned start_slot ,
unsigned num_scissors , const struct pipe_scissor_state * ss )
{
struct etna_context * ctx = etna_context ( pctx ) ;
2016-11-25 06:42:43 +00:00
assert ( ss - > minx < = ss - > maxx ) ;
assert ( ss - > miny < = ss - > maxy ) ;
2016-12-23 19:58:23 +00:00
2020-03-22 10:16:58 +00:00
ctx - > scissor = * ss ;
2016-12-23 19:58:23 +00:00
ctx - > dirty | = ETNA_DIRTY_SCISSOR ;
}
static void
etna_set_viewport_states ( struct pipe_context * pctx , unsigned start_slot ,
unsigned num_scissors , const struct pipe_viewport_state * vs )
{
struct etna_context * ctx = etna_context ( pctx ) ;
struct compiled_viewport_state * cs = & ctx - > viewport ;
ctx - > viewport_s = * vs ;
/**
* For Vivante GPU , viewport z transformation is 0. .1 to 0. .1 instead of
* - 1. .1 to 0. .1 .
* scaling and translation to 0. .1 already happened , so remove that
*
* z ' = ( z * 2 - 1 ) * scale + translate
* = z * ( 2 * scale ) + ( translate - scale )
*
* scale ' = 2 * scale
* translate ' = translate - scale
*/
/* must be fixp as v4 state deltas assume it is */
cs - > PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16 ( vs - > scale [ 0 ] ) ;
cs - > PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16 ( vs - > scale [ 1 ] ) ;
cs - > PA_VIEWPORT_SCALE_Z = fui ( vs - > scale [ 2 ] * 2.0f ) ;
cs - > PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16 ( vs - > translate [ 0 ] ) ;
cs - > PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16 ( vs - > translate [ 1 ] ) ;
cs - > PA_VIEWPORT_OFFSET_Z = fui ( vs - > translate [ 2 ] - vs - > scale [ 2 ] ) ;
/* Compute scissor rectangle (fixp) from viewport.
* Make sure left is always < right and top always < bottom .
*/
2020-03-22 10:07:16 +00:00
cs - > SE_SCISSOR_LEFT = MAX2 ( vs - > translate [ 0 ] - fabsf ( vs - > scale [ 0 ] ) , 0.0f ) ;
cs - > SE_SCISSOR_TOP = MAX2 ( vs - > translate [ 1 ] - fabsf ( vs - > scale [ 1 ] ) , 0.0f ) ;
cs - > SE_SCISSOR_RIGHT = ceilf ( MAX2 ( vs - > translate [ 0 ] + fabsf ( vs - > scale [ 0 ] ) , 0.0f ) ) ;
cs - > SE_SCISSOR_BOTTOM = ceilf ( MAX2 ( vs - > translate [ 1 ] + fabsf ( vs - > scale [ 1 ] ) , 0.0f ) ) ;
2016-12-23 19:58:23 +00:00
cs - > PE_DEPTH_NEAR = fui ( 0.0 ) ; /* not affected if depth mode is Z (as in GL) */
cs - > PE_DEPTH_FAR = fui ( 1.0 ) ;
ctx - > dirty | = ETNA_DIRTY_VIEWPORT ;
}
static void
etna_set_vertex_buffers ( struct pipe_context * pctx , unsigned start_slot ,
unsigned num_buffers , const struct pipe_vertex_buffer * vb )
{
struct etna_context * ctx = etna_context ( pctx ) ;
struct etna_vertexbuf_state * so = & ctx - > vertex_buffer ;
util_set_vertex_buffers_mask ( so - > vb , & so - > enabled_mask , vb , start_slot , num_buffers ) ;
so - > count = util_last_bit ( so - > enabled_mask ) ;
for ( unsigned idx = start_slot ; idx < start_slot + num_buffers ; + + idx ) {
struct compiled_set_vertex_buffer * cs = & so - > cvb [ idx ] ;
struct pipe_vertex_buffer * vbi = & so - > vb [ idx ] ;
2017-04-02 13:30:16 +01:00
assert ( ! vbi - > is_user_buffer ) ; /* XXX support user_buffer using
etna_usermem_map */
2016-12-23 19:58:23 +00:00
2017-04-02 13:30:16 +01:00
if ( vbi - > buffer . resource ) { /* GPU buffer */
cs - > FE_VERTEX_STREAM_BASE_ADDR . bo = etna_resource ( vbi - > buffer . resource ) - > bo ;
2016-12-23 19:58:23 +00:00
cs - > FE_VERTEX_STREAM_BASE_ADDR . offset = vbi - > buffer_offset ;
cs - > FE_VERTEX_STREAM_BASE_ADDR . flags = ETNA_RELOC_READ ;
cs - > FE_VERTEX_STREAM_CONTROL =
FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE ( vbi - > stride ) ;
} else {
cs - > FE_VERTEX_STREAM_BASE_ADDR . bo = NULL ;
cs - > FE_VERTEX_STREAM_CONTROL = 0 ;
}
}
ctx - > dirty | = ETNA_DIRTY_VERTEX_BUFFERS ;
}
static void
etna_blend_state_bind ( struct pipe_context * pctx , void * bs )
{
struct etna_context * ctx = etna_context ( pctx ) ;
ctx - > blend = bs ;
ctx - > dirty | = ETNA_DIRTY_BLEND ;
}
static void
etna_blend_state_delete ( struct pipe_context * pctx , void * bs )
{
FREE ( bs ) ;
}
static void
etna_rasterizer_state_bind ( struct pipe_context * pctx , void * rs )
{
struct etna_context * ctx = etna_context ( pctx ) ;
ctx - > rasterizer = rs ;
ctx - > dirty | = ETNA_DIRTY_RASTERIZER ;
}
static void
etna_rasterizer_state_delete ( struct pipe_context * pctx , void * rs )
{
FREE ( rs ) ;
}
static void
etna_zsa_state_bind ( struct pipe_context * pctx , void * zs )
{
struct etna_context * ctx = etna_context ( pctx ) ;
ctx - > zsa = zs ;
ctx - > dirty | = ETNA_DIRTY_ZSA ;
}
static void
etna_zsa_state_delete ( struct pipe_context * pctx , void * zs )
{
FREE ( zs ) ;
}
/** Create vertex element states, which define a layout for fetching
* vertices for rendering .
*/
static void *
etna_vertex_elements_state_create ( struct pipe_context * pctx ,
unsigned num_elements , const struct pipe_vertex_element * elements )
{
struct etna_context * ctx = etna_context ( pctx ) ;
2020-03-06 22:23:47 +00:00
struct etna_screen * screen = ctx - > screen ;
2016-12-23 19:58:23 +00:00
struct compiled_vertex_elements_state * cs = CALLOC_STRUCT ( compiled_vertex_elements_state ) ;
if ( ! cs )
return NULL ;
2020-03-06 22:23:47 +00:00
if ( num_elements > screen - > specs . vertex_max_elements ) {
2016-12-23 19:58:23 +00:00
BUG ( " number of elements (%u) exceeds chip maximum (%u) " , num_elements ,
2020-03-06 22:23:47 +00:00
screen - > specs . vertex_max_elements ) ;
2016-12-23 19:58:23 +00:00
return NULL ;
}
/* XXX could minimize number of consecutive stretches here by sorting, and
* permuting the inputs in shader or does Mesa do this already ? */
cs - > num_elements = num_elements ;
unsigned start_offset = 0 ; /* start of current consecutive stretch */
bool nonconsecutive = true ; /* previous value of nonconsecutive */
2020-01-06 02:38:15 +00:00
uint32_t buffer_mask = 0 ; /* mask of buffer_idx already seen */
2016-12-23 19:58:23 +00:00
for ( unsigned idx = 0 ; idx < num_elements ; + + idx ) {
2020-01-06 02:38:15 +00:00
unsigned buffer_idx = elements [ idx ] . vertex_buffer_index ;
2016-12-23 19:58:23 +00:00
unsigned element_size = util_format_get_blocksize ( elements [ idx ] . src_format ) ;
unsigned end_offset = elements [ idx ] . src_offset + element_size ;
uint32_t format_type , normalize ;
if ( nonconsecutive )
start_offset = elements [ idx ] . src_offset ;
2020-01-06 02:53:36 +00:00
/* guaranteed by PIPE_CAP_MAX_VERTEX_BUFFERS */
2020-03-06 22:23:47 +00:00
assert ( buffer_idx < screen - > specs . stream_count ) ;
2020-01-06 02:53:36 +00:00
2016-12-23 19:58:23 +00:00
/* maximum vertex size is 256 bytes */
2019-12-09 15:31:47 +00:00
assert ( element_size ! = 0 & & ( end_offset - start_offset ) < 256 ) ;
2016-12-23 19:58:23 +00:00
/* check whether next element is consecutive to this one */
nonconsecutive = ( idx = = ( num_elements - 1 ) ) | |
2020-01-06 02:38:15 +00:00
elements [ idx + 1 ] . vertex_buffer_index ! = buffer_idx | |
2016-12-23 19:58:23 +00:00
end_offset ! = elements [ idx + 1 ] . src_offset ;
format_type = translate_vertex_format_type ( elements [ idx ] . src_format ) ;
normalize = translate_vertex_format_normalize ( elements [ idx ] . src_format ) ;
assert ( format_type ! = ETNA_NO_MATCH ) ;
assert ( normalize ! = ETNA_NO_MATCH ) ;
2020-03-06 22:23:47 +00:00
if ( screen - > specs . halti < 5 ) {
2017-11-29 12:19:45 +00:00
cs - > FE_VERTEX_ELEMENT_CONFIG [ idx ] =
COND ( nonconsecutive , VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE ) |
format_type |
VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM ( util_format_get_nr_components ( elements [ idx ] . src_format ) ) |
normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN ( ENDIAN_MODE_NO_SWAP ) |
2020-01-06 02:38:15 +00:00
VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM ( buffer_idx ) |
2017-11-29 12:19:45 +00:00
VIVS_FE_VERTEX_ELEMENT_CONFIG_START ( elements [ idx ] . src_offset ) |
VIVS_FE_VERTEX_ELEMENT_CONFIG_END ( end_offset - start_offset ) ;
} else { /* HALTI5 spread vertex attrib config over two registers */
cs - > NFE_GENERIC_ATTRIB_CONFIG0 [ idx ] =
format_type |
VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM ( util_format_get_nr_components ( elements [ idx ] . src_format ) ) |
normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN ( ENDIAN_MODE_NO_SWAP ) |
2020-01-06 02:38:15 +00:00
VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM ( buffer_idx ) |
2017-11-29 12:19:45 +00:00
VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START ( elements [ idx ] . src_offset ) ;
cs - > NFE_GENERIC_ATTRIB_CONFIG1 [ idx ] =
COND ( nonconsecutive , VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE ) |
VIVS_NFE_GENERIC_ATTRIB_CONFIG1_END ( end_offset - start_offset ) ;
}
2019-10-19 18:12:53 +01:00
if ( util_format_is_pure_integer ( elements [ idx ] . src_format ) )
cs - > NFE_GENERIC_ATTRIB_SCALE [ idx ] = 1 ;
else
cs - > NFE_GENERIC_ATTRIB_SCALE [ idx ] = fui ( 1.0f ) ;
2020-01-06 02:38:15 +00:00
/* instance_divisor is part of elements state but should be the same for all buffers */
if ( buffer_mask & 1 < < buffer_idx )
assert ( cs - > NFE_VERTEX_STREAMS_VERTEX_DIVISOR [ buffer_idx ] = = elements [ idx ] . instance_divisor ) ;
else
cs - > NFE_VERTEX_STREAMS_VERTEX_DIVISOR [ buffer_idx ] = elements [ idx ] . instance_divisor ;
buffer_mask | = 1 < < buffer_idx ;
cs - > num_buffers = MAX2 ( cs - > num_buffers , buffer_idx + 1 ) ;
2016-12-23 19:58:23 +00:00
}
return cs ;
}
static void
etna_vertex_elements_state_delete ( struct pipe_context * pctx , void * ve )
{
FREE ( ve ) ;
}
static void
etna_vertex_elements_state_bind ( struct pipe_context * pctx , void * ve )
{
struct etna_context * ctx = etna_context ( pctx ) ;
ctx - > vertex_elements = ve ;
ctx - > dirty | = ETNA_DIRTY_VERTEX_ELEMENTS ;
}
2017-10-12 15:07:48 +01:00
static bool
etna_update_ts_config ( struct etna_context * ctx )
{
uint32_t new_ts_config = ctx - > framebuffer . TS_MEM_CONFIG ;
if ( ctx - > framebuffer_s . nr_cbufs > 0 ) {
struct etna_surface * c_surf = etna_surface ( ctx - > framebuffer_s . cbufs [ 0 ] ) ;
if ( c_surf - > level - > ts_size & & c_surf - > level - > ts_valid ) {
new_ts_config | = VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR ;
} else {
new_ts_config & = ~ VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR ;
}
}
if ( ctx - > framebuffer_s . zsbuf ) {
struct etna_surface * zs_surf = etna_surface ( ctx - > framebuffer_s . zsbuf ) ;
if ( zs_surf - > level - > ts_size & & zs_surf - > level - > ts_valid ) {
new_ts_config | = VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR ;
} else {
new_ts_config & = ~ VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR ;
}
}
2018-01-11 10:29:29 +00:00
if ( new_ts_config ! = ctx - > framebuffer . TS_MEM_CONFIG | |
( ctx - > dirty & ETNA_DIRTY_FRAMEBUFFER ) ) {
2017-10-12 15:07:48 +01:00
ctx - > framebuffer . TS_MEM_CONFIG = new_ts_config ;
ctx - > dirty | = ETNA_DIRTY_TS ;
}
ctx - > dirty & = ~ ETNA_DIRTY_DERIVE_TS ;
return true ;
}
2020-03-21 10:24:48 +00:00
static bool
etna_update_clipping ( struct etna_context * ctx )
{
const struct etna_rasterizer_state * rasterizer = etna_rasterizer_state ( ctx - > rasterizer ) ;
2020-03-22 21:42:35 +00:00
const struct pipe_framebuffer_state * fb = & ctx - > framebuffer_s ;
2020-03-21 10:24:48 +00:00
/* clip framebuffer against viewport */
2020-03-22 21:42:35 +00:00
uint32_t scissor_left = ctx - > viewport . SE_SCISSOR_LEFT ;
uint32_t scissor_top = ctx - > viewport . SE_SCISSOR_TOP ;
uint32_t scissor_right = MIN2 ( fb - > width , ctx - > viewport . SE_SCISSOR_RIGHT ) ;
uint32_t scissor_bottom = MIN2 ( fb - > height , ctx - > viewport . SE_SCISSOR_BOTTOM ) ;
2020-03-21 10:24:48 +00:00
/* clip against scissor */
if ( rasterizer - > scissor ) {
2020-03-22 10:16:58 +00:00
scissor_left = MAX2 ( ctx - > scissor . minx , scissor_left ) ;
scissor_top = MAX2 ( ctx - > scissor . miny , scissor_top ) ;
scissor_right = MIN2 ( ctx - > scissor . maxx , scissor_right ) ;
scissor_bottom = MIN2 ( ctx - > scissor . maxy , scissor_bottom ) ;
2020-03-21 10:24:48 +00:00
}
2020-03-22 10:13:12 +00:00
ctx - > clipping . minx = scissor_left ;
ctx - > clipping . miny = scissor_top ;
ctx - > clipping . maxx = scissor_right ;
ctx - > clipping . maxy = scissor_bottom ;
2020-03-21 10:24:48 +00:00
ctx - > dirty | = ETNA_DIRTY_SCISSOR_CLIP ;
return true ;
}
2016-12-23 19:58:23 +00:00
struct etna_state_updater {
bool ( * update ) ( struct etna_context * ctx ) ;
uint32_t dirty ;
} ;
static const struct etna_state_updater etna_state_updates [ ] = {
{
etna_shader_update_vertex , ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS ,
} ,
{
etna_shader_link , ETNA_DIRTY_SHADER ,
2017-06-04 20:06:32 +01:00
} ,
{
etna_update_blend , ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER
2017-06-05 20:11:02 +01:00
} ,
{
etna_update_blend_color , ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER ,
2017-10-12 15:07:48 +01:00
} ,
{
etna_update_ts_config , ETNA_DIRTY_DERIVE_TS ,
2020-03-21 10:24:48 +00:00
} ,
{
etna_update_clipping , ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT ,
2016-12-23 19:58:23 +00:00
}
} ;
bool
etna_state_update ( struct etna_context * ctx )
{
for ( unsigned int i = 0 ; i < ARRAY_SIZE ( etna_state_updates ) ; i + + )
if ( ctx - > dirty & etna_state_updates [ i ] . dirty )
if ( ! etna_state_updates [ i ] . update ( ctx ) )
return false ;
return true ;
}
void
etna_state_init ( struct pipe_context * pctx )
{
pctx - > set_blend_color = etna_set_blend_color ;
pctx - > set_stencil_ref = etna_set_stencil_ref ;
pctx - > set_clip_state = etna_set_clip_state ;
pctx - > set_sample_mask = etna_set_sample_mask ;
pctx - > set_constant_buffer = etna_set_constant_buffer ;
pctx - > set_framebuffer_state = etna_set_framebuffer_state ;
pctx - > set_polygon_stipple = etna_set_polygon_stipple ;
pctx - > set_scissor_states = etna_set_scissor_states ;
pctx - > set_viewport_states = etna_set_viewport_states ;
pctx - > set_vertex_buffers = etna_set_vertex_buffers ;
pctx - > bind_blend_state = etna_blend_state_bind ;
pctx - > delete_blend_state = etna_blend_state_delete ;
pctx - > bind_rasterizer_state = etna_rasterizer_state_bind ;
pctx - > delete_rasterizer_state = etna_rasterizer_state_delete ;
pctx - > bind_depth_stencil_alpha_state = etna_zsa_state_bind ;
pctx - > delete_depth_stencil_alpha_state = etna_zsa_state_delete ;
pctx - > create_vertex_elements_state = etna_vertex_elements_state_create ;
pctx - > delete_vertex_elements_state = etna_vertex_elements_state_delete ;
pctx - > bind_vertex_elements_state = etna_vertex_elements_state_bind ;
}