r600_texture.c revision c4993d15eb07d95ac465b5f25ea96072e4b008bf
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. */
35static 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. */
47static 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
61unsigned 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
67static 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
159static 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
207static 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
232static 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
245static 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
257static struct r600_resource_texture *
258r600_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
310struct 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
342static 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
363static 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
370struct 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
412bool 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_STAGING : PIPE_USAGE_STATIC;
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 */
451static INLINE unsigned u_box_volume( const struct pipe_box *box )
452{
453	return box->width * box->depth * box->height;
454}
455
456struct 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
573void 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
598void* 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
632void 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
651void 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
657static 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 */
702uint32_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
1021out_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;
1030out_unknown:
1031	/* R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format)); */
1032	return ~0;
1033}
1034