r600_texture.c revision e8ff0f63b6f078b17989e42dd05c9b69729b341b
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 <errno.h>
28#include <pipe/p_screen.h>
29#include <util/u_format.h>
30#include <util/u_math.h>
31#include <util/u_inlines.h>
32#include <util/u_memory.h>
33#include "state_tracker/drm_driver.h"
34#include "r600_screen.h"
35#include "r600_context.h"
36#include "r600_resource.h"
37#include "r600_state_inlines.h"
38#include "r600d.h"
39
40extern struct u_resource_vtbl r600_texture_vtbl;
41
42/* Copy from a tiled texture to a detiled one. */
43static void r600_copy_from_tiled_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
44{
45	struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
46	struct pipe_resource *texture = transfer->resource;
47	struct pipe_subresource subdst;
48
49	subdst.face = 0;
50	subdst.level = 0;
51	ctx->resource_copy_region(ctx, rtransfer->linear_texture,
52				subdst, 0, 0, 0, texture, transfer->sr,
53				transfer->box.x, transfer->box.y, transfer->box.z,
54				transfer->box.width, transfer->box.height);
55}
56
57static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
58					unsigned level, unsigned zslice,
59					unsigned face)
60{
61	unsigned long offset = rtex->offset[level];
62
63	switch (rtex->resource.base.b.target) {
64	case PIPE_TEXTURE_3D:
65		assert(face == 0);
66		return offset + zslice * rtex->layer_size[level];
67	case PIPE_TEXTURE_CUBE:
68		assert(zslice == 0);
69		return offset + face * rtex->layer_size[level];
70	default:
71		assert(zslice == 0 && face == 0);
72		return offset;
73	}
74}
75
76static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource_texture *rtex)
77{
78	struct pipe_resource *ptex = &rtex->resource.base.b;
79	unsigned long w, h, pitch, size, layer_size, i, offset;
80
81	rtex->bpt = util_format_get_blocksize(ptex->format);
82	for (i = 0, offset = 0; i <= ptex->last_level; i++) {
83		w = u_minify(ptex->width0, i);
84		h = u_minify(ptex->height0, i);
85		h = util_next_power_of_two(h);
86		pitch = util_format_get_stride(ptex->format, align(w, 64));
87		pitch = align(pitch, 256);
88		layer_size = pitch * h;
89		if (ptex->target == PIPE_TEXTURE_CUBE)
90			size = layer_size * 6;
91		else
92			size = layer_size * u_minify(ptex->depth0, i);
93		rtex->offset[i] = offset;
94		rtex->layer_size[i] = layer_size;
95		rtex->pitch[i] = pitch;
96		rtex->width[i] = w;
97		rtex->height[i] = h;
98		offset += size;
99	}
100	rtex->size = offset;
101}
102
103struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
104						const struct pipe_resource *templ)
105{
106	struct r600_resource_texture *rtex;
107	struct r600_resource *resource;
108	struct r600_screen *rscreen = r600_screen(screen);
109
110	rtex = CALLOC_STRUCT(r600_resource_texture);
111	if (!rtex) {
112		return NULL;
113	}
114	resource = &rtex->resource;
115	resource->base.b = *templ;
116	resource->base.vtbl = &r600_texture_vtbl;
117	pipe_reference_init(&resource->base.b.reference, 1);
118	resource->base.b.screen = screen;
119	r600_setup_miptree(rscreen, rtex);
120
121	/* FIXME alignment 4096 enought ? too much ? */
122	resource->domain = r600_domain_from_usage(resource->base.b.bind);
123	resource->bo = radeon_bo(rscreen->rw, 0, rtex->size, 4096, NULL);
124	if (resource->bo == NULL) {
125		FREE(rtex);
126		return NULL;
127	}
128	return &resource->base.b;
129}
130
131static void r600_texture_destroy_state(struct pipe_resource *ptexture)
132{
133	struct r600_resource_texture *rtexture = (struct r600_resource_texture*)ptexture;
134
135	for (int i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) {
136		radeon_state_fini(&rtexture->scissor[i]);
137		radeon_state_fini(&rtexture->db[i]);
138		for (int j = 0; j < 8; j++) {
139			radeon_state_fini(&rtexture->cb[j][i]);
140		}
141	}
142}
143
144static void r600_texture_destroy(struct pipe_screen *screen,
145				 struct pipe_resource *ptex)
146{
147	struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
148	struct r600_resource *resource = &rtex->resource;
149	struct r600_screen *rscreen = r600_screen(screen);
150
151	if (resource->bo) {
152		radeon_bo_decref(rscreen->rw, resource->bo);
153	}
154	if (rtex->uncompressed) {
155		radeon_bo_decref(rscreen->rw, rtex->uncompressed);
156	}
157	r600_texture_destroy_state(ptex);
158	FREE(rtex);
159}
160
161static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen,
162						struct pipe_resource *texture,
163						unsigned face, unsigned level,
164						unsigned zslice, unsigned flags)
165{
166	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
167	struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
168	unsigned long offset;
169
170	if (surface == NULL)
171		return NULL;
172	offset = r600_texture_get_offset(rtex, level, zslice, face);
173	pipe_reference_init(&surface->reference, 1);
174	pipe_resource_reference(&surface->texture, texture);
175	surface->format = texture->format;
176	surface->width = u_minify(texture->width0, level);
177	surface->height = u_minify(texture->height0, level);
178	surface->offset = offset;
179	surface->usage = flags;
180	surface->zslice = zslice;
181	surface->texture = texture;
182	surface->face = face;
183	surface->level = level;
184	return surface;
185}
186
187static void r600_tex_surface_destroy(struct pipe_surface *surface)
188{
189	pipe_resource_reference(&surface->texture, NULL);
190	FREE(surface);
191}
192
193struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
194					       const struct pipe_resource *templ,
195					       struct winsys_handle *whandle)
196{
197	struct radeon *rw = (struct radeon*)screen->winsys;
198	struct r600_resource_texture *rtex;
199	struct r600_resource *resource;
200	struct radeon_bo *bo = NULL;
201
202	bo = radeon_bo(rw, whandle->handle, 0, 0, NULL);
203	if (bo == NULL) {
204		return NULL;
205	}
206
207	/* Support only 2D textures without mipmaps */
208	if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
209	      templ->depth0 != 1 || templ->last_level != 0)
210		return NULL;
211
212	rtex = CALLOC_STRUCT(r600_resource_texture);
213	if (rtex == NULL)
214		return NULL;
215
216	resource = &rtex->resource;
217	resource->base.b = *templ;
218	resource->base.vtbl = &r600_texture_vtbl;
219	pipe_reference_init(&resource->base.b.reference, 1);
220	resource->base.b.screen = screen;
221	resource->bo = bo;
222	rtex->depth = 0;
223	rtex->pitch_override = whandle->stride;
224	rtex->bpt = util_format_get_blocksize(templ->format);
225	rtex->pitch[0] = whandle->stride;
226	rtex->width[0] = templ->width0;
227	rtex->height[0] = templ->height0;
228	rtex->offset[0] = 0;
229	rtex->size = align(rtex->pitch[0] * templ->height0, 64);
230
231	return &resource->base.b;
232}
233
234static unsigned int r600_texture_is_referenced(struct pipe_context *context,
235						struct pipe_resource *texture,
236						unsigned face, unsigned level)
237{
238	/* FIXME */
239	return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
240}
241
242struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
243						struct pipe_resource *texture,
244						struct pipe_subresource sr,
245						unsigned usage,
246						const struct pipe_box *box)
247{
248	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
249	struct pipe_resource resource;
250	struct r600_transfer *trans;
251
252	trans = CALLOC_STRUCT(r600_transfer);
253	if (trans == NULL)
254		return NULL;
255	pipe_resource_reference(&trans->transfer.resource, texture);
256	trans->transfer.sr = sr;
257	trans->transfer.usage = usage;
258	trans->transfer.box = *box;
259	trans->transfer.stride = rtex->pitch[sr.level];
260	trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
261	if (rtex->tilled && !rtex->depth) {
262		resource.target = PIPE_TEXTURE_2D;
263		resource.format = texture->format;
264		resource.width0 = box->width;
265		resource.height0 = box->height;
266		resource.depth0 = 0;
267		resource.last_level = 0;
268		resource.nr_samples = 0;
269		resource.usage = PIPE_USAGE_DYNAMIC;
270		resource.bind = 0;
271		resource.flags = 0;
272		/* For texture reading, the temporary (detiled) texture is used as
273		 * a render target when blitting from a tiled texture. */
274		if (usage & PIPE_TRANSFER_READ) {
275			resource.bind |= PIPE_BIND_RENDER_TARGET;
276		}
277		/* For texture writing, the temporary texture is used as a sampler
278		 * when blitting into a tiled texture. */
279		if (usage & PIPE_TRANSFER_WRITE) {
280			resource.bind |= PIPE_BIND_SAMPLER_VIEW;
281		}
282		/* Create the temporary texture. */
283		trans->linear_texture = ctx->screen->resource_create(ctx->screen, &resource);
284		if (trans->linear_texture == NULL) {
285			R600_ERR("failed to create temporary texture to hold untiled copy\n");
286			pipe_resource_reference(&trans->transfer.resource, NULL);
287			FREE(trans);
288			return NULL;
289		}
290		if (usage & PIPE_TRANSFER_READ) {
291			/* We cannot map a tiled texture directly because the data is
292			 * in a different order, therefore we do detiling using a blit. */
293			r600_copy_from_tiled_texture(ctx, trans);
294			/* Always referenced in the blit. */
295			ctx->flush(ctx, 0, NULL);
296		}
297	}
298	return &trans->transfer;
299}
300
301void r600_texture_transfer_destroy(struct pipe_context *ctx,
302				   struct pipe_transfer *transfer)
303{
304	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
305
306	if (rtransfer->linear_texture) {
307		pipe_resource_reference(&rtransfer->linear_texture, NULL);
308	}
309	pipe_resource_reference(&transfer->resource, NULL);
310	FREE(transfer);
311}
312
313void* r600_texture_transfer_map(struct pipe_context *ctx,
314				struct pipe_transfer* transfer)
315{
316	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
317	struct radeon_bo *bo;
318	enum pipe_format format = transfer->resource->format;
319	struct r600_screen *rscreen = r600_screen(ctx->screen);
320	struct r600_resource_texture *rtex;
321	unsigned long offset = 0;
322	char *map;
323	int r;
324
325	r600_flush(ctx, 0, NULL);
326	if (rtransfer->linear_texture) {
327		bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
328	} else {
329		rtex = (struct r600_resource_texture*)transfer->resource;
330		if (rtex->depth) {
331			r = r600_texture_from_depth(ctx, rtex, transfer->sr.level);
332			if (r) {
333				return NULL;
334			}
335			r600_flush(ctx, 0, NULL);
336			bo = rtex->uncompressed;
337		} else {
338			bo = ((struct r600_resource *)transfer->resource)->bo;
339		}
340		offset = rtransfer->offset +
341			transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
342			transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
343	}
344	if (radeon_bo_map(rscreen->rw, bo)) {
345		return NULL;
346	}
347	radeon_bo_wait(rscreen->rw, bo);
348
349	map = bo->data;
350	return map + offset;
351}
352
353void r600_texture_transfer_unmap(struct pipe_context *ctx,
354				 struct pipe_transfer* transfer)
355{
356	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
357	struct r600_screen *rscreen = r600_screen(ctx->screen);
358	struct r600_resource_texture *rtex;
359	struct radeon_bo *bo;
360
361	if (rtransfer->linear_texture) {
362		bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
363	} else {
364		rtex = (struct r600_resource_texture*)transfer->resource;
365		if (rtex->depth) {
366			bo = rtex->uncompressed;
367		} else {
368			bo = ((struct r600_resource *)transfer->resource)->bo;
369		}
370	}
371	radeon_bo_unmap(rscreen->rw, bo);
372}
373
374struct u_resource_vtbl r600_texture_vtbl =
375{
376	u_default_resource_get_handle,	/* get_handle */
377	r600_texture_destroy,		/* resource_destroy */
378	r600_texture_is_referenced,	/* is_resource_referenced */
379	r600_texture_get_transfer,	/* get_transfer */
380	r600_texture_transfer_destroy,	/* transfer_destroy */
381	r600_texture_transfer_map,	/* transfer_map */
382	u_default_transfer_flush_region,/* transfer_flush_region */
383	r600_texture_transfer_unmap,	/* transfer_unmap */
384	u_default_transfer_inline_write	/* transfer_inline_write */
385};
386
387void r600_init_screen_texture_functions(struct pipe_screen *screen)
388{
389	screen->get_tex_surface = r600_get_tex_surface;
390	screen->tex_surface_destroy = r600_tex_surface_destroy;
391}
392
393static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
394		const unsigned char *swizzle_view)
395{
396	unsigned i;
397	unsigned char swizzle[4];
398	unsigned result = 0;
399	const uint32_t swizzle_shift[4] = {
400		16, 19, 22, 25,
401	};
402	const uint32_t swizzle_bit[4] = {
403		0, 1, 2, 3,
404	};
405
406	if (swizzle_view) {
407		/* Combine two sets of swizzles. */
408		for (i = 0; i < 4; i++) {
409			swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
410				swizzle_format[swizzle_view[i]] : swizzle_view[i];
411		}
412	} else {
413		memcpy(swizzle, swizzle_format, 4);
414	}
415
416	/* Get swizzle. */
417	for (i = 0; i < 4; i++) {
418		switch (swizzle[i]) {
419		case UTIL_FORMAT_SWIZZLE_Y:
420			result |= swizzle_bit[1] << swizzle_shift[i];
421			break;
422		case UTIL_FORMAT_SWIZZLE_Z:
423			result |= swizzle_bit[2] << swizzle_shift[i];
424			break;
425		case UTIL_FORMAT_SWIZZLE_W:
426			result |= swizzle_bit[3] << swizzle_shift[i];
427			break;
428		case UTIL_FORMAT_SWIZZLE_0:
429			result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
430			break;
431		case UTIL_FORMAT_SWIZZLE_1:
432			result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
433			break;
434		default: /* UTIL_FORMAT_SWIZZLE_X */
435			result |= swizzle_bit[0] << swizzle_shift[i];
436		}
437	}
438	return result;
439}
440
441/* texture format translate */
442uint32_t r600_translate_texformat(enum pipe_format format,
443				  const unsigned char *swizzle_view,
444				  uint32_t *word4_p, uint32_t *yuv_format_p)
445{
446	uint32_t result = 0, word4 = 0, yuv_format = 0;
447	const struct util_format_description *desc;
448	boolean uniform = TRUE;
449	int i;
450	const uint32_t sign_bit[4] = {
451		S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
452		S_038010_FORMAT_COMP_Y(V_038010_SQ_FORMAT_COMP_SIGNED),
453		S_038010_FORMAT_COMP_Z(V_038010_SQ_FORMAT_COMP_SIGNED),
454		S_038010_FORMAT_COMP_W(V_038010_SQ_FORMAT_COMP_SIGNED)
455	};
456	desc = util_format_description(format);
457
458	word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
459
460	/* Colorspace (return non-RGB formats directly). */
461	switch (desc->colorspace) {
462		/* Depth stencil formats */
463	case UTIL_FORMAT_COLORSPACE_ZS:
464		switch (format) {
465		case PIPE_FORMAT_Z16_UNORM:
466			result = V_0280A0_COLOR_16;
467			goto out_word4;
468		case PIPE_FORMAT_Z24X8_UNORM:
469			result = V_0280A0_COLOR_8_24;
470			goto out_word4;
471		case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
472			result = V_0280A0_COLOR_8_24;
473			goto out_word4;
474		default:
475			goto out_unknown;
476		}
477
478	case UTIL_FORMAT_COLORSPACE_YUV:
479		yuv_format |= (1 << 30);
480		switch (format) {
481                case PIPE_FORMAT_UYVY:
482                case PIPE_FORMAT_YUYV:
483		default:
484			break;
485		}
486		goto out_unknown; /* TODO */
487
488	case UTIL_FORMAT_COLORSPACE_SRGB:
489		word4 |= S_038010_FORCE_DEGAMMA(1);
490		if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB)
491			goto out_unknown; /* fails for some reason - TODO */
492		break;
493
494	default:
495		break;
496	}
497
498	/* S3TC formats. TODO */
499	if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
500		goto out_unknown;
501	}
502
503
504	for (i = 0; i < desc->nr_channels; i++) {
505		if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
506			word4 |= sign_bit[i];
507		}
508	}
509
510	/* R8G8Bx_SNORM - TODO CxV8U8 */
511
512	/* RGTC - TODO */
513
514	/* See whether the components are of the same size. */
515	for (i = 1; i < desc->nr_channels; i++) {
516		uniform = uniform && desc->channel[0].size == desc->channel[i].size;
517	}
518
519	/* Non-uniform formats. */
520	if (!uniform) {
521		switch(desc->nr_channels) {
522		case 3:
523			if (desc->channel[0].size == 5 &&
524			    desc->channel[1].size == 6 &&
525			    desc->channel[2].size == 5) {
526				result |= V_0280A0_COLOR_5_6_5;
527				goto out_word4;
528			}
529			goto out_unknown;
530		case 4:
531			if (desc->channel[0].size == 5 &&
532			    desc->channel[1].size == 5 &&
533			    desc->channel[2].size == 5 &&
534			    desc->channel[3].size == 1) {
535				result |= V_0280A0_COLOR_1_5_5_5;
536				goto out_word4;
537			}
538			if (desc->channel[0].size == 10 &&
539			    desc->channel[1].size == 10 &&
540			    desc->channel[2].size == 10 &&
541			    desc->channel[3].size == 2) {
542				result |= V_0280A0_COLOR_10_10_10_2;
543				goto out_word4;
544			}
545			goto out_unknown;
546		}
547		goto out_unknown;
548	}
549
550	/* uniform formats */
551	switch (desc->channel[0].type) {
552	case UTIL_FORMAT_TYPE_UNSIGNED:
553	case UTIL_FORMAT_TYPE_SIGNED:
554		if (!desc->channel[0].normalized &&
555		    desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
556			goto out_unknown;
557		}
558
559		switch (desc->channel[0].size) {
560		case 4:
561			switch (desc->nr_channels) {
562			case 2:
563				result |= V_0280A0_COLOR_4_4;
564				goto out_word4;
565			case 4:
566				result |= V_0280A0_COLOR_4_4_4_4;
567				goto out_word4;
568			}
569			goto out_unknown;
570		case 8:
571			switch (desc->nr_channels) {
572			case 1:
573				result |= V_0280A0_COLOR_8;
574				goto out_word4;
575			case 2:
576				result |= V_0280A0_COLOR_8_8;
577				goto out_word4;
578			case 4:
579				result |= V_0280A0_COLOR_8_8_8_8;
580				goto out_word4;
581			}
582			goto out_unknown;
583		case 16:
584			switch (desc->nr_channels) {
585			case 1:
586				result |= V_0280A0_COLOR_16;
587				goto out_word4;
588			case 2:
589				result |= V_0280A0_COLOR_16_16;
590				goto out_word4;
591			case 4:
592				result |= V_0280A0_COLOR_16_16_16_16;
593				goto out_word4;
594			}
595		}
596		goto out_unknown;
597
598	case UTIL_FORMAT_TYPE_FLOAT:
599		switch (desc->channel[0].size) {
600		case 16:
601			switch (desc->nr_channels) {
602			case 1:
603				result |= V_0280A0_COLOR_16_FLOAT;
604				goto out_word4;
605			case 2:
606				result |= V_0280A0_COLOR_16_16_FLOAT;
607				goto out_word4;
608			case 4:
609				result |= V_0280A0_COLOR_16_16_16_16_FLOAT;
610				goto out_word4;
611			}
612			goto out_unknown;
613		case 32:
614			switch (desc->nr_channels) {
615			case 1:
616				result |= V_0280A0_COLOR_32_FLOAT;
617				goto out_word4;
618			case 2:
619				result |= V_0280A0_COLOR_32_32_FLOAT;
620				goto out_word4;
621			case 4:
622				result |= V_0280A0_COLOR_32_32_32_32_FLOAT;
623				goto out_word4;
624			}
625		}
626
627	}
628out_word4:
629	if (word4_p)
630		*word4_p = word4;
631	if (yuv_format_p)
632		*yuv_format_p = yuv_format;
633	return result;
634out_unknown:
635//	R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
636	return ~0;
637}
638
639int r600_texture_from_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
640{
641	struct r600_screen *rscreen = r600_screen(ctx->screen);
642	int r;
643
644	if (!rtexture->depth) {
645		/* This shouldn't happen maybe print a warning */
646		return 0;
647	}
648	if (rtexture->uncompressed && !rtexture->dirty) {
649		/* Uncompressed bo already in good state */
650		return 0;
651	}
652
653	/* allocate uncompressed texture */
654	if (rtexture->uncompressed == NULL) {
655		rtexture->uncompressed = radeon_bo(rscreen->rw, 0, rtexture->size, 4096, NULL);
656		if (rtexture->uncompressed == NULL) {
657			return -ENOMEM;
658		}
659	}
660
661	/* render a rectangle covering whole buffer to uncompress depth */
662	r = r600_blit_uncompress_depth(ctx, rtexture, level);
663	if (r) {
664		return r;
665	}
666
667	rtexture->dirty = 0;
668	return 0;
669}
670
671static void r600_texture_state_scissor(struct r600_screen *rscreen,
672					struct r600_resource_texture *rtexture,
673					unsigned level)
674{
675	struct radeon_state *rstate = &rtexture->scissor[level];
676
677	radeon_state_init(rstate, rscreen->rw, R600_STATE_SCISSOR, 0, 0);
678	/* set states (most default value are 0 and struct already
679	 * initialized to 0, thus avoid resetting them)
680	 */
681	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_0_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
682	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_0_TL] = 0x80000000;
683	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_1_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
684	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_1_TL] = 0x80000000;
685	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_2_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
686	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_2_TL] = 0x80000000;
687	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_3_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
688	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_3_TL] = 0x80000000;
689	rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_RULE] = 0x0000FFFF;
690	rstate->states[R600_SCISSOR__PA_SC_EDGERULE] = 0xAAAAAAAA;
691	rstate->states[R600_SCISSOR__PA_SC_GENERIC_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
692	rstate->states[R600_SCISSOR__PA_SC_GENERIC_SCISSOR_TL] = 0x80000000;
693	rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
694	rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_TL] = 0x80000000;
695	rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
696	rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_TL] = 0x80000000;
697	rstate->states[R600_SCISSOR__PA_SC_WINDOW_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
698	rstate->states[R600_SCISSOR__PA_SC_WINDOW_SCISSOR_TL] = 0x80000000;
699
700	radeon_state_pm4(rstate);
701}
702
703static void r600_texture_state_cb(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
704{
705	struct radeon_state *rstate;
706	struct r600_resource *rbuffer;
707	unsigned pitch, slice;
708	unsigned color_info;
709	unsigned format, swap, ntype;
710	const struct util_format_description *desc;
711
712	rstate = &rtexture->cb[cb][level];
713	radeon_state_init(rstate, rscreen->rw, R600_STATE_CB0 + cb, 0, 0);
714	rbuffer = &rtexture->resource;
715
716	/* set states (most default value are 0 and struct already
717	 * initialized to 0, thus avoid resetting them)
718	 */
719	pitch = (rtexture->pitch[level] / rtexture->bpt) / 8 - 1;
720	slice = (rtexture->pitch[level] / rtexture->bpt) * rtexture->height[level] / 64 - 1;
721	ntype = 0;
722	desc = util_format_description(rbuffer->base.b.format);
723	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
724		ntype = V_0280A0_NUMBER_SRGB;
725	format = r600_translate_colorformat(rtexture->resource.base.b.format);
726	swap = r600_translate_colorswap(rtexture->resource.base.b.format);
727	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
728		rstate->bo[0] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
729		rstate->bo[1] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
730		rstate->bo[2] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
731		rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
732		rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
733		rstate->placement[4] = RADEON_GEM_DOMAIN_GTT;
734		rstate->nbo = 3;
735		color_info = 0;
736	} else {
737		rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
738		rstate->bo[1] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
739		rstate->bo[2] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
740		rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
741		rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
742		rstate->placement[4] = RADEON_GEM_DOMAIN_GTT;
743		rstate->nbo = 3;
744		color_info = S_0280A0_SOURCE_FORMAT(1);
745	}
746	color_info |= S_0280A0_FORMAT(format) |
747		S_0280A0_COMP_SWAP(swap) |
748		S_0280A0_BLEND_CLAMP(1) |
749		S_0280A0_NUMBER_TYPE(ntype);
750	rstate->states[R600_CB0__CB_COLOR0_BASE] = rtexture->offset[level] >> 8;
751	rstate->states[R600_CB0__CB_COLOR0_INFO] = color_info;
752	rstate->states[R600_CB0__CB_COLOR0_SIZE] = S_028060_PITCH_TILE_MAX(pitch) |
753						S_028060_SLICE_TILE_MAX(slice);
754
755	radeon_state_pm4(rstate);
756}
757
758static void r600_texture_state_db(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned level)
759{
760	struct radeon_state *rstate = &rtexture->db[level];
761	struct r600_resource *rbuffer;
762	unsigned pitch, slice, format;
763
764	radeon_state_init(rstate, rscreen->rw, R600_STATE_DB, 0, 0);
765	rbuffer = &rtexture->resource;
766	rtexture->tilled = 1;
767	rtexture->array_mode = 2;
768	rtexture->tile_type = 1;
769	rtexture->depth = 1;
770
771	/* set states (most default value are 0 and struct already
772	 * initialized to 0, thus avoid resetting them)
773	 */
774	pitch = (rtexture->pitch[level] / rtexture->bpt) / 8 - 1;
775	slice = (rtexture->pitch[level] / rtexture->bpt) * rtexture->height[level] / 64 - 1;
776	format = r600_translate_dbformat(rbuffer->base.b.format);
777	rstate->states[R600_DB__DB_DEPTH_BASE] = rtexture->offset[level] >> 8;
778	rstate->states[R600_DB__DB_DEPTH_INFO] = S_028010_ARRAY_MODE(rtexture->array_mode) |
779					S_028010_FORMAT(format);
780	rstate->states[R600_DB__DB_DEPTH_VIEW] = 0x00000000;
781	rstate->states[R600_DB__DB_PREFETCH_LIMIT] = (rtexture->height[level] / 8) -1;
782	rstate->states[R600_DB__DB_DEPTH_SIZE] = S_028000_PITCH_TILE_MAX(pitch) |
783						S_028000_SLICE_TILE_MAX(slice);
784	rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
785	rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
786	rstate->nbo = 1;
787
788	radeon_state_pm4(rstate);
789}
790
791int r600_texture_scissor(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
792{
793	struct r600_screen *rscreen = r600_screen(ctx->screen);
794
795	if (!rtexture->scissor[level].cpm4) {
796		r600_texture_state_scissor(rscreen, rtexture, level);
797	}
798	return 0;
799}
800
801static void r600_texture_state_viewport(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned level)
802{
803	struct radeon_state *rstate = &rtexture->viewport[level];
804
805	radeon_state_init(rstate, rscreen->rw, R600_STATE_VIEWPORT, 0, 0);
806
807	/* set states (most default value are 0 and struct already
808	 * initialized to 0, thus avoid resetting them)
809	 */
810	rstate->states[R600_VIEWPORT__PA_CL_VPORT_XOFFSET_0] = fui((float)rtexture->width[level]/2.0);
811	rstate->states[R600_VIEWPORT__PA_CL_VPORT_XSCALE_0] = fui((float)rtexture->width[level]/2.0);
812	rstate->states[R600_VIEWPORT__PA_CL_VPORT_YOFFSET_0] = fui((float)rtexture->height[level]/2.0);
813	rstate->states[R600_VIEWPORT__PA_CL_VPORT_YSCALE_0] = fui((float)-rtexture->height[level]/2.0);
814	rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZOFFSET_0] = 0x3F000000;
815	rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZSCALE_0] = 0x3F000000;
816	rstate->states[R600_VIEWPORT__PA_CL_VTE_CNTL] = 0x0000043F;
817	rstate->states[R600_VIEWPORT__PA_SC_VPORT_ZMAX_0] = 0x3F800000;
818
819	radeon_state_pm4(rstate);
820}
821
822int r600_texture_cb(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
823{
824	struct r600_screen *rscreen = r600_screen(ctx->screen);
825
826	if (!rtexture->cb[cb][level].cpm4) {
827		r600_texture_state_cb(rscreen, rtexture, cb, level);
828	}
829	return 0;
830}
831
832int r600_texture_db(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
833{
834	struct r600_screen *rscreen = r600_screen(ctx->screen);
835
836	if (!rtexture->db[level].cpm4) {
837		r600_texture_state_db(rscreen, rtexture, level);
838	}
839	return 0;
840}
841
842int r600_texture_viewport(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
843{
844	struct r600_screen *rscreen = r600_screen(ctx->screen);
845
846	if (!rtexture->viewport[level].cpm4) {
847		r600_texture_state_viewport(rscreen, rtexture, level);
848	}
849	return 0;
850}
851