1 2#include "main/macros.h" 3#include "main/mtypes.h" 4#include "main/enums.h" 5#include "main/bufferobj.h" 6#include "main/context.h" 7#include "main/formats.h" 8#include "main/glformats.h" 9#include "main/image.h" 10#include "main/pbo.h" 11#include "main/renderbuffer.h" 12#include "main/texcompress.h" 13#include "main/texgetimage.h" 14#include "main/texobj.h" 15#include "main/teximage.h" 16#include "main/texstore.h" 17 18#include "drivers/common/meta.h" 19 20#include "intel_mipmap_tree.h" 21#include "intel_buffer_objects.h" 22#include "intel_batchbuffer.h" 23#include "intel_tex.h" 24#include "intel_blit.h" 25#include "intel_fbo.h" 26#include "intel_image.h" 27#include "intel_tiled_memcpy.h" 28#include "brw_context.h" 29 30#define FILE_DEBUG_FLAG DEBUG_TEXTURE 31 32/* Make sure one doesn't end up shrinking base level zero unnecessarily. 33 * Determining the base level dimension by shifting higher level dimension 34 * ends up in off-by-one value in case base level has NPOT size (for example, 35 * 293 != 146 << 1). 36 * Choose the original base level dimension when shifted dimensions agree. 37 * Otherwise assume real resize is intended and use the new shifted value. 38 */ 39static unsigned 40get_base_dim(unsigned old_base_dim, unsigned new_level_dim, unsigned level) 41{ 42 const unsigned old_level_dim = old_base_dim >> level; 43 const unsigned new_base_dim = new_level_dim << level; 44 45 return old_level_dim == new_level_dim ? old_base_dim : new_base_dim; 46} 47 48/* Work back from the specified level of the image to the baselevel and create a 49 * miptree of that size. 50 */ 51struct intel_mipmap_tree * 52intel_miptree_create_for_teximage(struct brw_context *brw, 53 struct intel_texture_object *intelObj, 54 struct intel_texture_image *intelImage, 55 uint32_t layout_flags) 56{ 57 GLuint lastLevel; 58 int width, height, depth; 59 const struct intel_mipmap_tree *old_mt = intelObj->mt; 60 const unsigned level = intelImage->base.Base.Level; 61 62 intel_get_image_dims(&intelImage->base.Base, &width, &height, &depth); 63 64 DBG("%s\n", __func__); 65 66 /* Figure out image dimensions at start level. */ 67 switch(intelObj->base.Target) { 68 case GL_TEXTURE_2D_MULTISAMPLE: 69 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 70 case GL_TEXTURE_RECTANGLE: 71 case GL_TEXTURE_EXTERNAL_OES: 72 assert(level == 0); 73 break; 74 case GL_TEXTURE_3D: 75 depth = old_mt ? get_base_dim(old_mt->logical_depth0, depth, level) : 76 depth << level; 77 /* Fall through */ 78 case GL_TEXTURE_2D: 79 case GL_TEXTURE_2D_ARRAY: 80 case GL_TEXTURE_CUBE_MAP: 81 case GL_TEXTURE_CUBE_MAP_ARRAY: 82 height = old_mt ? get_base_dim(old_mt->logical_height0, height, level) : 83 height << level; 84 /* Fall through */ 85 case GL_TEXTURE_1D: 86 case GL_TEXTURE_1D_ARRAY: 87 width = old_mt ? get_base_dim(old_mt->logical_width0, width, level) : 88 width << level; 89 break; 90 default: 91 unreachable("Unexpected target"); 92 } 93 94 /* Guess a reasonable value for lastLevel. This is probably going 95 * to be wrong fairly often and might mean that we have to look at 96 * resizable buffers, or require that buffers implement lazy 97 * pagetable arrangements. 98 */ 99 if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || 100 intelObj->base.Sampler.MinFilter == GL_LINEAR) && 101 intelImage->base.Base.Level == 0 && 102 !intelObj->base.GenerateMipmap) { 103 lastLevel = 0; 104 } else { 105 lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target, 106 width, height, depth) - 1; 107 } 108 109 return intel_miptree_create(brw, 110 intelObj->base.Target, 111 intelImage->base.Base.TexFormat, 112 0, 113 lastLevel, 114 width, 115 height, 116 depth, 117 intelImage->base.Base.NumSamples, 118 layout_flags | MIPTREE_LAYOUT_TILING_ANY); 119} 120 121static void 122intelTexImage(struct gl_context * ctx, 123 GLuint dims, 124 struct gl_texture_image *texImage, 125 GLenum format, GLenum type, const void *pixels, 126 const struct gl_pixelstore_attrib *unpack) 127{ 128 struct intel_texture_image *intelImage = intel_texture_image(texImage); 129 bool ok; 130 131 bool tex_busy = intelImage->mt && drm_intel_bo_busy(intelImage->mt->bo); 132 133 DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n", 134 __func__, _mesa_get_format_name(texImage->TexFormat), 135 _mesa_enum_to_string(texImage->TexObject->Target), 136 _mesa_enum_to_string(format), _mesa_enum_to_string(type), 137 texImage->Level, texImage->Width, texImage->Height, texImage->Depth); 138 139 /* Allocate storage for texture data. */ 140 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { 141 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 142 return; 143 } 144 145 assert(intelImage->mt); 146 147 if (intelImage->mt->format == MESA_FORMAT_S_UINT8) 148 intelImage->mt->r8stencil_needs_update = true; 149 150 ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0, 151 texImage->Width, texImage->Height, 152 texImage->Depth, 153 format, type, pixels, 154 tex_busy, unpack); 155 if (ok) 156 return; 157 158 ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage, 159 0, 0, 0, /*x,y,z offsets*/ 160 texImage->Width, 161 texImage->Height, 162 texImage->Depth, 163 format, type, pixels, unpack, 164 false /*allocate_storage*/); 165 if (ok) 166 return; 167 168 DBG("%s: upload image %dx%dx%d pixels %p\n", 169 __func__, texImage->Width, texImage->Height, texImage->Depth, 170 pixels); 171 172 _mesa_store_teximage(ctx, dims, texImage, 173 format, type, pixels, unpack); 174} 175 176 177static void 178intel_set_texture_image_mt(struct brw_context *brw, 179 struct gl_texture_image *image, 180 GLenum internal_format, 181 struct intel_mipmap_tree *mt) 182 183{ 184 struct gl_texture_object *texobj = image->TexObject; 185 struct intel_texture_object *intel_texobj = intel_texture_object(texobj); 186 struct intel_texture_image *intel_image = intel_texture_image(image); 187 188 _mesa_init_teximage_fields(&brw->ctx, image, 189 mt->logical_width0, mt->logical_height0, 1, 190 0, internal_format, mt->format); 191 192 brw->ctx.Driver.FreeTextureImageBuffer(&brw->ctx, image); 193 194 intel_texobj->needs_validate = true; 195 intel_image->base.RowStride = mt->pitch / mt->cpp; 196 assert(mt->pitch % mt->cpp == 0); 197 198 intel_miptree_reference(&intel_image->mt, mt); 199 200 /* Immediately validate the image to the object. */ 201 intel_miptree_reference(&intel_texobj->mt, mt); 202} 203 204static struct intel_mipmap_tree * 205create_mt_for_planar_dri_image(struct brw_context *brw, 206 GLenum target, __DRIimage *image) 207{ 208 struct intel_image_format *f = image->planar_format; 209 struct intel_mipmap_tree *planar_mt; 210 211 for (int i = 0; i < f->nplanes; i++) { 212 const int index = f->planes[i].buffer_index; 213 const uint32_t dri_format = f->planes[i].dri_format; 214 const mesa_format format = driImageFormatToGLFormat(dri_format); 215 const uint32_t width = image->width >> f->planes[i].width_shift; 216 const uint32_t height = image->height >> f->planes[i].height_shift; 217 218 /* Disable creation of the texture's aux buffers because the driver 219 * exposes no EGL API to manage them. That is, there is no API for 220 * resolving the aux buffer's content to the main buffer nor for 221 * invalidating the aux buffer's content. 222 */ 223 struct intel_mipmap_tree *mt = 224 intel_miptree_create_for_bo(brw, image->bo, format, 225 image->offsets[index], 226 width, height, 1, 227 image->strides[index], 228 MIPTREE_LAYOUT_DISABLE_AUX); 229 if (mt == NULL) 230 return NULL; 231 232 mt->target = target; 233 mt->total_width = width; 234 mt->total_height = height; 235 236 if (i == 0) 237 planar_mt = mt; 238 else 239 planar_mt->plane[i - 1] = mt; 240 } 241 242 return planar_mt; 243} 244 245/** 246 * Binds a BO to a texture image, as if it was uploaded by glTexImage2D(). 247 * 248 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, 249 */ 250static struct intel_mipmap_tree * 251create_mt_for_dri_image(struct brw_context *brw, 252 GLenum target, __DRIimage *image) 253{ 254 struct intel_mipmap_tree *mt; 255 uint32_t draw_x, draw_y; 256 257 /* Disable creation of the texture's aux buffers because the driver exposes 258 * no EGL API to manage them. That is, there is no API for resolving the aux 259 * buffer's content to the main buffer nor for invalidating the aux buffer's 260 * content. 261 */ 262 mt = intel_miptree_create_for_bo(brw, image->bo, image->format, 263 0, image->width, image->height, 1, 264 image->pitch, 265 MIPTREE_LAYOUT_DISABLE_AUX); 266 if (mt == NULL) 267 return NULL; 268 269 mt->target = target; 270 mt->total_width = image->width; 271 mt->total_height = image->height; 272 mt->level[0].slice[0].x_offset = image->tile_x; 273 mt->level[0].slice[0].y_offset = image->tile_y; 274 275 intel_miptree_get_tile_offsets(mt, 0, 0, &draw_x, &draw_y); 276 277 /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION 278 * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has 279 * trouble resolving back to destination image due to alignment issues. 280 */ 281 if (!brw->has_surface_tile_offset && 282 (draw_x != 0 || draw_y != 0)) { 283 _mesa_error(&brw->ctx, GL_INVALID_OPERATION, __func__); 284 intel_miptree_release(&mt); 285 return NULL; 286 } 287 288 mt->offset = image->offset; 289 290 return mt; 291} 292 293void 294intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 295 GLint texture_format, 296 __DRIdrawable *dPriv) 297{ 298 struct gl_framebuffer *fb = dPriv->driverPrivate; 299 struct brw_context *brw = pDRICtx->driverPrivate; 300 struct gl_context *ctx = &brw->ctx; 301 struct intel_renderbuffer *rb; 302 struct gl_texture_object *texObj; 303 struct gl_texture_image *texImage; 304 mesa_format texFormat = MESA_FORMAT_NONE; 305 struct intel_mipmap_tree *mt; 306 GLenum internal_format = 0; 307 308 texObj = _mesa_get_current_tex_object(ctx, target); 309 310 if (!texObj) 311 return; 312 313 if (dPriv->lastStamp != dPriv->dri2.stamp || 314 !pDRICtx->driScreenPriv->dri2.useInvalidate) 315 intel_update_renderbuffers(pDRICtx, dPriv); 316 317 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); 318 /* If the miptree isn't set, then intel_update_renderbuffers was unable 319 * to get the BO for the drawable from the window system. 320 */ 321 if (!rb || !rb->mt) 322 return; 323 324 if (rb->mt->cpp == 4) { 325 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { 326 internal_format = GL_RGB; 327 texFormat = MESA_FORMAT_B8G8R8X8_UNORM; 328 } 329 else { 330 internal_format = GL_RGBA; 331 texFormat = MESA_FORMAT_B8G8R8A8_UNORM; 332 } 333 } else if (rb->mt->cpp == 2) { 334 internal_format = GL_RGB; 335 texFormat = MESA_FORMAT_B5G6R5_UNORM; 336 } 337 338 intel_miptree_make_shareable(brw, rb->mt); 339 mt = intel_miptree_create_for_bo(brw, rb->mt->bo, texFormat, 0, 340 rb->Base.Base.Width, 341 rb->Base.Base.Height, 342 1, rb->mt->pitch, 0); 343 if (mt == NULL) 344 return; 345 mt->target = target; 346 mt->total_width = rb->Base.Base.Width; 347 mt->total_height = rb->Base.Base.Height; 348 349 _mesa_lock_texture(&brw->ctx, texObj); 350 texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 351 intel_set_texture_image_mt(brw, texImage, internal_format, mt); 352 intel_miptree_release(&mt); 353 _mesa_unlock_texture(&brw->ctx, texObj); 354} 355 356static GLboolean 357intel_bind_renderbuffer_tex_image(struct gl_context *ctx, 358 struct gl_renderbuffer *rb, 359 struct gl_texture_image *image) 360{ 361 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 362 struct intel_texture_image *intel_image = intel_texture_image(image); 363 struct gl_texture_object *texobj = image->TexObject; 364 struct intel_texture_object *intel_texobj = intel_texture_object(texobj); 365 366 /* We can only handle RB allocated with AllocRenderbufferStorage, or 367 * window-system renderbuffers. 368 */ 369 assert(!rb->TexImage); 370 371 if (!irb->mt) 372 return false; 373 374 _mesa_lock_texture(ctx, texobj); 375 _mesa_init_teximage_fields(ctx, image, 376 rb->Width, rb->Height, 1, 377 0, rb->InternalFormat, rb->Format); 378 image->NumSamples = rb->NumSamples; 379 380 intel_miptree_reference(&intel_image->mt, irb->mt); 381 382 /* Immediately validate the image to the object. */ 383 intel_miptree_reference(&intel_texobj->mt, intel_image->mt); 384 385 intel_texobj->needs_validate = true; 386 _mesa_unlock_texture(ctx, texobj); 387 388 return true; 389} 390 391void 392intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) 393{ 394 /* The old interface didn't have the format argument, so copy our 395 * implementation's behavior at the time. 396 */ 397 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 398} 399 400static void 401intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, 402 struct gl_texture_object *texObj, 403 struct gl_texture_image *texImage, 404 GLeglImageOES image_handle) 405{ 406 struct brw_context *brw = brw_context(ctx); 407 struct intel_mipmap_tree *mt; 408 __DRIscreen *dri_screen = brw->screen->driScrnPriv; 409 __DRIimage *image; 410 411 image = dri_screen->dri2.image->lookupEGLImage(dri_screen, image_handle, 412 dri_screen->loaderPrivate); 413 if (image == NULL) 414 return; 415 416 /* We support external textures only for EGLImages created with 417 * EGL_EXT_image_dma_buf_import. We may lift that restriction in the future. 418 */ 419 if (target == GL_TEXTURE_EXTERNAL_OES && !image->dma_buf_imported) { 420 _mesa_error(ctx, GL_INVALID_OPERATION, 421 "glEGLImageTargetTexture2DOES(external target is enabled only " 422 "for images created with EGL_EXT_image_dma_buf_import"); 423 return; 424 } 425 426 /* Disallow depth/stencil textures: we don't have a way to pass the 427 * separate stencil miptree of a GL_DEPTH_STENCIL texture through. 428 */ 429 if (image->has_depthstencil) { 430 _mesa_error(ctx, GL_INVALID_OPERATION, __func__); 431 return; 432 } 433 434 if (image->planar_format && image->planar_format->nplanes > 0) 435 mt = create_mt_for_planar_dri_image(brw, target, image); 436 else 437 mt = create_mt_for_dri_image(brw, target, image); 438 if (mt == NULL) 439 return; 440 441 struct intel_texture_object *intel_texobj = intel_texture_object(texObj); 442 intel_texobj->planar_format = image->planar_format; 443 444 const GLenum internal_format = 445 image->internal_format != 0 ? 446 image->internal_format : _mesa_get_format_base_format(mt->format); 447 intel_set_texture_image_mt(brw, texImage, internal_format, mt); 448 intel_miptree_release(&mt); 449} 450 451/** 452 * \brief A fast path for glGetTexImage. 453 * 454 * \see intel_readpixels_tiled_memcpy() 455 */ 456bool 457intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx, 458 struct gl_texture_image *texImage, 459 GLint xoffset, GLint yoffset, 460 GLsizei width, GLsizei height, 461 GLenum format, GLenum type, 462 GLvoid *pixels, 463 const struct gl_pixelstore_attrib *packing) 464{ 465 struct brw_context *brw = brw_context(ctx); 466 struct intel_texture_image *image = intel_texture_image(texImage); 467 int dst_pitch; 468 469 /* The miptree's buffer. */ 470 drm_intel_bo *bo; 471 472 int error = 0; 473 474 uint32_t cpp; 475 mem_copy_fn mem_copy = NULL; 476 477 /* This fastpath is restricted to specific texture types: 478 * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support 479 * more types. 480 * 481 * FINISHME: The restrictions below on packing alignment and packing row 482 * length are likely unneeded now because we calculate the destination stride 483 * with _mesa_image_row_stride. However, before removing the restrictions 484 * we need tests. 485 */ 486 if (!brw->has_llc || 487 !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) || 488 !(texImage->TexObject->Target == GL_TEXTURE_2D || 489 texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) || 490 pixels == NULL || 491 _mesa_is_bufferobj(packing->BufferObj) || 492 packing->Alignment > 4 || 493 packing->SkipPixels > 0 || 494 packing->SkipRows > 0 || 495 (packing->RowLength != 0 && packing->RowLength != width) || 496 packing->SwapBytes || 497 packing->LsbFirst || 498 packing->Invert) 499 return false; 500 501 /* We can't handle copying from RGBX or BGRX because the tiled_memcpy 502 * function doesn't set the last channel to 1. Note this checks BaseFormat 503 * rather than TexFormat in case the RGBX format is being simulated with an 504 * RGBA format. 505 */ 506 if (texImage->_BaseFormat == GL_RGB) 507 return false; 508 509 if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp)) 510 return false; 511 512 /* If this is a nontrivial texture view, let another path handle it instead. */ 513 if (texImage->TexObject->MinLayer) 514 return false; 515 516 if (!image->mt || 517 (image->mt->tiling != I915_TILING_X && 518 image->mt->tiling != I915_TILING_Y)) { 519 /* The algorithm is written only for X- or Y-tiled memory. */ 520 return false; 521 } 522 523 /* Since we are going to write raw data to the miptree, we need to resolve 524 * any pending fast color clears before we start. 525 */ 526 intel_miptree_all_slices_resolve_color(brw, image->mt, 0); 527 528 bo = image->mt->bo; 529 530 if (drm_intel_bo_references(brw->batch.bo, bo)) { 531 perf_debug("Flushing before mapping a referenced bo.\n"); 532 intel_batchbuffer_flush(brw); 533 } 534 535 error = brw_bo_map(brw, bo, false /* write enable */, "miptree"); 536 if (error) { 537 DBG("%s: failed to map bo\n", __func__); 538 return false; 539 } 540 541 dst_pitch = _mesa_image_row_stride(packing, width, format, type); 542 543 DBG("%s: level=%d x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x " 544 "mesa_format=0x%x tiling=%d " 545 "packing=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n", 546 __func__, texImage->Level, xoffset, yoffset, width, height, 547 format, type, texImage->TexFormat, image->mt->tiling, 548 packing->Alignment, packing->RowLength, packing->SkipPixels, 549 packing->SkipRows); 550 551 int level = texImage->Level + texImage->TexObject->MinLevel; 552 553 /* Adjust x and y offset based on miplevel */ 554 xoffset += image->mt->level[level].level_x; 555 yoffset += image->mt->level[level].level_y; 556 557 tiled_to_linear( 558 xoffset * cpp, (xoffset + width) * cpp, 559 yoffset, yoffset + height, 560 pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp, 561 bo->virtual, 562 dst_pitch, image->mt->pitch, 563 brw->has_swizzling, 564 image->mt->tiling, 565 mem_copy 566 ); 567 568 drm_intel_bo_unmap(bo); 569 return true; 570} 571 572static void 573intel_get_tex_sub_image(struct gl_context *ctx, 574 GLint xoffset, GLint yoffset, GLint zoffset, 575 GLsizei width, GLsizei height, GLint depth, 576 GLenum format, GLenum type, GLvoid *pixels, 577 struct gl_texture_image *texImage) 578{ 579 struct brw_context *brw = brw_context(ctx); 580 bool ok; 581 582 DBG("%s\n", __func__); 583 584 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 585 if (_mesa_meta_pbo_GetTexSubImage(ctx, 3, texImage, 586 xoffset, yoffset, zoffset, 587 width, height, depth, format, type, 588 pixels, &ctx->Pack)) { 589 /* Flush to guarantee coherency between the render cache and other 590 * caches the PBO could potentially be bound to after this point. 591 * See the related comment in intelReadPixels() for a more detailed 592 * explanation. 593 */ 594 brw_emit_mi_flush(brw); 595 return; 596 } 597 598 perf_debug("%s: fallback to CPU mapping in PBO case\n", __func__); 599 } 600 601 ok = intel_gettexsubimage_tiled_memcpy(ctx, texImage, xoffset, yoffset, 602 width, height, 603 format, type, pixels, &ctx->Pack); 604 605 if(ok) 606 return; 607 608 _mesa_meta_GetTexSubImage(ctx, xoffset, yoffset, zoffset, 609 width, height, depth, 610 format, type, pixels, texImage); 611 612 DBG("%s - DONE\n", __func__); 613} 614 615static void 616flush_astc_denorms(struct gl_context *ctx, GLuint dims, 617 struct gl_texture_image *texImage, 618 GLint xoffset, GLint yoffset, GLint zoffset, 619 GLsizei width, GLsizei height, GLsizei depth) 620{ 621 struct compressed_pixelstore store; 622 _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, 623 width, height, depth, 624 &ctx->Unpack, &store); 625 626 for (int slice = 0; slice < store.CopySlices; slice++) { 627 628 /* Map dest texture buffer */ 629 GLubyte *dstMap; 630 GLint dstRowStride; 631 ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, 632 xoffset, yoffset, width, height, 633 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, 634 &dstMap, &dstRowStride); 635 if (!dstMap) 636 continue; 637 638 for (int i = 0; i < store.CopyRowsPerSlice; i++) { 639 640 /* An ASTC block is stored in little endian mode. The byte that 641 * contains bits 0..7 is stored at the lower address in memory. 642 */ 643 struct astc_void_extent { 644 uint16_t header : 12; 645 uint16_t dontcare[3]; 646 uint16_t R; 647 uint16_t G; 648 uint16_t B; 649 uint16_t A; 650 } *blocks = (struct astc_void_extent*) dstMap; 651 652 /* Iterate over every copied block in the row */ 653 for (int j = 0; j < store.CopyBytesPerRow / 16; j++) { 654 655 /* Check if the header matches that of an LDR void-extent block */ 656 if (blocks[j].header == 0xDFC) { 657 658 /* Flush UNORM16 values that would be denormalized */ 659 if (blocks[j].A < 4) blocks[j].A = 0; 660 if (blocks[j].B < 4) blocks[j].B = 0; 661 if (blocks[j].G < 4) blocks[j].G = 0; 662 if (blocks[j].R < 4) blocks[j].R = 0; 663 } 664 } 665 666 dstMap += dstRowStride; 667 } 668 669 ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); 670 } 671} 672 673 674static void 675intelCompressedTexSubImage(struct gl_context *ctx, GLuint dims, 676 struct gl_texture_image *texImage, 677 GLint xoffset, GLint yoffset, GLint zoffset, 678 GLsizei width, GLsizei height, GLsizei depth, 679 GLenum format, 680 GLsizei imageSize, const GLvoid *data) 681{ 682 /* Upload the compressed data blocks */ 683 _mesa_store_compressed_texsubimage(ctx, dims, texImage, 684 xoffset, yoffset, zoffset, 685 width, height, depth, 686 format, imageSize, data); 687 688 /* Fix up copied ASTC blocks if necessary */ 689 GLenum gl_format = _mesa_compressed_format_to_glenum(ctx, 690 texImage->TexFormat); 691 bool is_linear_astc = _mesa_is_astc_format(gl_format) && 692 !_mesa_is_srgb_format(gl_format); 693 struct brw_context *brw = (struct brw_context*) ctx; 694 if (brw->gen == 9 && is_linear_astc) 695 flush_astc_denorms(ctx, dims, texImage, 696 xoffset, yoffset, zoffset, 697 width, height, depth); 698} 699 700void 701intelInitTextureImageFuncs(struct dd_function_table *functions) 702{ 703 functions->TexImage = intelTexImage; 704 functions->CompressedTexSubImage = intelCompressedTexSubImage; 705 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; 706 functions->BindRenderbufferTexImage = intel_bind_renderbuffer_tex_image; 707 functions->GetTexSubImage = intel_get_tex_sub_image; 708} 709