Home | History | Annotate | Download | only in drm
      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