1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2013 LunarG, Inc. 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 shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #include "core/ilo_state_vf.h" 29 #include "core/ilo_state_sol.h" 30 #include "core/ilo_state_surface.h" 31 32 #include "ilo_screen.h" 33 #include "ilo_format.h" 34 #include "ilo_resource.h" 35 36 /* 37 * From the Ivy Bridge PRM, volume 1 part 1, page 105: 38 * 39 * "In addition to restrictions on maximum height, width, and depth, 40 * surfaces are also restricted to a maximum size in bytes. This 41 * maximum is 2 GB for all products and all surface types." 42 */ 43 static const size_t ilo_max_resource_size = 1u << 31; 44 45 static const char * 46 resource_get_bo_name(const struct pipe_resource *templ) 47 { 48 static const char *target_names[PIPE_MAX_TEXTURE_TYPES] = { 49 [PIPE_BUFFER] = "buf", 50 [PIPE_TEXTURE_1D] = "tex-1d", 51 [PIPE_TEXTURE_2D] = "tex-2d", 52 [PIPE_TEXTURE_3D] = "tex-3d", 53 [PIPE_TEXTURE_CUBE] = "tex-cube", 54 [PIPE_TEXTURE_RECT] = "tex-rect", 55 [PIPE_TEXTURE_1D_ARRAY] = "tex-1d-array", 56 [PIPE_TEXTURE_2D_ARRAY] = "tex-2d-array", 57 [PIPE_TEXTURE_CUBE_ARRAY] = "tex-cube-array", 58 }; 59 const char *name = target_names[templ->target]; 60 61 if (templ->target == PIPE_BUFFER) { 62 switch (templ->bind) { 63 case PIPE_BIND_VERTEX_BUFFER: 64 name = "buf-vb"; 65 break; 66 case PIPE_BIND_INDEX_BUFFER: 67 name = "buf-ib"; 68 break; 69 case PIPE_BIND_CONSTANT_BUFFER: 70 name = "buf-cb"; 71 break; 72 case PIPE_BIND_STREAM_OUTPUT: 73 name = "buf-so"; 74 break; 75 default: 76 break; 77 } 78 } 79 80 return name; 81 } 82 83 static bool 84 resource_get_cpu_init(const struct pipe_resource *templ) 85 { 86 return (templ->bind & (PIPE_BIND_DEPTH_STENCIL | 87 PIPE_BIND_RENDER_TARGET | 88 PIPE_BIND_STREAM_OUTPUT)) ? false : true; 89 } 90 91 static enum gen_surface_type 92 get_surface_type(enum pipe_texture_target target) 93 { 94 switch (target) { 95 case PIPE_TEXTURE_1D: 96 case PIPE_TEXTURE_1D_ARRAY: 97 return GEN6_SURFTYPE_1D; 98 case PIPE_TEXTURE_2D: 99 case PIPE_TEXTURE_RECT: 100 case PIPE_TEXTURE_2D_ARRAY: 101 return GEN6_SURFTYPE_2D; 102 case PIPE_TEXTURE_3D: 103 return GEN6_SURFTYPE_3D; 104 case PIPE_TEXTURE_CUBE: 105 case PIPE_TEXTURE_CUBE_ARRAY: 106 return GEN6_SURFTYPE_CUBE; 107 default: 108 assert(!"unknown texture target"); 109 return GEN6_SURFTYPE_NULL; 110 } 111 } 112 113 static enum pipe_format 114 resource_get_image_format(const struct pipe_resource *templ, 115 const struct ilo_dev *dev, 116 bool *separate_stencil_ret) 117 { 118 enum pipe_format format = templ->format; 119 bool separate_stencil; 120 121 /* silently promote ETC1 */ 122 if (templ->format == PIPE_FORMAT_ETC1_RGB8) 123 format = PIPE_FORMAT_R8G8B8X8_UNORM; 124 125 /* separate stencil buffers */ 126 separate_stencil = false; 127 if ((templ->bind & PIPE_BIND_DEPTH_STENCIL) && 128 util_format_is_depth_and_stencil(templ->format)) { 129 switch (templ->format) { 130 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 131 /* Gen6 requires HiZ to be available for all levels */ 132 if (ilo_dev_gen(dev) >= ILO_GEN(7) || templ->last_level == 0) { 133 format = PIPE_FORMAT_Z32_FLOAT; 134 separate_stencil = true; 135 } 136 break; 137 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 138 format = PIPE_FORMAT_Z24X8_UNORM; 139 separate_stencil = true; 140 break; 141 default: 142 break; 143 } 144 } 145 146 if (separate_stencil_ret) 147 *separate_stencil_ret = separate_stencil; 148 149 return format; 150 } 151 152 static inline enum gen_surface_format 153 pipe_to_surface_format(const struct ilo_dev *dev, enum pipe_format format) 154 { 155 switch (format) { 156 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 157 return GEN6_FORMAT_R32_FLOAT_X8X24_TYPELESS; 158 case PIPE_FORMAT_Z32_FLOAT: 159 return GEN6_FORMAT_R32_FLOAT; 160 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 161 case PIPE_FORMAT_Z24X8_UNORM: 162 return GEN6_FORMAT_R24_UNORM_X8_TYPELESS; 163 case PIPE_FORMAT_Z16_UNORM: 164 return GEN6_FORMAT_R16_UNORM; 165 case PIPE_FORMAT_S8_UINT: 166 return GEN6_FORMAT_R8_UINT; 167 default: 168 return ilo_format_translate_color(dev, format); 169 } 170 } 171 172 static void 173 resource_get_image_info(const struct pipe_resource *templ, 174 const struct ilo_dev *dev, 175 enum pipe_format image_format, 176 struct ilo_image_info *info) 177 { 178 memset(info, 0, sizeof(*info)); 179 180 info->type = get_surface_type(templ->target); 181 182 info->format = pipe_to_surface_format(dev, image_format); 183 info->interleaved_stencil = util_format_is_depth_and_stencil(image_format); 184 info->is_integer = util_format_is_pure_integer(image_format); 185 info->compressed = util_format_is_compressed(image_format); 186 info->block_width = util_format_get_blockwidth(image_format); 187 info->block_height = util_format_get_blockheight(image_format); 188 info->block_size = util_format_get_blocksize(image_format); 189 190 info->width = templ->width0; 191 info->height = templ->height0; 192 info->depth = templ->depth0; 193 info->array_size = templ->array_size; 194 info->level_count = templ->last_level + 1; 195 info->sample_count = (templ->nr_samples) ? templ->nr_samples : 1; 196 197 info->aux_disable = (templ->usage == PIPE_USAGE_STAGING); 198 199 if (templ->bind & PIPE_BIND_LINEAR) 200 info->valid_tilings = 1 << GEN6_TILING_NONE; 201 202 /* 203 * Tiled images must be mapped via GTT to get a linear view. Prefer linear 204 * images when the image size is greater than one-fourth of the mappable 205 * aperture. 206 */ 207 if (templ->usage == PIPE_USAGE_STAGING) 208 info->prefer_linear_threshold = dev->aperture_mappable / 4; 209 210 info->bind_surface_sampler = (templ->bind & PIPE_BIND_SAMPLER_VIEW); 211 info->bind_surface_dp_render = (templ->bind & PIPE_BIND_RENDER_TARGET); 212 info->bind_surface_dp_typed = (templ->bind & 213 (PIPE_BIND_SHADER_IMAGE | PIPE_BIND_COMPUTE_RESOURCE)); 214 info->bind_zs = (templ->bind & PIPE_BIND_DEPTH_STENCIL); 215 info->bind_scanout = (templ->bind & PIPE_BIND_SCANOUT); 216 info->bind_cursor = (templ->bind & PIPE_BIND_CURSOR); 217 } 218 219 static enum gen_surface_tiling 220 winsys_to_surface_tiling(enum intel_tiling_mode tiling) 221 { 222 switch (tiling) { 223 case INTEL_TILING_NONE: 224 return GEN6_TILING_NONE; 225 case INTEL_TILING_X: 226 return GEN6_TILING_X; 227 case INTEL_TILING_Y: 228 return GEN6_TILING_Y; 229 default: 230 assert(!"unknown tiling"); 231 return GEN6_TILING_NONE; 232 } 233 } 234 235 static inline enum intel_tiling_mode 236 surface_to_winsys_tiling(enum gen_surface_tiling tiling) 237 { 238 switch (tiling) { 239 case GEN6_TILING_NONE: 240 return INTEL_TILING_NONE; 241 case GEN6_TILING_X: 242 return INTEL_TILING_X; 243 case GEN6_TILING_Y: 244 return INTEL_TILING_Y; 245 default: 246 assert(!"unknown tiling"); 247 return GEN6_TILING_NONE; 248 } 249 } 250 251 static void 252 tex_free_slices(struct ilo_texture *tex) 253 { 254 FREE(tex->slices[0]); 255 } 256 257 static bool 258 tex_alloc_slices(struct ilo_texture *tex) 259 { 260 const struct pipe_resource *templ = &tex->base; 261 struct ilo_texture_slice *slices; 262 int depth, lv; 263 264 /* sum the depths of all levels */ 265 depth = 0; 266 for (lv = 0; lv <= templ->last_level; lv++) 267 depth += u_minify(templ->depth0, lv); 268 269 /* 270 * There are (depth * tex->base.array_size) slices in total. Either depth 271 * is one (non-3D) or templ->array_size is one (non-array), but it does 272 * not matter. 273 */ 274 slices = CALLOC(depth * templ->array_size, sizeof(*slices)); 275 if (!slices) 276 return false; 277 278 tex->slices[0] = slices; 279 280 /* point to the respective positions in the buffer */ 281 for (lv = 1; lv <= templ->last_level; lv++) { 282 tex->slices[lv] = tex->slices[lv - 1] + 283 u_minify(templ->depth0, lv - 1) * templ->array_size; 284 } 285 286 return true; 287 } 288 289 static bool 290 tex_create_bo(struct ilo_texture *tex) 291 { 292 struct ilo_screen *is = ilo_screen(tex->base.screen); 293 const char *name = resource_get_bo_name(&tex->base); 294 const bool cpu_init = resource_get_cpu_init(&tex->base); 295 struct intel_bo *bo; 296 297 bo = intel_winsys_alloc_bo(is->dev.winsys, name, 298 tex->image.bo_stride * tex->image.bo_height, cpu_init); 299 300 /* set the tiling for transfer and export */ 301 if (bo && (tex->image.tiling == GEN6_TILING_X || 302 tex->image.tiling == GEN6_TILING_Y)) { 303 const enum intel_tiling_mode tiling = 304 surface_to_winsys_tiling(tex->image.tiling); 305 306 if (intel_bo_set_tiling(bo, tiling, tex->image.bo_stride)) { 307 intel_bo_unref(bo); 308 bo = NULL; 309 } 310 } 311 if (!bo) 312 return false; 313 314 intel_bo_unref(tex->vma.bo); 315 ilo_vma_set_bo(&tex->vma, &is->dev, bo, 0); 316 317 return true; 318 } 319 320 static bool 321 tex_create_separate_stencil(struct ilo_texture *tex) 322 { 323 struct pipe_resource templ = tex->base; 324 struct pipe_resource *s8; 325 326 /* 327 * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other 328 * tilings. But that should be fine since it will never be bound as the 329 * stencil buffer, and our transfer code can handle all tilings. 330 */ 331 templ.format = PIPE_FORMAT_S8_UINT; 332 333 /* no stencil texturing */ 334 templ.bind &= ~PIPE_BIND_SAMPLER_VIEW; 335 336 s8 = tex->base.screen->resource_create(tex->base.screen, &templ); 337 if (!s8) 338 return false; 339 340 tex->separate_s8 = ilo_texture(s8); 341 342 assert(tex->separate_s8->image_format == PIPE_FORMAT_S8_UINT); 343 344 return true; 345 } 346 347 static bool 348 tex_create_hiz(struct ilo_texture *tex) 349 { 350 const struct pipe_resource *templ = &tex->base; 351 const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height; 352 struct ilo_screen *is = ilo_screen(tex->base.screen); 353 struct intel_bo *bo; 354 355 bo = intel_winsys_alloc_bo(is->dev.winsys, "hiz texture", size, false); 356 if (!bo) 357 return false; 358 359 ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096); 360 ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0); 361 362 if (tex->imported) { 363 unsigned lv; 364 365 for (lv = 0; lv <= templ->last_level; lv++) { 366 if (tex->image.aux.enables & (1 << lv)) { 367 const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ? 368 u_minify(templ->depth0, lv) : templ->array_size; 369 /* this will trigger HiZ resolves */ 370 const unsigned flags = ILO_TEXTURE_CPU_WRITE; 371 372 ilo_texture_set_slice_flags(tex, lv, 0, num_slices, flags, flags); 373 } 374 } 375 } 376 377 return true; 378 } 379 380 static bool 381 tex_create_mcs(struct ilo_texture *tex) 382 { 383 const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height; 384 struct ilo_screen *is = ilo_screen(tex->base.screen); 385 struct intel_bo *bo; 386 387 assert(tex->image.aux.enables == (1 << (tex->base.last_level + 1)) - 1); 388 389 bo = intel_winsys_alloc_bo(is->dev.winsys, "mcs texture", size, false); 390 if (!bo) 391 return false; 392 393 ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096); 394 ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0); 395 396 return true; 397 } 398 399 static void 400 tex_destroy(struct ilo_texture *tex) 401 { 402 if (tex->separate_s8) 403 tex_destroy(tex->separate_s8); 404 405 intel_bo_unref(tex->vma.bo); 406 intel_bo_unref(tex->aux_vma.bo); 407 408 tex_free_slices(tex); 409 FREE(tex); 410 } 411 412 static bool 413 tex_alloc_bos(struct ilo_texture *tex) 414 { 415 if (!tex->imported && !tex_create_bo(tex)) 416 return false; 417 418 switch (tex->image.aux.type) { 419 case ILO_IMAGE_AUX_HIZ: 420 if (!tex_create_hiz(tex)) 421 return false; 422 break; 423 case ILO_IMAGE_AUX_MCS: 424 if (!tex_create_mcs(tex)) 425 return false; 426 break; 427 default: 428 break; 429 } 430 431 return true; 432 } 433 434 static struct intel_bo * 435 tex_import_handle(struct ilo_texture *tex, 436 const struct winsys_handle *handle, 437 struct ilo_image_info *info) 438 { 439 struct ilo_screen *is = ilo_screen(tex->base.screen); 440 const struct pipe_resource *templ = &tex->base; 441 const char *name = resource_get_bo_name(&tex->base); 442 enum intel_tiling_mode tiling; 443 unsigned long pitch; 444 struct intel_bo *bo; 445 446 bo = intel_winsys_import_handle(is->dev.winsys, name, handle, 447 tex->image.bo_height, &tiling, &pitch); 448 /* modify image info */ 449 if (bo) { 450 const uint8_t valid_tilings = 1 << winsys_to_surface_tiling(tiling); 451 452 if (info->valid_tilings && !(info->valid_tilings & valid_tilings)) { 453 intel_bo_unref(bo); 454 return NULL; 455 } 456 457 info->valid_tilings = valid_tilings; 458 info->force_bo_stride = pitch; 459 460 /* assume imported RTs are also scanouts */ 461 if (!info->bind_scanout) 462 info->bind_scanout = (templ->usage & PIPE_BIND_RENDER_TARGET); 463 } 464 465 return bo; 466 } 467 468 static bool 469 tex_init_image(struct ilo_texture *tex, 470 const struct winsys_handle *handle, 471 bool *separate_stencil) 472 { 473 struct ilo_screen *is = ilo_screen(tex->base.screen); 474 const struct pipe_resource *templ = &tex->base; 475 struct ilo_image *img = &tex->image; 476 struct intel_bo *imported_bo = NULL; 477 struct ilo_image_info info; 478 479 tex->image_format = resource_get_image_format(templ, 480 &is->dev, separate_stencil); 481 resource_get_image_info(templ, &is->dev, tex->image_format, &info); 482 483 if (handle) { 484 imported_bo = tex_import_handle(tex, handle, &info); 485 if (!imported_bo) 486 return false; 487 } 488 489 if (!ilo_image_init(img, &is->dev, &info)) { 490 intel_bo_unref(imported_bo); 491 return false; 492 } 493 494 /* 495 * HiZ requires 8x4 alignment and some levels might need HiZ disabled. It 496 * is generally fine except on Gen6, where HiZ and separate stencil must be 497 * enabled together. For PIPE_FORMAT_Z24X8_UNORM with separate stencil, we 498 * can live with stencil values being interleaved for levels where HiZ is 499 * disabled. But it is not the case for PIPE_FORMAT_Z32_FLOAT with 500 * separate stencil. If HiZ was disabled for a level, we had to change the 501 * format to PIPE_FORMAT_Z32_FLOAT_S8X24_UINT for the level and that format 502 * had a different bpp. In other words, HiZ has to be available for all 503 * levels. 504 */ 505 if (ilo_dev_gen(&is->dev) == ILO_GEN(6) && 506 templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && 507 tex->image_format == PIPE_FORMAT_Z32_FLOAT && 508 img->aux.enables != (1 << templ->last_level)) { 509 tex->image_format = templ->format; 510 info.format = pipe_to_surface_format(&is->dev, tex->image_format); 511 info.interleaved_stencil = true; 512 513 memset(img, 0, sizeof(*img)); 514 if (!ilo_image_init(img, &is->dev, &info)) { 515 intel_bo_unref(imported_bo); 516 return false; 517 } 518 } 519 520 if (img->bo_height > ilo_max_resource_size / img->bo_stride || 521 !ilo_vma_init(&tex->vma, &is->dev, img->bo_stride * img->bo_height, 522 4096)) { 523 intel_bo_unref(imported_bo); 524 return false; 525 } 526 527 if (imported_bo) { 528 ilo_vma_set_bo(&tex->vma, &is->dev, imported_bo, 0); 529 tex->imported = true; 530 } 531 532 if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) { 533 /* require on-the-fly tiling/untiling or format conversion */ 534 if (img->tiling == GEN8_TILING_W || *separate_stencil || 535 tex->image_format != templ->format) 536 return false; 537 } 538 539 if (!tex_alloc_slices(tex)) 540 return false; 541 542 return true; 543 } 544 545 static struct pipe_resource * 546 tex_create(struct pipe_screen *screen, 547 const struct pipe_resource *templ, 548 const struct winsys_handle *handle) 549 { 550 struct ilo_texture *tex; 551 bool separate_stencil; 552 553 tex = CALLOC_STRUCT(ilo_texture); 554 if (!tex) 555 return NULL; 556 557 tex->base = *templ; 558 tex->base.screen = screen; 559 pipe_reference_init(&tex->base.reference, 1); 560 561 if (!tex_init_image(tex, handle, &separate_stencil)) { 562 FREE(tex); 563 return NULL; 564 } 565 566 if (!tex_alloc_bos(tex) || 567 (separate_stencil && !tex_create_separate_stencil(tex))) { 568 tex_destroy(tex); 569 return NULL; 570 } 571 572 return &tex->base; 573 } 574 575 static bool 576 tex_get_handle(struct ilo_texture *tex, struct winsys_handle *handle) 577 { 578 struct ilo_screen *is = ilo_screen(tex->base.screen); 579 enum intel_tiling_mode tiling; 580 int err; 581 582 /* must match what tex_create_bo() sets */ 583 if (tex->image.tiling == GEN8_TILING_W) 584 tiling = INTEL_TILING_NONE; 585 else 586 tiling = surface_to_winsys_tiling(tex->image.tiling); 587 588 err = intel_winsys_export_handle(is->dev.winsys, tex->vma.bo, tiling, 589 tex->image.bo_stride, tex->image.bo_height, handle); 590 591 return !err; 592 } 593 594 static bool 595 buf_create_bo(struct ilo_buffer_resource *buf) 596 { 597 struct ilo_screen *is = ilo_screen(buf->base.screen); 598 const char *name = resource_get_bo_name(&buf->base); 599 const bool cpu_init = resource_get_cpu_init(&buf->base); 600 struct intel_bo *bo; 601 602 bo = intel_winsys_alloc_bo(is->dev.winsys, name, buf->bo_size, cpu_init); 603 if (!bo) 604 return false; 605 606 intel_bo_unref(buf->vma.bo); 607 ilo_vma_set_bo(&buf->vma, &is->dev, bo, 0); 608 609 return true; 610 } 611 612 static void 613 buf_destroy(struct ilo_buffer_resource *buf) 614 { 615 intel_bo_unref(buf->vma.bo); 616 FREE(buf); 617 } 618 619 static struct pipe_resource * 620 buf_create(struct pipe_screen *screen, const struct pipe_resource *templ) 621 { 622 const struct ilo_screen *is = ilo_screen(screen); 623 struct ilo_buffer_resource *buf; 624 uint32_t alignment; 625 unsigned size; 626 627 buf = CALLOC_STRUCT(ilo_buffer_resource); 628 if (!buf) 629 return NULL; 630 631 buf->base = *templ; 632 buf->base.screen = screen; 633 pipe_reference_init(&buf->base.reference, 1); 634 635 size = templ->width0; 636 637 /* 638 * As noted in ilo_format_translate(), we treat some 3-component formats as 639 * 4-component formats to work around hardware limitations. Imagine the 640 * case where the vertex buffer holds a single PIPE_FORMAT_R16G16B16_FLOAT 641 * vertex, and buf->bo_size is 6. The hardware would fail to fetch it at 642 * boundary check because the vertex buffer is expected to hold a 643 * PIPE_FORMAT_R16G16B16A16_FLOAT vertex and that takes at least 8 bytes. 644 * 645 * For the workaround to work, we should add 2 to the bo size. But that 646 * would waste a page when the bo size is already page aligned. Let's 647 * round it to page size for now and revisit this when needed. 648 */ 649 if ((templ->bind & PIPE_BIND_VERTEX_BUFFER) && 650 ilo_dev_gen(&is->dev) < ILO_GEN(7.5)) 651 size = align(size, 4096); 652 653 if (templ->bind & PIPE_BIND_VERTEX_BUFFER) 654 size = ilo_state_vertex_buffer_size(&is->dev, size, &alignment); 655 if (templ->bind & PIPE_BIND_INDEX_BUFFER) 656 size = ilo_state_index_buffer_size(&is->dev, size, &alignment); 657 if (templ->bind & PIPE_BIND_STREAM_OUTPUT) 658 size = ilo_state_sol_buffer_size(&is->dev, size, &alignment); 659 660 buf->bo_size = size; 661 ilo_vma_init(&buf->vma, &is->dev, buf->bo_size, 4096); 662 663 if (buf->bo_size < templ->width0 || buf->bo_size > ilo_max_resource_size || 664 !buf_create_bo(buf)) { 665 FREE(buf); 666 return NULL; 667 } 668 669 return &buf->base; 670 } 671 672 static boolean 673 ilo_can_create_resource(struct pipe_screen *screen, 674 const struct pipe_resource *templ) 675 { 676 struct ilo_screen *is = ilo_screen(screen); 677 enum pipe_format image_format; 678 struct ilo_image_info info; 679 struct ilo_image img; 680 681 if (templ->target == PIPE_BUFFER) 682 return (templ->width0 <= ilo_max_resource_size); 683 684 image_format = resource_get_image_format(templ, &is->dev, NULL); 685 resource_get_image_info(templ, &is->dev, image_format, &info); 686 687 memset(&img, 0, sizeof(img)); 688 ilo_image_init(&img, &ilo_screen(screen)->dev, &info); 689 690 /* as in tex_init_image() */ 691 if (ilo_dev_gen(&is->dev) == ILO_GEN(6) && 692 templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && 693 image_format == PIPE_FORMAT_Z32_FLOAT && 694 img.aux.enables != (1 << templ->last_level)) { 695 info.format = pipe_to_surface_format(&is->dev, templ->format); 696 info.interleaved_stencil = true; 697 memset(&img, 0, sizeof(img)); 698 ilo_image_init(&img, &ilo_screen(screen)->dev, &info); 699 } 700 701 return (img.bo_height <= ilo_max_resource_size / img.bo_stride); 702 } 703 704 static struct pipe_resource * 705 ilo_resource_create(struct pipe_screen *screen, 706 const struct pipe_resource *templ) 707 { 708 if (templ->target == PIPE_BUFFER) 709 return buf_create(screen, templ); 710 else 711 return tex_create(screen, templ, NULL); 712 } 713 714 static struct pipe_resource * 715 ilo_resource_from_handle(struct pipe_screen *screen, 716 const struct pipe_resource *templ, 717 struct winsys_handle *handle, 718 unsigned usage) 719 { 720 if (templ->target == PIPE_BUFFER) 721 return NULL; 722 else 723 return tex_create(screen, templ, handle); 724 } 725 726 static boolean 727 ilo_resource_get_handle(struct pipe_screen *screen, 728 struct pipe_context *ctx, 729 struct pipe_resource *res, 730 struct winsys_handle *handle, 731 unsigned usage) 732 { 733 if (res->target == PIPE_BUFFER) 734 return false; 735 else 736 return tex_get_handle(ilo_texture(res), handle); 737 738 } 739 740 static void 741 ilo_resource_destroy(struct pipe_screen *screen, 742 struct pipe_resource *res) 743 { 744 if (res->target == PIPE_BUFFER) 745 buf_destroy((struct ilo_buffer_resource *) res); 746 else 747 tex_destroy(ilo_texture(res)); 748 } 749 750 /** 751 * Initialize resource-related functions. 752 */ 753 void 754 ilo_init_resource_functions(struct ilo_screen *is) 755 { 756 is->base.can_create_resource = ilo_can_create_resource; 757 is->base.resource_create = ilo_resource_create; 758 is->base.resource_from_handle = ilo_resource_from_handle; 759 is->base.resource_get_handle = ilo_resource_get_handle; 760 is->base.resource_destroy = ilo_resource_destroy; 761 } 762 763 bool 764 ilo_resource_rename_bo(struct pipe_resource *res) 765 { 766 if (res->target == PIPE_BUFFER) { 767 return buf_create_bo((struct ilo_buffer_resource *) res); 768 } else { 769 struct ilo_texture *tex = ilo_texture(res); 770 771 /* an imported texture cannot be renamed */ 772 if (tex->imported) 773 return false; 774 775 return tex_create_bo(tex); 776 } 777 } 778