r600g: implement timestamp query and get_timestamp hook
[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 "r600d.h"
29
30 #include <errno.h>
31 #include "util/u_format_s3tc.h"
32 #include "util/u_memory.h"
33
34 /* Copy from a full GPU texture to a transfer's staging one. */
35 static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
36 {
37 struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
38 struct pipe_resource *texture = transfer->resource;
39
40 ctx->resource_copy_region(ctx, &rtransfer->staging->b.b,
41 0, 0, 0, 0, texture, transfer->level,
42 &transfer->box);
43 }
44
45
46 /* Copy from a transfer's staging texture to a full GPU one. */
47 static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
48 {
49 struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
50 struct pipe_resource *texture = transfer->resource;
51 struct pipe_box sbox;
52
53 u_box_origin_2d(transfer->box.width, transfer->box.height, &sbox);
54
55 ctx->resource_copy_region(ctx, texture, transfer->level,
56 transfer->box.x, transfer->box.y, transfer->box.z,
57 &rtransfer->staging->b.b,
58 0, &sbox);
59 }
60
61 unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
62 unsigned level, unsigned layer)
63 {
64 return rtex->offset[level] + layer * rtex->layer_size[level];
65 }
66
67 static int r600_init_surface(struct r600_screen *rscreen,
68 struct radeon_surface *surface,
69 const struct pipe_resource *ptex,
70 unsigned array_mode,
71 bool is_transfer, bool is_flushed_depth)
72 {
73 const struct util_format_description *desc =
74 util_format_description(ptex->format);
75 bool is_depth, is_stencil;
76
77 is_depth = util_format_has_depth(desc);
78 is_stencil = util_format_has_stencil(desc);
79
80 surface->npix_x = ptex->width0;
81 surface->npix_y = ptex->height0;
82 surface->npix_z = ptex->depth0;
83 surface->blk_w = util_format_get_blockwidth(ptex->format);
84 surface->blk_h = util_format_get_blockheight(ptex->format);
85 surface->blk_d = 1;
86 surface->array_size = 1;
87 surface->last_level = ptex->last_level;
88
89 if (rscreen->chip_class >= EVERGREEN &&
90 !is_transfer && !is_flushed_depth &&
91 ptex->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
92 surface->bpe = 4; /* stencil is allocated separately on evergreen */
93 } else {
94 surface->bpe = util_format_get_blocksize(ptex->format);
95 /* align byte per element on dword */
96 if (surface->bpe == 3) {
97 surface->bpe = 4;
98 }
99 }
100
101 surface->nsamples = ptex->nr_samples ? ptex->nr_samples : 1;
102 surface->flags = 0;
103
104 switch (array_mode) {
105 case V_038000_ARRAY_1D_TILED_THIN1:
106 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
107 break;
108 case V_038000_ARRAY_2D_TILED_THIN1:
109 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
110 break;
111 case V_038000_ARRAY_LINEAR_ALIGNED:
112 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
113 break;
114 case V_038000_ARRAY_LINEAR_GENERAL:
115 default:
116 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
117 break;
118 }
119 switch (ptex->target) {
120 case PIPE_TEXTURE_1D:
121 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
122 break;
123 case PIPE_TEXTURE_RECT:
124 case PIPE_TEXTURE_2D:
125 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
126 break;
127 case PIPE_TEXTURE_3D:
128 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
129 break;
130 case PIPE_TEXTURE_1D_ARRAY:
131 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
132 surface->array_size = ptex->array_size;
133 break;
134 case PIPE_TEXTURE_2D_ARRAY:
135 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
136 surface->array_size = ptex->array_size;
137 break;
138 case PIPE_TEXTURE_CUBE:
139 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE);
140 break;
141 case PIPE_BUFFER:
142 default:
143 return -EINVAL;
144 }
145 if (ptex->bind & PIPE_BIND_SCANOUT) {
146 surface->flags |= RADEON_SURF_SCANOUT;
147 }
148
149 if (!is_transfer && !is_flushed_depth && is_depth) {
150 surface->flags |= RADEON_SURF_ZBUFFER;
151
152 if (is_stencil) {
153 surface->flags |= RADEON_SURF_SBUFFER;
154 }
155 }
156 return 0;
157 }
158
159 static int r600_setup_surface(struct pipe_screen *screen,
160 struct r600_resource_texture *rtex,
161 unsigned pitch_in_bytes_override)
162 {
163 struct pipe_resource *ptex = &rtex->resource.b.b;
164 struct r600_screen *rscreen = (struct r600_screen*)screen;
165 unsigned i;
166 int r;
167
168 r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface);
169 if (r) {
170 return r;
171 }
172 rtex->size = rtex->surface.bo_size;
173 if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) {
174 /* old ddx on evergreen over estimate alignment for 1d, only 1 level
175 * for those
176 */
177 rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe;
178 rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override;
179 rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y;
180 if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
181 rtex->surface.stencil_offset = rtex->surface.level[0].slice_size;
182 }
183 }
184 for (i = 0; i <= ptex->last_level; i++) {
185 rtex->offset[i] = rtex->surface.level[i].offset;
186 rtex->layer_size[i] = rtex->surface.level[i].slice_size;
187 rtex->pitch_in_bytes[i] = rtex->surface.level[i].pitch_bytes;
188 switch (rtex->surface.level[i].mode) {
189 case RADEON_SURF_MODE_LINEAR_ALIGNED:
190 rtex->array_mode[i] = V_038000_ARRAY_LINEAR_ALIGNED;
191 break;
192 case RADEON_SURF_MODE_1D:
193 rtex->array_mode[i] = V_038000_ARRAY_1D_TILED_THIN1;
194 break;
195 case RADEON_SURF_MODE_2D:
196 rtex->array_mode[i] = V_038000_ARRAY_2D_TILED_THIN1;
197 break;
198 default:
199 case RADEON_SURF_MODE_LINEAR:
200 rtex->array_mode[i] = 0;
201 break;
202 }
203 }
204 return 0;
205 }
206
207 static boolean r600_texture_get_handle(struct pipe_screen* screen,
208 struct pipe_resource *ptex,
209 struct winsys_handle *whandle)
210 {
211 struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
212 struct r600_resource *resource = &rtex->resource;
213 struct radeon_surface *surface = &rtex->surface;
214 struct r600_screen *rscreen = (struct r600_screen*)screen;
215
216 rscreen->ws->buffer_set_tiling(resource->buf,
217 NULL,
218 surface->level[0].mode >= RADEON_SURF_MODE_1D ?
219 RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
220 surface->level[0].mode >= RADEON_SURF_MODE_2D ?
221 RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
222 surface->bankw, surface->bankh,
223 surface->tile_split,
224 surface->stencil_tile_split,
225 surface->mtilea,
226 rtex->pitch_in_bytes[0]);
227
228 return rscreen->ws->buffer_get_handle(resource->buf,
229 rtex->pitch_in_bytes[0], whandle);
230 }
231
232 static void r600_texture_destroy(struct pipe_screen *screen,
233 struct pipe_resource *ptex)
234 {
235 struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
236 struct r600_resource *resource = &rtex->resource;
237
238 if (rtex->flushed_depth_texture)
239 pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
240
241 pb_reference(&resource->buf, NULL);
242 FREE(rtex);
243 }
244
245 static const struct u_resource_vtbl r600_texture_vtbl =
246 {
247 r600_texture_get_handle, /* get_handle */
248 r600_texture_destroy, /* resource_destroy */
249 r600_texture_get_transfer, /* get_transfer */
250 r600_texture_transfer_destroy, /* transfer_destroy */
251 r600_texture_transfer_map, /* transfer_map */
252 NULL, /* transfer_flush_region */
253 r600_texture_transfer_unmap, /* transfer_unmap */
254 NULL /* transfer_inline_write */
255 };
256
257 static struct r600_resource_texture *
258 r600_texture_create_object(struct pipe_screen *screen,
259 const struct pipe_resource *base,
260 unsigned array_mode,
261 unsigned pitch_in_bytes_override,
262 struct pb_buffer *buf,
263 boolean alloc_bo,
264 struct radeon_surface *surface)
265 {
266 struct r600_resource_texture *rtex;
267 struct r600_resource *resource;
268 struct r600_screen *rscreen = (struct r600_screen*)screen;
269 int r;
270
271 rtex = CALLOC_STRUCT(r600_resource_texture);
272 if (rtex == NULL)
273 return NULL;
274
275 resource = &rtex->resource;
276 resource->b.b = *base;
277 resource->b.vtbl = &r600_texture_vtbl;
278 pipe_reference_init(&resource->b.b.reference, 1);
279 resource->b.b.screen = screen;
280 rtex->pitch_override = pitch_in_bytes_override;
281 rtex->real_format = base->format;
282
283 /* don't include stencil-only formats which we don't support for rendering */
284 rtex->is_depth = util_format_has_depth(util_format_description(rtex->resource.b.b.format));
285
286 rtex->surface = *surface;
287 r = r600_setup_surface(screen, rtex,
288 pitch_in_bytes_override);
289 if (r) {
290 FREE(rtex);
291 return NULL;
292 }
293
294 /* Now create the backing buffer. */
295 if (!buf && alloc_bo) {
296 unsigned base_align = rtex->surface.bo_alignment;
297
298 if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) {
299 FREE(rtex);
300 return NULL;
301 }
302 } else if (buf) {
303 resource->buf = buf;
304 resource->cs_buf = rscreen->ws->buffer_get_cs_handle(buf);
305 resource->domains = RADEON_DOMAIN_GTT | RADEON_DOMAIN_VRAM;
306 }
307 return rtex;
308 }
309
310 struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
311 const struct pipe_resource *templ)
312 {
313 struct r600_screen *rscreen = (struct r600_screen*)screen;
314 struct radeon_surface surface;
315 unsigned array_mode = 0;
316 int r;
317
318 if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER)) {
319 if (!(templ->bind & PIPE_BIND_SCANOUT) &&
320 templ->usage != PIPE_USAGE_STAGING &&
321 templ->usage != PIPE_USAGE_STREAM) {
322 array_mode = V_038000_ARRAY_2D_TILED_THIN1;
323 } else if (util_format_is_compressed(templ->format)) {
324 array_mode = V_038000_ARRAY_1D_TILED_THIN1;
325 }
326 }
327
328 r = r600_init_surface(rscreen, &surface, templ, array_mode,
329 templ->flags & R600_RESOURCE_FLAG_TRANSFER,
330 templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH);
331 if (r) {
332 return NULL;
333 }
334 r = rscreen->ws->surface_best(rscreen->ws, &surface);
335 if (r) {
336 return NULL;
337 }
338 return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
339 0, NULL, TRUE, &surface);
340 }
341
342 static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
343 struct pipe_resource *texture,
344 const struct pipe_surface *templ)
345 {
346 struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
347 unsigned level = templ->u.tex.level;
348
349 assert(templ->u.tex.first_layer == templ->u.tex.last_layer);
350 if (surface == NULL)
351 return NULL;
352 pipe_reference_init(&surface->base.reference, 1);
353 pipe_resource_reference(&surface->base.texture, texture);
354 surface->base.context = pipe;
355 surface->base.format = templ->format;
356 surface->base.width = u_minify(texture->width0, level);
357 surface->base.height = u_minify(texture->height0, level);
358 surface->base.usage = templ->usage;
359 surface->base.u = templ->u;
360 return &surface->base;
361 }
362
363 static void r600_surface_destroy(struct pipe_context *pipe,
364 struct pipe_surface *surface)
365 {
366 pipe_resource_reference(&surface->texture, NULL);
367 FREE(surface);
368 }
369
370 struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
371 const struct pipe_resource *templ,
372 struct winsys_handle *whandle)
373 {
374 struct r600_screen *rscreen = (struct r600_screen*)screen;
375 struct pb_buffer *buf = NULL;
376 unsigned stride = 0;
377 unsigned array_mode = 0;
378 enum radeon_bo_layout micro, macro;
379 struct radeon_surface surface;
380 int r;
381
382 /* Support only 2D textures without mipmaps */
383 if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
384 templ->depth0 != 1 || templ->last_level != 0)
385 return NULL;
386
387 buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, &stride);
388 if (!buf)
389 return NULL;
390
391 rscreen->ws->buffer_get_tiling(buf, &micro, &macro,
392 &surface.bankw, &surface.bankh,
393 &surface.tile_split,
394 &surface.stencil_tile_split,
395 &surface.mtilea);
396
397 if (macro == RADEON_LAYOUT_TILED)
398 array_mode = V_0280A0_ARRAY_2D_TILED_THIN1;
399 else if (micro == RADEON_LAYOUT_TILED)
400 array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
401 else
402 array_mode = 0;
403
404 r = r600_init_surface(rscreen, &surface, templ, array_mode, false, false);
405 if (r) {
406 return NULL;
407 }
408 return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
409 stride, buf, FALSE, &surface);
410 }
411
412 bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
413 struct pipe_resource *texture,
414 struct r600_resource_texture **staging)
415 {
416 struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
417 struct pipe_resource resource;
418 struct r600_resource_texture **flushed_depth_texture = staging ?
419 staging : &rtex->flushed_depth_texture;
420
421 if (!staging && rtex->flushed_depth_texture)
422 return true; /* it's ready */
423
424 resource.target = texture->target;
425 resource.format = texture->format;
426 resource.width0 = texture->width0;
427 resource.height0 = texture->height0;
428 resource.depth0 = texture->depth0;
429 resource.array_size = texture->array_size;
430 resource.last_level = texture->last_level;
431 resource.nr_samples = texture->nr_samples;
432 resource.usage = staging ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT;
433 resource.bind = texture->bind & ~PIPE_BIND_DEPTH_STENCIL;
434 resource.flags = texture->flags | R600_RESOURCE_FLAG_FLUSHED_DEPTH;
435
436 if (staging)
437 resource.flags |= R600_RESOURCE_FLAG_TRANSFER;
438
439 *flushed_depth_texture = (struct r600_resource_texture *)ctx->screen->resource_create(ctx->screen, &resource);
440 if (*flushed_depth_texture == NULL) {
441 R600_ERR("failed to create temporary texture to hold flushed depth\n");
442 return false;
443 }
444
445 (*flushed_depth_texture)->is_flushing_texture = TRUE;
446 return true;
447 }
448
449 /* Needs adjustment for pixelformat:
450 */
451 static INLINE unsigned u_box_volume( const struct pipe_box *box )
452 {
453 return box->width * box->depth * box->height;
454 }
455
456 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
457 struct pipe_resource *texture,
458 unsigned level,
459 unsigned usage,
460 const struct pipe_box *box)
461 {
462 struct r600_context *rctx = (struct r600_context*)ctx;
463 struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
464 struct pipe_resource resource;
465 struct r600_transfer *trans;
466 boolean use_staging_texture = FALSE;
467
468 /* We cannot map a tiled texture directly because the data is
469 * in a different order, therefore we do detiling using a blit.
470 *
471 * Also, use a temporary in GTT memory for read transfers, as
472 * the CPU is much happier reading out of cached system memory
473 * than uncached VRAM.
474 */
475 if (R600_TEX_IS_TILED(rtex, level)) {
476 use_staging_texture = TRUE;
477 }
478
479 if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024)
480 use_staging_texture = TRUE;
481
482 /* Use a staging texture for uploads if the underlying BO is busy. */
483 if (!(usage & PIPE_TRANSFER_READ) &&
484 (rctx->ws->cs_is_buffer_referenced(rctx->cs, rtex->resource.cs_buf, RADEON_USAGE_READWRITE) ||
485 rctx->ws->buffer_is_busy(rtex->resource.buf, RADEON_USAGE_READWRITE))) {
486 use_staging_texture = TRUE;
487 }
488
489 if (texture->flags & R600_RESOURCE_FLAG_TRANSFER) {
490 use_staging_texture = FALSE;
491 }
492
493 if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
494 return NULL;
495 }
496
497 trans = CALLOC_STRUCT(r600_transfer);
498 if (trans == NULL)
499 return NULL;
500 pipe_resource_reference(&trans->transfer.resource, texture);
501 trans->transfer.level = level;
502 trans->transfer.usage = usage;
503 trans->transfer.box = *box;
504 if (rtex->is_depth) {
505 /* XXX: only readback the rectangle which is being mapped?
506 */
507 /* XXX: when discard is true, no need to read back from depth texture
508 */
509 struct r600_resource_texture *staging_depth;
510
511 if (!r600_init_flushed_depth_texture(ctx, texture, &staging_depth)) {
512 R600_ERR("failed to create temporary texture to hold untiled copy\n");
513 pipe_resource_reference(&trans->transfer.resource, NULL);
514 FREE(trans);
515 return NULL;
516 }
517
518 r600_blit_uncompress_depth(ctx, rtex, staging_depth,
519 level, level,
520 box->z, box->z + box->depth - 1,
521 0, 0);
522
523 trans->transfer.stride = staging_depth->pitch_in_bytes[level];
524 trans->offset = r600_texture_get_offset(staging_depth, level, box->z);
525 trans->staging = (struct r600_resource*)staging_depth;
526 return &trans->transfer;
527 } else if (use_staging_texture) {
528 resource.target = PIPE_TEXTURE_2D;
529 resource.format = texture->format;
530 resource.width0 = box->width;
531 resource.height0 = box->height;
532 resource.depth0 = 1;
533 resource.array_size = 1;
534 resource.last_level = 0;
535 resource.nr_samples = 0;
536 resource.usage = PIPE_USAGE_STAGING;
537 resource.bind = 0;
538 resource.flags = R600_RESOURCE_FLAG_TRANSFER;
539 /* For texture reading, the temporary (detiled) texture is used as
540 * a render target when blitting from a tiled texture. */
541 if (usage & PIPE_TRANSFER_READ) {
542 resource.bind |= PIPE_BIND_RENDER_TARGET;
543 }
544 /* For texture writing, the temporary texture is used as a sampler
545 * when blitting into a tiled texture. */
546 if (usage & PIPE_TRANSFER_WRITE) {
547 resource.bind |= PIPE_BIND_SAMPLER_VIEW;
548 }
549 /* Create the temporary texture. */
550 trans->staging = (struct r600_resource*)ctx->screen->resource_create(ctx->screen, &resource);
551 if (trans->staging == NULL) {
552 R600_ERR("failed to create temporary texture to hold untiled copy\n");
553 pipe_resource_reference(&trans->transfer.resource, NULL);
554 FREE(trans);
555 return NULL;
556 }
557
558 trans->transfer.stride =
559 ((struct r600_resource_texture *)trans->staging)->pitch_in_bytes[0];
560 if (usage & PIPE_TRANSFER_READ) {
561 r600_copy_to_staging_texture(ctx, trans);
562 /* Always referenced in the blit. */
563 r600_flush(ctx, NULL, 0);
564 }
565 return &trans->transfer;
566 }
567 trans->transfer.stride = rtex->pitch_in_bytes[level];
568 trans->transfer.layer_stride = rtex->layer_size[level];
569 trans->offset = r600_texture_get_offset(rtex, level, box->z);
570 return &trans->transfer;
571 }
572
573 void r600_texture_transfer_destroy(struct pipe_context *ctx,
574 struct pipe_transfer *transfer)
575 {
576 struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
577 struct pipe_resource *texture = transfer->resource;
578 struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
579
580 if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtransfer->staging) {
581 if (rtex->is_depth) {
582 ctx->resource_copy_region(ctx, texture, transfer->level,
583 transfer->box.x, transfer->box.y, transfer->box.z,
584 &rtransfer->staging->b.b, transfer->level,
585 &transfer->box);
586 } else {
587 r600_copy_from_staging_texture(ctx, rtransfer);
588 }
589 }
590
591 if (rtransfer->staging)
592 pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
593
594 pipe_resource_reference(&transfer->resource, NULL);
595 FREE(transfer);
596 }
597
598 void* r600_texture_transfer_map(struct pipe_context *ctx,
599 struct pipe_transfer* transfer)
600 {
601 struct r600_context *rctx = (struct r600_context *)ctx;
602 struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
603 struct radeon_winsys_cs_handle *buf;
604 struct r600_resource_texture *rtex =
605 (struct r600_resource_texture*)transfer->resource;
606 enum pipe_format format = transfer->resource->format;
607 unsigned offset = 0;
608 char *map;
609
610 if ((transfer->resource->bind & PIPE_BIND_GLOBAL) && transfer->resource->target == PIPE_BUFFER) {
611 return r600_compute_global_transfer_map(ctx, transfer);
612 }
613
614 if (rtransfer->staging) {
615 buf = ((struct r600_resource *)rtransfer->staging)->cs_buf;
616 } else {
617 buf = ((struct r600_resource *)transfer->resource)->cs_buf;
618 }
619
620 if (rtex->is_depth || !rtransfer->staging)
621 offset = rtransfer->offset +
622 transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
623 transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
624
625 if (!(map = rctx->ws->buffer_map(buf, rctx->cs, transfer->usage))) {
626 return NULL;
627 }
628
629 return map + offset;
630 }
631
632 void r600_texture_transfer_unmap(struct pipe_context *ctx,
633 struct pipe_transfer* transfer)
634 {
635 struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
636 struct r600_context *rctx = (struct r600_context*)ctx;
637 struct radeon_winsys_cs_handle *buf;
638
639 if ((transfer->resource->bind & PIPE_BIND_GLOBAL) && transfer->resource->target == PIPE_BUFFER) {
640 return r600_compute_global_transfer_unmap(ctx, transfer);
641 }
642
643 if (rtransfer->staging) {
644 buf = ((struct r600_resource *)rtransfer->staging)->cs_buf;
645 } else {
646 buf = ((struct r600_resource *)transfer->resource)->cs_buf;
647 }
648 rctx->ws->buffer_unmap(buf);
649 }
650
651 void r600_init_surface_functions(struct r600_context *r600)
652 {
653 r600->context.create_surface = r600_create_surface;
654 r600->context.surface_destroy = r600_surface_destroy;
655 }
656
657 static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
658 const unsigned char *swizzle_view)
659 {
660 unsigned i;
661 unsigned char swizzle[4];
662 unsigned result = 0;
663 const uint32_t swizzle_shift[4] = {
664 16, 19, 22, 25,
665 };
666 const uint32_t swizzle_bit[4] = {
667 0, 1, 2, 3,
668 };
669
670 if (swizzle_view) {
671 util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);
672 } else {
673 memcpy(swizzle, swizzle_format, 4);
674 }
675
676 /* Get swizzle. */
677 for (i = 0; i < 4; i++) {
678 switch (swizzle[i]) {
679 case UTIL_FORMAT_SWIZZLE_Y:
680 result |= swizzle_bit[1] << swizzle_shift[i];
681 break;
682 case UTIL_FORMAT_SWIZZLE_Z:
683 result |= swizzle_bit[2] << swizzle_shift[i];
684 break;
685 case UTIL_FORMAT_SWIZZLE_W:
686 result |= swizzle_bit[3] << swizzle_shift[i];
687 break;
688 case UTIL_FORMAT_SWIZZLE_0:
689 result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
690 break;
691 case UTIL_FORMAT_SWIZZLE_1:
692 result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
693 break;
694 default: /* UTIL_FORMAT_SWIZZLE_X */
695 result |= swizzle_bit[0] << swizzle_shift[i];
696 }
697 }
698 return result;
699 }
700
701 /* texture format translate */
702 uint32_t r600_translate_texformat(struct pipe_screen *screen,
703 enum pipe_format format,
704 const unsigned char *swizzle_view,
705 uint32_t *word4_p, uint32_t *yuv_format_p)
706 {
707 uint32_t result = 0, word4 = 0, yuv_format = 0;
708 const struct util_format_description *desc;
709 boolean uniform = TRUE;
710 static int r600_enable_s3tc = -1;
711 bool is_srgb_valid = FALSE;
712
713 int i;
714 const uint32_t sign_bit[4] = {
715 S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
716 S_038010_FORMAT_COMP_Y(V_038010_SQ_FORMAT_COMP_SIGNED),
717 S_038010_FORMAT_COMP_Z(V_038010_SQ_FORMAT_COMP_SIGNED),
718 S_038010_FORMAT_COMP_W(V_038010_SQ_FORMAT_COMP_SIGNED)
719 };
720 desc = util_format_description(format);
721
722 word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
723
724 /* Colorspace (return non-RGB formats directly). */
725 switch (desc->colorspace) {
726 /* Depth stencil formats */
727 case UTIL_FORMAT_COLORSPACE_ZS:
728 switch (format) {
729 case PIPE_FORMAT_Z16_UNORM:
730 result = FMT_16;
731 goto out_word4;
732 case PIPE_FORMAT_X24S8_UINT:
733 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
734 case PIPE_FORMAT_Z24X8_UNORM:
735 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
736 result = FMT_8_24;
737 goto out_word4;
738 case PIPE_FORMAT_S8X24_UINT:
739 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
740 case PIPE_FORMAT_X8Z24_UNORM:
741 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
742 result = FMT_24_8;
743 goto out_word4;
744 case PIPE_FORMAT_S8_UINT:
745 result = FMT_8;
746 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
747 goto out_word4;
748 case PIPE_FORMAT_Z32_FLOAT:
749 result = FMT_32_FLOAT;
750 goto out_word4;
751 case PIPE_FORMAT_X32_S8X24_UINT:
752 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
753 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
754 result = FMT_X24_8_32_FLOAT;
755 goto out_word4;
756 default:
757 goto out_unknown;
758 }
759
760 case UTIL_FORMAT_COLORSPACE_YUV:
761 yuv_format |= (1 << 30);
762 switch (format) {
763 case PIPE_FORMAT_UYVY:
764 case PIPE_FORMAT_YUYV:
765 default:
766 break;
767 }
768 goto out_unknown; /* XXX */
769
770 case UTIL_FORMAT_COLORSPACE_SRGB:
771 word4 |= S_038010_FORCE_DEGAMMA(1);
772 break;
773
774 default:
775 break;
776 }
777
778 if (r600_enable_s3tc == -1) {
779 struct r600_screen *rscreen = (struct r600_screen *)screen;
780 if (rscreen->info.drm_minor >= 9)
781 r600_enable_s3tc = 1;
782 else
783 r600_enable_s3tc = debug_get_bool_option("R600_ENABLE_S3TC", FALSE);
784 }
785
786 if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
787 if (!r600_enable_s3tc)
788 goto out_unknown;
789
790 switch (format) {
791 case PIPE_FORMAT_RGTC1_SNORM:
792 case PIPE_FORMAT_LATC1_SNORM:
793 word4 |= sign_bit[0];
794 case PIPE_FORMAT_RGTC1_UNORM:
795 case PIPE_FORMAT_LATC1_UNORM:
796 result = FMT_BC4;
797 goto out_word4;
798 case PIPE_FORMAT_RGTC2_SNORM:
799 case PIPE_FORMAT_LATC2_SNORM:
800 word4 |= sign_bit[0] | sign_bit[1];
801 case PIPE_FORMAT_RGTC2_UNORM:
802 case PIPE_FORMAT_LATC2_UNORM:
803 result = FMT_BC5;
804 goto out_word4;
805 default:
806 goto out_unknown;
807 }
808 }
809
810 if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
811
812 if (!r600_enable_s3tc)
813 goto out_unknown;
814
815 if (!util_format_s3tc_enabled) {
816 goto out_unknown;
817 }
818
819 switch (format) {
820 case PIPE_FORMAT_DXT1_RGB:
821 case PIPE_FORMAT_DXT1_RGBA:
822 case PIPE_FORMAT_DXT1_SRGB:
823 case PIPE_FORMAT_DXT1_SRGBA:
824 result = FMT_BC1;
825 is_srgb_valid = TRUE;
826 goto out_word4;
827 case PIPE_FORMAT_DXT3_RGBA:
828 case PIPE_FORMAT_DXT3_SRGBA:
829 result = FMT_BC2;
830 is_srgb_valid = TRUE;
831 goto out_word4;
832 case PIPE_FORMAT_DXT5_RGBA:
833 case PIPE_FORMAT_DXT5_SRGBA:
834 result = FMT_BC3;
835 is_srgb_valid = TRUE;
836 goto out_word4;
837 default:
838 goto out_unknown;
839 }
840 }
841
842 if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
843 switch (format) {
844 case PIPE_FORMAT_R8G8_B8G8_UNORM:
845 case PIPE_FORMAT_G8R8_B8R8_UNORM:
846 result = FMT_GB_GR;
847 goto out_word4;
848 case PIPE_FORMAT_G8R8_G8B8_UNORM:
849 case PIPE_FORMAT_R8G8_R8B8_UNORM:
850 result = FMT_BG_RG;
851 goto out_word4;
852 default:
853 goto out_unknown;
854 }
855 }
856
857 if (format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
858 result = FMT_5_9_9_9_SHAREDEXP;
859 goto out_word4;
860 } else if (format == PIPE_FORMAT_R11G11B10_FLOAT) {
861 result = FMT_10_11_11_FLOAT;
862 goto out_word4;
863 }
864
865
866 for (i = 0; i < desc->nr_channels; i++) {
867 if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
868 word4 |= sign_bit[i];
869 }
870 }
871
872 /* R8G8Bx_SNORM - XXX CxV8U8 */
873
874 /* See whether the components are of the same size. */
875 for (i = 1; i < desc->nr_channels; i++) {
876 uniform = uniform && desc->channel[0].size == desc->channel[i].size;
877 }
878
879 /* Non-uniform formats. */
880 if (!uniform) {
881 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB &&
882 desc->channel[0].pure_integer)
883 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
884 switch(desc->nr_channels) {
885 case 3:
886 if (desc->channel[0].size == 5 &&
887 desc->channel[1].size == 6 &&
888 desc->channel[2].size == 5) {
889 result = FMT_5_6_5;
890 goto out_word4;
891 }
892 goto out_unknown;
893 case 4:
894 if (desc->channel[0].size == 5 &&
895 desc->channel[1].size == 5 &&
896 desc->channel[2].size == 5 &&
897 desc->channel[3].size == 1) {
898 result = FMT_1_5_5_5;
899 goto out_word4;
900 }
901 if (desc->channel[0].size == 10 &&
902 desc->channel[1].size == 10 &&
903 desc->channel[2].size == 10 &&
904 desc->channel[3].size == 2) {
905 result = FMT_2_10_10_10;
906 goto out_word4;
907 }
908 goto out_unknown;
909 }
910 goto out_unknown;
911 }
912
913 /* Find the first non-VOID channel. */
914 for (i = 0; i < 4; i++) {
915 if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
916 break;
917 }
918 }
919
920 if (i == 4)
921 goto out_unknown;
922
923 /* uniform formats */
924 switch (desc->channel[i].type) {
925 case UTIL_FORMAT_TYPE_UNSIGNED:
926 case UTIL_FORMAT_TYPE_SIGNED:
927 #if 0
928 if (!desc->channel[i].normalized &&
929 desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
930 goto out_unknown;
931 }
932 #endif
933 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB &&
934 desc->channel[i].pure_integer)
935 word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
936
937 switch (desc->channel[i].size) {
938 case 4:
939 switch (desc->nr_channels) {
940 case 2:
941 result = FMT_4_4;
942 goto out_word4;
943 case 4:
944 result = FMT_4_4_4_4;
945 goto out_word4;
946 }
947 goto out_unknown;
948 case 8:
949 switch (desc->nr_channels) {
950 case 1:
951 result = FMT_8;
952 goto out_word4;
953 case 2:
954 result = FMT_8_8;
955 goto out_word4;
956 case 4:
957 result = FMT_8_8_8_8;
958 is_srgb_valid = TRUE;
959 goto out_word4;
960 }
961 goto out_unknown;
962 case 16:
963 switch (desc->nr_channels) {
964 case 1:
965 result = FMT_16;
966 goto out_word4;
967 case 2:
968 result = FMT_16_16;
969 goto out_word4;
970 case 4:
971 result = FMT_16_16_16_16;
972 goto out_word4;
973 }
974 goto out_unknown;
975 case 32:
976 switch (desc->nr_channels) {
977 case 1:
978 result = FMT_32;
979 goto out_word4;
980 case 2:
981 result = FMT_32_32;
982 goto out_word4;
983 case 4:
984 result = FMT_32_32_32_32;
985 goto out_word4;
986 }
987 }
988 goto out_unknown;
989
990 case UTIL_FORMAT_TYPE_FLOAT:
991 switch (desc->channel[i].size) {
992 case 16:
993 switch (desc->nr_channels) {
994 case 1:
995 result = FMT_16_FLOAT;
996 goto out_word4;
997 case 2:
998 result = FMT_16_16_FLOAT;
999 goto out_word4;
1000 case 4:
1001 result = FMT_16_16_16_16_FLOAT;
1002 goto out_word4;
1003 }
1004 goto out_unknown;
1005 case 32:
1006 switch (desc->nr_channels) {
1007 case 1:
1008 result = FMT_32_FLOAT;
1009 goto out_word4;
1010 case 2:
1011 result = FMT_32_32_FLOAT;
1012 goto out_word4;
1013 case 4:
1014 result = FMT_32_32_32_32_FLOAT;
1015 goto out_word4;
1016 }
1017 }
1018 goto out_unknown;
1019 }
1020
1021 out_word4:
1022
1023 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB && !is_srgb_valid)
1024 return ~0;
1025 if (word4_p)
1026 *word4_p = word4;
1027 if (yuv_format_p)
1028 *yuv_format_p = yuv_format;
1029 return result;
1030 out_unknown:
1031 /* R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format)); */
1032 return ~0;
1033 }