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