intel_tex_image.c revision 019c9ee2204723a9a041316e055e0602e514cad4
1 2#include "main/glheader.h" 3#include "main/macros.h" 4#include "main/mfeatures.h" 5#include "main/mtypes.h" 6#include "main/enums.h" 7#include "main/bufferobj.h" 8#include "main/context.h" 9#include "main/formats.h" 10#include "main/pbo.h" 11#include "main/renderbuffer.h" 12#include "main/texcompress.h" 13#include "main/texstore.h" 14#include "main/texgetimage.h" 15#include "main/texobj.h" 16#include "main/teximage.h" 17 18#include "intel_context.h" 19#include "intel_mipmap_tree.h" 20#include "intel_buffer_objects.h" 21#include "intel_batchbuffer.h" 22#include "intel_tex.h" 23#include "intel_blit.h" 24#include "intel_fbo.h" 25#include "intel_span.h" 26 27#define FILE_DEBUG_FLAG DEBUG_TEXTURE 28 29/* Functions to store texture images. Where possible, mipmap_tree's 30 * will be created or further instantiated with image data, otherwise 31 * images will be stored in malloc'd memory. A validation step is 32 * required to pull those images into a mipmap tree, or otherwise 33 * decide a fallback is required. 34 */ 35 36 37 38/* Otherwise, store it in memory if (Border != 0) or (any dimension == 39 * 1). 40 * 41 * Otherwise, if max_level >= level >= min_level, create tree with 42 * space for textures from min_level down to max_level. 43 * 44 * Otherwise, create tree with space for textures from (level 45 * 0)..(1x1). Consider pruning this tree at a validation if the 46 * saving is worth it. 47 */ 48static struct intel_mipmap_tree * 49intel_miptree_create_for_teximage(struct intel_context *intel, 50 struct intel_texture_object *intelObj, 51 struct intel_texture_image *intelImage, 52 GLboolean expect_accelerated_upload) 53{ 54 GLuint firstLevel; 55 GLuint lastLevel; 56 GLuint width = intelImage->base.Base.Width; 57 GLuint height = intelImage->base.Base.Height; 58 GLuint depth = intelImage->base.Base.Depth; 59 GLuint i; 60 61 DBG("%s\n", __FUNCTION__); 62 63 if (intelImage->base.Base.Border) 64 return NULL; 65 66 if (intelImage->base.Base.Level > intelObj->base.BaseLevel && 67 (intelImage->base.Base.Width == 1 || 68 (intelObj->base.Target != GL_TEXTURE_1D && 69 intelImage->base.Base.Height == 1) || 70 (intelObj->base.Target == GL_TEXTURE_3D && 71 intelImage->base.Base.Depth == 1))) { 72 /* For this combination, we're at some lower mipmap level and 73 * some important dimension is 1. We can't extrapolate up to a 74 * likely base level width/height/depth for a full mipmap stack 75 * from this info, so just allocate this one level. 76 */ 77 firstLevel = intelImage->base.Base.Level; 78 lastLevel = intelImage->base.Base.Level; 79 } else { 80 /* If this image disrespects BaseLevel, allocate from level zero. 81 * Usually BaseLevel == 0, so it's unlikely to happen. 82 */ 83 if (intelImage->base.Base.Level < intelObj->base.BaseLevel) 84 firstLevel = 0; 85 else 86 firstLevel = intelObj->base.BaseLevel; 87 88 /* Figure out image dimensions at start level. */ 89 for (i = intelImage->base.Base.Level; i > firstLevel; i--) { 90 width <<= 1; 91 if (height != 1) 92 height <<= 1; 93 if (depth != 1) 94 depth <<= 1; 95 } 96 97 /* Guess a reasonable value for lastLevel. This is probably going 98 * to be wrong fairly often and might mean that we have to look at 99 * resizable buffers, or require that buffers implement lazy 100 * pagetable arrangements. 101 */ 102 if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || 103 intelObj->base.Sampler.MinFilter == GL_LINEAR) && 104 intelImage->base.Base.Level == firstLevel && 105 (intel->gen < 4 || firstLevel == 0)) { 106 lastLevel = firstLevel; 107 } else { 108 lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); 109 } 110 } 111 112 return intel_miptree_create(intel, 113 intelObj->base.Target, 114 intelImage->base.Base.TexFormat, 115 firstLevel, 116 lastLevel, 117 width, 118 height, 119 depth, 120 expect_accelerated_upload); 121} 122 123/* There are actually quite a few combinations this will work for, 124 * more than what I've listed here. 125 */ 126static bool 127check_pbo_format(GLenum format, GLenum type, 128 gl_format mesa_format) 129{ 130 switch (mesa_format) { 131 case MESA_FORMAT_ARGB8888: 132 return (format == GL_BGRA && (type == GL_UNSIGNED_BYTE || 133 type == GL_UNSIGNED_INT_8_8_8_8_REV)); 134 case MESA_FORMAT_RGB565: 135 return (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5); 136 case MESA_FORMAT_L8: 137 return (format == GL_LUMINANCE && type == GL_UNSIGNED_BYTE); 138 case MESA_FORMAT_YCBCR: 139 return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE); 140 default: 141 return false; 142 } 143} 144 145 146/* XXX: Do this for TexSubImage also: 147 */ 148static bool 149try_pbo_upload(struct intel_context *intel, 150 struct intel_texture_image *intelImage, 151 const struct gl_pixelstore_attrib *unpack, 152 GLenum format, GLenum type, 153 GLint width, GLint height, const void *pixels) 154{ 155 struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); 156 GLuint src_offset, src_stride; 157 GLuint dst_x, dst_y, dst_stride; 158 drm_intel_bo *dst_buffer, *src_buffer; 159 160 if (!_mesa_is_bufferobj(unpack->BufferObj)) 161 return false; 162 163 DBG("trying pbo upload\n"); 164 165 if (!intelImage->mt) { 166 DBG("%s: no miptree\n", __FUNCTION__); 167 return false; 168 } 169 170 if (intel->ctx._ImageTransferState || 171 unpack->SkipPixels || unpack->SkipRows) { 172 DBG("%s: image transfer\n", __FUNCTION__); 173 return false; 174 } 175 176 if (!check_pbo_format(format, type, intelImage->base.Base.TexFormat)) { 177 DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", 178 __FUNCTION__, _mesa_get_format_name(intelImage->base.Base.TexFormat), 179 format, type); 180 return false; 181 } 182 183 dst_buffer = intelImage->mt->region->bo; 184 src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset); 185 /* note: potential 64-bit ptr to 32-bit int cast */ 186 src_offset += (GLuint) (unsigned long) pixels; 187 188 if (unpack->RowLength > 0) 189 src_stride = unpack->RowLength; 190 else 191 src_stride = width; 192 193 intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level, 194 intelImage->base.Base.Face, 0, 195 &dst_x, &dst_y); 196 197 dst_stride = intelImage->mt->region->pitch; 198 199 if (!intelEmitCopyBlit(intel, 200 intelImage->mt->cpp, 201 src_stride, src_buffer, 202 src_offset, GL_FALSE, 203 dst_stride, dst_buffer, 0, 204 intelImage->mt->region->tiling, 205 0, 0, dst_x, dst_y, width, height, 206 GL_COPY)) { 207 DBG("%s: blit failed\n", __FUNCTION__); 208 return false; 209 } 210 211 DBG("%s: success\n", __FUNCTION__); 212 return true; 213} 214 215/** 216 * \param scatter Scatter if true. Gather if false. 217 * 218 * \see intel_tex_image_x8z24_scatter 219 * \see intel_tex_image_x8z24_gather 220 */ 221static void 222intel_tex_image_s8z24_scattergather(struct intel_context *intel, 223 struct intel_texture_image *intel_image, 224 bool scatter) 225{ 226 struct gl_context *ctx = &intel->ctx; 227 struct gl_renderbuffer *depth_rb = intel_image->depth_rb; 228 struct gl_renderbuffer *stencil_rb = intel_image->stencil_rb; 229 230 int w = intel_image->base.Base.Width; 231 int h = intel_image->base.Base.Height; 232 233 uint32_t depth_row[w]; 234 uint8_t stencil_row[w]; 235 236 intel_renderbuffer_map(intel, depth_rb); 237 intel_renderbuffer_map(intel, stencil_rb); 238 239 if (scatter) { 240 for (int y = 0; y < h; ++y) { 241 depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); 242 for (int x = 0; x < w; ++x) { 243 stencil_row[x] = depth_row[x] >> 24; 244 } 245 stencil_rb->PutRow(ctx, stencil_rb, w, 0, y, stencil_row, NULL); 246 } 247 } else { /* gather */ 248 for (int y = 0; y < h; ++y) { 249 depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); 250 stencil_rb->GetRow(ctx, stencil_rb, w, 0, y, stencil_row); 251 for (int x = 0; x < w; ++x) { 252 uint32_t s8_x24 = stencil_row[x] << 24; 253 uint32_t x8_z24 = depth_row[x] & 0x00ffffff; 254 depth_row[x] = s8_x24 | x8_z24; 255 } 256 depth_rb->PutRow(ctx, depth_rb, w, 0, y, depth_row, NULL); 257 } 258 } 259 260 intel_renderbuffer_unmap(intel, depth_rb); 261 intel_renderbuffer_unmap(intel, stencil_rb); 262} 263 264/** 265 * Copy the x8 bits from intel_image->depth_rb to intel_image->stencil_rb. 266 */ 267void 268intel_tex_image_s8z24_scatter(struct intel_context *intel, 269 struct intel_texture_image *intel_image) 270{ 271 intel_tex_image_s8z24_scattergather(intel, intel_image, true); 272} 273 274/** 275 * Copy the data in intel_image->stencil_rb to the x8 bits in 276 * intel_image->depth_rb. 277 */ 278void 279intel_tex_image_s8z24_gather(struct intel_context *intel, 280 struct intel_texture_image *intel_image) 281{ 282 intel_tex_image_s8z24_scattergather(intel, intel_image, false); 283} 284 285static bool 286intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, 287 struct intel_texture_image *image) 288{ 289 struct gl_context *ctx = &intel->ctx; 290 291 bool ok = true; 292 int width = image->base.Base.Width; 293 int height = image->base.Base.Height; 294 struct gl_renderbuffer *drb; 295 struct gl_renderbuffer *srb; 296 struct intel_renderbuffer *idrb; 297 struct intel_renderbuffer *isrb; 298 299 assert(intel->has_separate_stencil); 300 assert(image->base.Base.TexFormat == MESA_FORMAT_S8_Z24); 301 assert(image->mt != NULL); 302 303 drb = intel_create_wrapped_renderbuffer(ctx, width, height, 304 MESA_FORMAT_X8_Z24); 305 srb = intel_create_wrapped_renderbuffer(ctx, width, height, 306 MESA_FORMAT_S8); 307 308 if (!drb || !srb) { 309 if (drb) { 310 drb->Delete(drb); 311 } 312 if (srb) { 313 srb->Delete(srb); 314 } 315 return false; 316 } 317 318 idrb = intel_renderbuffer(drb); 319 isrb = intel_renderbuffer(srb); 320 321 intel_region_reference(&idrb->region, image->mt->region); 322 ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8, 323 width, height); 324 325 if (!ok) { 326 drb->Delete(drb); 327 srb->Delete(srb); 328 return false; 329 } 330 331 intel_renderbuffer_set_draw_offset(idrb, image, 0); 332 intel_renderbuffer_set_draw_offset(isrb, image, 0); 333 334 _mesa_reference_renderbuffer(&image->depth_rb, drb); 335 _mesa_reference_renderbuffer(&image->stencil_rb, srb); 336 337 return true; 338} 339 340static void 341intelTexImage(struct gl_context * ctx, 342 GLint dims, 343 GLenum target, GLint level, 344 GLint internalFormat, 345 GLint width, GLint height, GLint depth, 346 GLint border, 347 GLenum format, GLenum type, const void *pixels, 348 const struct gl_pixelstore_attrib *unpack, 349 struct gl_texture_object *texObj, 350 struct gl_texture_image *texImage, GLsizei imageSize) 351{ 352 struct intel_context *intel = intel_context(ctx); 353 struct intel_texture_object *intelObj = intel_texture_object(texObj); 354 struct intel_texture_image *intelImage = intel_texture_image(texImage); 355 GLint texelBytes; 356 GLuint dstRowStride = 0; 357 358 DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, 359 _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); 360 361 if (_mesa_is_format_compressed(texImage->TexFormat)) { 362 texelBytes = 0; 363 } 364 else { 365 texelBytes = _mesa_get_format_bytes(texImage->TexFormat); 366 367 if (!intelImage->mt) { 368 assert(texImage->RowStride == width); 369 } 370 } 371 372 if (intelObj->mt && 373 intel_miptree_match_image(intelObj->mt, &intelImage->base.Base)) { 374 /* Use an existing miptree when possible */ 375 intel_miptree_reference(&intelImage->mt, intelObj->mt); 376 assert(intelImage->mt); 377 } else if (intelImage->base.Base.Border == 0) { 378 /* Didn't fit in the object miptree, but it's suitable for inclusion in 379 * a miptree, so create one just for our level and store it in the image. 380 * It'll get moved into the object miptree at validate time. 381 */ 382 intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj, 383 intelImage, 384 pixels == NULL); 385 386 /* Even if the object currently has a mipmap tree associated 387 * with it, this one is a more likely candidate to represent the 388 * whole object since our level didn't fit what was there 389 * before, and any lower levels would fit into our miptree. 390 */ 391 intel_miptree_reference(&intelObj->mt, intelImage->mt); 392 } else { 393 /* Allocate fallback texImage->Data storage through swrast. */ 394 ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat, 395 width, height, depth); 396 } 397 398 /* Attempt to use the blitter for PBO image uploads. 399 */ 400 if (dims <= 2 && 401 try_pbo_upload(intel, intelImage, unpack, format, type, 402 width, height, pixels)) { 403 return; 404 } 405 406 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, 407 format, type, 408 pixels, unpack, "glTexImage"); 409 410 if (intelImage->mt) { 411 if (pixels != NULL) { 412 /* Flush any queued rendering with the texture before mapping. */ 413 if (drm_intel_bo_references(intel->batch.bo, 414 intelImage->mt->region->bo)) { 415 intel_flush(ctx); 416 } 417 texImage->Data = intel_miptree_image_map(intel, 418 intelImage->mt, 419 intelImage->base.Base.Face, 420 intelImage->base.Base.Level, 421 &dstRowStride, 422 intelImage->base.Base.ImageOffsets); 423 } 424 425 texImage->RowStride = dstRowStride / intelImage->mt->cpp; 426 } 427 428 DBG("Upload image %dx%dx%d row_len %d pitch %d pixels %d\n", 429 width, height, depth, width * texelBytes, dstRowStride, 430 pixels ? 1 : 0); 431 432 /* Copy data. Would like to know when it's ok for us to eg. use 433 * the blitter to copy. Or, use the hardware to do the format 434 * conversion and copy: 435 */ 436 if (pixels) { 437 if (!_mesa_texstore(ctx, dims, 438 texImage->_BaseFormat, 439 texImage->TexFormat, 440 texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */ 441 dstRowStride, 442 texImage->ImageOffsets, 443 width, height, depth, 444 format, type, pixels, unpack)) { 445 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 446 } 447 } 448 449 _mesa_unmap_teximage_pbo(ctx, unpack); 450 451 if (intel->must_use_separate_stencil 452 && texImage->TexFormat == MESA_FORMAT_S8_Z24) { 453 intel_tex_image_s8z24_create_renderbuffers(intel, intelImage); 454 intel_tex_image_s8z24_scatter(intel, intelImage); 455 } 456 457 if (intelImage->mt) { 458 if (pixels != NULL) 459 intel_miptree_image_unmap(intel, intelImage->mt); 460 texImage->Data = NULL; 461 } 462} 463 464 465static void 466intelTexImage3D(struct gl_context * ctx, 467 GLenum target, GLint level, 468 GLint internalFormat, 469 GLint width, GLint height, GLint depth, 470 GLint border, 471 GLenum format, GLenum type, const void *pixels, 472 const struct gl_pixelstore_attrib *unpack, 473 struct gl_texture_object *texObj, 474 struct gl_texture_image *texImage) 475{ 476 intelTexImage(ctx, 3, target, level, 477 internalFormat, width, height, depth, border, 478 format, type, pixels, unpack, texObj, texImage, 0); 479} 480 481 482static void 483intelTexImage2D(struct gl_context * ctx, 484 GLenum target, GLint level, 485 GLint internalFormat, 486 GLint width, GLint height, GLint border, 487 GLenum format, GLenum type, const void *pixels, 488 const struct gl_pixelstore_attrib *unpack, 489 struct gl_texture_object *texObj, 490 struct gl_texture_image *texImage) 491{ 492 intelTexImage(ctx, 2, target, level, 493 internalFormat, width, height, 1, border, 494 format, type, pixels, unpack, texObj, texImage, 0); 495} 496 497 498static void 499intelTexImage1D(struct gl_context * ctx, 500 GLenum target, GLint level, 501 GLint internalFormat, 502 GLint width, GLint border, 503 GLenum format, GLenum type, const void *pixels, 504 const struct gl_pixelstore_attrib *unpack, 505 struct gl_texture_object *texObj, 506 struct gl_texture_image *texImage) 507{ 508 intelTexImage(ctx, 1, target, level, 509 internalFormat, width, 1, 1, border, 510 format, type, pixels, unpack, texObj, texImage, 0); 511} 512 513 514/** 515 * Binds a region to a texture image, like it was uploaded by glTexImage2D(). 516 * 517 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, 518 */ 519static void 520intel_set_texture_image_region(struct gl_context *ctx, 521 struct gl_texture_image *image, 522 struct intel_region *region, 523 GLenum target, 524 GLenum internalFormat, 525 gl_format format) 526{ 527 struct intel_context *intel = intel_context(ctx); 528 struct intel_texture_image *intel_image = intel_texture_image(image); 529 530 _mesa_init_teximage_fields(&intel->ctx, target, image, 531 region->width, region->height, 1, 532 0, internalFormat, format); 533 534 ctx->Driver.FreeTextureImageBuffer(ctx, image); 535 536 intel_image->mt = intel_miptree_create_for_region(intel, target, 537 image->TexFormat, 538 region); 539 if (intel_image->mt == NULL) 540 return; 541 542 image->RowStride = region->pitch; 543} 544 545void 546intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 547 GLint texture_format, 548 __DRIdrawable *dPriv) 549{ 550 struct gl_framebuffer *fb = dPriv->driverPrivate; 551 struct intel_context *intel = pDRICtx->driverPrivate; 552 struct gl_context *ctx = &intel->ctx; 553 struct intel_texture_object *intelObj; 554 struct intel_renderbuffer *rb; 555 struct gl_texture_object *texObj; 556 struct gl_texture_image *texImage; 557 int level = 0, internalFormat; 558 gl_format texFormat; 559 560 texObj = _mesa_get_current_tex_object(ctx, target); 561 intelObj = intel_texture_object(texObj); 562 563 if (!intelObj) 564 return; 565 566 if (dPriv->lastStamp != dPriv->dri2.stamp || 567 !pDRICtx->driScreenPriv->dri2.useInvalidate) 568 intel_update_renderbuffers(pDRICtx, dPriv); 569 570 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); 571 /* If the region isn't set, then intel_update_renderbuffers was unable 572 * to get the buffers for the drawable. 573 */ 574 if (rb->region == NULL) 575 return; 576 577 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { 578 internalFormat = GL_RGB; 579 texFormat = MESA_FORMAT_XRGB8888; 580 } 581 else { 582 internalFormat = GL_RGBA; 583 texFormat = MESA_FORMAT_ARGB8888; 584 } 585 586 _mesa_lock_texture(&intel->ctx, texObj); 587 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 588 intel_set_texture_image_region(ctx, texImage, rb->region, target, 589 internalFormat, texFormat); 590 _mesa_unlock_texture(&intel->ctx, texObj); 591} 592 593void 594intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) 595{ 596 /* The old interface didn't have the format argument, so copy our 597 * implementation's behavior at the time. 598 */ 599 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 600} 601 602#if FEATURE_OES_EGL_image 603static void 604intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, 605 struct gl_texture_object *texObj, 606 struct gl_texture_image *texImage, 607 GLeglImageOES image_handle) 608{ 609 struct intel_context *intel = intel_context(ctx); 610 __DRIscreen *screen; 611 __DRIimage *image; 612 613 screen = intel->intelScreen->driScrnPriv; 614 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 615 screen->loaderPrivate); 616 if (image == NULL) 617 return; 618 619 intel_set_texture_image_region(ctx, texImage, image->region, 620 target, image->internal_format, image->format); 621} 622#endif 623 624void 625intelInitTextureImageFuncs(struct dd_function_table *functions) 626{ 627 functions->TexImage1D = intelTexImage1D; 628 functions->TexImage2D = intelTexImage2D; 629 functions->TexImage3D = intelTexImage3D; 630 631#if FEATURE_OES_EGL_image 632 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; 633#endif 634} 635