57
56
return tile_mode | 0x100;
61
nvc0_miptree_zslice_offset(struct nvc0_miptree *mt, unsigned l, unsigned z)
63
unsigned nblocksy; /* height of texture level aligned to tile height */
65
unsigned stride_2d; /* to next slice within a 3D tile */
66
unsigned stride_3d; /* to slice in the next (in z direction !) 3D tile */
68
unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(mt->level[l].tile_mode, 2);
69
unsigned tile_d = 1 << tile_d_shift;
71
nblocksy = util_format_get_nblocksy(mt->base.base.format,
72
u_minify(mt->base.base.height0, l));
74
nblocksy = align(nblocksy, NVC0_TILE_HEIGHT(mt->level[l].tile_mode));
76
stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
78
stride_3d = (nblocksy * mt->level[l].pitch) << tile_d_shift;
80
return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
84
nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
86
struct nvc0_miptree *mt = nvc0_miptree(pt);
88
nouveau_screen_bo_release(pscreen, mt->base.bo);
94
nvc0_miptree_get_handle(struct pipe_screen *pscreen,
95
struct pipe_resource *pt,
96
struct winsys_handle *whandle)
98
struct nvc0_miptree *mt = nvc0_miptree(pt);
101
if (!mt || !mt->base.bo)
60
nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
62
const unsigned ms = util_logbase2(mt->base.base.nr_samples);
66
compressed = FALSE; /* not yet supported */
68
if (mt->base.base.bind & PIPE_BIND_CURSOR)
69
return NOUVEAU_BO_TILE_SCANOUT;
71
switch (mt->base.base.format) {
72
case PIPE_FORMAT_Z16_UNORM:
74
tile_flags = 0x0200 + (ms << 8);
78
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
80
tile_flags = 0x5100 + (ms << 8);
84
case PIPE_FORMAT_Z24X8_UNORM:
85
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
87
tile_flags = 0x1700 + (ms << 8);
91
case PIPE_FORMAT_Z32_FLOAT:
93
tile_flags = 0x8600 + (ms << 8);
97
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
99
tile_flags = 0xce00 + (ms << 8);
104
switch (util_format_get_blocksizebits(mt->base.base.format)) {
107
tile_flags = 0xf400 + (ms << 9);
114
case 0: tile_flags = 0xe600; break;
115
case 1: tile_flags = 0xeb00; break;
116
case 2: tile_flags = 0xed00; break;
117
case 3: tile_flags = 0xf200; break;
128
case 0: tile_flags = 0xdb00; break;
129
case 1: tile_flags = 0xdd00; break;
130
case 2: tile_flags = 0xdf00; break;
131
case 3: tile_flags = 0xe400; break;
149
if (mt->base.base.bind & PIPE_BIND_SCANOUT)
150
tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
152
if (unlikely(mt->base.base.flags & NOUVEAU_RESOURCE_FLAG_LINEAR))
153
tile_flags &= ~0xff00;
158
static INLINE boolean
159
nvc0_miptree_init_ms_mode(struct nv50_miptree *mt)
161
switch (mt->base.base.nr_samples) {
163
mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8;
168
mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4;
173
mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2;
178
mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
181
NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
104
stride = util_format_get_stride(mt->base.base.format,
105
mt->base.base.width0);
107
return nouveau_screen_bo_get_handle(pscreen,
188
nv50_miptree_init_layout_linear(struct nv50_miptree *);
191
nvc0_miptree_init_layout_video(struct nv50_miptree *mt)
193
const struct pipe_resource *pt = &mt->base.base;
194
const unsigned blocksize = util_format_get_blocksize(pt->format);
196
unsigned nbx = util_format_get_nblocksx(pt->format, pt->width0);
197
unsigned nby = util_format_get_nblocksy(pt->format, pt->height0);
199
assert(pt->last_level == 0);
200
assert(mt->ms_x == 0 &&
202
assert(!util_format_is_compressed(pt->format));
205
mt->level[0].tile_mode = 0x10;
206
mt->level[0].pitch = align(nbx * blocksize, 64);
207
mt->total_size = align(nby, 16) * mt->level[0].pitch;
209
if (pt->array_size > 1) {
210
mt->layer_stride = align(mt->total_size, NVC0_TILE_SIZE(0x10));
211
mt->total_size = mt->layer_stride * pt->array_size;
216
nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
218
struct pipe_resource *pt = &mt->base.base;
220
const unsigned blocksize = util_format_get_blocksize(pt->format);
222
mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
224
w = pt->width0 << mt->ms_x;
225
h = pt->height0 << mt->ms_y;
227
/* For 3D textures, a mipmap is spanned by all the layers, for array
228
* textures and cube maps, each layer contains its own mipmaps.
230
d = mt->layout_3d ? pt->depth0 : 1;
232
for (l = 0; l <= pt->last_level; ++l) {
233
struct nv50_miptree_level *lvl = &mt->level[l];
234
unsigned tsx, tsy, tsz;
235
unsigned nbx = util_format_get_nblocksx(pt->format, w);
236
unsigned nby = util_format_get_nblocksy(pt->format, h);
238
lvl->offset = mt->total_size;
240
lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d);
242
tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
243
tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode);
244
tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode);
246
lvl->pitch = align(nbx * blocksize, tsx);
248
mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
255
if (pt->array_size > 1) {
256
mt->layer_stride = align(mt->total_size,
257
NVC0_TILE_SIZE(mt->level[0].tile_mode));
258
mt->total_size = mt->layer_stride * pt->array_size;
113
262
const struct u_resource_vtbl nvc0_miptree_vtbl =
115
nvc0_miptree_get_handle, /* get_handle */
116
nvc0_miptree_destroy, /* resource_destroy */
264
nv50_miptree_get_handle, /* get_handle */
265
nv50_miptree_destroy, /* resource_destroy */
117
266
nvc0_miptree_transfer_new, /* get_transfer */
118
267
nvc0_miptree_transfer_del, /* transfer_destroy */
119
nvc0_miptree_transfer_map, /* transfer_map */
268
nvc0_miptree_transfer_map, /* transfer_map */
120
269
u_default_transfer_flush_region, /* transfer_flush_region */
121
270
nvc0_miptree_transfer_unmap, /* transfer_unmap */
122
271
u_default_transfer_inline_write /* transfer_inline_write */
141
289
pipe_reference_init(&pt->reference, 1);
142
290
pt->screen = pscreen;
144
mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
148
d = mt->layout_3d ? pt->depth0 : 1;
150
switch (pt->format) {
151
case PIPE_FORMAT_Z16_UNORM:
152
tile_flags = 0x0700; /* COMPRESSED */
153
tile_flags = 0x0100; /* NORMAL */
155
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
156
tile_flags = 0x5300; /* MSAA 4, COMPRESSED */
157
tile_flags = 0x4600; /* NORMAL */
159
case PIPE_FORMAT_Z24X8_UNORM:
160
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
161
tile_flags = 0x1100; /* NORMAL */
162
if (w * h >= 128 * 128 && 0)
163
tile_flags = 0x1700; /* COMPRESSED, requires magic */
165
case PIPE_FORMAT_R32G32B32A32_FLOAT:
166
tile_flags = 0xf500; /* COMPRESSED */
167
tile_flags = 0xf700; /* MSAA 2 */
168
tile_flags = 0xf900; /* MSAA 4 */
169
tile_flags = 0xfe00; /* NORMAL */
171
case PIPE_FORMAT_Z32_FLOAT:
174
case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
175
tile_flags = 0xce00; /* COMPRESSED */
176
tile_flags = 0xcf00; /* MSAA 2, COMPRESSED */
177
tile_flags = 0xd000; /* MSAA 4, COMPRESSED */
178
tile_flags = 0xc300; /* NORMAL */
180
case PIPE_FORMAT_R16G16B16A16_UNORM:
181
tile_flags = 0xe900; /* COMPRESSED */
182
tile_flags = 0xfe00; /* NORMAL */
185
tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */
186
tile_flags = 0xfe00; /* NORMAL 32 BIT */
187
if (w * h >= 128 * 128 && 0)
188
tile_flags = 0xdb00; /* COMPRESSED 32 BIT, requires magic */
192
/* For 3D textures, a mipmap is spanned by all the layers, for array
193
* textures and cube maps, each layer contains its own mipmaps.
195
for (l = 0; l <= pt->last_level; ++l) {
196
struct nvc0_miptree_level *lvl = &mt->level[l];
197
unsigned nbx = util_format_get_nblocksx(pt->format, w);
198
unsigned nby = util_format_get_nblocksy(pt->format, h);
199
unsigned blocksize = util_format_get_blocksize(pt->format);
201
lvl->offset = mt->total_size;
202
lvl->tile_mode = get_tile_dims(nbx, nby, d);
203
lvl->pitch = align(nbx * blocksize, NVC0_TILE_PITCH(lvl->tile_mode));
205
mt->total_size += lvl->pitch *
206
align(nby, NVC0_TILE_HEIGHT(lvl->tile_mode)) *
207
align(d, NVC0_TILE_DEPTH(lvl->tile_mode));
214
if (pt->array_size > 1) {
215
mt->layer_stride = align(mt->total_size,
216
NVC0_TILE_SIZE(mt->level[0].tile_mode));
217
mt->total_size = mt->layer_stride * pt->array_size;
220
alloc_size = mt->total_size;
221
if (tile_flags == 0x1700)
222
alloc_size *= 3; /* HiZ, XXX: correct size */
224
ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
292
tile_flags = nvc0_mt_choose_storage_type(mt, TRUE);
294
if (!nvc0_miptree_init_ms_mode(mt)) {
299
if (unlikely(pt->flags & NVC0_RESOURCE_FLAG_VIDEO)) {
300
nvc0_miptree_init_layout_video(mt);
302
if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) {
303
nvc0_miptree_init_layout_tiled(mt);
305
if (!nv50_miptree_init_layout_linear(mt)) {
310
ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096,
225
312
mt->level[0].tile_mode, tile_flags,
236
struct pipe_resource *
237
nvc0_miptree_from_handle(struct pipe_screen *pscreen,
238
const struct pipe_resource *templ,
239
struct winsys_handle *whandle)
323
/* Offset of zslice @z from start of level @l. */
325
nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
241
struct nvc0_miptree *mt;
244
/* only supports 2D, non-mipmapped textures for the moment */
245
if ((templ->target != PIPE_TEXTURE_2D &&
246
templ->target != PIPE_TEXTURE_RECT) ||
247
templ->last_level != 0 ||
248
templ->depth0 != 1 ||
249
templ->array_size > 1)
252
mt = CALLOC_STRUCT(nvc0_miptree);
256
mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
257
if (mt->base.bo == NULL) {
262
mt->base.base = *templ;
263
mt->base.vtbl = &nvc0_miptree_vtbl;
264
pipe_reference_init(&mt->base.base.reference, 1);
265
mt->base.base.screen = pscreen;
266
mt->level[0].pitch = stride;
267
mt->level[0].offset = 0;
268
mt->level[0].tile_mode = mt->base.bo->tile_mode;
270
/* no need to adjust bo reference count */
271
return &mt->base.base;
327
const struct pipe_resource *pt = &mt->base.base;
329
unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode);
330
unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode);
332
unsigned nby = util_format_get_nblocksy(pt->format,
333
u_minify(pt->height0, l));
335
/* to next 2D tile slice within a 3D tile */
336
unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
338
/* to slice in the next (in z direction) 3D tile */
339
unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
341
return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d;
275
344
/* Surface functions.
280
349
struct pipe_resource *pt,
281
350
const struct pipe_surface *templ)
283
struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */
284
struct nvc0_surface *ns;
285
struct pipe_surface *ps;
286
struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level];
288
ns = CALLOC_STRUCT(nvc0_surface);
352
struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ);
293
pipe_reference_init(&ps->reference, 1);
294
pipe_resource_reference(&ps->texture, pt);
296
ps->format = templ->format;
297
ps->usage = templ->usage;
298
ps->u.tex.level = templ->u.tex.level;
299
ps->u.tex.first_layer = templ->u.tex.first_layer;
300
ps->u.tex.last_layer = templ->u.tex.last_layer;
302
ns->width = u_minify(pt->width0, ps->u.tex.level);
303
ns->height = u_minify(pt->height0, ps->u.tex.level);
304
ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
305
ns->offset = lvl->offset;
307
/* comment says there are going to be removed, but they're used by the st */
308
ps->width = ns->width;
309
ps->height = ns->height;
315
nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
317
struct nvc0_surface *s = nvc0_surface(ps);
319
pipe_resource_reference(&ps->texture, NULL);
355
ns->base.context = pipe;