1 /* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 * 26 * Authors: 27 * Marek Olk <maraeo (at) gmail.com> 28 */ 29 30 #include "radeon_drm_winsys.h" 31 #include "util/u_format.h" 32 #include <radeon_surface.h> 33 34 static unsigned cik_get_macro_tile_index(struct radeon_surf *surf) 35 { 36 unsigned index, tileb; 37 38 tileb = 8 * 8 * surf->bpe; 39 tileb = MIN2(surf->tile_split, tileb); 40 41 for (index = 0; tileb > 64; index++) 42 tileb >>= 1; 43 44 assert(index < 16); 45 return index; 46 } 47 48 #define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03) 49 #define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07) 50 51 static void set_micro_tile_mode(struct radeon_surf *surf, 52 struct radeon_info *info) 53 { 54 uint32_t tile_mode; 55 56 if (info->chip_class < SI) { 57 surf->micro_tile_mode = 0; 58 return; 59 } 60 61 tile_mode = info->si_tile_mode_array[surf->tiling_index[0]]; 62 63 if (info->chip_class >= CIK) 64 surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode); 65 else 66 surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode); 67 } 68 69 static void surf_level_winsys_to_drm(struct radeon_surface_level *level_drm, 70 const struct radeon_surf_level *level_ws, 71 unsigned bpe) 72 { 73 level_drm->offset = level_ws->offset; 74 level_drm->slice_size = level_ws->slice_size; 75 level_drm->nblk_x = level_ws->nblk_x; 76 level_drm->nblk_y = level_ws->nblk_y; 77 level_drm->pitch_bytes = level_ws->nblk_x * bpe; 78 level_drm->mode = level_ws->mode; 79 } 80 81 static void surf_level_drm_to_winsys(struct radeon_surf_level *level_ws, 82 const struct radeon_surface_level *level_drm, 83 unsigned bpe) 84 { 85 level_ws->offset = level_drm->offset; 86 level_ws->slice_size = level_drm->slice_size; 87 level_ws->nblk_x = level_drm->nblk_x; 88 level_ws->nblk_y = level_drm->nblk_y; 89 level_ws->mode = level_drm->mode; 90 assert(level_drm->nblk_x * bpe == level_drm->pitch_bytes); 91 } 92 93 static void surf_winsys_to_drm(struct radeon_surface *surf_drm, 94 const struct pipe_resource *tex, 95 unsigned flags, unsigned bpe, 96 enum radeon_surf_mode mode, 97 const struct radeon_surf *surf_ws) 98 { 99 int i; 100 101 memset(surf_drm, 0, sizeof(*surf_drm)); 102 103 surf_drm->npix_x = tex->width0; 104 surf_drm->npix_y = tex->height0; 105 surf_drm->npix_z = tex->depth0; 106 surf_drm->blk_w = util_format_get_blockwidth(tex->format); 107 surf_drm->blk_h = util_format_get_blockheight(tex->format); 108 surf_drm->blk_d = 1; 109 surf_drm->array_size = 1; 110 surf_drm->last_level = tex->last_level; 111 surf_drm->bpe = bpe; 112 surf_drm->nsamples = tex->nr_samples ? tex->nr_samples : 1; 113 114 surf_drm->flags = flags; 115 surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, TYPE); 116 surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, MODE); 117 surf_drm->flags |= RADEON_SURF_SET(mode, MODE) | 118 RADEON_SURF_HAS_SBUFFER_MIPTREE | 119 RADEON_SURF_HAS_TILE_MODE_INDEX; 120 121 switch (tex->target) { 122 case PIPE_TEXTURE_1D: 123 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE); 124 break; 125 case PIPE_TEXTURE_RECT: 126 case PIPE_TEXTURE_2D: 127 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 128 break; 129 case PIPE_TEXTURE_3D: 130 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE); 131 break; 132 case PIPE_TEXTURE_1D_ARRAY: 133 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE); 134 surf_drm->array_size = tex->array_size; 135 break; 136 case PIPE_TEXTURE_CUBE_ARRAY: /* cube array layout like 2d array */ 137 assert(tex->array_size % 6 == 0); 138 /* fall through */ 139 case PIPE_TEXTURE_2D_ARRAY: 140 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE); 141 surf_drm->array_size = tex->array_size; 142 break; 143 case PIPE_TEXTURE_CUBE: 144 surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE); 145 break; 146 case PIPE_BUFFER: 147 default: 148 assert(0); 149 } 150 151 surf_drm->bo_size = surf_ws->surf_size; 152 surf_drm->bo_alignment = surf_ws->surf_alignment; 153 154 surf_drm->bankw = surf_ws->bankw; 155 surf_drm->bankh = surf_ws->bankh; 156 surf_drm->mtilea = surf_ws->mtilea; 157 surf_drm->tile_split = surf_ws->tile_split; 158 159 for (i = 0; i <= surf_drm->last_level; i++) { 160 surf_level_winsys_to_drm(&surf_drm->level[i], &surf_ws->level[i], 161 bpe * surf_drm->nsamples); 162 163 surf_drm->tiling_index[i] = surf_ws->tiling_index[i]; 164 } 165 166 if (flags & RADEON_SURF_SBUFFER) { 167 surf_drm->stencil_tile_split = surf_ws->stencil_tile_split; 168 169 for (i = 0; i <= surf_drm->last_level; i++) { 170 surf_level_winsys_to_drm(&surf_drm->stencil_level[i], 171 &surf_ws->stencil_level[i], 172 surf_drm->nsamples); 173 surf_drm->stencil_tiling_index[i] = surf_ws->stencil_tiling_index[i]; 174 } 175 } 176 } 177 178 static void surf_drm_to_winsys(struct radeon_drm_winsys *ws, 179 struct radeon_surf *surf_ws, 180 const struct radeon_surface *surf_drm) 181 { 182 int i; 183 184 memset(surf_ws, 0, sizeof(*surf_ws)); 185 186 surf_ws->blk_w = surf_drm->blk_w; 187 surf_ws->blk_h = surf_drm->blk_h; 188 surf_ws->bpe = surf_drm->bpe; 189 surf_ws->is_linear = surf_drm->level[0].mode <= RADEON_SURF_MODE_LINEAR_ALIGNED; 190 surf_ws->flags = surf_drm->flags; 191 192 surf_ws->surf_size = surf_drm->bo_size; 193 surf_ws->surf_alignment = surf_drm->bo_alignment; 194 195 surf_ws->bankw = surf_drm->bankw; 196 surf_ws->bankh = surf_drm->bankh; 197 surf_ws->mtilea = surf_drm->mtilea; 198 surf_ws->tile_split = surf_drm->tile_split; 199 200 surf_ws->macro_tile_index = cik_get_macro_tile_index(surf_ws); 201 202 for (i = 0; i <= surf_drm->last_level; i++) { 203 surf_level_drm_to_winsys(&surf_ws->level[i], &surf_drm->level[i], 204 surf_drm->bpe * surf_drm->nsamples); 205 surf_ws->tiling_index[i] = surf_drm->tiling_index[i]; 206 } 207 208 if (surf_ws->flags & RADEON_SURF_SBUFFER) { 209 surf_ws->stencil_tile_split = surf_drm->stencil_tile_split; 210 211 for (i = 0; i <= surf_drm->last_level; i++) { 212 surf_level_drm_to_winsys(&surf_ws->stencil_level[i], 213 &surf_drm->stencil_level[i], 214 surf_drm->nsamples); 215 surf_ws->stencil_tiling_index[i] = surf_drm->stencil_tiling_index[i]; 216 } 217 } 218 219 set_micro_tile_mode(surf_ws, &ws->info); 220 } 221 222 static int radeon_winsys_surface_init(struct radeon_winsys *rws, 223 const struct pipe_resource *tex, 224 unsigned flags, unsigned bpe, 225 enum radeon_surf_mode mode, 226 struct radeon_surf *surf_ws) 227 { 228 struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; 229 struct radeon_surface surf_drm; 230 int r; 231 232 surf_winsys_to_drm(&surf_drm, tex, flags, bpe, mode, surf_ws); 233 234 if (!(flags & (RADEON_SURF_IMPORTED | RADEON_SURF_FMASK))) { 235 r = radeon_surface_best(ws->surf_man, &surf_drm); 236 if (r) 237 return r; 238 } 239 240 r = radeon_surface_init(ws->surf_man, &surf_drm); 241 if (r) 242 return r; 243 244 surf_drm_to_winsys(ws, surf_ws, &surf_drm); 245 return 0; 246 } 247 248 void radeon_surface_init_functions(struct radeon_drm_winsys *ws) 249 { 250 ws->base.surface_init = radeon_winsys_surface_init; 251 } 252