drm/radeon/kms: align height of fb allocation.
Subsystems (2)
Dave Airlie
maintainerPATCH 1/2 drm/radeon/kms: align height of fb allocation.
From: Dave Airlie <[email protected]>
this aligns the height of the fb allocation so it doesn't trip over the size checks later when we use this from userspace to copy the buffer at X start.
Signed-off-by Dave Airlie <[email protected]>
--- drivers/gpu/drm/radeon/radeon_fb.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/gpu/drm/radeon/radeon_fb.c +4 -1
@@ -113,11 +113,14 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,u32 tiling_flags =0 ;int ret;int aligned_size, size; +int height = mode_cmd->height;/* need to align pitch with crtc limits */ mode_cmd->pitch =radeon_align_pitch (rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp +1 ) /8 ); - size = mode_cmd->pitch * mode_cmd->height; +if (rdev->family >=CHIP_R600 ) + height =ALIGN (mode_cmd->height,8 ); + size = mode_cmd->pitch * height; aligned_size =ALIGN (size,PAGE_SIZE ); ret = radeon_gem_object_create(rdev, aligned_size, 0, RADEON_GEM_DOMAIN_VRAM,
Signature · 1 line
1.7.3.2
Dave Airlie
maintainerPATCH 2/2 drm/radeon: overhaul texture checking. (v3)
From: Dave Airlie <[email protected]>
the texture checking code didn't work for block formats like s3tc, this overhauls it to work for all types.
v2: add texture array support.
v3: add subsampled formats
Signed-off-by Dave Airlie <[email protected]>
--- drivers/gpu/drm/radeon/r600_cs.c | 353 ++++++++++++++++++++++++++------------ drivers/gpu/drm/radeon/r600d.h | 5 + 2 files changed, 245 insertions(+), 113 deletions(-)
drivers/gpu/drm/radeon/r600_cs.c +241 -114
@@ -71,75 +71,164 @@ struct r600_cs_track {u64 db_bo_mc; }; +#define FMT_8_BIT (fmt, vc) [fmt] = { 1, 1, 1, vc } +#define FMT_16_BIT (fmt, vc) [fmt] = { 1, 1, 2, vc } +#define FMT_24_BIT (fmt) [fmt] = { 1, 1, 3, 0 } +#define FMT_32_BIT (fmt, vc) [fmt] = { 1, 1, 4, vc } +#define FMT_48_BIT (fmt) [fmt] = { 1, 1, 6, 0 } +#define FMT_64_BIT (fmt, vc) [fmt] = { 1, 1, 8, vc } +#define FMT_96_BIT (fmt) [fmt] = { 1, 1, 12, 0 } +#define FMT_128_BIT (fmt, vc) [fmt] = { 1, 1, 16, vc } + +struct gpu_formats { +unsigned blockwidth; +unsigned blockheight; +unsigned blocksize; +unsigned valid_color; +}; + +static const struct gpu_formats color_formats_table[] = { +/* 8 bit */ +FMT_8_BIT (V_038004_COLOR_8 ,1 ), +FMT_8_BIT (V_038004_COLOR_4_4 ,1 ), +FMT_8_BIT (V_038004_COLOR_3_3_2 ,1 ), +FMT_8_BIT (V_038004_FMT_1 ,0 ), + +/* 16-bit */ +FMT_16_BIT (V_038004_COLOR_16 ,1 ), +FMT_16_BIT (V_038004_COLOR_16_FLOAT ,1 ), +FMT_16_BIT (V_038004_COLOR_8_8 ,1 ), +FMT_16_BIT (V_038004_COLOR_5_6_5 ,1 ), +FMT_16_BIT (V_038004_COLOR_6_5_5 ,1 ), +FMT_16_BIT (V_038004_COLOR_1_5_5_5 ,1 ), +FMT_16_BIT (V_038004_COLOR_4_4_4_4 ,1 ), +FMT_16_BIT (V_038004_COLOR_5_5_5_1 ,1 ), + +/* 24-bit */ +FMT_24_BIT (V_038004_FMT_8_8_8 ), + +/* 32-bit */ +FMT_32_BIT (V_038004_COLOR_32 ,1 ), +FMT_32_BIT (V_038004_COLOR_32_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_16_16 ,1 ), +FMT_32_BIT (V_038004_COLOR_16_16_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_8_24 ,1 ), +FMT_32_BIT (V_038004_COLOR_8_24_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_24_8 ,1 ), +FMT_32_BIT (V_038004_COLOR_24_8_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_10_11_11 ,1 ), +FMT_32_BIT (V_038004_COLOR_10_11_11_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_11_11_10 ,1 ), +FMT_32_BIT (V_038004_COLOR_11_11_10_FLOAT ,1 ), +FMT_32_BIT (V_038004_COLOR_2_10_10_10 ,1 ), +FMT_32_BIT (V_038004_COLOR_8_8_8_8 ,1 ), +FMT_32_BIT (V_038004_COLOR_10_10_10_2 ,1 ), +FMT_32_BIT (V_038004_FMT_5_9_9_9_SHAREDEXP ,0 ), +FMT_32_BIT (V_038004_FMT_32_AS_8 ,0 ), +FMT_32_BIT (V_038004_FMT_32_AS_8_8 ,0 ), + +/* 48-bit */ +FMT_48_BIT (V_038004_FMT_16_16_16 ), +FMT_48_BIT (V_038004_FMT_16_16_16_FLOAT ), + +/* 64-bit */ +FMT_64_BIT (V_038004_COLOR_X24_8_32_FLOAT ,1 ), +FMT_64_BIT (V_038004_COLOR_32_32 ,1 ), +FMT_64_BIT (V_038004_COLOR_32_32_FLOAT ,1 ), +FMT_64_BIT (V_038004_COLOR_16_16_16_16 ,1 ), +FMT_64_BIT (V_038004_COLOR_16_16_16_16_FLOAT ,1 ), + +FMT_96_BIT (V_038004_FMT_32_32_32 ), +FMT_96_BIT (V_038004_FMT_32_32_32_FLOAT ), + +/* 128-bit */ +FMT_128_BIT (V_038004_COLOR_32_32_32_32 ,1 ), +FMT_128_BIT (V_038004_COLOR_32_32_32_32_FLOAT ,1 ), + + [V_038004_FMT_GB_GR ] = {2 ,1 ,4 ,0 }, + [V_038004_FMT_BG_RG ] = {2 ,1 ,4 ,0 }, + +/* block compressed formats */ + [V_038004_FMT_BC1 ] = {4 ,4 ,8 ,0 }, + [V_038004_FMT_BC2 ] = {4 ,4 ,16 ,0 }, + [V_038004_FMT_BC3 ] = {4 ,4 ,16 ,0 }, + [V_038004_FMT_BC4 ] = {4 ,4 ,8 ,0 }, + [V_038004_FMT_BC5 ] = {4 ,4 ,16 ,0 }, + +}; + +static inline bool fmt_is_valid_color (u32 format) +{ +if (format >ARRAY_SIZE (color_formats_table)) +return false; + +if (color_formats_table[format].valid_color) +return true; + +return false; +} + +static inline bool fmt_is_valid_texture (u32 format) +{ +if (format >ARRAY_SIZE (color_formats_table)) +return false; + +if (color_formats_table[format].blockwidth >0 ) +return true; + +return false; +} + +static inline int fmt_get_blocksize (u32 format) +{ +if (format >ARRAY_SIZE (color_formats_table)) +return 0 ; + +return color_formats_table[format].blocksize; +} + +static inline int fmt_get_nblocksx (u32 format,u32 w) +{ +unsigned bw; +if (format >ARRAY_SIZE (color_formats_table)) +return 0 ; + + bw = color_formats_table[format].blockwidth; +if (bw ==0 ) +return 0 ; + +return (w + bw -1 ) / bw; +} + +static inline int fmt_get_nblocksy (u32 format,u32 h) +{ +unsigned bh; +if (format >ARRAY_SIZE (color_formats_table)) +return 0 ; + + bh = color_formats_table[format].blockheight; +if (bh ==0 ) +return 0 ; + +return (h + bh -1 ) / bh; +} +static inline int r600_bpe_from_format (u32 *bpe,u32 format) { -switch (format) { -case V_038004_COLOR_8 : -case V_038004_COLOR_4_4 : -case V_038004_COLOR_3_3_2 : -case V_038004_FMT_1 : - *bpe =1 ; -break ; -case V_038004_COLOR_16 : -case V_038004_COLOR_16_FLOAT : -case V_038004_COLOR_8_8 : -case V_038004_COLOR_5_6_5 : -case V_038004_COLOR_6_5_5 : -case V_038004_COLOR_1_5_5_5 : -case V_038004_COLOR_4_4_4_4 : -case V_038004_COLOR_5_5_5_1 : - *bpe =2 ; -break ; -case V_038004_FMT_8_8_8 : - *bpe =3 ; -break ; -case V_038004_COLOR_32 : -case V_038004_COLOR_32_FLOAT : -case V_038004_COLOR_16_16 : -case V_038004_COLOR_16_16_FLOAT : -case V_038004_COLOR_8_24 : -case V_038004_COLOR_8_24_FLOAT : -case V_038004_COLOR_24_8 : -case V_038004_COLOR_24_8_FLOAT : -case V_038004_COLOR_10_11_11 : -case V_038004_COLOR_10_11_11_FLOAT : -case V_038004_COLOR_11_11_10 : -case V_038004_COLOR_11_11_10_FLOAT : -case V_038004_COLOR_2_10_10_10 : -case V_038004_COLOR_8_8_8_8 : -case V_038004_COLOR_10_10_10_2 : -case V_038004_FMT_5_9_9_9_SHAREDEXP : -case V_038004_FMT_32_AS_8 : -case V_038004_FMT_32_AS_8_8 : - *bpe =4 ; -break ; -case V_038004_COLOR_X24_8_32_FLOAT : -case V_038004_COLOR_32_32 : -case V_038004_COLOR_32_32_FLOAT : -case V_038004_COLOR_16_16_16_16 : -case V_038004_COLOR_16_16_16_16_FLOAT : - *bpe =8 ; -break ; -case V_038004_FMT_16_16_16 : -case V_038004_FMT_16_16_16_FLOAT : - *bpe =6 ; -break ; -case V_038004_FMT_32_32_32 : -case V_038004_FMT_32_32_32_FLOAT : - *bpe =12 ; -break ; -case V_038004_COLOR_32_32_32_32 : -case V_038004_COLOR_32_32_32_32_FLOAT : - *bpe =16 ; -break ; -case V_038004_FMT_GB_GR : -case V_038004_FMT_BG_RG : -case V_038004_COLOR_INVALID : -default : - *bpe =16 ; -return -EINVAL ; - } +unsigned res; +if (format >ARRAY_SIZE (color_formats_table)) + goto fail; + + res = color_formats_table[format].blocksize; +if (res ==0 ) + goto fail; + + *bpe = res;return 0 ; + +fail: + *bpe =16 ; +return -EINVAL ; }struct array_mode_checker {
@@ -148,7 +237,7 @@ struct array_mode_checker {u32 nbanks;u32 npipes;u32 nsamples; -u32 bpe; +u32 blocksize; };/* returns alignment in pixels for pitch/height/depth and bytes for base */
@@ -162,7 +251,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *valueu32 tile_height =8 ;u32 macro_tile_width = values->nbanks;u32 macro_tile_height = values->npipes; -u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples; +u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;switch (values->array_mode) {
@@ -174,7 +263,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value *base_align =1 ;break ;case ARRAY_LINEAR_ALIGNED : - *pitch_align =max ((u32 )64 , (u32)(values->group_size / values->bpe)); + *pitch_align =max ((u32 )64 , (u32)(values->group_size / values->blocksize)); *height_align = tile_height; *depth_align =1 ; *base_align = values->group_size;
@@ -182,7 +271,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *valuecase ARRAY_1D_TILED_THIN1 : *pitch_align =max ((u32 )tile_width, (u32)(values->group_size / - (tile_height * values->bpe * values->nsamples))); + (tile_height * values->blocksize * values->nsamples))); *height_align = tile_height; *depth_align =1 ; *base_align = values->group_size;
@@ -190,12 +279,12 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *valuecase ARRAY_2D_TILED_THIN1 : *pitch_align =max ((u32 )macro_tile_width, (u32)(((values->group_size / tile_height) / - (values->bpe * values->nsamples)) * + (values->blocksize * values->nsamples)) * values->nbanks)) * tile_width; *height_align = macro_tile_height * tile_height; *depth_align =1 ; *base_align =max (macro_tile_bytes, - (*pitch_align) * values->bpe * (*height_align) * values->nsamples); + (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);break ;default :return -EINVAL ;
@@ -234,21 +323,22 @@ static void r600_cs_track_init(struct r600_cs_track *track)static inline int r600_cs_track_validate_cb (struct radeon_cs_parser *p,int i) {struct r600_cs_track *track = p->track; -u32 bpe =0 , slice_tile_max, size, tmp; +u32 slice_tile_max, size, tmp;u32 height, height_align, pitch, pitch_align, depth_align;u64 base_offset, base_align;struct array_mode_checker array_check;volatile u32 *ib = p->ib->ptr;unsigned array_mode; - +u32 format;if (G_0280A0_TILE_MODE (track->cb_color_info[i])) {dev_warn (p->dev,"FMASK or CMASK buffer are not supported by this kernel\n" );return -EINVAL ; } size =radeon_bo_size (track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; -if (r600_bpe_from_format (&bpe,G_0280A0_FORMAT (track->cb_color_info[i]))) { + format =G_0280A0_FORMAT (track->cb_color_info[i]); +if (!fmt_is_valid_color (format)) {dev_warn (p->dev,"%s:%d cb invalid format %d for %d (0x%08X)\n" , - __func__, __LINE__,G_0280A0_FORMAT (track->cb_color_info[i]), + __func__, __LINE__, format, i, track->cb_color_info[i]);return -EINVAL ; }
@@ -267,7 +357,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; array_check.nsamples = track->nsamples; - array_check.bpe = bpe; + array_check.blocksize =fmt_get_blocksize (format);if (r600_get_array_mode_alignment (&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
@@ -311,7 +401,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) }/* check offset */ - tmp = height * pitch * bpe; + tmp =fmt_get_nblocksy (format, height) *fmt_get_nblocksx (format, pitch) *fmt_get_blocksize (format);if ((tmp + track->cb_color_bo_offset[i]) >radeon_bo_size (track->cb_color_bo[i])) {if (array_mode ==V_0280A0_ARRAY_LINEAR_GENERAL ) {/* the initial DDX does bad things with the CB size occasionally */
@@ -436,7 +526,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; array_check.nsamples = track->nsamples; - array_check.bpe = bpe; + array_check.blocksize = bpe;if (r600_get_array_mode_alignment (&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
@@ -1113,39 +1203,61 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idxreturn 0 ; } -static inline unsigned minify (unsigned size,unsigned levels) +static inline unsigned mip_minify (unsigned size,unsigned level) { - size = size >> levels; -if (size <1 ) - size =1 ; -return size; +unsigned val; + + val =max (1U , size >> level); +if (level >0 ) + val =roundup_pow_of_two (val); +return val; } -static void r600_texture_size (unsigned nfaces,unsigned blevel,unsigned nlevels, -unsigned w0,unsigned h0,unsigned d0,unsigned bpe, -unsigned pitch_align, +static void r600_texture_size (unsigned nfaces,unsigned blevel,unsigned llevel, +unsigned w0,unsigned h0,unsigned d0,unsigned format, +unsigned block_align,unsigned height_align,unsigned base_align,unsigned *l0_size,unsigned *mipmap_size) { -unsigned offset, i, level, face; -unsigned width, height, depth, rowstride, size; - - w0 =minify (w0,0 ); - h0 =minify (h0,0 ); - d0 =minify (d0,0 ); +unsigned offset, i, level; +unsigned width, height, depth, size; +unsigned blocksize; +unsigned nbx, nby; +unsigned nlevels = llevel - blevel +1 ; + + *l0_size =-1 ; + blocksize =fmt_get_blocksize (format); + + w0 =mip_minify (w0,0 ); + h0 =mip_minify (h0,0 ); + d0 =mip_minify (d0,0 );for (i =0 , offset =0 , level = blevel; i < nlevels; i++, level++) { - width =minify (w0, i); - height =minify (h0, i); - depth =minify (d0, i); -for (face =0 ; face < nfaces; face++) { - rowstride =ALIGN ((width * bpe), pitch_align); - size = height * rowstride * depth; - offset += size; - offset = (offset +0x1f ) & ~0x1f ; - } + width =mip_minify (w0, i); + nbx =fmt_get_nblocksx (format, width); + + nbx =round_up (nbx, block_align); + + height =mip_minify (h0, i); + nby =fmt_get_nblocksy (format, height); + nby =round_up (nby, height_align); + + depth =mip_minify (d0, i); + + size = nbx * nby * blocksize; +if (nfaces) + size *= nfaces; +else + size *= depth; + +if (i ==0 ) + *l0_size = size; + +if (i ==0 || i ==1 ) + offset =round_up (offset, base_align); + + offset += size; } - *l0_size =ALIGN ((w0 * bpe), pitch_align) * h0 * d0; *mipmap_size = offset; -if (!nlevels) +if (llevel ==0 ) *mipmap_size = *l0_size;if (!blevel) *mipmap_size -= *l0_size;
@@ -1169,11 +1281,13 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i u32 tiling_flags) {struct r600_cs_track *track = p->track; -u32 nfaces, nlevels, blevel, w0, h0, d0, bpe =0 ; +u32 nfaces, llevel, blevel, w0, h0, d0;u32 word0, word1, l0_size, mipmap_size;u32 height_align, pitch, pitch_align, depth_align; +u32 array, barray, larray;u64 base_align;struct array_mode_checker array_check; +u32 format;/* on legacy kernel we don't perform advanced check */ if (p->rdev ==NULL )
@@ -1199,19 +1313,25 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 icase V_038000_SQ_TEX_DIM_3D :break ;case V_038000_SQ_TEX_DIM_CUBEMAP : - nfaces =6 ; +if (p->family >=CHIP_RV770 ) + nfaces =8 ; +else + nfaces =6 ;break ;case V_038000_SQ_TEX_DIM_1D_ARRAY :case V_038000_SQ_TEX_DIM_2D_ARRAY : + array =1 ; +break ;case V_038000_SQ_TEX_DIM_2D_MSAA :case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA :default :dev_warn (p->dev,"this kernel doesn't support %d texture dim\n" ,G_038000_DIM (word0));return -EINVAL ; } -if (r600_bpe_from_format (&bpe,G_038004_DATA_FORMAT (word1))) { + format =G_038004_DATA_FORMAT (word1); +if (!fmt_is_valid_texture (format)) {dev_warn (p->dev,"%s:%d texture invalid format %d\n" , - __func__, __LINE__,G_038004_DATA_FORMAT (word1)); + __func__, __LINE__, format);return -EINVAL ; }
@@ -1222,7 +1342,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; array_check.nsamples =1 ; - array_check.bpe = bpe; + array_check.blocksize =fmt_get_blocksize (format);if (r600_get_array_mode_alignment (&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
@@ -1251,22 +1371,29 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i word0 =radeon_get_ib_value (p, idx +4 ); word1 =radeon_get_ib_value (p, idx +5 ); blevel =G_038010_BASE_LEVEL (word0); - nlevels =G_038014_LAST_LEVEL (word1); -r600_texture_size (nfaces, blevel, nlevels, w0, h0, d0, bpe, - (pitch_align * bpe), + llevel =G_038014_LAST_LEVEL (word1); +if (array ==1 ) { + barray =G_038014_BASE_ARRAY (word1); + larray =G_038014_LAST_ARRAY (word1); + + nfaces = larray - barray +1 ; + } +r600_texture_size (nfaces, blevel, llevel, w0, h0, d0, format, + pitch_align, height_align, base_align, &l0_size, &mipmap_size);/* using get ib will give us the offset into the texture bo */ word0 =radeon_get_ib_value (p, idx +2 ) <<8 ;if ((l0_size + word0) >radeon_bo_size (texture)) {dev_warn (p->dev,"texture bo too small (%d %d %d %d -> %d have %ld)\n" , - w0, h0, bpe, word0, l0_size,radeon_bo_size (texture)); + w0, h0, format, word0, l0_size,radeon_bo_size (texture)); +dev_warn (p->dev,"alignments %d %d %d %lld\n" , pitch, pitch_align, height_align, base_align);return -EINVAL ; }/* using get ib will give us the offset into the mipmap bo */ word0 =radeon_get_ib_value (p, idx +3 ) <<8 ;if ((mipmap_size + word0) >radeon_bo_size (mipmap)) {/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", -w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ +w0, h0, format, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ }return 0 ; }
drivers/gpu/drm/radeon/r600d.h +5 -0
@@ -1304,6 +1304,11 @@#define V_038004_FMT_16_16_16_FLOAT 0x0000002E#define V_038004_FMT_32_32_32 0x0000002F#define V_038004_FMT_32_32_32_FLOAT 0x00000030 +#define V_038004_FMT_BC1 0x00000031 +#define V_038004_FMT_BC2 0x00000032 +#define V_038004_FMT_BC3 0x00000033 +#define V_038004_FMT_BC4 0x00000034 +#define V_038004_FMT_BC5 0x00000035#define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010#define S_038010_FORMAT_COMP_X (x) (((x) & 0x3) << 0)#define G_038010_FORMAT_COMP_X (x) (((x) >> 0) & 0x3)
Signature · 1 line
1.7.3.2