r600g: get rid of r600_texture::array_mode
[mesa.git] / src / gallium / drivers / r600 / r600_texture.c
1 /*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Jerome Glisse
25 * Corbin Simpson
26 */
27 #include "r600_formats.h"
28 #include "evergreen_compute.h"
29 #include "r600d.h"
30
31 #include <errno.h>
32 #include "util/u_format_s3tc.h"
33 #include "util/u_memory.h"
34
35
36 /* Same as resource_copy_region, except that both upsampling and downsampling are allowed. */
37 static void r600_copy_region_with_blit(struct pipe_context *pipe,
38 struct pipe_resource *dst,
39 unsigned dst_level,
40 unsigned dstx, unsigned dsty, unsigned dstz,
41 struct pipe_resource *src,
42 unsigned src_level,
43 const struct pipe_box *src_box)
44 {
45 struct pipe_blit_info blit;
46
47 memset(&blit, 0, sizeof(blit));
48 blit.src.resource = src;
49 blit.src.format = src->format;
50 blit.src.level = src_level;
51 blit.src.box = *src_box;
52 blit.dst.resource = dst;
53 blit.dst.format = dst->format;
54 blit.dst.level = dst_level;
55 blit.dst.box.x = dstx;
56 blit.dst.box.y = dsty;
57 blit.dst.box.z = dstz;
58 blit.dst.box.width = src_box->width;
59 blit.dst.box.height = src_box->height;
60 blit.dst.box.depth = src_box->depth;
61 blit.mask = util_format_get_mask(src->format) &
62 util_format_get_mask(dst->format);
63 blit.filter = PIPE_TEX_FILTER_NEAREST;
64
65 if (blit.mask) {
66 pipe->blit(pipe, &blit);
67 }
68 }
69
70 /* Copy from a full GPU texture to a transfer's staging one. */
71 static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
72 {
73 struct r600_context *rctx = (struct r600_context*)ctx;
74 struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
75 struct pipe_resource *dst = &rtransfer->staging->b.b;
76 struct pipe_resource *src = transfer->resource;
77
78 if (src->nr_samples > 1) {
79 r600_copy_region_with_blit(ctx, dst, 0, 0, 0, 0,
80 src, transfer->level, &transfer->box);
81 return;
82 }
83
84 if (!rctx->screen->dma_blit(ctx, dst, 0, 0, 0, 0,
85 src, transfer->level,
86 &transfer->box)) {
87 ctx->resource_copy_region(ctx, dst, 0, 0, 0, 0,
88 src, transfer->level, &transfer->box);
89 }
90 }
91
92 /* Copy from a transfer's staging texture to a full GPU one. */
93 static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
94 {
95 struct r600_context *rctx = (struct r600_context*)ctx;
96 struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
97 struct pipe_resource *dst = transfer->resource;
98 struct pipe_resource *src = &rtransfer->staging->b.b;
99 struct pipe_box sbox;
100
101 u_box_3d(0, 0, 0, transfer->box.width, transfer->box.height, transfer->box.depth, &sbox);
102
103 if (dst->nr_samples > 1) {
104 r600_copy_region_with_blit(ctx, dst, transfer->level,
105 transfer->box.x, transfer->box.y, transfer->box.z,
106 src, 0, &sbox);
107 return;
108 }
109
110 if (!rctx->screen->dma_blit(ctx, dst, transfer->level,
111 transfer->box.x, transfer->box.y, transfer->box.z,
112 src, 0, &sbox)) {
113 ctx->resource_copy_region(ctx, dst, transfer->level,
114 transfer->box.x, transfer->box.y, transfer->box.z,
115 src, 0, &sbox);
116 }
117 }
118
119 static unsigned r600_texture_get_offset(struct r600_texture *rtex, unsigned level,
120 const struct pipe_box *box)
121 {
122 enum pipe_format format = rtex->resource.b.b.format;
123
124 return rtex->surface.level[level].offset +
125 box->z * rtex->surface.level[level].slice_size +
126 box->y / util_format_get_blockheight(format) * rtex->surface.level[level].pitch_bytes +
127 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
128 }
129
130 static int r600_init_surface(struct r600_screen *rscreen,
131 struct radeon_surface *surface,
132 const struct pipe_resource *ptex,
133 unsigned array_mode,
134 bool is_flushed_depth)
135 {
136 const struct util_format_description *desc =
137 util_format_description(ptex->format);
138 bool is_depth, is_stencil;
139
140 is_depth = util_format_has_depth(desc);
141 is_stencil = util_format_has_stencil(desc);
142
143 surface->npix_x = ptex->width0;
144 surface->npix_y = ptex->height0;
145 surface->npix_z = ptex->depth0;
146 surface->blk_w = util_format_get_blockwidth(ptex->format);
147 surface->blk_h = util_format_get_blockheight(ptex->format);
148 surface->blk_d = 1;
149 surface->array_size = 1;
150 surface->last_level = ptex->last_level;
151
152 if (rscreen->b.chip_class >= EVERGREEN && !is_flushed_depth &&
153 ptex->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
154 surface->bpe = 4; /* stencil is allocated separately on evergreen */
155 } else {
156 surface->bpe = util_format_get_blocksize(ptex->format);
157 /* align byte per element on dword */
158 if (surface->bpe == 3) {
159 surface->bpe = 4;
160 }
161 }
162
163 surface->nsamples = ptex->nr_samples ? ptex->nr_samples : 1;
164 surface->flags = 0;
165
166 switch (array_mode) {
167 case V_038000_ARRAY_1D_TILED_THIN1:
168 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
169 break;
170 case V_038000_ARRAY_2D_TILED_THIN1:
171 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
172 break;
173 case V_038000_ARRAY_LINEAR_ALIGNED:
174 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
175 break;
176 case V_038000_ARRAY_LINEAR_GENERAL:
177 default:
178 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
179 break;
180 }
181 switch (ptex->target) {
182 case PIPE_TEXTURE_1D:
183 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
184 break;
185 case PIPE_TEXTURE_RECT:
186 case PIPE_TEXTURE_2D:
187 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
188 break;
189 case PIPE_TEXTURE_3D:
190 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
191 break;
192 case PIPE_TEXTURE_1D_ARRAY:
193 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
194 surface->array_size = ptex->array_size;
195 break;
196 case PIPE_TEXTURE_2D_ARRAY:
197 case PIPE_TEXTURE_CUBE_ARRAY: /* cube array layout like 2d layout for now */
198 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
199 surface->array_size = ptex->array_size;
200 break;
201 case PIPE_TEXTURE_CUBE:
202 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE);
203 break;
204 case PIPE_BUFFER:
205 default:
206 return -EINVAL;
207 }
208 if (ptex->bind & PIPE_BIND_SCANOUT) {
209 surface->flags |= RADEON_SURF_SCANOUT;
210 }
211
212 if (!is_flushed_depth && is_depth) {
213 surface->flags |= RADEON_SURF_ZBUFFER;
214
215 if (is_stencil) {
216 surface->flags |= RADEON_SURF_SBUFFER |
217 RADEON_SURF_HAS_SBUFFER_MIPTREE;
218 }
219 }
220 return 0;
221 }
222
223 static int r600_setup_surface(struct pipe_screen *screen,
224 struct r600_texture *rtex,
225 unsigned pitch_in_bytes_override)
226 {
227 struct r600_screen *rscreen = (struct r600_screen*)screen;
228 int r;
229
230 r = rscreen->b.ws->surface_init(rscreen->b.ws, &rtex->surface);
231 if (r) {
232 return r;
233 }
234 rtex->size = rtex->surface.bo_size;
235 if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) {
236 /* old ddx on evergreen over estimate alignment for 1d, only 1 level
237 * for those
238 */
239 rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe;
240 rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override;
241 rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y;
242 if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
243 rtex->surface.stencil_offset =
244 rtex->surface.stencil_level[0].offset = rtex->surface.level[0].slice_size;
245 }
246 }
247 return 0;
248 }
249
250 static boolean r600_texture_get_handle(struct pipe_screen* screen,
251 struct pipe_resource *ptex,
252 struct winsys_handle *whandle)
253 {
254 struct r600_texture *rtex = (struct r600_texture*)ptex;
255 struct r600_resource *resource = &rtex->resource;
256 struct radeon_surface *surface = &rtex->surface;
257 struct r600_screen *rscreen = (struct r600_screen*)screen;
258
259 rscreen->b.ws->buffer_set_tiling(resource->buf,
260 NULL,
261 surface->level[0].mode >= RADEON_SURF_MODE_1D ?
262 RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
263 surface->level[0].mode >= RADEON_SURF_MODE_2D ?
264 RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
265 surface->bankw, surface->bankh,
266 surface->tile_split,
267 surface->stencil_tile_split,
268 surface->mtilea,
269 rtex->surface.level[0].pitch_bytes);
270
271 return rscreen->b.ws->buffer_get_handle(resource->buf,
272 rtex->surface.level[0].pitch_bytes, whandle);
273 }
274
275 static void r600_texture_destroy(struct pipe_screen *screen,
276 struct pipe_resource *ptex)
277 {
278 struct r600_texture *rtex = (struct r600_texture*)ptex;
279 struct r600_resource *resource = &rtex->resource;
280
281 if (rtex->flushed_depth_texture)
282 pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
283
284 pipe_resource_reference((struct pipe_resource**)&rtex->htile, NULL);
285 if (rtex->cmask_buffer != &rtex->resource) {
286 pipe_resource_reference((struct pipe_resource**)&rtex->cmask_buffer, NULL);
287 }
288 pb_reference(&resource->buf, NULL);
289 FREE(rtex);
290 }
291
292 static const struct u_resource_vtbl r600_texture_vtbl;
293
294 /* The number of samples can be specified independently of the texture. */
295 void r600_texture_get_fmask_info(struct r600_screen *rscreen,
296 struct r600_texture *rtex,
297 unsigned nr_samples,
298 struct r600_fmask_info *out)
299 {
300 /* FMASK is allocated like an ordinary texture. */
301 struct radeon_surface fmask = rtex->surface;
302
303 memset(out, 0, sizeof(*out));
304
305 fmask.bo_alignment = 0;
306 fmask.bo_size = 0;
307 fmask.nsamples = 1;
308 fmask.flags |= RADEON_SURF_FMASK;
309
310 switch (nr_samples) {
311 case 2:
312 case 4:
313 fmask.bpe = 1;
314 fmask.bankh = 4;
315 break;
316 case 8:
317 fmask.bpe = 4;
318 break;
319 default:
320 R600_ERR("Invalid sample count for FMASK allocation.\n");
321 return;
322 }
323
324 /* Overallocate FMASK on R600-R700 to fix colorbuffer corruption.
325 * This can be fixed by writing a separate FMASK allocator specifically
326 * for R600-R700 asics. */
327 if (rscreen->b.chip_class <= R700) {
328 fmask.bpe *= 2;
329 }
330
331 if (rscreen->b.ws->surface_init(rscreen->b.ws, &fmask)) {
332 R600_ERR("Got error in surface_init while allocating FMASK.\n");
333 return;
334 }
335
336 assert(fmask.level[0].mode == RADEON_SURF_MODE_2D);
337
338 out->slice_tile_max = (fmask.level[0].nblk_x * fmask.level[0].nblk_y) / 64;
339 if (out->slice_tile_max)
340 out->slice_tile_max -= 1;
341
342 out->bank_height = fmask.bankh;
343 out->alignment = MAX2(256, fmask.bo_alignment);
344 out->size = fmask.bo_size;
345 }
346
347 static void r600_texture_allocate_fmask(struct r600_screen *rscreen,
348 struct r600_texture *rtex)
349 {
350 struct r600_fmask_info fmask;
351
352 r600_texture_get_fmask_info(rscreen, rtex,
353 rtex->resource.b.b.nr_samples, &fmask);
354
355 rtex->fmask.bank_height = fmask.bank_height;
356 rtex->fmask.slice_tile_max = fmask.slice_tile_max;
357 rtex->fmask.offset = align(rtex->size, fmask.alignment);
358 rtex->fmask.size = fmask.size;
359 rtex->size = rtex->fmask.offset + rtex->fmask.size;
360 #if 0
361 printf("FMASK width=%u, height=%i, bits=%u, size=%u\n",
362 fmask.npix_x, fmask.npix_y, fmask.bpe * fmask.nsamples, rtex->fmask_size);
363 #endif
364 }
365
366 void r600_texture_get_cmask_info(struct r600_screen *rscreen,
367 struct r600_texture *rtex,
368 struct r600_cmask_info *out)
369 {
370 unsigned cmask_tile_width = 8;
371 unsigned cmask_tile_height = 8;
372 unsigned cmask_tile_elements = cmask_tile_width * cmask_tile_height;
373 unsigned element_bits = 4;
374 unsigned cmask_cache_bits = 1024;
375 unsigned num_pipes = rscreen->tiling_info.num_channels;
376 unsigned pipe_interleave_bytes = rscreen->tiling_info.group_bytes;
377
378 unsigned elements_per_macro_tile = (cmask_cache_bits / element_bits) * num_pipes;
379 unsigned pixels_per_macro_tile = elements_per_macro_tile * cmask_tile_elements;
380 unsigned sqrt_pixels_per_macro_tile = sqrt(pixels_per_macro_tile);
381 unsigned macro_tile_width = util_next_power_of_two(sqrt_pixels_per_macro_tile);
382 unsigned macro_tile_height = pixels_per_macro_tile / macro_tile_width;
383
384 unsigned pitch_elements = align(rtex->surface.npix_x, macro_tile_width);
385 unsigned height = align(rtex->surface.npix_y, macro_tile_height);
386
387 unsigned base_align = num_pipes * pipe_interleave_bytes;
388 unsigned slice_bytes =
389 ((pitch_elements * height * element_bits + 7) / 8) / cmask_tile_elements;
390
391 assert(macro_tile_width % 128 == 0);
392 assert(macro_tile_height % 128 == 0);
393
394 out->slice_tile_max = ((pitch_elements * height) / (128*128)) - 1;
395 out->alignment = MAX2(256, base_align);
396 out->size = rtex->surface.array_size * align(slice_bytes, base_align);
397 }
398
399 static void r600_texture_allocate_cmask(struct r600_screen *rscreen,
400 struct r600_texture *rtex)
401 {
402 struct r600_cmask_info cmask;
403
404 r600_texture_get_cmask_info(rscreen, rtex, &cmask);
405
406 rtex->cmask.slice_tile_max = cmask.slice_tile_max;
407 rtex->cmask.offset = align(rtex->size, cmask.alignment);
408 rtex->cmask.size = cmask.size;
409 rtex->size = rtex->cmask.offset + rtex->cmask.size;
410 #if 0
411 printf("CMASK: macro tile width = %u, macro tile height = %u, "
412 "pitch elements = %u, height = %u, slice tile max = %u\n",
413 macro_tile_width, macro_tile_height, pitch_elements, height,
414 rtex->cmask_slice_tile_max);
415 #endif
416 }
417
418 void r600_texture_init_cmask(struct r600_screen *rscreen,
419 struct r600_texture *rtex) {
420 struct r600_cmask_info cmask;
421
422 assert(rtex->cmask.size == 0);
423
424 r600_texture_get_cmask_info(rscreen, rtex, &cmask);
425 rtex->cmask.slice_tile_max = cmask.slice_tile_max;
426 rtex->cmask.offset = 0;
427 rtex->cmask.size = cmask.size;
428 rtex->cmask_buffer = (struct r600_resource *)pipe_buffer_create(&rscreen->b.b,
429 PIPE_BIND_CUSTOM, PIPE_USAGE_STATIC, rtex->cmask.size);
430
431 if (rtex->cmask_buffer == NULL) {
432 rtex->cmask.size = 0;
433 }
434 }
435
436 static struct r600_texture *
437 r600_texture_create_object(struct pipe_screen *screen,
438 const struct pipe_resource *base,
439 unsigned pitch_in_bytes_override,
440 struct pb_buffer *buf,
441 struct radeon_surface *surface)
442 {
443 struct r600_texture *rtex;
444 struct r600_resource *resource;
445 struct r600_screen *rscreen = (struct r600_screen*)screen;
446 int r;
447
448 rtex = CALLOC_STRUCT(r600_texture);
449 if (rtex == NULL)
450 return NULL;
451
452 resource = &rtex->resource;
453 resource->b.b = *base;
454 resource->b.vtbl = &r600_texture_vtbl;
455 pipe_reference_init(&resource->b.b.reference, 1);
456 resource->b.b.screen = screen;
457 rtex->pitch_override = pitch_in_bytes_override;
458
459 /* don't include stencil-only formats which we don't support for rendering */
460 rtex->is_depth = util_format_has_depth(util_format_description(rtex->resource.b.b.format));
461
462 rtex->surface = *surface;
463 r = r600_setup_surface(screen, rtex, pitch_in_bytes_override);
464 if (r) {
465 FREE(rtex);
466 return NULL;
467 }
468
469 rtex->cmask_buffer = NULL;
470 if (base->nr_samples > 1 && !rtex->is_depth && !buf) {
471 r600_texture_allocate_fmask(rscreen, rtex);
472 r600_texture_allocate_cmask(rscreen, rtex);
473 rtex->cmask_buffer = &rtex->resource;
474 }
475
476 if (!rtex->is_depth && base->nr_samples > 1 &&
477 (!rtex->fmask.size || !rtex->cmask.size)) {
478 FREE(rtex);
479 return NULL;
480 }
481
482 /* Tiled depth textures utilize the non-displayable tile order. */
483 rtex->non_disp_tiling = rtex->is_depth && rtex->surface.level[0].mode >= RADEON_SURF_MODE_1D;
484
485 /* only enable hyperz for PIPE_TEXTURE_2D not for PIPE_TEXTURE_2D_ARRAY
486 * Thought it might still be interessting to use hyperz for texture
487 * array without using fast clear features
488 */
489 rtex->htile = NULL;
490 if (!(base->flags & (R600_RESOURCE_FLAG_TRANSFER | R600_RESOURCE_FLAG_FLUSHED_DEPTH)) &&
491 util_format_is_depth_or_stencil(base->format) &&
492 rscreen->b.info.drm_minor >= 26 &&
493 !(rscreen->debug_flags & DBG_NO_HYPERZ) &&
494 base->target == PIPE_TEXTURE_2D &&
495 rtex->surface.level[0].nblk_x >= 32 &&
496 rtex->surface.level[0].nblk_y >= 32) {
497 unsigned sw = rtex->surface.level[0].nblk_x * rtex->surface.blk_w;
498 unsigned sh = rtex->surface.level[0].nblk_y * rtex->surface.blk_h;
499 unsigned htile_size;
500 unsigned npipes = rscreen->b.info.r600_num_tile_pipes;
501
502 /* this alignment and htile size only apply to linear htile buffer */
503 sw = align(sw, 16 << 3);
504 sh = align(sh, npipes << 3);
505 htile_size = (sw >> 3) * (sh >> 3) * 4;
506 /* must be aligned with 2K * npipes */
507 htile_size = align(htile_size, (2 << 10) * npipes);
508
509 rtex->htile = (struct r600_resource*)pipe_buffer_create(&rscreen->b.b, PIPE_BIND_CUSTOM,
510 PIPE_USAGE_STATIC, htile_size);
511 if (rtex->htile == NULL) {
512 /* this is not a fatal error as we can still keep rendering
513 * without htile buffer
514 */
515 R600_ERR("r600: failed to create bo for htile buffers\n");
516 } else {
517 r600_screen_clear_buffer(rscreen, &rtex->htile->b.b, 0, htile_size, 0);
518 }
519 }
520
521 /* Now create the backing buffer. */
522 if (!buf) {
523 unsigned base_align = rtex->surface.bo_alignment;
524 unsigned usage = rtex->surface.level[0].mode >= RADEON_SURF_MODE_1D ?
525 PIPE_USAGE_STATIC : base->usage;
526
527 if (!r600_init_resource(rscreen, resource, rtex->size, base_align, FALSE, usage)) {
528 FREE(rtex);
529 return NULL;
530 }
531 } else {
532 /* This is usually the window framebuffer. We want it in VRAM, always. */
533 resource->buf = buf;
534 resource->cs_buf = rscreen->b.ws->buffer_get_cs_handle(buf);
535 resource->domains = RADEON_DOMAIN_VRAM;
536 }
537
538 if (rtex->cmask.size) {
539 /* Initialize the cmask to 0xCC (= compressed state). */
540 r600_screen_clear_buffer(rscreen, &rtex->cmask_buffer->b.b,
541 rtex->cmask.offset, rtex->cmask.size, 0xCC);
542 }
543
544 if (rscreen->debug_flags & DBG_VM) {
545 fprintf(stderr, "VM start=0x%llX end=0x%llX | Texture %ix%ix%i, %i levels, %i samples, %s\n",
546 r600_resource_va(screen, &rtex->resource.b.b),
547 r600_resource_va(screen, &rtex->resource.b.b) + rtex->resource.buf->size,
548 base->width0, base->height0, util_max_layer(base, 0)+1, base->last_level+1,
549 base->nr_samples ? base->nr_samples : 1, util_format_short_name(base->format));
550 }
551
552 if (rscreen->debug_flags & DBG_TEX_DEPTH && rtex->is_depth && rtex->non_disp_tiling) {
553 printf("Texture: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
554 "blk_h=%u, blk_d=%u, array_size=%u, last_level=%u, "
555 "bpe=%u, nsamples=%u, flags=%u\n",
556 rtex->surface.npix_x, rtex->surface.npix_y,
557 rtex->surface.npix_z, rtex->surface.blk_w,
558 rtex->surface.blk_h, rtex->surface.blk_d,
559 rtex->surface.array_size, rtex->surface.last_level,
560 rtex->surface.bpe, rtex->surface.nsamples,
561 rtex->surface.flags);
562 if (rtex->surface.flags & RADEON_SURF_ZBUFFER) {
563 for (int i = 0; i <= rtex->surface.last_level; i++) {
564 printf(" Z %i: offset=%llu, slice_size=%llu, npix_x=%u, "
565 "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
566 "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
567 i, (unsigned long long)rtex->surface.level[i].offset,
568 (unsigned long long)rtex->surface.level[i].slice_size,
569 u_minify(rtex->resource.b.b.width0, i),
570 u_minify(rtex->resource.b.b.height0, i),
571 u_minify(rtex->resource.b.b.depth0, i),
572 rtex->surface.level[i].nblk_x,
573 rtex->surface.level[i].nblk_y,
574 rtex->surface.level[i].nblk_z,
575 rtex->surface.level[i].pitch_bytes,
576 rtex->surface.level[i].mode);
577 }
578 }
579 if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
580 for (int i = 0; i <= rtex->surface.last_level; i++) {
581 printf(" S %i: offset=%llu, slice_size=%llu, npix_x=%u, "
582 "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
583 "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
584 i, (unsigned long long)rtex->surface.stencil_level[i].offset,
585 (unsigned long long)rtex->surface.stencil_level[i].slice_size,
586 u_minify(rtex->resource.b.b.width0, i),
587 u_minify(rtex->resource.b.b.height0, i),
588 u_minify(rtex->resource.b.b.depth0, i),
589 rtex->surface.stencil_level[i].nblk_x,
590 rtex->surface.stencil_level[i].nblk_y,
591 rtex->surface.stencil_level[i].nblk_z,
592 rtex->surface.stencil_level[i].pitch_bytes,
593 rtex->surface.stencil_level[i].mode);
594 }
595 }
596 }
597 return rtex;
598 }
599
600 struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
601 const struct pipe_resource *templ)
602 {
603 struct r600_screen *rscreen = (struct r600_screen*)screen;
604 struct radeon_surface surface;
605 const struct util_format_description *desc = util_format_description(templ->format);
606 unsigned array_mode;
607 int r;
608
609 /* Default tiling mode for staging textures. */
610 array_mode = V_038000_ARRAY_LINEAR_ALIGNED;
611
612 /* Tiling doesn't work with the 422 (SUBSAMPLED) formats. That's not an issue,
613 * because 422 formats are used for videos, which prefer linear buffers
614 * for fast uploads anyway. */
615 if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) &&
616 (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) &&
617 !(templ->bind & PIPE_BIND_LINEAR)) {
618 if (templ->flags & R600_RESOURCE_FLAG_FORCE_TILING) {
619 array_mode = V_038000_ARRAY_2D_TILED_THIN1;
620 } else if (!(templ->bind & PIPE_BIND_SCANOUT) &&
621 templ->usage != PIPE_USAGE_STAGING &&
622 templ->usage != PIPE_USAGE_STREAM &&
623 templ->target != PIPE_TEXTURE_1D &&
624 templ->target != PIPE_TEXTURE_1D_ARRAY &&
625 templ->height0 > 3) {
626 array_mode = V_038000_ARRAY_2D_TILED_THIN1;
627 } else if (util_format_is_compressed(templ->format)) {
628 array_mode = V_038000_ARRAY_1D_TILED_THIN1;
629 }
630 }
631
632 r = r600_init_surface(rscreen, &surface, templ, array_mode,
633 templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH);
634 if (r) {
635 return NULL;
636 }
637 r = rscreen->b.ws->surface_best(rscreen->b.ws, &surface);
638 if (r) {
639 return NULL;
640 }
641 return (struct pipe_resource *)r600_texture_create_object(screen, templ,
642 0, NULL, &surface);
643 }
644
645 struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
646 struct pipe_resource *texture,
647 const struct pipe_surface *templ,
648 unsigned width, unsigned height)
649 {
650 struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
651
652 assert(templ->u.tex.first_layer <= util_max_layer(texture, templ->u.tex.level));
653 assert(templ->u.tex.last_layer <= util_max_layer(texture, templ->u.tex.level));
654 assert(templ->u.tex.first_layer == templ->u.tex.last_layer);
655 if (surface == NULL)
656 return NULL;
657 pipe_reference_init(&surface->base.reference, 1);
658 pipe_resource_reference(&surface->base.texture, texture);
659 surface->base.context = pipe;
660 surface->base.format = templ->format;
661 surface->base.width = width;
662 surface->base.height = height;
663 surface->base.u = templ->u;
664 return &surface->base;
665 }
666
667 static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
668 struct pipe_resource *tex,
669 const struct pipe_surface *templ)
670 {
671 unsigned level = templ->u.tex.level;
672
673 return r600_create_surface_custom(pipe, tex, templ,
674 u_minify(tex->width0, level),
675 u_minify(tex->height0, level));
676 }
677
678 static void r600_surface_destroy(struct pipe_context *pipe,
679 struct pipe_surface *surface)
680 {
681 struct r600_surface *surf = (struct r600_surface*)surface;
682 pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_fmask, NULL);
683 pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_cmask, NULL);
684 pipe_resource_reference(&surface->texture, NULL);
685 FREE(surface);
686 }
687
688 struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
689 const struct pipe_resource *templ,
690 struct winsys_handle *whandle)
691 {
692 struct r600_screen *rscreen = (struct r600_screen*)screen;
693 struct pb_buffer *buf = NULL;
694 unsigned stride = 0;
695 unsigned array_mode = 0;
696 enum radeon_bo_layout micro, macro;
697 struct radeon_surface surface;
698 int r;
699
700 /* Support only 2D textures without mipmaps */
701 if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
702 templ->depth0 != 1 || templ->last_level != 0)
703 return NULL;
704
705 buf = rscreen->b.ws->buffer_from_handle(rscreen->b.ws, whandle, &stride);
706 if (!buf)
707 return NULL;
708
709 rscreen->b.ws->buffer_get_tiling(buf, &micro, &macro,
710 &surface.bankw, &surface.bankh,
711 &surface.tile_split,
712 &surface.stencil_tile_split,
713 &surface.mtilea);
714
715 if (macro == RADEON_LAYOUT_TILED)
716 array_mode = V_0280A0_ARRAY_2D_TILED_THIN1;
717 else if (micro == RADEON_LAYOUT_TILED)
718 array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
719 else
720 array_mode = V_038000_ARRAY_LINEAR_ALIGNED;
721
722 r = r600_init_surface(rscreen, &surface, templ, array_mode, false);
723 if (r) {
724 return NULL;
725 }
726 return (struct pipe_resource *)r600_texture_create_object(screen, templ,
727 stride, buf, &surface);
728 }
729
730 bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
731 struct pipe_resource *texture,
732 struct r600_texture **staging)
733 {
734 struct r600_texture *rtex = (struct r600_texture*)texture;
735 struct pipe_resource resource;
736 struct r600_texture **flushed_depth_texture = staging ?
737 staging : &rtex->flushed_depth_texture;
738
739 if (!staging && rtex->flushed_depth_texture)
740 return true; /* it's ready */
741
742 resource.target = texture->target;
743 resource.format = texture->format;
744 resource.width0 = texture->width0;
745 resource.height0 = texture->height0;
746 resource.depth0 = texture->depth0;
747 resource.array_size = texture->array_size;
748 resource.last_level = texture->last_level;
749 resource.nr_samples = texture->nr_samples;
750 resource.usage = staging ? PIPE_USAGE_STAGING : PIPE_USAGE_STATIC;
751 resource.bind = texture->bind & ~PIPE_BIND_DEPTH_STENCIL;
752 resource.flags = texture->flags | R600_RESOURCE_FLAG_FLUSHED_DEPTH;
753
754 if (staging)
755 resource.flags |= R600_RESOURCE_FLAG_TRANSFER;
756
757 *flushed_depth_texture = (struct r600_texture *)ctx->screen->resource_create(ctx->screen, &resource);
758 if (*flushed_depth_texture == NULL) {
759 R600_ERR("failed to create temporary texture to hold flushed depth\n");
760 return false;
761 }
762
763 (*flushed_depth_texture)->is_flushing_texture = TRUE;
764 (*flushed_depth_texture)->non_disp_tiling = false;
765 return true;
766 }
767
768 /**
769 * Initialize the pipe_resource descriptor to be of the same size as the box,
770 * which is supposed to hold a subregion of the texture "orig" at the given
771 * mipmap level.
772 */
773 static void r600_init_temp_resource_from_box(struct pipe_resource *res,
774 struct pipe_resource *orig,
775 const struct pipe_box *box,
776 unsigned level, unsigned flags)
777 {
778 memset(res, 0, sizeof(*res));
779 res->format = orig->format;
780 res->width0 = box->width;
781 res->height0 = box->height;
782 res->depth0 = 1;
783 res->array_size = 1;
784 res->usage = flags & R600_RESOURCE_FLAG_TRANSFER ? PIPE_USAGE_STAGING : PIPE_USAGE_STATIC;
785 res->flags = flags;
786
787 /* We must set the correct texture target and dimensions for a 3D box. */
788 if (box->depth > 1 && util_max_layer(orig, level) > 0)
789 res->target = orig->target;
790 else
791 res->target = PIPE_TEXTURE_2D;
792
793 switch (res->target) {
794 case PIPE_TEXTURE_1D_ARRAY:
795 case PIPE_TEXTURE_2D_ARRAY:
796 case PIPE_TEXTURE_CUBE_ARRAY:
797 res->array_size = box->depth;
798 break;
799 case PIPE_TEXTURE_3D:
800 res->depth0 = box->depth;
801 break;
802 default:;
803 }
804 }
805
806 static void *r600_texture_transfer_map(struct pipe_context *ctx,
807 struct pipe_resource *texture,
808 unsigned level,
809 unsigned usage,
810 const struct pipe_box *box,
811 struct pipe_transfer **ptransfer)
812 {
813 struct r600_context *rctx = (struct r600_context*)ctx;
814 struct r600_texture *rtex = (struct r600_texture*)texture;
815 struct r600_transfer *trans;
816 boolean use_staging_texture = FALSE;
817 struct r600_resource *buf;
818 unsigned offset = 0;
819 char *map;
820
821 if ((texture->bind & PIPE_BIND_GLOBAL) && texture->target == PIPE_BUFFER) {
822 return r600_compute_global_transfer_map(ctx, texture, level, usage, box, ptransfer);
823 }
824
825 /* We cannot map a tiled texture directly because the data is
826 * in a different order, therefore we do detiling using a blit.
827 *
828 * Also, use a temporary in GTT memory for read transfers, as
829 * the CPU is much happier reading out of cached system memory
830 * than uncached VRAM.
831 */
832 if (rtex->surface.level[level].mode >= RADEON_SURF_MODE_1D) {
833 use_staging_texture = TRUE;
834 }
835
836 /* Use a staging texture for uploads if the underlying BO is busy. */
837 if (!(usage & PIPE_TRANSFER_READ) &&
838 (r600_rings_is_buffer_referenced(rctx, rtex->resource.cs_buf, RADEON_USAGE_READWRITE) ||
839 rctx->b.ws->buffer_is_busy(rtex->resource.buf, RADEON_USAGE_READWRITE))) {
840 use_staging_texture = TRUE;
841 }
842
843 if (texture->flags & R600_RESOURCE_FLAG_TRANSFER) {
844 use_staging_texture = FALSE;
845 }
846
847 if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
848 return NULL;
849 }
850
851 trans = CALLOC_STRUCT(r600_transfer);
852 if (trans == NULL)
853 return NULL;
854 trans->transfer.resource = texture;
855 trans->transfer.level = level;
856 trans->transfer.usage = usage;
857 trans->transfer.box = *box;
858
859 if (rtex->is_depth) {
860 struct r600_texture *staging_depth;
861
862 if (rtex->resource.b.b.nr_samples > 1) {
863 /* MSAA depth buffers need to be converted to single sample buffers.
864 *
865 * Mapping MSAA depth buffers can occur if ReadPixels is called
866 * with a multisample GLX visual.
867 *
868 * First downsample the depth buffer to a temporary texture,
869 * then decompress the temporary one to staging.
870 *
871 * Only the region being mapped is transfered.
872 */
873 struct pipe_resource resource;
874
875 r600_init_temp_resource_from_box(&resource, texture, box, level, 0);
876
877 if (!r600_init_flushed_depth_texture(ctx, &resource, &staging_depth)) {
878 R600_ERR("failed to create temporary texture to hold untiled copy\n");
879 FREE(trans);
880 return NULL;
881 }
882
883 if (usage & PIPE_TRANSFER_READ) {
884 struct pipe_resource *temp = ctx->screen->resource_create(ctx->screen, &resource);
885
886 r600_copy_region_with_blit(ctx, temp, 0, 0, 0, 0, texture, level, box);
887 r600_blit_decompress_depth(ctx, (struct r600_texture*)temp, staging_depth,
888 0, 0, 0, box->depth, 0, 0);
889 pipe_resource_reference((struct pipe_resource**)&temp, NULL);
890 }
891 }
892 else {
893 /* XXX: only readback the rectangle which is being mapped? */
894 /* XXX: when discard is true, no need to read back from depth texture */
895 if (!r600_init_flushed_depth_texture(ctx, texture, &staging_depth)) {
896 R600_ERR("failed to create temporary texture to hold untiled copy\n");
897 FREE(trans);
898 return NULL;
899 }
900
901 r600_blit_decompress_depth(ctx, rtex, staging_depth,
902 level, level,
903 box->z, box->z + box->depth - 1,
904 0, 0);
905
906 offset = r600_texture_get_offset(staging_depth, level, box);
907 }
908
909 trans->transfer.stride = staging_depth->surface.level[level].pitch_bytes;
910 trans->transfer.layer_stride = staging_depth->surface.level[level].slice_size;
911 trans->staging = (struct r600_resource*)staging_depth;
912 } else if (use_staging_texture) {
913 struct pipe_resource resource;
914 struct r600_texture *staging;
915
916 r600_init_temp_resource_from_box(&resource, texture, box, level,
917 R600_RESOURCE_FLAG_TRANSFER);
918
919 /* Create the temporary texture. */
920 staging = (struct r600_texture*)ctx->screen->resource_create(ctx->screen, &resource);
921 if (staging == NULL) {
922 R600_ERR("failed to create temporary texture to hold untiled copy\n");
923 FREE(trans);
924 return NULL;
925 }
926 trans->staging = &staging->resource;
927 trans->transfer.stride = staging->surface.level[0].pitch_bytes;
928 trans->transfer.layer_stride = staging->surface.level[0].slice_size;
929 if (usage & PIPE_TRANSFER_READ) {
930 r600_copy_to_staging_texture(ctx, trans);
931 }
932 } else {
933 /* the resource is mapped directly */
934 trans->transfer.stride = rtex->surface.level[level].pitch_bytes;
935 trans->transfer.layer_stride = rtex->surface.level[level].slice_size;
936 offset = r600_texture_get_offset(rtex, level, box);
937 }
938
939 if (trans->staging) {
940 buf = trans->staging;
941 } else {
942 buf = &rtex->resource;
943 }
944
945 if (!(map = r600_buffer_mmap_sync_with_rings(rctx, buf, usage))) {
946 pipe_resource_reference((struct pipe_resource**)&trans->staging, NULL);
947 FREE(trans);
948 return NULL;
949 }
950
951 *ptransfer = &trans->transfer;
952 return map + offset;
953 }
954
955 static void r600_texture_transfer_unmap(struct pipe_context *ctx,
956 struct pipe_transfer* transfer)
957 {
958 struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
959 struct r600_context *rctx = (struct r600_context*)ctx;
960 struct radeon_winsys_cs_handle *buf;
961 struct pipe_resource *texture = transfer->resource;
962 struct r600_texture *rtex = (struct r600_texture*)texture;
963
964 if ((transfer->resource->bind & PIPE_BIND_GLOBAL) && transfer->resource->target == PIPE_BUFFER) {
965 return r600_compute_global_transfer_unmap(ctx, transfer);
966 }
967
968 if (rtransfer->staging) {
969 buf = ((struct r600_resource *)rtransfer->staging)->cs_buf;
970 } else {
971 buf = ((struct r600_resource *)transfer->resource)->cs_buf;
972 }
973 rctx->b.ws->buffer_unmap(buf);
974
975 if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtransfer->staging) {
976 if (rtex->is_depth && rtex->resource.b.b.nr_samples <= 1) {
977 ctx->resource_copy_region(ctx, texture, transfer->level,
978 transfer->box.x, transfer->box.y, transfer->box.z,
979 &rtransfer->staging->b.b, transfer->level,
980 &transfer->box);
981 } else {
982 r600_copy_from_staging_texture(ctx, rtransfer);
983 }
984 }
985
986 if (rtransfer->staging)
987 pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
988
989 FREE(transfer);
990 }
991
992 void r600_init_surface_functions(struct r600_context *r600)
993 {
994 r600->b.b.create_surface = r600_create_surface;
995 r600->b.b.surface_destroy = r600_surface_destroy;
996 }
997
998 unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
999 const unsigned char *swizzle_view,
1000 boolean vtx)
1001 {
1002 unsigned i;
1003 unsigned char swizzle[4];
1004 unsigned result = 0;
1005 const uint32_t tex_swizzle_shift[4] = {
1006 16, 19, 22, 25,
1007 };
1008 const uint32_t vtx_swizzle_shift[4] = {
1009 3, 6, 9, 12,
1010 };
1011 const uint32_t swizzle_bit[4] = {
1012 0, 1, 2, 3,
1013 };
1014 const uint32_t *swizzle_shift = tex_swizzle_shift;
1015
1016 if (vtx)
1017 swizzle_shift = vtx_swizzle_shift;
1018
1019 if (swizzle_view) {
1020 util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);
1021 } else {
1022 memcpy(swizzle, swizzle_format, 4);
1023 }
1024
1025 /* Get swizzle. */
1026 for (i = 0; i < 4; i++) {
1027 switch (swizzle[i]) {
1028 case UTIL_FORMAT_SWIZZLE_Y:
1029 result |= swizzle_bit[1] << swizzle_shift[i];
1030 break;
1031 case UTIL_FORMAT_SWIZZLE_Z:
1032 result |= swizzle_bit[2] << swizzle_shift[i];
1033 break;
1034 case UTIL_FORMAT_SWIZZLE_W:
1035 result |= swizzle_bit[3] << swizzle_shift[i];
1036 break;
1037 case UTIL_FORMAT_SWIZZLE_0:
1038 result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
1039 break;
1040 case UTIL_FORMAT_SWIZZLE_1:
1041 result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
1042 break;
1043 default: /* UTIL_FORMAT_SWIZZLE_X */
1044 result |= swizzle_bit[0] << swizzle_shift[i];
1045 }
1046 }
1047 return result;
1048 }
1049
1050 /* texture format translate */
1051 uint32_t r600_translate_texformat(struct pipe_screen *screen,
1052 enum pipe_format format,
1053 const unsigned char *swizzle_view,
1054 uint32_t *word4_p, uint32_t *yuv_format_p)
1055 {
1056 struct r600_screen *rscreen = (struct r600_screen *)screen;
1057 uint32_t result = 0, word4 = 0, yuv_format = 0;
1058 const struct util_format_description *desc;
1059 boolean uniform = TRUE;
1060 bool enable_s3tc = rscreen->b.info.drm_minor >= 9;
1061 bool is_srgb_valid = FALSE;
1062 const unsigned char swizzle_xxxx[4] = {0, 0, 0, 0};
1063 const unsigned char swizzle_yyyy[4] = {1, 1, 1, 1};
1064
1065 int i;
1066 const uint32_t sign_bit[4] = {
1067 S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
1068 S_038010_FORMAT_COMP_Y(V_038010_SQ_FORMAT_COMP_SIGNED),
1069 S_038010_FORMAT_COMP_Z(V_038010_SQ_FORMAT_COMP_SIGNED),
1070 S_038010_FORMAT_COMP_W(V_038010_SQ_FORMAT_COMP_SIGNED)
1071 };
1072 desc = util_format_description(format);
1073
1074 /* Depth and stencil swizzling is handled separately. */
1075 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) {
1076 word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view, FALSE);
1077 }
1078
1079 /* Colorspace (return non-RGB formats directly). */
1080 switch (desc->colorspace) {
1081 /* Depth stencil formats */
1082 case UTIL_FORMAT_COLORSPACE_ZS:
1083 switch (format) {
1084 /* Depth sampler formats. */
1085 case PIPE_FORMAT_Z16_UNORM:
1086 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1087 result = FMT_16;
1088 goto out_word4;
1089 case PIPE_FORMAT_Z24X8_UNORM:
1090 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
1091 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1092 result = FMT_8_24;
1093 goto out_word4;
1094 case PIPE_FORMAT_X8Z24_UNORM:
1095 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
1096 if (rscreen->b.chip_class < EVERGREEN)
1097 goto out_unknown;
1098 word4 |= r600_get_swizzle_combined(swizzle_yyyy, swizzle_view, FALSE);
1099 result = FMT_24_8;
1100 goto out_word4;
1101 case PIPE_FORMAT_Z32_FLOAT:
1102 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1103 result = FMT_32_FLOAT;
1104 goto out_word4;
1105 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
1106 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1107 result = FMT_X24_8_32_FLOAT;
1108 goto out_word4;
1109 /* Stencil sampler formats. */
1110 case PIPE_FORMAT_S8_UINT:
1111 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1112 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1113 result = FMT_8;
1114 goto out_word4;
1115 case PIPE_FORMAT_X24S8_UINT:
1116 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1117 word4 |= r600_get_swizzle_combined(swizzle_yyyy, swizzle_view, FALSE);
1118 result = FMT_8_24;
1119 goto out_word4;
1120 case PIPE_FORMAT_S8X24_UINT:
1121 if (rscreen->b.chip_class < EVERGREEN)
1122 goto out_unknown;
1123 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1124 word4 |= r600_get_swizzle_combined(swizzle_xxxx, swizzle_view, FALSE);
1125 result = FMT_24_8;
1126 goto out_word4;
1127 case PIPE_FORMAT_X32_S8X24_UINT:
1128 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1129 word4 |= r600_get_swizzle_combined(swizzle_yyyy, swizzle_view, FALSE);
1130 result = FMT_X24_8_32_FLOAT;
1131 goto out_word4;
1132 default:
1133 goto out_unknown;
1134 }
1135
1136 case UTIL_FORMAT_COLORSPACE_YUV:
1137 yuv_format |= (1 << 30);
1138 switch (format) {
1139 case PIPE_FORMAT_UYVY:
1140 case PIPE_FORMAT_YUYV:
1141 default:
1142 break;
1143 }
1144 goto out_unknown; /* XXX */
1145
1146 case UTIL_FORMAT_COLORSPACE_SRGB:
1147 word4 |= S_038010_FORCE_DEGAMMA(1);
1148 break;
1149
1150 default:
1151 break;
1152 }
1153
1154 if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
1155 if (!enable_s3tc)
1156 goto out_unknown;
1157
1158 switch (format) {
1159 case PIPE_FORMAT_RGTC1_SNORM:
1160 case PIPE_FORMAT_LATC1_SNORM:
1161 word4 |= sign_bit[0];
1162 case PIPE_FORMAT_RGTC1_UNORM:
1163 case PIPE_FORMAT_LATC1_UNORM:
1164 result = FMT_BC4;
1165 goto out_word4;
1166 case PIPE_FORMAT_RGTC2_SNORM:
1167 case PIPE_FORMAT_LATC2_SNORM:
1168 word4 |= sign_bit[0] | sign_bit[1];
1169 case PIPE_FORMAT_RGTC2_UNORM:
1170 case PIPE_FORMAT_LATC2_UNORM:
1171 result = FMT_BC5;
1172 goto out_word4;
1173 default:
1174 goto out_unknown;
1175 }
1176 }
1177
1178 if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
1179
1180 if (!enable_s3tc)
1181 goto out_unknown;
1182
1183 if (!util_format_s3tc_enabled) {
1184 goto out_unknown;
1185 }
1186
1187 switch (format) {
1188 case PIPE_FORMAT_DXT1_RGB:
1189 case PIPE_FORMAT_DXT1_RGBA:
1190 case PIPE_FORMAT_DXT1_SRGB:
1191 case PIPE_FORMAT_DXT1_SRGBA:
1192 result = FMT_BC1;
1193 is_srgb_valid = TRUE;
1194 goto out_word4;
1195 case PIPE_FORMAT_DXT3_RGBA:
1196 case PIPE_FORMAT_DXT3_SRGBA:
1197 result = FMT_BC2;
1198 is_srgb_valid = TRUE;
1199 goto out_word4;
1200 case PIPE_FORMAT_DXT5_RGBA:
1201 case PIPE_FORMAT_DXT5_SRGBA:
1202 result = FMT_BC3;
1203 is_srgb_valid = TRUE;
1204 goto out_word4;
1205 default:
1206 goto out_unknown;
1207 }
1208 }
1209
1210 if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
1211 switch (format) {
1212 case PIPE_FORMAT_R8G8_B8G8_UNORM:
1213 case PIPE_FORMAT_G8R8_B8R8_UNORM:
1214 result = FMT_GB_GR;
1215 goto out_word4;
1216 case PIPE_FORMAT_G8R8_G8B8_UNORM:
1217 case PIPE_FORMAT_R8G8_R8B8_UNORM:
1218 result = FMT_BG_RG;
1219 goto out_word4;
1220 default:
1221 goto out_unknown;
1222 }
1223 }
1224
1225 if (format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
1226 result = FMT_5_9_9_9_SHAREDEXP;
1227 goto out_word4;
1228 } else if (format == PIPE_FORMAT_R11G11B10_FLOAT) {
1229 result = FMT_10_11_11_FLOAT;
1230 goto out_word4;
1231 }
1232
1233
1234 for (i = 0; i < desc->nr_channels; i++) {
1235 if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
1236 word4 |= sign_bit[i];
1237 }
1238 }
1239
1240 /* R8G8Bx_SNORM - XXX CxV8U8 */
1241
1242 /* See whether the components are of the same size. */
1243 for (i = 1; i < desc->nr_channels; i++) {
1244 uniform = uniform && desc->channel[0].size == desc->channel[i].size;
1245 }
1246
1247 /* Non-uniform formats. */
1248 if (!uniform) {
1249 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB &&
1250 desc->channel[0].pure_integer)
1251 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1252 switch(desc->nr_channels) {
1253 case 3:
1254 if (desc->channel[0].size == 5 &&
1255 desc->channel[1].size == 6 &&
1256 desc->channel[2].size == 5) {
1257 result = FMT_5_6_5;
1258 goto out_word4;
1259 }
1260 goto out_unknown;
1261 case 4:
1262 if (desc->channel[0].size == 5 &&
1263 desc->channel[1].size == 5 &&
1264 desc->channel[2].size == 5 &&
1265 desc->channel[3].size == 1) {
1266 result = FMT_1_5_5_5;
1267 goto out_word4;
1268 }
1269 if (desc->channel[0].size == 10 &&
1270 desc->channel[1].size == 10 &&
1271 desc->channel[2].size == 10 &&
1272 desc->channel[3].size == 2) {
1273 result = FMT_2_10_10_10;
1274 goto out_word4;
1275 }
1276 goto out_unknown;
1277 }
1278 goto out_unknown;
1279 }
1280
1281 /* Find the first non-VOID channel. */
1282 for (i = 0; i < 4; i++) {
1283 if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
1284 break;
1285 }
1286 }
1287
1288 if (i == 4)
1289 goto out_unknown;
1290
1291 /* uniform formats */
1292 switch (desc->channel[i].type) {
1293 case UTIL_FORMAT_TYPE_UNSIGNED:
1294 case UTIL_FORMAT_TYPE_SIGNED:
1295 #if 0
1296 if (!desc->channel[i].normalized &&
1297 desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
1298 goto out_unknown;
1299 }
1300 #endif
1301 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB &&
1302 desc->channel[i].pure_integer)
1303 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
1304
1305 switch (desc->channel[i].size) {
1306 case 4:
1307 switch (desc->nr_channels) {
1308 case 2:
1309 result = FMT_4_4;
1310 goto out_word4;
1311 case 4:
1312 result = FMT_4_4_4_4;
1313 goto out_word4;
1314 }
1315 goto out_unknown;
1316 case 8:
1317 switch (desc->nr_channels) {
1318 case 1:
1319 result = FMT_8;
1320 goto out_word4;
1321 case 2:
1322 result = FMT_8_8;
1323 goto out_word4;
1324 case 4:
1325 result = FMT_8_8_8_8;
1326 is_srgb_valid = TRUE;
1327 goto out_word4;
1328 }
1329 goto out_unknown;
1330 case 16:
1331 switch (desc->nr_channels) {
1332 case 1:
1333 result = FMT_16;
1334 goto out_word4;
1335 case 2:
1336 result = FMT_16_16;
1337 goto out_word4;
1338 case 4:
1339 result = FMT_16_16_16_16;
1340 goto out_word4;
1341 }
1342 goto out_unknown;
1343 case 32:
1344 switch (desc->nr_channels) {
1345 case 1:
1346 result = FMT_32;
1347 goto out_word4;
1348 case 2:
1349 result = FMT_32_32;
1350 goto out_word4;
1351 case 4:
1352 result = FMT_32_32_32_32;
1353 goto out_word4;
1354 }
1355 }
1356 goto out_unknown;
1357
1358 case UTIL_FORMAT_TYPE_FLOAT:
1359 switch (desc->channel[i].size) {
1360 case 16:
1361 switch (desc->nr_channels) {
1362 case 1:
1363 result = FMT_16_FLOAT;
1364 goto out_word4;
1365 case 2:
1366 result = FMT_16_16_FLOAT;
1367 goto out_word4;
1368 case 4:
1369 result = FMT_16_16_16_16_FLOAT;
1370 goto out_word4;
1371 }
1372 goto out_unknown;
1373 case 32:
1374 switch (desc->nr_channels) {
1375 case 1:
1376 result = FMT_32_FLOAT;
1377 goto out_word4;
1378 case 2:
1379 result = FMT_32_32_FLOAT;
1380 goto out_word4;
1381 case 4:
1382 result = FMT_32_32_32_32_FLOAT;
1383 goto out_word4;
1384 }
1385 }
1386 goto out_unknown;
1387 }
1388
1389 out_word4:
1390
1391 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB && !is_srgb_valid)
1392 return ~0;
1393 if (word4_p)
1394 *word4_p = word4;
1395 if (yuv_format_p)
1396 *yuv_format_p = yuv_format;
1397 return result;
1398 out_unknown:
1399 /* R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format)); */
1400 return ~0;
1401 }
1402
1403 static const struct u_resource_vtbl r600_texture_vtbl =
1404 {
1405 r600_texture_get_handle, /* get_handle */
1406 r600_texture_destroy, /* resource_destroy */
1407 r600_texture_transfer_map, /* transfer_map */
1408 NULL, /* transfer_flush_region */
1409 r600_texture_transfer_unmap, /* transfer_unmap */
1410 NULL /* transfer_inline_write */
1411 };