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