freedreno_resource.c revision 93905a8df1d982d171ee690f9ec73f90f00fa49f
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3/* 4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark@freedesktop.org> 27 */ 28 29#include "util/u_format.h" 30#include "util/u_format_rgtc.h" 31#include "util/u_format_zs.h" 32#include "util/u_inlines.h" 33#include "util/u_transfer.h" 34#include "util/u_string.h" 35#include "util/u_surface.h" 36 37#include "freedreno_resource.h" 38#include "freedreno_screen.h" 39#include "freedreno_surface.h" 40#include "freedreno_context.h" 41#include "freedreno_query_hw.h" 42#include "freedreno_util.h" 43 44#include <errno.h> 45 46 47static bool 48pending(struct fd_resource *rsc, enum fd_resource_status status) 49{ 50 return (rsc->status & status) || 51 (rsc->stencil && (rsc->stencil->status & status)); 52} 53 54static void 55fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc) 56{ 57 int i; 58 59 /* Go through the entire state and see if the resource is bound 60 * anywhere. If it is, mark the relevant state as dirty. This is called on 61 * realloc_bo. 62 */ 63 64 /* Constbufs */ 65 for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS && !(ctx->dirty & FD_DIRTY_CONSTBUF); i++) { 66 if (ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer == prsc) 67 ctx->dirty |= FD_DIRTY_CONSTBUF; 68 if (ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer == prsc) 69 ctx->dirty |= FD_DIRTY_CONSTBUF; 70 } 71 72 /* VBOs */ 73 for (i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) { 74 if (ctx->vtx.vertexbuf.vb[i].buffer == prsc) 75 ctx->dirty |= FD_DIRTY_VTXBUF; 76 } 77 78 /* Index buffer */ 79 if (ctx->indexbuf.buffer == prsc) 80 ctx->dirty |= FD_DIRTY_INDEXBUF; 81 82 /* Textures */ 83 for (i = 0; i < ctx->verttex.num_textures && !(ctx->dirty & FD_DIRTY_VERTTEX); i++) { 84 if (ctx->verttex.textures[i] && (ctx->verttex.textures[i]->texture == prsc)) 85 ctx->dirty |= FD_DIRTY_VERTTEX; 86 } 87 for (i = 0; i < ctx->fragtex.num_textures && !(ctx->dirty & FD_DIRTY_FRAGTEX); i++) { 88 if (ctx->fragtex.textures[i] && (ctx->fragtex.textures[i]->texture == prsc)) 89 ctx->dirty |= FD_DIRTY_FRAGTEX; 90 } 91} 92 93static void 94realloc_bo(struct fd_resource *rsc, uint32_t size) 95{ 96 struct fd_screen *screen = fd_screen(rsc->base.b.screen); 97 uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE | 98 DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */ 99 100 /* if we start using things other than write-combine, 101 * be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT 102 */ 103 104 if (rsc->bo) 105 fd_bo_del(rsc->bo); 106 107 rsc->bo = fd_bo_new(screen->dev, size, flags); 108 rsc->timestamp = 0; 109 rsc->status = 0; 110 rsc->pending_ctx = NULL; 111 list_delinit(&rsc->list); 112 util_range_set_empty(&rsc->valid_buffer_range); 113} 114 115static unsigned 116fd_resource_layer_offset(struct fd_resource *rsc, 117 struct fd_resource_slice *slice, 118 unsigned layer) 119{ 120 if (rsc->layer_first) 121 return layer * rsc->layer_size; 122 else 123 return layer * slice->size0; 124} 125 126static void 127fd_resource_flush_z32s8(struct fd_transfer *trans, const struct pipe_box *box) 128{ 129 struct fd_resource *rsc = fd_resource(trans->base.resource); 130 struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level); 131 struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level); 132 enum pipe_format format = trans->base.resource->format; 133 134 float *depth = fd_bo_map(rsc->bo) + slice->offset + 135 fd_resource_layer_offset(rsc, slice, trans->base.box.z) + 136 (trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4; 137 uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset + 138 fd_resource_layer_offset(rsc->stencil, sslice, trans->base.box.z) + 139 (trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x; 140 141 if (format != PIPE_FORMAT_X32_S8X24_UINT) 142 util_format_z32_float_s8x24_uint_unpack_z_float( 143 depth, slice->pitch * 4, 144 trans->staging, trans->base.stride, 145 box->width, box->height); 146 147 util_format_z32_float_s8x24_uint_unpack_s_8uint( 148 stencil, sslice->pitch, 149 trans->staging, trans->base.stride, 150 box->width, box->height); 151} 152 153static void 154fd_resource_flush_rgtc(struct fd_transfer *trans, const struct pipe_box *box) 155{ 156 struct fd_resource *rsc = fd_resource(trans->base.resource); 157 struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level); 158 enum pipe_format format = trans->base.resource->format; 159 160 uint8_t *data = fd_bo_map(rsc->bo) + slice->offset + 161 fd_resource_layer_offset(rsc, slice, trans->base.box.z) + 162 ((trans->base.box.y + box->y) * slice->pitch + 163 trans->base.box.x + box->x) * rsc->cpp; 164 165 uint8_t *source = trans->staging + 166 util_format_get_nblocksy(format, box->y) * trans->base.stride + 167 util_format_get_stride(format, box->x); 168 169 switch (format) { 170 case PIPE_FORMAT_RGTC1_UNORM: 171 case PIPE_FORMAT_RGTC1_SNORM: 172 case PIPE_FORMAT_LATC1_UNORM: 173 case PIPE_FORMAT_LATC1_SNORM: 174 util_format_rgtc1_unorm_unpack_rgba_8unorm( 175 data, slice->pitch * rsc->cpp, 176 source, trans->base.stride, 177 box->width, box->height); 178 break; 179 case PIPE_FORMAT_RGTC2_UNORM: 180 case PIPE_FORMAT_RGTC2_SNORM: 181 case PIPE_FORMAT_LATC2_UNORM: 182 case PIPE_FORMAT_LATC2_SNORM: 183 util_format_rgtc2_unorm_unpack_rgba_8unorm( 184 data, slice->pitch * rsc->cpp, 185 source, trans->base.stride, 186 box->width, box->height); 187 break; 188 default: 189 assert(!"Unexpected format\n"); 190 break; 191 } 192} 193 194static void 195fd_resource_flush(struct fd_transfer *trans, const struct pipe_box *box) 196{ 197 enum pipe_format format = trans->base.resource->format; 198 199 switch (format) { 200 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 201 case PIPE_FORMAT_X32_S8X24_UINT: 202 fd_resource_flush_z32s8(trans, box); 203 break; 204 case PIPE_FORMAT_RGTC1_UNORM: 205 case PIPE_FORMAT_RGTC1_SNORM: 206 case PIPE_FORMAT_RGTC2_UNORM: 207 case PIPE_FORMAT_RGTC2_SNORM: 208 case PIPE_FORMAT_LATC1_UNORM: 209 case PIPE_FORMAT_LATC1_SNORM: 210 case PIPE_FORMAT_LATC2_UNORM: 211 case PIPE_FORMAT_LATC2_SNORM: 212 fd_resource_flush_rgtc(trans, box); 213 break; 214 default: 215 assert(!"Unexpected staging transfer type"); 216 break; 217 } 218} 219 220static void fd_resource_transfer_flush_region(struct pipe_context *pctx, 221 struct pipe_transfer *ptrans, 222 const struct pipe_box *box) 223{ 224 struct fd_resource *rsc = fd_resource(ptrans->resource); 225 struct fd_transfer *trans = fd_transfer(ptrans); 226 227 if (ptrans->resource->target == PIPE_BUFFER) 228 util_range_add(&rsc->valid_buffer_range, 229 ptrans->box.x + box->x, 230 ptrans->box.x + box->x + box->width); 231 232 if (trans->staging) 233 fd_resource_flush(trans, box); 234} 235 236static void 237fd_resource_transfer_unmap(struct pipe_context *pctx, 238 struct pipe_transfer *ptrans) 239{ 240 struct fd_context *ctx = fd_context(pctx); 241 struct fd_resource *rsc = fd_resource(ptrans->resource); 242 struct fd_transfer *trans = fd_transfer(ptrans); 243 244 if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { 245 struct pipe_box box; 246 u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); 247 fd_resource_flush(trans, &box); 248 } 249 250 if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 251 fd_bo_cpu_fini(rsc->bo); 252 if (rsc->stencil) 253 fd_bo_cpu_fini(rsc->stencil->bo); 254 } 255 256 util_range_add(&rsc->valid_buffer_range, 257 ptrans->box.x, 258 ptrans->box.x + ptrans->box.width); 259 260 pipe_resource_reference(&ptrans->resource, NULL); 261 util_slab_free(&ctx->transfer_pool, ptrans); 262 263 if (trans->staging) 264 free(trans->staging); 265} 266 267static void * 268fd_resource_transfer_map(struct pipe_context *pctx, 269 struct pipe_resource *prsc, 270 unsigned level, unsigned usage, 271 const struct pipe_box *box, 272 struct pipe_transfer **pptrans) 273{ 274 struct fd_context *ctx = fd_context(pctx); 275 struct fd_resource *rsc = fd_resource(prsc); 276 struct fd_resource_slice *slice = fd_resource_slice(rsc, level); 277 struct fd_transfer *trans; 278 struct pipe_transfer *ptrans; 279 enum pipe_format format = prsc->format; 280 uint32_t op = 0; 281 uint32_t offset; 282 char *buf; 283 int ret = 0; 284 285 DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage, 286 box->width, box->height, box->x, box->y); 287 288 ptrans = util_slab_alloc(&ctx->transfer_pool); 289 if (!ptrans) 290 return NULL; 291 292 /* util_slab_alloc() doesn't zero: */ 293 trans = fd_transfer(ptrans); 294 memset(trans, 0, sizeof(*trans)); 295 296 pipe_resource_reference(&ptrans->resource, prsc); 297 ptrans->level = level; 298 ptrans->usage = usage; 299 ptrans->box = *box; 300 ptrans->stride = util_format_get_nblocksx(format, slice->pitch) * rsc->cpp; 301 ptrans->layer_stride = slice->size0; 302 303 if (usage & PIPE_TRANSFER_READ) 304 op |= DRM_FREEDRENO_PREP_READ; 305 306 if (usage & PIPE_TRANSFER_WRITE) 307 op |= DRM_FREEDRENO_PREP_WRITE; 308 309 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { 310 realloc_bo(rsc, fd_bo_size(rsc->bo)); 311 if (rsc->stencil) 312 realloc_bo(rsc->stencil, fd_bo_size(rsc->stencil->bo)); 313 fd_invalidate_resource(ctx, prsc); 314 } else if ((usage & PIPE_TRANSFER_WRITE) && 315 prsc->target == PIPE_BUFFER && 316 !util_ranges_intersect(&rsc->valid_buffer_range, 317 box->x, box->x + box->width)) { 318 /* We are trying to write to a previously uninitialized range. No need 319 * to wait. 320 */ 321 } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 322 /* If the GPU is writing to the resource, or if it is reading from the 323 * resource and we're trying to write to it, flush the renders. 324 */ 325 if (((ptrans->usage & PIPE_TRANSFER_WRITE) && 326 pending(rsc, FD_PENDING_READ | FD_PENDING_WRITE)) || 327 pending(rsc, FD_PENDING_WRITE)) 328 fd_context_render(pctx); 329 330 /* The GPU keeps track of how the various bo's are being used, and 331 * will wait if necessary for the proper operation to have 332 * completed. 333 */ 334 ret = fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op); 335 if (ret) 336 goto fail; 337 } 338 339 buf = fd_bo_map(rsc->bo); 340 if (!buf) { 341 fd_resource_transfer_unmap(pctx, ptrans); 342 return NULL; 343 } 344 345 offset = slice->offset + 346 box->y / util_format_get_blockheight(format) * ptrans->stride + 347 box->x / util_format_get_blockwidth(format) * rsc->cpp + 348 fd_resource_layer_offset(rsc, slice, box->z); 349 350 if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || 351 prsc->format == PIPE_FORMAT_X32_S8X24_UINT) { 352 assert(trans->base.box.depth == 1); 353 354 trans->base.stride = trans->base.box.width * rsc->cpp * 2; 355 trans->staging = malloc(trans->base.stride * trans->base.box.height); 356 if (!trans->staging) 357 goto fail; 358 359 /* if we're not discarding the whole range (or resource), we must copy 360 * the real data in. 361 */ 362 if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE | 363 PIPE_TRANSFER_DISCARD_RANGE))) { 364 struct fd_resource_slice *sslice = 365 fd_resource_slice(rsc->stencil, level); 366 void *sbuf = fd_bo_map(rsc->stencil->bo); 367 if (!sbuf) 368 goto fail; 369 370 float *depth = (float *)(buf + slice->offset + 371 fd_resource_layer_offset(rsc, slice, box->z) + 372 box->y * slice->pitch * 4 + box->x * 4); 373 uint8_t *stencil = sbuf + sslice->offset + 374 fd_resource_layer_offset(rsc->stencil, sslice, box->z) + 375 box->y * sslice->pitch + box->x; 376 377 if (format != PIPE_FORMAT_X32_S8X24_UINT) 378 util_format_z32_float_s8x24_uint_pack_z_float( 379 trans->staging, trans->base.stride, 380 depth, slice->pitch * 4, 381 box->width, box->height); 382 383 util_format_z32_float_s8x24_uint_pack_s_8uint( 384 trans->staging, trans->base.stride, 385 stencil, sslice->pitch, 386 box->width, box->height); 387 } 388 389 buf = trans->staging; 390 offset = 0; 391 } else if (rsc->internal_format != format && 392 util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_RGTC) { 393 assert(trans->base.box.depth == 1); 394 395 trans->base.stride = util_format_get_stride( 396 format, trans->base.box.width); 397 trans->staging = malloc( 398 util_format_get_2d_size(format, trans->base.stride, 399 trans->base.box.height)); 400 if (!trans->staging) 401 goto fail; 402 403 /* if we're not discarding the whole range (or resource), we must copy 404 * the real data in. 405 */ 406 if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE | 407 PIPE_TRANSFER_DISCARD_RANGE))) { 408 uint8_t *rgba8 = (uint8_t *)buf + slice->offset + 409 fd_resource_layer_offset(rsc, slice, box->z) + 410 box->y * slice->pitch * rsc->cpp + box->x * rsc->cpp; 411 412 switch (format) { 413 case PIPE_FORMAT_RGTC1_UNORM: 414 case PIPE_FORMAT_RGTC1_SNORM: 415 case PIPE_FORMAT_LATC1_UNORM: 416 case PIPE_FORMAT_LATC1_SNORM: 417 util_format_rgtc1_unorm_pack_rgba_8unorm( 418 trans->staging, trans->base.stride, 419 rgba8, slice->pitch * rsc->cpp, 420 box->width, box->height); 421 break; 422 case PIPE_FORMAT_RGTC2_UNORM: 423 case PIPE_FORMAT_RGTC2_SNORM: 424 case PIPE_FORMAT_LATC2_UNORM: 425 case PIPE_FORMAT_LATC2_SNORM: 426 util_format_rgtc2_unorm_pack_rgba_8unorm( 427 trans->staging, trans->base.stride, 428 rgba8, slice->pitch * rsc->cpp, 429 box->width, box->height); 430 break; 431 default: 432 assert(!"Unexpected format"); 433 break; 434 } 435 } 436 437 buf = trans->staging; 438 offset = 0; 439 } 440 441 *pptrans = ptrans; 442 443 return buf + offset; 444 445fail: 446 fd_resource_transfer_unmap(pctx, ptrans); 447 return NULL; 448} 449 450static void 451fd_resource_destroy(struct pipe_screen *pscreen, 452 struct pipe_resource *prsc) 453{ 454 struct fd_resource *rsc = fd_resource(prsc); 455 if (rsc->bo) 456 fd_bo_del(rsc->bo); 457 list_delinit(&rsc->list); 458 util_range_destroy(&rsc->valid_buffer_range); 459 FREE(rsc); 460} 461 462static boolean 463fd_resource_get_handle(struct pipe_screen *pscreen, 464 struct pipe_resource *prsc, 465 struct winsys_handle *handle) 466{ 467 struct fd_resource *rsc = fd_resource(prsc); 468 469 return fd_screen_bo_get_handle(pscreen, rsc->bo, 470 rsc->slices[0].pitch * rsc->cpp, handle); 471} 472 473 474static const struct u_resource_vtbl fd_resource_vtbl = { 475 .resource_get_handle = fd_resource_get_handle, 476 .resource_destroy = fd_resource_destroy, 477 .transfer_map = fd_resource_transfer_map, 478 .transfer_flush_region = fd_resource_transfer_flush_region, 479 .transfer_unmap = fd_resource_transfer_unmap, 480 .transfer_inline_write = u_default_transfer_inline_write, 481}; 482 483static uint32_t 484setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format format) 485{ 486 struct pipe_resource *prsc = &rsc->base.b; 487 enum util_format_layout layout = util_format_description(format)->layout; 488 uint32_t level, size = 0; 489 uint32_t width = prsc->width0; 490 uint32_t height = prsc->height0; 491 uint32_t depth = prsc->depth0; 492 /* in layer_first layout, the level (slice) contains just one 493 * layer (since in fact the layer contains the slices) 494 */ 495 uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size; 496 497 for (level = 0; level <= prsc->last_level; level++) { 498 struct fd_resource_slice *slice = fd_resource_slice(rsc, level); 499 uint32_t blocks; 500 501 if (layout == UTIL_FORMAT_LAYOUT_ASTC) 502 slice->pitch = width = 503 util_align_npot(width, 32 * util_format_get_blockwidth(format)); 504 else 505 slice->pitch = width = align(width, 32); 506 slice->offset = size; 507 blocks = util_format_get_nblocks(format, width, height); 508 /* 1d array and 2d array textures must all have the same layer size 509 * for each miplevel on a3xx. 3d textures can have different layer 510 * sizes for high levels, but the hw auto-sizer is buggy (or at least 511 * different than what this code does), so as soon as the layer size 512 * range gets into range, we stop reducing it. 513 */ 514 if (prsc->target == PIPE_TEXTURE_3D && ( 515 level == 1 || 516 (level > 1 && rsc->slices[level - 1].size0 > 0xf000))) 517 slice->size0 = align(blocks * rsc->cpp, alignment); 518 else if (level == 0 || rsc->layer_first || alignment == 1) 519 slice->size0 = align(blocks * rsc->cpp, alignment); 520 else 521 slice->size0 = rsc->slices[level - 1].size0; 522 523 size += slice->size0 * depth * layers_in_level; 524 525 width = u_minify(width, 1); 526 height = u_minify(height, 1); 527 depth = u_minify(depth, 1); 528 } 529 530 return size; 531} 532 533static uint32_t 534slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) 535{ 536 /* on a3xx, 2d array and 3d textures seem to want their 537 * layers aligned to page boundaries: 538 */ 539 switch (tmpl->target) { 540 case PIPE_TEXTURE_3D: 541 case PIPE_TEXTURE_1D_ARRAY: 542 case PIPE_TEXTURE_2D_ARRAY: 543 return 4096; 544 default: 545 return 1; 546 } 547} 548 549/** 550 * Create a new texture object, using the given template info. 551 */ 552static struct pipe_resource * 553fd_resource_create(struct pipe_screen *pscreen, 554 const struct pipe_resource *tmpl) 555{ 556 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); 557 struct pipe_resource *prsc = &rsc->base.b; 558 enum pipe_format format = tmpl->format; 559 uint32_t size, alignment; 560 561 DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " 562 "nr_samples=%u, usage=%u, bind=%x, flags=%x", 563 tmpl->target, util_format_name(format), 564 tmpl->width0, tmpl->height0, tmpl->depth0, 565 tmpl->array_size, tmpl->last_level, tmpl->nr_samples, 566 tmpl->usage, tmpl->bind, tmpl->flags); 567 568 if (!rsc) 569 return NULL; 570 571 *prsc = *tmpl; 572 573 pipe_reference_init(&prsc->reference, 1); 574 list_inithead(&rsc->list); 575 prsc->screen = pscreen; 576 577 util_range_init(&rsc->valid_buffer_range); 578 579 rsc->base.vtbl = &fd_resource_vtbl; 580 581 if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) 582 format = PIPE_FORMAT_Z32_FLOAT; 583 else if (fd_screen(pscreen)->gpu_id < 400 && 584 util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_RGTC) 585 format = PIPE_FORMAT_R8G8B8A8_UNORM; 586 rsc->internal_format = format; 587 rsc->cpp = util_format_get_blocksize(format); 588 589 assert(rsc->cpp); 590 591 alignment = slice_alignment(pscreen, tmpl); 592 if (is_a4xx(fd_screen(pscreen))) { 593 switch (tmpl->target) { 594 case PIPE_TEXTURE_3D: 595 rsc->layer_first = false; 596 break; 597 default: 598 rsc->layer_first = true; 599 alignment = 1; 600 break; 601 } 602 } 603 604 size = setup_slices(rsc, alignment, format); 605 606 if (rsc->layer_first) { 607 rsc->layer_size = align(size, 4096); 608 size = rsc->layer_size * prsc->array_size; 609 } 610 611 realloc_bo(rsc, size); 612 if (!rsc->bo) 613 goto fail; 614 615 /* There is no native Z32F_S8 sampling or rendering format, so this must 616 * be emulated via two separate textures. The depth texture still keeps 617 * its Z32F_S8 format though, and we also keep a reference to a separate 618 * S8 texture. 619 */ 620 if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { 621 struct pipe_resource stencil = *tmpl; 622 stencil.format = PIPE_FORMAT_S8_UINT; 623 rsc->stencil = fd_resource(fd_resource_create(pscreen, &stencil)); 624 if (!rsc->stencil) 625 goto fail; 626 } 627 628 return prsc; 629fail: 630 fd_resource_destroy(pscreen, prsc); 631 return NULL; 632} 633 634/** 635 * Create a texture from a winsys_handle. The handle is often created in 636 * another process by first creating a pipe texture and then calling 637 * resource_get_handle. 638 */ 639static struct pipe_resource * 640fd_resource_from_handle(struct pipe_screen *pscreen, 641 const struct pipe_resource *tmpl, 642 struct winsys_handle *handle) 643{ 644 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); 645 struct fd_resource_slice *slice = &rsc->slices[0]; 646 struct pipe_resource *prsc = &rsc->base.b; 647 648 DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " 649 "nr_samples=%u, usage=%u, bind=%x, flags=%x", 650 tmpl->target, util_format_name(tmpl->format), 651 tmpl->width0, tmpl->height0, tmpl->depth0, 652 tmpl->array_size, tmpl->last_level, tmpl->nr_samples, 653 tmpl->usage, tmpl->bind, tmpl->flags); 654 655 if (!rsc) 656 return NULL; 657 658 *prsc = *tmpl; 659 660 pipe_reference_init(&prsc->reference, 1); 661 list_inithead(&rsc->list); 662 prsc->screen = pscreen; 663 664 util_range_init(&rsc->valid_buffer_range); 665 666 rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch); 667 if (!rsc->bo) 668 goto fail; 669 670 rsc->base.vtbl = &fd_resource_vtbl; 671 rsc->cpp = util_format_get_blocksize(tmpl->format); 672 slice->pitch /= rsc->cpp; 673 674 assert(rsc->cpp); 675 676 return prsc; 677 678fail: 679 fd_resource_destroy(pscreen, prsc); 680 return NULL; 681} 682 683static void fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond); 684static void fd_blitter_pipe_end(struct fd_context *ctx); 685 686/** 687 * _copy_region using pipe (3d engine) 688 */ 689static bool 690fd_blitter_pipe_copy_region(struct fd_context *ctx, 691 struct pipe_resource *dst, 692 unsigned dst_level, 693 unsigned dstx, unsigned dsty, unsigned dstz, 694 struct pipe_resource *src, 695 unsigned src_level, 696 const struct pipe_box *src_box) 697{ 698 /* not until we allow rendertargets to be buffers */ 699 if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER) 700 return false; 701 702 if (!util_blitter_is_copy_supported(ctx->blitter, dst, src)) 703 return false; 704 705 fd_blitter_pipe_begin(ctx, false); 706 util_blitter_copy_texture(ctx->blitter, 707 dst, dst_level, dstx, dsty, dstz, 708 src, src_level, src_box); 709 fd_blitter_pipe_end(ctx); 710 711 return true; 712} 713 714/** 715 * Copy a block of pixels from one resource to another. 716 * The resource must be of the same format. 717 * Resources with nr_samples > 1 are not allowed. 718 */ 719static void 720fd_resource_copy_region(struct pipe_context *pctx, 721 struct pipe_resource *dst, 722 unsigned dst_level, 723 unsigned dstx, unsigned dsty, unsigned dstz, 724 struct pipe_resource *src, 725 unsigned src_level, 726 const struct pipe_box *src_box) 727{ 728 struct fd_context *ctx = fd_context(pctx); 729 730 /* TODO if we have 2d core, or other DMA engine that could be used 731 * for simple copies and reasonably easily synchronized with the 3d 732 * core, this is where we'd plug it in.. 733 */ 734 735 /* try blit on 3d pipe: */ 736 if (fd_blitter_pipe_copy_region(ctx, 737 dst, dst_level, dstx, dsty, dstz, 738 src, src_level, src_box)) 739 return; 740 741 /* else fallback to pure sw: */ 742 util_resource_copy_region(pctx, 743 dst, dst_level, dstx, dsty, dstz, 744 src, src_level, src_box); 745} 746 747bool 748fd_render_condition_check(struct pipe_context *pctx) 749{ 750 struct fd_context *ctx = fd_context(pctx); 751 752 if (!ctx->cond_query) 753 return true; 754 755 union pipe_query_result res = { 0 }; 756 bool wait = 757 ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT && 758 ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT; 759 760 if (pctx->get_query_result(pctx, ctx->cond_query, wait, &res)) 761 return (bool)res.u64 != ctx->cond_cond; 762 763 return true; 764} 765 766/** 767 * Optimal hardware path for blitting pixels. 768 * Scaling, format conversion, up- and downsampling (resolve) are allowed. 769 */ 770static void 771fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 772{ 773 struct fd_context *ctx = fd_context(pctx); 774 struct pipe_blit_info info = *blit_info; 775 776 if (info.src.resource->nr_samples > 1 && 777 info.dst.resource->nr_samples <= 1 && 778 !util_format_is_depth_or_stencil(info.src.resource->format) && 779 !util_format_is_pure_integer(info.src.resource->format)) { 780 DBG("color resolve unimplemented"); 781 return; 782 } 783 784 if (info.render_condition_enable && !fd_render_condition_check(pctx)) 785 return; 786 787 if (util_try_blit_via_copy_region(pctx, &info)) { 788 return; /* done */ 789 } 790 791 if (info.mask & PIPE_MASK_S) { 792 DBG("cannot blit stencil, skipping"); 793 info.mask &= ~PIPE_MASK_S; 794 } 795 796 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { 797 DBG("blit unsupported %s -> %s", 798 util_format_short_name(info.src.resource->format), 799 util_format_short_name(info.dst.resource->format)); 800 return; 801 } 802 803 fd_blitter_pipe_begin(ctx, info.render_condition_enable); 804 util_blitter_blit(ctx->blitter, &info); 805 fd_blitter_pipe_end(ctx); 806} 807 808static void 809fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) 810{ 811 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb); 812 util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx); 813 util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp); 814 util_blitter_save_so_targets(ctx->blitter, ctx->streamout.num_targets, 815 ctx->streamout.targets); 816 util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer); 817 util_blitter_save_viewport(ctx->blitter, &ctx->viewport); 818 util_blitter_save_scissor(ctx->blitter, &ctx->scissor); 819 util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp); 820 util_blitter_save_blend(ctx->blitter, ctx->blend); 821 util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); 822 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); 823 util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); 824 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer); 825 util_blitter_save_fragment_sampler_states(ctx->blitter, 826 ctx->fragtex.num_samplers, 827 (void **)ctx->fragtex.samplers); 828 util_blitter_save_fragment_sampler_views(ctx->blitter, 829 ctx->fragtex.num_textures, ctx->fragtex.textures); 830 if (!render_cond) 831 util_blitter_save_render_condition(ctx->blitter, 832 ctx->cond_query, ctx->cond_cond, ctx->cond_mode); 833 834 fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT); 835} 836 837static void 838fd_blitter_pipe_end(struct fd_context *ctx) 839{ 840 fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL); 841} 842 843static void 844fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc) 845{ 846 struct fd_resource *rsc = fd_resource(prsc); 847 848 if (pending(rsc, FD_PENDING_WRITE | FD_PENDING_READ)) 849 fd_context_render(pctx); 850} 851 852void 853fd_resource_screen_init(struct pipe_screen *pscreen) 854{ 855 pscreen->resource_create = fd_resource_create; 856 pscreen->resource_from_handle = fd_resource_from_handle; 857 pscreen->resource_get_handle = u_resource_get_handle_vtbl; 858 pscreen->resource_destroy = u_resource_destroy_vtbl; 859} 860 861void 862fd_resource_context_init(struct pipe_context *pctx) 863{ 864 pctx->transfer_map = u_transfer_map_vtbl; 865 pctx->transfer_flush_region = u_transfer_flush_region_vtbl; 866 pctx->transfer_unmap = u_transfer_unmap_vtbl; 867 pctx->transfer_inline_write = u_transfer_inline_write_vtbl; 868 pctx->create_surface = fd_create_surface; 869 pctx->surface_destroy = fd_surface_destroy; 870 pctx->resource_copy_region = fd_resource_copy_region; 871 pctx->blit = fd_blit; 872 pctx->flush_resource = fd_flush_resource; 873} 874