freedreno_resource.c revision bda1354aac9d32e236048af4d353d5530f644c34
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_zs.h" 31#include "util/u_inlines.h" 32#include "util/u_transfer.h" 33#include "util/u_string.h" 34#include "util/u_surface.h" 35 36#include "freedreno_resource.h" 37#include "freedreno_screen.h" 38#include "freedreno_surface.h" 39#include "freedreno_context.h" 40#include "freedreno_query_hw.h" 41#include "freedreno_util.h" 42 43#include <errno.h> 44 45static void 46fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc) 47{ 48 int i; 49 50 /* Go through the entire state and see if the resource is bound 51 * anywhere. If it is, mark the relevant state as dirty. This is called on 52 * realloc_bo. 53 */ 54 55 /* Constbufs */ 56 for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS && !(ctx->dirty & FD_DIRTY_CONSTBUF); i++) { 57 if (ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer == prsc) 58 ctx->dirty |= FD_DIRTY_CONSTBUF; 59 if (ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer == prsc) 60 ctx->dirty |= FD_DIRTY_CONSTBUF; 61 } 62 63 /* VBOs */ 64 for (i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) { 65 if (ctx->vtx.vertexbuf.vb[i].buffer == prsc) 66 ctx->dirty |= FD_DIRTY_VTXBUF; 67 } 68 69 /* Index buffer */ 70 if (ctx->indexbuf.buffer == prsc) 71 ctx->dirty |= FD_DIRTY_INDEXBUF; 72 73 /* Textures */ 74 for (i = 0; i < ctx->verttex.num_textures && !(ctx->dirty & FD_DIRTY_VERTTEX); i++) { 75 if (ctx->verttex.textures[i] && (ctx->verttex.textures[i]->texture == prsc)) 76 ctx->dirty |= FD_DIRTY_VERTTEX; 77 } 78 for (i = 0; i < ctx->fragtex.num_textures && !(ctx->dirty & FD_DIRTY_FRAGTEX); i++) { 79 if (ctx->fragtex.textures[i] && (ctx->fragtex.textures[i]->texture == prsc)) 80 ctx->dirty |= FD_DIRTY_FRAGTEX; 81 } 82} 83 84static void 85realloc_bo(struct fd_resource *rsc, uint32_t size) 86{ 87 struct fd_screen *screen = fd_screen(rsc->base.b.screen); 88 uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE | 89 DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */ 90 91 /* if we start using things other than write-combine, 92 * be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT 93 */ 94 95 if (rsc->bo) 96 fd_bo_del(rsc->bo); 97 98 rsc->bo = fd_bo_new(screen->dev, size, flags); 99 rsc->timestamp = 0; 100 rsc->dirty = rsc->reading = rsc->writing = false; 101 list_delinit(&rsc->list); 102 util_range_set_empty(&rsc->valid_buffer_range); 103} 104 105/* Currently this is only used for flushing Z32_S8 texture transfers, but 106 * eventually it should handle everything. 107 */ 108static void 109fd_resource_flush(struct fd_transfer *trans, const struct pipe_box *box) 110{ 111 struct fd_resource *rsc = fd_resource(trans->base.resource); 112 struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level); 113 struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level); 114 enum pipe_format format = trans->base.resource->format; 115 116 float *depth = fd_bo_map(rsc->bo) + slice->offset + 117 (trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4; 118 uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset + 119 (trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x; 120 121 assert(format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || 122 format == PIPE_FORMAT_X32_S8X24_UINT); 123 124 if (format != PIPE_FORMAT_X32_S8X24_UINT) 125 util_format_z32_float_s8x24_uint_unpack_z_float( 126 depth, slice->pitch * 4, 127 trans->staging, trans->base.stride, 128 box->width, box->height); 129 130 util_format_z32_float_s8x24_uint_unpack_s_8uint( 131 stencil, sslice->pitch, 132 trans->staging, trans->base.stride, 133 box->width, box->height); 134} 135 136static void fd_resource_transfer_flush_region(struct pipe_context *pctx, 137 struct pipe_transfer *ptrans, 138 const struct pipe_box *box) 139{ 140 struct fd_resource *rsc = fd_resource(ptrans->resource); 141 struct fd_transfer *trans = fd_transfer(ptrans); 142 143 if (ptrans->resource->target == PIPE_BUFFER) 144 util_range_add(&rsc->valid_buffer_range, 145 ptrans->box.x + box->x, 146 ptrans->box.x + box->x + box->width); 147 148 if (trans->staging) 149 fd_resource_flush(trans, box); 150} 151 152static void 153fd_resource_transfer_unmap(struct pipe_context *pctx, 154 struct pipe_transfer *ptrans) 155{ 156 struct fd_context *ctx = fd_context(pctx); 157 struct fd_resource *rsc = fd_resource(ptrans->resource); 158 struct fd_transfer *trans = fd_transfer(ptrans); 159 160 if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { 161 struct pipe_box box; 162 u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); 163 fd_resource_flush(trans, &box); 164 } 165 166 if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 167 fd_bo_cpu_fini(rsc->bo); 168 if (rsc->stencil) 169 fd_bo_cpu_fini(rsc->stencil->bo); 170 } 171 172 util_range_add(&rsc->valid_buffer_range, 173 ptrans->box.x, 174 ptrans->box.x + ptrans->box.width); 175 176 pipe_resource_reference(&ptrans->resource, NULL); 177 util_slab_free(&ctx->transfer_pool, ptrans); 178 179 if (trans->staging) 180 free(trans->staging); 181} 182 183static void * 184fd_resource_transfer_map(struct pipe_context *pctx, 185 struct pipe_resource *prsc, 186 unsigned level, unsigned usage, 187 const struct pipe_box *box, 188 struct pipe_transfer **pptrans) 189{ 190 struct fd_context *ctx = fd_context(pctx); 191 struct fd_resource *rsc = fd_resource(prsc); 192 struct fd_resource_slice *slice = fd_resource_slice(rsc, level); 193 struct fd_transfer *trans; 194 struct pipe_transfer *ptrans; 195 enum pipe_format format = prsc->format; 196 uint32_t op = 0; 197 uint32_t offset; 198 char *buf; 199 int ret = 0; 200 201 DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage, 202 box->width, box->height, box->x, box->y); 203 204 ptrans = util_slab_alloc(&ctx->transfer_pool); 205 if (!ptrans) 206 return NULL; 207 208 /* util_slab_alloc() doesn't zero: */ 209 trans = fd_transfer(ptrans); 210 memset(trans, 0, sizeof(*trans)); 211 212 pipe_resource_reference(&ptrans->resource, prsc); 213 ptrans->level = level; 214 ptrans->usage = usage; 215 ptrans->box = *box; 216 ptrans->stride = slice->pitch * rsc->cpp; 217 ptrans->layer_stride = slice->size0; 218 219 if (usage & PIPE_TRANSFER_READ) 220 op |= DRM_FREEDRENO_PREP_READ; 221 222 if (usage & PIPE_TRANSFER_WRITE) 223 op |= DRM_FREEDRENO_PREP_WRITE; 224 225 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { 226 realloc_bo(rsc, fd_bo_size(rsc->bo)); 227 if (rsc->stencil) 228 realloc_bo(rsc->stencil, fd_bo_size(rsc->stencil->bo)); 229 fd_invalidate_resource(ctx, prsc); 230 } else if ((usage & PIPE_TRANSFER_WRITE) && 231 prsc->target == PIPE_BUFFER && 232 !util_ranges_intersect(&rsc->valid_buffer_range, 233 box->x, box->x + box->width)) { 234 /* We are trying to write to a previously uninitialized range. No need 235 * to wait. 236 */ 237 } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 238 /* If the GPU is writing to the resource, or if it is reading from the 239 * resource and we're trying to write to it, flush the renders. 240 */ 241 if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty) || 242 ((ptrans->usage & PIPE_TRANSFER_WRITE) && rsc->reading) || 243 ((ptrans->usage & PIPE_TRANSFER_READ) && rsc->writing)) 244 fd_context_render(pctx); 245 246 /* The GPU keeps track of how the various bo's are being used, and 247 * will wait if necessary for the proper operation to have 248 * completed. 249 */ 250 ret = fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op); 251 if (ret) 252 goto fail; 253 } 254 255 buf = fd_bo_map(rsc->bo); 256 if (!buf) { 257 fd_resource_transfer_unmap(pctx, ptrans); 258 return NULL; 259 } 260 261 if (rsc->layer_first) { 262 offset = slice->offset + 263 box->y / util_format_get_blockheight(format) * ptrans->stride + 264 box->x / util_format_get_blockwidth(format) * rsc->cpp + 265 box->z * rsc->layer_size; 266 } else { 267 offset = slice->offset + 268 box->y / util_format_get_blockheight(format) * ptrans->stride + 269 box->x / util_format_get_blockwidth(format) * rsc->cpp + 270 box->z * slice->size0; 271 } 272 273 if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || 274 prsc->format == PIPE_FORMAT_X32_S8X24_UINT) { 275 trans->base.stride = trans->base.box.width * rsc->cpp * 2; 276 trans->staging = malloc(trans->base.stride * trans->base.box.height); 277 if (!trans->staging) 278 goto fail; 279 280 /* if we're not discarding the whole range (or resource), we must copy 281 * the real data in. 282 */ 283 if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE | 284 PIPE_TRANSFER_DISCARD_RANGE))) { 285 struct fd_resource_slice *sslice = 286 fd_resource_slice(rsc->stencil, level); 287 void *sbuf = fd_bo_map(rsc->stencil->bo); 288 if (!sbuf) 289 goto fail; 290 291 float *depth = (float *)(buf + slice->offset + 292 box->y * slice->pitch * 4 + box->x * 4); 293 uint8_t *stencil = sbuf + sslice->offset + 294 box->y * sslice->pitch + box->x; 295 296 if (format != PIPE_FORMAT_X32_S8X24_UINT) 297 util_format_z32_float_s8x24_uint_pack_z_float( 298 trans->staging, trans->base.stride, 299 depth, slice->pitch * 4, 300 box->width, box->height); 301 302 util_format_z32_float_s8x24_uint_pack_s_8uint( 303 trans->staging, trans->base.stride, 304 stencil, sslice->pitch, 305 box->width, box->height); 306 } 307 308 buf = trans->staging; 309 offset = 0; 310 } 311 312 *pptrans = ptrans; 313 314 return buf + offset; 315 316fail: 317 fd_resource_transfer_unmap(pctx, ptrans); 318 return NULL; 319} 320 321static void 322fd_resource_destroy(struct pipe_screen *pscreen, 323 struct pipe_resource *prsc) 324{ 325 struct fd_resource *rsc = fd_resource(prsc); 326 if (rsc->bo) 327 fd_bo_del(rsc->bo); 328 list_delinit(&rsc->list); 329 util_range_destroy(&rsc->valid_buffer_range); 330 FREE(rsc); 331} 332 333static boolean 334fd_resource_get_handle(struct pipe_screen *pscreen, 335 struct pipe_resource *prsc, 336 struct winsys_handle *handle) 337{ 338 struct fd_resource *rsc = fd_resource(prsc); 339 340 return fd_screen_bo_get_handle(pscreen, rsc->bo, 341 rsc->slices[0].pitch * rsc->cpp, handle); 342} 343 344 345static const struct u_resource_vtbl fd_resource_vtbl = { 346 .resource_get_handle = fd_resource_get_handle, 347 .resource_destroy = fd_resource_destroy, 348 .transfer_map = fd_resource_transfer_map, 349 .transfer_flush_region = fd_resource_transfer_flush_region, 350 .transfer_unmap = fd_resource_transfer_unmap, 351 .transfer_inline_write = u_default_transfer_inline_write, 352}; 353 354static uint32_t 355setup_slices(struct fd_resource *rsc, uint32_t alignment) 356{ 357 struct pipe_resource *prsc = &rsc->base.b; 358 uint32_t level, size = 0; 359 uint32_t width = prsc->width0; 360 uint32_t height = prsc->height0; 361 uint32_t depth = prsc->depth0; 362 /* in layer_first layout, the level (slice) contains just one 363 * layer (since in fact the layer contains the slices) 364 */ 365 uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size; 366 367 for (level = 0; level <= prsc->last_level; level++) { 368 struct fd_resource_slice *slice = fd_resource_slice(rsc, level); 369 370 slice->pitch = width = align(width, 32); 371 slice->offset = size; 372 /* 1d array and 2d array textures must all have the same layer size 373 * for each miplevel on a3xx. 3d textures can have different layer 374 * sizes for high levels, but the hw auto-sizer is buggy (or at least 375 * different than what this code does), so as soon as the layer size 376 * range gets into range, we stop reducing it. 377 */ 378 if (prsc->target == PIPE_TEXTURE_3D && ( 379 level == 1 || 380 (level > 1 && rsc->slices[level - 1].size0 > 0xf000))) 381 slice->size0 = align(slice->pitch * height * rsc->cpp, alignment); 382 else if (level == 0 || rsc->layer_first || alignment == 1) 383 slice->size0 = align(slice->pitch * height * rsc->cpp, alignment); 384 else 385 slice->size0 = rsc->slices[level - 1].size0; 386 387 size += slice->size0 * depth * layers_in_level; 388 389 width = u_minify(width, 1); 390 height = u_minify(height, 1); 391 depth = u_minify(depth, 1); 392 } 393 394 return size; 395} 396 397static uint32_t 398slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) 399{ 400 /* on a3xx, 2d array and 3d textures seem to want their 401 * layers aligned to page boundaries: 402 */ 403 switch (tmpl->target) { 404 case PIPE_TEXTURE_3D: 405 case PIPE_TEXTURE_1D_ARRAY: 406 case PIPE_TEXTURE_2D_ARRAY: 407 return 4096; 408 default: 409 return 1; 410 } 411} 412 413/** 414 * Create a new texture object, using the given template info. 415 */ 416static struct pipe_resource * 417fd_resource_create(struct pipe_screen *pscreen, 418 const struct pipe_resource *tmpl) 419{ 420 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); 421 struct pipe_resource *prsc = &rsc->base.b; 422 uint32_t size; 423 424 DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " 425 "nr_samples=%u, usage=%u, bind=%x, flags=%x", 426 tmpl->target, util_format_name(tmpl->format), 427 tmpl->width0, tmpl->height0, tmpl->depth0, 428 tmpl->array_size, tmpl->last_level, tmpl->nr_samples, 429 tmpl->usage, tmpl->bind, tmpl->flags); 430 431 if (!rsc) 432 return NULL; 433 434 *prsc = *tmpl; 435 436 pipe_reference_init(&prsc->reference, 1); 437 list_inithead(&rsc->list); 438 prsc->screen = pscreen; 439 440 util_range_init(&rsc->valid_buffer_range); 441 442 rsc->base.vtbl = &fd_resource_vtbl; 443 if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) 444 rsc->cpp = util_format_get_blocksize(PIPE_FORMAT_Z32_FLOAT); 445 else 446 rsc->cpp = util_format_get_blocksize(tmpl->format); 447 448 assert(rsc->cpp); 449 450 if (is_a4xx(fd_screen(pscreen))) { 451 switch (tmpl->target) { 452 case PIPE_TEXTURE_3D: 453 /* TODO 3D_ARRAY? */ 454 rsc->layer_first = false; 455 break; 456 default: 457 rsc->layer_first = true; 458 break; 459 } 460 } 461 462 size = setup_slices(rsc, slice_alignment(pscreen, tmpl)); 463 464 if (rsc->layer_first) { 465 rsc->layer_size = align(size, 4096); 466 size = rsc->layer_size * prsc->array_size; 467 } 468 469 realloc_bo(rsc, size); 470 if (!rsc->bo) 471 goto fail; 472 473 /* There is no native Z32F_S8 sampling or rendering format, so this must 474 * be emulated via two separate textures. The depth texture still keeps 475 * its Z32F_S8 format though, and we also keep a reference to a separate 476 * S8 texture. 477 */ 478 if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { 479 struct pipe_resource stencil = *tmpl; 480 stencil.format = PIPE_FORMAT_S8_UINT; 481 rsc->stencil = fd_resource(fd_resource_create(pscreen, &stencil)); 482 if (!rsc->stencil) 483 goto fail; 484 } 485 486 return prsc; 487fail: 488 fd_resource_destroy(pscreen, prsc); 489 return NULL; 490} 491 492/** 493 * Create a texture from a winsys_handle. The handle is often created in 494 * another process by first creating a pipe texture and then calling 495 * resource_get_handle. 496 */ 497static struct pipe_resource * 498fd_resource_from_handle(struct pipe_screen *pscreen, 499 const struct pipe_resource *tmpl, 500 struct winsys_handle *handle) 501{ 502 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); 503 struct fd_resource_slice *slice = &rsc->slices[0]; 504 struct pipe_resource *prsc = &rsc->base.b; 505 506 DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " 507 "nr_samples=%u, usage=%u, bind=%x, flags=%x", 508 tmpl->target, util_format_name(tmpl->format), 509 tmpl->width0, tmpl->height0, tmpl->depth0, 510 tmpl->array_size, tmpl->last_level, tmpl->nr_samples, 511 tmpl->usage, tmpl->bind, tmpl->flags); 512 513 if (!rsc) 514 return NULL; 515 516 *prsc = *tmpl; 517 518 pipe_reference_init(&prsc->reference, 1); 519 list_inithead(&rsc->list); 520 prsc->screen = pscreen; 521 522 util_range_init(&rsc->valid_buffer_range); 523 524 rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch); 525 if (!rsc->bo) 526 goto fail; 527 528 rsc->base.vtbl = &fd_resource_vtbl; 529 rsc->cpp = util_format_get_blocksize(tmpl->format); 530 slice->pitch /= rsc->cpp; 531 532 assert(rsc->cpp); 533 534 return prsc; 535 536fail: 537 fd_resource_destroy(pscreen, prsc); 538 return NULL; 539} 540 541static void fd_blitter_pipe_begin(struct fd_context *ctx); 542static void fd_blitter_pipe_end(struct fd_context *ctx); 543 544/** 545 * _copy_region using pipe (3d engine) 546 */ 547static bool 548fd_blitter_pipe_copy_region(struct fd_context *ctx, 549 struct pipe_resource *dst, 550 unsigned dst_level, 551 unsigned dstx, unsigned dsty, unsigned dstz, 552 struct pipe_resource *src, 553 unsigned src_level, 554 const struct pipe_box *src_box) 555{ 556 /* not until we allow rendertargets to be buffers */ 557 if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER) 558 return false; 559 560 if (!util_blitter_is_copy_supported(ctx->blitter, dst, src)) 561 return false; 562 563 fd_blitter_pipe_begin(ctx); 564 util_blitter_copy_texture(ctx->blitter, 565 dst, dst_level, dstx, dsty, dstz, 566 src, src_level, src_box); 567 fd_blitter_pipe_end(ctx); 568 569 return true; 570} 571 572/** 573 * Copy a block of pixels from one resource to another. 574 * The resource must be of the same format. 575 * Resources with nr_samples > 1 are not allowed. 576 */ 577static void 578fd_resource_copy_region(struct pipe_context *pctx, 579 struct pipe_resource *dst, 580 unsigned dst_level, 581 unsigned dstx, unsigned dsty, unsigned dstz, 582 struct pipe_resource *src, 583 unsigned src_level, 584 const struct pipe_box *src_box) 585{ 586 struct fd_context *ctx = fd_context(pctx); 587 588 /* TODO if we have 2d core, or other DMA engine that could be used 589 * for simple copies and reasonably easily synchronized with the 3d 590 * core, this is where we'd plug it in.. 591 */ 592 593 /* try blit on 3d pipe: */ 594 if (fd_blitter_pipe_copy_region(ctx, 595 dst, dst_level, dstx, dsty, dstz, 596 src, src_level, src_box)) 597 return; 598 599 /* else fallback to pure sw: */ 600 util_resource_copy_region(pctx, 601 dst, dst_level, dstx, dsty, dstz, 602 src, src_level, src_box); 603} 604 605/** 606 * Optimal hardware path for blitting pixels. 607 * Scaling, format conversion, up- and downsampling (resolve) are allowed. 608 */ 609static void 610fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 611{ 612 struct fd_context *ctx = fd_context(pctx); 613 struct pipe_blit_info info = *blit_info; 614 615 if (info.src.resource->nr_samples > 1 && 616 info.dst.resource->nr_samples <= 1 && 617 !util_format_is_depth_or_stencil(info.src.resource->format) && 618 !util_format_is_pure_integer(info.src.resource->format)) { 619 DBG("color resolve unimplemented"); 620 return; 621 } 622 623 if (util_try_blit_via_copy_region(pctx, &info)) { 624 return; /* done */ 625 } 626 627 if (info.mask & PIPE_MASK_S) { 628 DBG("cannot blit stencil, skipping"); 629 info.mask &= ~PIPE_MASK_S; 630 } 631 632 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { 633 DBG("blit unsupported %s -> %s", 634 util_format_short_name(info.src.resource->format), 635 util_format_short_name(info.dst.resource->format)); 636 return; 637 } 638 639 fd_blitter_pipe_begin(ctx); 640 util_blitter_blit(ctx->blitter, &info); 641 fd_blitter_pipe_end(ctx); 642} 643 644static void 645fd_blitter_pipe_begin(struct fd_context *ctx) 646{ 647 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb); 648 util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx); 649 util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp); 650 util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer); 651 util_blitter_save_viewport(ctx->blitter, &ctx->viewport); 652 util_blitter_save_scissor(ctx->blitter, &ctx->scissor); 653 util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp); 654 util_blitter_save_blend(ctx->blitter, ctx->blend); 655 util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); 656 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); 657 util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); 658 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer); 659 util_blitter_save_fragment_sampler_states(ctx->blitter, 660 ctx->fragtex.num_samplers, 661 (void **)ctx->fragtex.samplers); 662 util_blitter_save_fragment_sampler_views(ctx->blitter, 663 ctx->fragtex.num_textures, ctx->fragtex.textures); 664 665 fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT); 666} 667 668static void 669fd_blitter_pipe_end(struct fd_context *ctx) 670{ 671 fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL); 672} 673 674static void 675fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc) 676{ 677 struct fd_resource *rsc = fd_resource(prsc); 678 679 if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty)) 680 fd_context_render(pctx); 681} 682 683void 684fd_resource_screen_init(struct pipe_screen *pscreen) 685{ 686 pscreen->resource_create = fd_resource_create; 687 pscreen->resource_from_handle = fd_resource_from_handle; 688 pscreen->resource_get_handle = u_resource_get_handle_vtbl; 689 pscreen->resource_destroy = u_resource_destroy_vtbl; 690} 691 692void 693fd_resource_context_init(struct pipe_context *pctx) 694{ 695 pctx->transfer_map = u_transfer_map_vtbl; 696 pctx->transfer_flush_region = u_transfer_flush_region_vtbl; 697 pctx->transfer_unmap = u_transfer_unmap_vtbl; 698 pctx->transfer_inline_write = u_transfer_inline_write_vtbl; 699 pctx->create_surface = fd_create_surface; 700 pctx->surface_destroy = fd_surface_destroy; 701 pctx->resource_copy_region = fd_resource_copy_region; 702 pctx->blit = fd_blit; 703 pctx->flush_resource = fd_flush_resource; 704} 705