r600_texture.c revision f70f79f6f6027bdf2f7de09bb39e12a24420f338
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_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 radeon *radeon = (struct radeon *)screen->winsys;
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(rtex);
120
121	/* FIXME alignment 4096 enought ? too much ? */
122	resource->domain = r600_domain_from_usage(resource->base.b.bind);
123	resource->size = rtex->size;
124	resource->bo = radeon_ws_bo(radeon, rtex->size, 4096);
125	if (resource->bo == NULL) {
126		FREE(rtex);
127		return NULL;
128	}
129	return &resource->base.b;
130}
131
132static void r600_texture_destroy_state(struct pipe_resource *ptexture)
133{
134	struct r600_resource_texture *rtexture = (struct r600_resource_texture*)ptexture;
135
136	for (int i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) {
137		radeon_state_fini(&rtexture->scissor[i]);
138		radeon_state_fini(&rtexture->db[i]);
139		for (int j = 0; j < 8; j++) {
140			radeon_state_fini(&rtexture->cb[j][i]);
141		}
142	}
143}
144
145static void r600_texture_destroy(struct pipe_screen *screen,
146				 struct pipe_resource *ptex)
147{
148	struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
149	struct r600_resource *resource = &rtex->resource;
150	struct radeon *radeon = (struct radeon *)screen->winsys;
151
152	if (resource->bo) {
153		radeon_ws_bo_reference(radeon, &resource->bo, NULL);
154	}
155	if (rtex->uncompressed) {
156		radeon_ws_bo_reference(radeon, &rtex->uncompressed, NULL);
157	}
158	r600_texture_destroy_state(ptex);
159	FREE(rtex);
160}
161
162static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen,
163						struct pipe_resource *texture,
164						unsigned face, unsigned level,
165						unsigned zslice, unsigned flags)
166{
167	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
168	struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
169	unsigned long offset;
170
171	if (surface == NULL)
172		return NULL;
173	offset = r600_texture_get_offset(rtex, level, zslice, face);
174	pipe_reference_init(&surface->reference, 1);
175	pipe_resource_reference(&surface->texture, texture);
176	surface->format = texture->format;
177	surface->width = u_minify(texture->width0, level);
178	surface->height = u_minify(texture->height0, level);
179	surface->offset = offset;
180	surface->usage = flags;
181	surface->zslice = zslice;
182	surface->texture = texture;
183	surface->face = face;
184	surface->level = level;
185	return surface;
186}
187
188static void r600_tex_surface_destroy(struct pipe_surface *surface)
189{
190	pipe_resource_reference(&surface->texture, NULL);
191	FREE(surface);
192}
193
194struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
195					       const struct pipe_resource *templ,
196					       struct winsys_handle *whandle)
197{
198	struct radeon *rw = (struct radeon*)screen->winsys;
199	struct r600_resource_texture *rtex;
200	struct r600_resource *resource;
201	struct radeon_ws_bo *bo = NULL;
202
203	/* Support only 2D textures without mipmaps */
204	if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
205	      templ->depth0 != 1 || templ->last_level != 0)
206		return NULL;
207
208	rtex = CALLOC_STRUCT(r600_resource_texture);
209	if (rtex == NULL)
210		return NULL;
211
212	bo = radeon_ws_bo_handle(rw, whandle->handle);
213	if (bo == NULL) {
214		FREE(rtex);
215		return NULL;
216	}
217
218	resource = &rtex->resource;
219	resource->base.b = *templ;
220	resource->base.vtbl = &r600_texture_vtbl;
221	pipe_reference_init(&resource->base.b.reference, 1);
222	resource->base.b.screen = screen;
223	resource->bo = bo;
224	rtex->depth = 0;
225	rtex->pitch_override = whandle->stride;
226	rtex->bpt = util_format_get_blocksize(templ->format);
227	rtex->pitch[0] = whandle->stride;
228	rtex->width[0] = templ->width0;
229	rtex->height[0] = templ->height0;
230	rtex->offset[0] = 0;
231	rtex->size = align(rtex->pitch[0] * templ->height0, 64);
232
233	return &resource->base.b;
234}
235
236static unsigned int r600_texture_is_referenced(struct pipe_context *context,
237						struct pipe_resource *texture,
238						unsigned face, unsigned level)
239{
240	/* FIXME */
241	return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
242}
243
244struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
245						struct pipe_resource *texture,
246						struct pipe_subresource sr,
247						unsigned usage,
248						const struct pipe_box *box)
249{
250	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
251	struct pipe_resource resource;
252	struct r600_transfer *trans;
253
254	trans = CALLOC_STRUCT(r600_transfer);
255	if (trans == NULL)
256		return NULL;
257	pipe_resource_reference(&trans->transfer.resource, texture);
258	trans->transfer.sr = sr;
259	trans->transfer.usage = usage;
260	trans->transfer.box = *box;
261	trans->transfer.stride = rtex->pitch[sr.level];
262	trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
263	if (rtex->tilled && !rtex->depth) {
264		resource.target = PIPE_TEXTURE_2D;
265		resource.format = texture->format;
266		resource.width0 = box->width;
267		resource.height0 = box->height;
268		resource.depth0 = 0;
269		resource.last_level = 0;
270		resource.nr_samples = 0;
271		resource.usage = PIPE_USAGE_DYNAMIC;
272		resource.bind = 0;
273		resource.flags = 0;
274		/* For texture reading, the temporary (detiled) texture is used as
275		 * a render target when blitting from a tiled texture. */
276		if (usage & PIPE_TRANSFER_READ) {
277			resource.bind |= PIPE_BIND_RENDER_TARGET;
278		}
279		/* For texture writing, the temporary texture is used as a sampler
280		 * when blitting into a tiled texture. */
281		if (usage & PIPE_TRANSFER_WRITE) {
282			resource.bind |= PIPE_BIND_SAMPLER_VIEW;
283		}
284		/* Create the temporary texture. */
285		trans->linear_texture = ctx->screen->resource_create(ctx->screen, &resource);
286		if (trans->linear_texture == NULL) {
287			R600_ERR("failed to create temporary texture to hold untiled copy\n");
288			pipe_resource_reference(&trans->transfer.resource, NULL);
289			FREE(trans);
290			return NULL;
291		}
292		if (usage & PIPE_TRANSFER_READ) {
293			/* We cannot map a tiled texture directly because the data is
294			 * in a different order, therefore we do detiling using a blit. */
295			r600_copy_from_tiled_texture(ctx, trans);
296			/* Always referenced in the blit. */
297			ctx->flush(ctx, 0, NULL);
298		}
299	}
300	return &trans->transfer;
301}
302
303void r600_texture_transfer_destroy(struct pipe_context *ctx,
304				   struct pipe_transfer *transfer)
305{
306	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
307
308	if (rtransfer->linear_texture) {
309		pipe_resource_reference(&rtransfer->linear_texture, NULL);
310	}
311	pipe_resource_reference(&transfer->resource, NULL);
312	FREE(transfer);
313}
314
315void* r600_texture_transfer_map(struct pipe_context *ctx,
316				struct pipe_transfer* transfer)
317{
318	struct r600_screen *rscreen = r600_screen(ctx->screen);
319	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
320	struct radeon_ws_bo *bo;
321	enum pipe_format format = transfer->resource->format;
322	struct radeon *radeon = (struct radeon *)ctx->screen->winsys;
323	struct r600_resource_texture *rtex;
324	unsigned long offset = 0;
325	char *map;
326	int r;
327
328	r600_flush(ctx, 0, NULL);
329	if (rtransfer->linear_texture) {
330		bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
331	} else {
332		rtex = (struct r600_resource_texture*)transfer->resource;
333		if (rtex->depth && rscreen->chip_class != EVERGREEN) {
334			r = r600_texture_from_depth(ctx, rtex, transfer->sr.level);
335			if (r) {
336				return NULL;
337			}
338			r600_flush(ctx, 0, NULL);
339			bo = rtex->uncompressed;
340		} else {
341			bo = ((struct r600_resource *)transfer->resource)->bo;
342		}
343		offset = rtransfer->offset +
344			transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
345			transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
346	}
347	map = radeon_ws_bo_map(radeon, bo);
348	if (!map) {
349		return NULL;
350	}
351	radeon_ws_bo_wait(radeon, bo);
352
353	return map + offset;
354}
355
356void r600_texture_transfer_unmap(struct pipe_context *ctx,
357				 struct pipe_transfer* transfer)
358{
359	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
360	struct radeon *radeon = (struct radeon *)ctx->screen->winsys;
361	struct r600_resource_texture *rtex;
362	struct radeon_ws_bo *bo;
363
364	if (rtransfer->linear_texture) {
365		bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
366	} else {
367		rtex = (struct r600_resource_texture*)transfer->resource;
368		if (rtex->depth) {
369			bo = rtex->uncompressed;
370		} else {
371			bo = ((struct r600_resource *)transfer->resource)->bo;
372		}
373	}
374	radeon_ws_bo_unmap(radeon, bo);
375}
376
377struct u_resource_vtbl r600_texture_vtbl =
378{
379	u_default_resource_get_handle,	/* get_handle */
380	r600_texture_destroy,		/* resource_destroy */
381	r600_texture_is_referenced,	/* is_resource_referenced */
382	r600_texture_get_transfer,	/* get_transfer */
383	r600_texture_transfer_destroy,	/* transfer_destroy */
384	r600_texture_transfer_map,	/* transfer_map */
385	u_default_transfer_flush_region,/* transfer_flush_region */
386	r600_texture_transfer_unmap,	/* transfer_unmap */
387	u_default_transfer_inline_write	/* transfer_inline_write */
388};
389
390void r600_init_screen_texture_functions(struct pipe_screen *screen)
391{
392	screen->get_tex_surface = r600_get_tex_surface;
393	screen->tex_surface_destroy = r600_tex_surface_destroy;
394}
395
396static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
397		const unsigned char *swizzle_view)
398{
399	unsigned i;
400	unsigned char swizzle[4];
401	unsigned result = 0;
402	const uint32_t swizzle_shift[4] = {
403		16, 19, 22, 25,
404	};
405	const uint32_t swizzle_bit[4] = {
406		0, 1, 2, 3,
407	};
408
409	if (swizzle_view) {
410		/* Combine two sets of swizzles. */
411		for (i = 0; i < 4; i++) {
412			swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
413				swizzle_format[swizzle_view[i]] : swizzle_view[i];
414		}
415	} else {
416		memcpy(swizzle, swizzle_format, 4);
417	}
418
419	/* Get swizzle. */
420	for (i = 0; i < 4; i++) {
421		switch (swizzle[i]) {
422		case UTIL_FORMAT_SWIZZLE_Y:
423			result |= swizzle_bit[1] << swizzle_shift[i];
424			break;
425		case UTIL_FORMAT_SWIZZLE_Z:
426			result |= swizzle_bit[2] << swizzle_shift[i];
427			break;
428		case UTIL_FORMAT_SWIZZLE_W:
429			result |= swizzle_bit[3] << swizzle_shift[i];
430			break;
431		case UTIL_FORMAT_SWIZZLE_0:
432			result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
433			break;
434		case UTIL_FORMAT_SWIZZLE_1:
435			result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
436			break;
437		default: /* UTIL_FORMAT_SWIZZLE_X */
438			result |= swizzle_bit[0] << swizzle_shift[i];
439		}
440	}
441	return result;
442}
443
444/* texture format translate */
445uint32_t r600_translate_texformat(enum pipe_format format,
446				  const unsigned char *swizzle_view,
447				  uint32_t *word4_p, uint32_t *yuv_format_p)
448{
449	uint32_t result = 0, word4 = 0, yuv_format = 0;
450	const struct util_format_description *desc;
451	boolean uniform = TRUE;
452	int i;
453	const uint32_t sign_bit[4] = {
454		S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
455		S_038010_FORMAT_COMP_Y(V_038010_SQ_FORMAT_COMP_SIGNED),
456		S_038010_FORMAT_COMP_Z(V_038010_SQ_FORMAT_COMP_SIGNED),
457		S_038010_FORMAT_COMP_W(V_038010_SQ_FORMAT_COMP_SIGNED)
458	};
459	desc = util_format_description(format);
460
461	word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
462
463	/* Colorspace (return non-RGB formats directly). */
464	switch (desc->colorspace) {
465		/* Depth stencil formats */
466	case UTIL_FORMAT_COLORSPACE_ZS:
467		switch (format) {
468		case PIPE_FORMAT_Z16_UNORM:
469			result = V_0280A0_COLOR_16;
470			goto out_word4;
471		case PIPE_FORMAT_Z24X8_UNORM:
472			result = V_0280A0_COLOR_8_24;
473			goto out_word4;
474		case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
475			result = V_0280A0_COLOR_8_24;
476			goto out_word4;
477		default:
478			goto out_unknown;
479		}
480
481	case UTIL_FORMAT_COLORSPACE_YUV:
482		yuv_format |= (1 << 30);
483		switch (format) {
484                case PIPE_FORMAT_UYVY:
485                case PIPE_FORMAT_YUYV:
486		default:
487			break;
488		}
489		goto out_unknown; /* TODO */
490
491	case UTIL_FORMAT_COLORSPACE_SRGB:
492		word4 |= S_038010_FORCE_DEGAMMA(1);
493		if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB)
494			goto out_unknown; /* fails for some reason - TODO */
495		break;
496
497	default:
498		break;
499	}
500
501	/* S3TC formats. TODO */
502	if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
503		goto out_unknown;
504	}
505
506
507	for (i = 0; i < desc->nr_channels; i++) {
508		if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
509			word4 |= sign_bit[i];
510		}
511	}
512
513	/* R8G8Bx_SNORM - TODO CxV8U8 */
514
515	/* RGTC - TODO */
516
517	/* See whether the components are of the same size. */
518	for (i = 1; i < desc->nr_channels; i++) {
519		uniform = uniform && desc->channel[0].size == desc->channel[i].size;
520	}
521
522	/* Non-uniform formats. */
523	if (!uniform) {
524		switch(desc->nr_channels) {
525		case 3:
526			if (desc->channel[0].size == 5 &&
527			    desc->channel[1].size == 6 &&
528			    desc->channel[2].size == 5) {
529				result = V_0280A0_COLOR_5_6_5;
530				goto out_word4;
531			}
532			goto out_unknown;
533		case 4:
534			if (desc->channel[0].size == 5 &&
535			    desc->channel[1].size == 5 &&
536			    desc->channel[2].size == 5 &&
537			    desc->channel[3].size == 1) {
538				result = V_0280A0_COLOR_1_5_5_5;
539				goto out_word4;
540			}
541			if (desc->channel[0].size == 10 &&
542			    desc->channel[1].size == 10 &&
543			    desc->channel[2].size == 10 &&
544			    desc->channel[3].size == 2) {
545				result = V_0280A0_COLOR_10_10_10_2;
546				goto out_word4;
547			}
548			goto out_unknown;
549		}
550		goto out_unknown;
551	}
552
553	/* uniform formats */
554	switch (desc->channel[0].type) {
555	case UTIL_FORMAT_TYPE_UNSIGNED:
556	case UTIL_FORMAT_TYPE_SIGNED:
557		if (!desc->channel[0].normalized &&
558		    desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
559			goto out_unknown;
560		}
561
562		switch (desc->channel[0].size) {
563		case 4:
564			switch (desc->nr_channels) {
565			case 2:
566				result = V_0280A0_COLOR_4_4;
567				goto out_word4;
568			case 4:
569				result = V_0280A0_COLOR_4_4_4_4;
570				goto out_word4;
571			}
572			goto out_unknown;
573		case 8:
574			switch (desc->nr_channels) {
575			case 1:
576				result = V_0280A0_COLOR_8;
577				goto out_word4;
578			case 2:
579				result = V_0280A0_COLOR_8_8;
580				goto out_word4;
581			case 4:
582				result = V_0280A0_COLOR_8_8_8_8;
583				goto out_word4;
584			}
585			goto out_unknown;
586		case 16:
587			switch (desc->nr_channels) {
588			case 1:
589				result = V_0280A0_COLOR_16;
590				goto out_word4;
591			case 2:
592				result = V_0280A0_COLOR_16_16;
593				goto out_word4;
594			case 4:
595				result = V_0280A0_COLOR_16_16_16_16;
596				goto out_word4;
597			}
598		}
599		goto out_unknown;
600
601	case UTIL_FORMAT_TYPE_FLOAT:
602		switch (desc->channel[0].size) {
603		case 16:
604			switch (desc->nr_channels) {
605			case 1:
606				result = V_0280A0_COLOR_16_FLOAT;
607				goto out_word4;
608			case 2:
609				result = V_0280A0_COLOR_16_16_FLOAT;
610				goto out_word4;
611			case 4:
612				result = V_0280A0_COLOR_16_16_16_16_FLOAT;
613				goto out_word4;
614			}
615			goto out_unknown;
616		case 32:
617			switch (desc->nr_channels) {
618			case 1:
619				result = V_0280A0_COLOR_32_FLOAT;
620				goto out_word4;
621			case 2:
622				result = V_0280A0_COLOR_32_32_FLOAT;
623				goto out_word4;
624			case 4:
625				result = V_0280A0_COLOR_32_32_32_32_FLOAT;
626				goto out_word4;
627			}
628		}
629
630	}
631out_word4:
632	if (word4_p)
633		*word4_p = word4;
634	if (yuv_format_p)
635		*yuv_format_p = yuv_format;
636	return result;
637out_unknown:
638//	R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
639	return ~0;
640}
641
642int r600_texture_from_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
643{
644	struct r600_screen *rscreen = r600_screen(ctx->screen);
645	int r;
646
647	if (!rtexture->depth) {
648		/* This shouldn't happen maybe print a warning */
649		return 0;
650	}
651	if (rtexture->uncompressed && !rtexture->dirty) {
652		/* Uncompressed bo already in good state */
653		return 0;
654	}
655
656	/* allocate uncompressed texture */
657	if (rtexture->uncompressed == NULL) {
658		rtexture->uncompressed = radeon_ws_bo(rscreen->rw, rtexture->size, 4096);
659		if (rtexture->uncompressed == NULL) {
660			return -ENOMEM;
661		}
662	}
663
664	/* render a rectangle covering whole buffer to uncompress depth */
665	r = r600_blit_uncompress_depth(ctx, rtexture, level);
666	if (r) {
667		return r;
668	}
669
670	rtexture->dirty = 0;
671	return 0;
672}
673
674
675
676int r600_texture_scissor(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
677{
678	struct r600_screen *rscreen = r600_screen(ctx->screen);
679	struct r600_context *rctx = r600_context(ctx);
680
681	if (!rtexture->scissor[level].cpm4) {
682		rctx->vtbl->texture_state_scissor(rscreen, rtexture, level);
683	}
684	return 0;
685}
686
687int r600_texture_cb(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
688{
689	struct r600_screen *rscreen = r600_screen(ctx->screen);
690	struct r600_context *rctx = r600_context(ctx);
691
692	if (!rtexture->cb[cb][level].cpm4) {
693		rctx->vtbl->texture_state_cb(rscreen, rtexture, cb, level);
694	}
695	return 0;
696}
697
698int r600_texture_db(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
699{
700	struct r600_screen *rscreen = r600_screen(ctx->screen);
701	struct r600_context *rctx = r600_context(ctx);
702
703	if (!rtexture->db[level].cpm4) {
704		rctx->vtbl->texture_state_db(rscreen, rtexture, level);
705	}
706	return 0;
707}
708
709int r600_texture_viewport(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
710{
711	struct r600_screen *rscreen = r600_screen(ctx->screen);
712	struct r600_context *rctx = r600_context(ctx);
713
714	if (!rtexture->viewport[level].cpm4) {
715		rctx->vtbl->texture_state_viewport(rscreen, rtexture, level);
716	}
717	return 0;
718}
719