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 Olšák <maraeo@gmail.com>
28  */
29 
30 #include "radeon_drm_winsys.h"
31 #include "util/u_format.h"
32 #include <radeon_surface.h>
33 
cik_get_macro_tile_index(struct radeon_surf * surf)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 
set_micro_tile_mode(struct radeon_surf * surf,struct radeon_info * info)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 
surf_level_winsys_to_drm(struct radeon_surface_level * level_drm,const struct radeon_surf_level * level_ws,unsigned bpe)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 
surf_level_drm_to_winsys(struct radeon_surf_level * level_ws,const struct radeon_surface_level * level_drm,unsigned bpe)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 
surf_winsys_to_drm(struct radeon_surface * surf_drm,const struct pipe_resource * tex,unsigned flags,unsigned bpe,enum radeon_surf_mode mode,const struct radeon_surf * surf_ws)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 
surf_drm_to_winsys(struct radeon_drm_winsys * ws,struct radeon_surf * surf_ws,const struct radeon_surface * surf_drm)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 
radeon_winsys_surface_init(struct radeon_winsys * rws,const struct pipe_resource * tex,unsigned flags,unsigned bpe,enum radeon_surf_mode mode,struct radeon_surf * surf_ws)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 
radeon_surface_init_functions(struct radeon_drm_winsys * ws)248 void radeon_surface_init_functions(struct radeon_drm_winsys *ws)
249 {
250     ws->base.surface_init = radeon_winsys_surface_init;
251 }
252