@ -49,6 +49,8 @@
# include "vrend_blitter.h"
# define DEST_SWIZZLE_SNIPPET_SIZE 64
struct vrend_blitter_ctx {
virgl_gl_context gl_context ;
bool initialised ;
@ -59,10 +61,9 @@ struct vrend_blitter_ctx {
GLuint vs ;
GLuint vs_pos_only ;
GLuint fs_texfetch_col [ PIPE_MAX_TEXTURE_TYPES ] ;
GLuint fs_texfetch_col_ignore_alpha [ PIPE_MAX_TEXTURE_TYPES ] ;
GLuint fs_texfetch_col_emu_alpha [ PIPE_MAX_TEXTURE_TYPES ] ;
GLuint fs_texfetch_depth [ PIPE_MAX_TEXTURE_TYPES ] ;
GLuint fs_texfetch_depth_msaa [ PIPE_MAX_TEXTURE_TYPES ] ;
GLuint fs_texfetch_col_swizzle ;
GLuint fb_id ;
unsigned dst_width ;
@ -105,68 +106,44 @@ static bool blit_build_vs_passthrough(struct vrend_blitter_ctx *blit_ctx)
return true ;
}
static GLuint blit_build_frag_tex_col ( struct vrend_blitter_ctx * blit_ctx , int tgsi_tex_target )
static void create_dest_swizzle_snippet ( const uint8_t swizzle [ 4 ] ,
char snippet [ DEST_SWIZZLE_SNIPPET_SIZE ] )
{
GLuint fs_id ;
char shader_buf [ 4096 ] ;
int is_shad ;
const char * twm ;
const char * ext_str = " " ;
switch ( tgsi_tex_target ) {
case TGSI_TEXTURE_1D :
case TGSI_TEXTURE_BUFFER :
twm = " .x " ;
break ;
case TGSI_TEXTURE_1D_ARRAY :
case TGSI_TEXTURE_2D :
case TGSI_TEXTURE_RECT :
case TGSI_TEXTURE_2D_MSAA :
default :
twm = " .xy " ;
break ;
case TGSI_TEXTURE_SHADOW1D :
case TGSI_TEXTURE_SHADOW2D :
case TGSI_TEXTURE_SHADOW1D_ARRAY :
case TGSI_TEXTURE_SHADOWRECT :
case TGSI_TEXTURE_3D :
case TGSI_TEXTURE_CUBE :
case TGSI_TEXTURE_2D_ARRAY :
case TGSI_TEXTURE_2D_ARRAY_MSAA :
twm = " .xyz " ;
break ;
case TGSI_TEXTURE_SHADOWCUBE :
case TGSI_TEXTURE_SHADOW2D_ARRAY :
case TGSI_TEXTURE_SHADOWCUBE_ARRAY :
case TGSI_TEXTURE_CUBE_ARRAY :
twm = " " ;
break ;
static const uint8_t invalid_swizzle = 0xff ;
ssize_t si = 0 ;
uint8_t inverse [ 4 ] = { invalid_swizzle , invalid_swizzle , invalid_swizzle ,
invalid_swizzle } ;
for ( int i = 0 ; i < 4 ; + + i ) {
if ( swizzle [ i ] > 3 ) continue ;
if ( inverse [ swizzle [ i ] ] = = invalid_swizzle )
inverse [ swizzle [ i ] ] = i ;
}
if ( tgsi_tex_target = = TGSI_TEXTURE_CUBE_ARRAY | |
tgsi_tex_target = = TGSI_TEXTURE_SHADOWCUBE_ARRAY )
ext_str = " #extension GL_ARB_texture_cube_map_array : require \n " ;
snprintf ( shader_buf , 4096 , blit_ctx - > use_gles ? FS_TEXFETCH_COL_GLES : FS_TEXFETCH_COL_GL ,
ext_str , vrend_shader_samplertypeconv ( tgsi_tex_target , & is_shad ) , twm , " " ) ;
fs_id = glCreateShader ( GL_FRAGMENT_SHADER ) ;
if ( ! build_and_check ( fs_id , shader_buf ) ) {
glDeleteShader ( fs_id ) ;
return 0 ;
for ( int i = 0 ; i < 4 ; + + i ) {
int res = - 1 ;
if ( inverse [ i ] > 3 ) {
/* Use 0.0f for unused color values, 1.0f for an unused alpha value */
res = snprintf ( & snippet [ si ] , DEST_SWIZZLE_SNIPPET_SIZE - si ,
i < 3 ? " 0.0f, " : " 1.0f " ) ;
} else {
res = snprintf ( & snippet [ si ] , DEST_SWIZZLE_SNIPPET_SIZE - si ,
" texel.%c%s " , " rgba " [ inverse [ i ] ] , i < 3 ? " , " : " " ) ;
}
si + = res > 0 ? res : 0 ;
}
return fs_id ;
}
static GLuint blit_build_frag_tex_col_ignore_alpha ( struct vrend_blitter_ctx * blit_ctx , int tgsi_tex_target )
static GLuint blit_build_frag_tex_col ( struct vrend_blitter_ctx * blit_ctx ,
int tgsi_tex_target ,
const uint8_t swizzle [ 4 ] )
{
GLuint fs_id ;
char shader_buf [ 4096 ] ;
int is_shad ;
const char * twm ;
const char * ext_str = " " ;
char dest_swizzle_snippet [ DEST_SWIZZLE_SNIPPET_SIZE ] = " texel " ;
switch ( tgsi_tex_target ) {
case TGSI_TEXTURE_1D :
case TGSI_TEXTURE_BUFFER :
@ -201,62 +178,12 @@ static GLuint blit_build_frag_tex_col_ignore_alpha(struct vrend_blitter_ctx *bli
tgsi_tex_target = = TGSI_TEXTURE_SHADOWCUBE_ARRAY )
ext_str = " #extension GL_ARB_texture_cube_map_array : require \n " ;
snprintf ( shader_buf , 4096 , blit_ctx - > use_gles ? FS_TEXFETCH_COL_IGNORE_ALPHA_GLES : FS_TEXFETCH_COL_IGNORE_ALPHA_GL ,
ext_str , vrend_shader_samplertypeconv ( tgsi_tex_target , & is_shad ) , twm , " " ) ;
fs_id = glCreateShader ( GL_FRAGMENT_SHADER ) ;
if ( ! build_and_check ( fs_id , shader_buf ) ) {
glDeleteShader ( fs_id ) ;
return 0 ;
}
return fs_id ;
}
if ( swizzle )
create_dest_swizzle_snippet ( swizzle , dest_swizzle_snippet ) ;
static GLuint blit_build_frag_tex_col_emu_alpha ( struct vrend_blitter_ctx * blit_ctx , int tgsi_tex_target )
{
GLuint fs_id ;
char shader_buf [ 4096 ] ;
int is_shad ;
const char * twm ;
const char * ext_str = " " ;
switch ( tgsi_tex_target ) {
case TGSI_TEXTURE_1D :
case TGSI_TEXTURE_BUFFER :
twm = " .x " ;
break ;
case TGSI_TEXTURE_1D_ARRAY :
case TGSI_TEXTURE_2D :
case TGSI_TEXTURE_RECT :
case TGSI_TEXTURE_2D_MSAA :
default :
twm = " .xy " ;
break ;
case TGSI_TEXTURE_SHADOW1D :
case TGSI_TEXTURE_SHADOW2D :
case TGSI_TEXTURE_SHADOW1D_ARRAY :
case TGSI_TEXTURE_SHADOWRECT :
case TGSI_TEXTURE_3D :
case TGSI_TEXTURE_CUBE :
case TGSI_TEXTURE_2D_ARRAY :
case TGSI_TEXTURE_2D_ARRAY_MSAA :
twm = " .xyz " ;
break ;
case TGSI_TEXTURE_SHADOWCUBE :
case TGSI_TEXTURE_SHADOW2D_ARRAY :
case TGSI_TEXTURE_SHADOWCUBE_ARRAY :
case TGSI_TEXTURE_CUBE_ARRAY :
twm = " " ;
break ;
}
if ( tgsi_tex_target = = TGSI_TEXTURE_CUBE_ARRAY | |
tgsi_tex_target = = TGSI_TEXTURE_SHADOWCUBE_ARRAY )
ext_str = " #extension GL_ARB_texture_cube_map_array : require \n " ;
snprintf ( shader_buf , 4096 , blit_ctx - > use_gles ? FS_TEXFETCH_COL_ALPHA_DEST_GLES : FS_TEXFETCH_COL_ALPHA_DEST_GL ,
ext_str , vrend_shader_samplertypeconv ( tgsi_tex_target , & is_shad ) , twm , " " ) ;
snprintf ( shader_buf , 4096 , blit_ctx - > use_gles ? FS_TEXFETCH_COL_GLES : FS_TEXFETCH_COL_GL ,
ext_str , vrend_shader_samplertypeconv ( tgsi_tex_target , & is_shad ) , twm ,
dest_swizzle_snippet ) ;
fs_id = glCreateShader ( GL_FRAGMENT_SHADER ) ;
@ -378,55 +305,30 @@ static GLuint blit_get_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, i
}
}
static GLuint blit_get_frag_tex_col ( struct vrend_blitter_ctx * blit_ctx , int pipe_tex_target , unsigned nr_samples )
static GLuint blit_get_frag_tex_col ( struct vrend_blitter_ctx * blit_ctx , int pipe_tex_target , unsigned nr_samples , const struct vrend_format_table * entry )
{
assert ( pipe_tex_target < PIPE_MAX_TEXTURE_TYPES ) ;
if ( nr_samples > 1 ) {
return 0 ;
} else {
GLuint * shader = & blit_ctx - > fs_texfetch_col [ pipe_tex_target ] ;
if ( ! * shader ) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex ( pipe_tex_target , 0 ) ;
* shader = blit_build_frag_tex_col ( blit_ctx , tgsi_tex ) ;
} else if ( entry - > flags & VREND_BIND_NEED_SWIZZLE ) {
GLuint * shader = & blit_ctx - > fs_texfetch_col_swizzle ;
if ( shader ) {
glDeleteShader ( * shader ) ;
}
return * shader ;
}
}
static GLuint blit_get_frag_tex_col_ignore_alpha ( struct vrend_blitter_ctx * blit_ctx , int pipe_tex_target , unsigned nr_samples )
{
assert ( pipe_tex_target < PIPE_MAX_TEXTURE_TYPES ) ;
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex ( pipe_tex_target , 0 ) ;
if ( nr_samples > 1 ) {
return 0 ;
} else {
GLuint * shader = & blit_ctx - > fs_texfetch_col_ignore_alpha [ pipe_tex_target ] ;
if ( ! * shader ) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex ( pipe_tex_target , 0 ) ;
* shader = blit_build_frag_tex_col ( blit_ctx , tgsi_tex , entry - > swizzle ) ;
* shader = blit_build_frag_tex_col_ignore_alpha ( blit_ctx , tgsi_tex ) ;
}
return * shader ;
}
}
static GLuint blit_get_frag_tex_col_emu_alpha ( struct vrend_blitter_ctx * blit_ctx , int pipe_tex_target , unsigned nr_samples )
{
assert ( pipe_tex_target < PIPE_MAX_TEXTURE_TYPES ) ;
if ( nr_samples > 1 ) {
return 0 ;
} else {
GLuint * shader = & blit_ctx - > fs_texfetch_col_emu_alpha [ pipe_tex_target ] ;
GLuint * shader = & blit_ctx - > fs_texfetch_col [ pipe_tex_target ] ;
if ( ! * shader ) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex ( pipe_tex_target , 0 ) ;
* shader = blit_build_frag_tex_col_emu_alpha ( blit_ctx , tgsi_tex ) ;
* shader = blit_build_frag_tex_col ( blit_ctx , tgsi_tex , NULL ) ;
}
return * shader ;
}
@ -652,6 +554,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx,
util_format_description ( dst_res - > base . format ) ;
const struct vrend_format_table * src_entry =
vrend_get_format_table_entry ( info - > src . format ) ;
const struct vrend_format_table * dst_entry =
vrend_get_format_table_entry ( info - > dst . format ) ;
has_depth = util_format_has_depth ( src_desc ) & &
util_format_has_depth ( dst_desc ) ;
@ -678,12 +582,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx,
if ( blit_depth | | blit_stencil )
fs_id = blit_get_frag_tex_writedepth ( blit_ctx , src_res - > base . target , src_res - > base . nr_samples ) ;
else if ( vrend_format_is_emulated_alpha ( info - > dst . format ) )
fs_id = blit_get_frag_tex_col_emu_alpha ( blit_ctx , src_res - > base . target , src_res - > base . nr_samples ) ;
else if ( src_res - > base . format = = VIRGL_FORMAT_R8G8B8X8_UNORM )
fs_id = blit_get_frag_tex_col_ignore_alpha ( blit_ctx , src_res - > base . target , src_res - > base . nr_samples ) ;
else
fs_id = blit_get_frag_tex_col ( blit_ctx , src_res - > base . target , src_res - > base . nr_samples ) ;
fs_id = blit_get_frag_tex_col ( blit_ctx , src_res - > base . target , src_res - > base . nr_samples , dst_entry ) ;
glAttachShader ( prog_id , fs_id ) ;
glLinkProgram ( prog_id ) ;