intel_tex_image.c revision 66681b4c8cb1ef16f42c1591298cb30c83bca09b
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#include "main/texstore.h" 18 19#include "intel_context.h" 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_span.h" 27 28#define FILE_DEBUG_FLAG DEBUG_TEXTURE 29 30/* Functions to store texture images. Where possible, mipmap_tree's 31 * will be created or further instantiated with image data, otherwise 32 * images will be stored in malloc'd memory. A validation step is 33 * required to pull those images into a mipmap tree, or otherwise 34 * decide a fallback is required. 35 */ 36 37 38 39/* Otherwise, store it in memory if (Border != 0) or (any dimension == 40 * 1). 41 * 42 * Otherwise, if max_level >= level >= min_level, create tree with 43 * space for textures from min_level down to max_level. 44 * 45 * Otherwise, create tree with space for textures from (level 46 * 0)..(1x1). Consider pruning this tree at a validation if the 47 * saving is worth it. 48 */ 49struct intel_mipmap_tree * 50intel_miptree_create_for_teximage(struct intel_context *intel, 51 struct intel_texture_object *intelObj, 52 struct intel_texture_image *intelImage, 53 bool expect_accelerated_upload) 54{ 55 GLuint firstLevel; 56 GLuint lastLevel; 57 int width, height, depth; 58 GLuint i; 59 60 intel_miptree_get_dimensions_for_image(&intelImage->base.Base, 61 &width, &height, &depth); 62 63 DBG("%s\n", __FUNCTION__); 64 65 if (intelImage->base.Base.Border) 66 return NULL; 67 68 if (intelImage->base.Base.Level > intelObj->base.BaseLevel && 69 (width == 1 || 70 (intelObj->base.Target != GL_TEXTURE_1D && height == 1) || 71 (intelObj->base.Target == GL_TEXTURE_3D && 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 gl_context *ctx, 150 struct gl_texture_image *image, 151 const struct gl_pixelstore_attrib *unpack, 152 GLenum format, GLenum type, 153 GLint width, GLint height, const void *pixels) 154{ 155 struct intel_texture_image *intelImage = intel_texture_image(image); 156 struct intel_context *intel = intel_context(ctx); 157 struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); 158 GLuint src_offset, src_stride; 159 GLuint dst_x, dst_y, dst_stride; 160 drm_intel_bo *dst_buffer, *src_buffer; 161 162 if (!_mesa_is_bufferobj(unpack->BufferObj)) 163 return false; 164 165 DBG("trying pbo upload\n"); 166 167 if (intel->ctx._ImageTransferState || 168 unpack->SkipPixels || unpack->SkipRows) { 169 DBG("%s: image transfer\n", __FUNCTION__); 170 return false; 171 } 172 173 if (!check_pbo_format(format, type, intelImage->base.Base.TexFormat)) { 174 DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", 175 __FUNCTION__, _mesa_get_format_name(intelImage->base.Base.TexFormat), 176 format, type); 177 return false; 178 } 179 180 ctx->Driver.AllocTextureImageBuffer(ctx, image, image->TexFormat, 181 width, height, 1); 182 183 if (!intelImage->mt) { 184 DBG("%s: no miptree\n", __FUNCTION__); 185 return false; 186 } 187 188 dst_buffer = intelImage->mt->region->bo; 189 src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset); 190 /* note: potential 64-bit ptr to 32-bit int cast */ 191 src_offset += (GLuint) (unsigned long) pixels; 192 193 if (unpack->RowLength > 0) 194 src_stride = unpack->RowLength; 195 else 196 src_stride = width; 197 198 intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level, 199 intelImage->base.Base.Face, 0, 200 &dst_x, &dst_y); 201 202 dst_stride = intelImage->mt->region->pitch; 203 204 if (!intelEmitCopyBlit(intel, 205 intelImage->mt->cpp, 206 src_stride, src_buffer, 207 src_offset, false, 208 dst_stride, dst_buffer, 0, 209 intelImage->mt->region->tiling, 210 0, 0, dst_x, dst_y, width, height, 211 GL_COPY)) { 212 DBG("%s: blit failed\n", __FUNCTION__); 213 return false; 214 } 215 216 DBG("%s: success\n", __FUNCTION__); 217 return true; 218} 219 220/** 221 * \param scatter Scatter if true. Gather if false. 222 * 223 * \see intel_tex_image_x8z24_scatter 224 * \see intel_tex_image_x8z24_gather 225 */ 226static void 227intel_tex_image_s8z24_scattergather(struct intel_context *intel, 228 struct intel_texture_image *intel_image, 229 bool scatter) 230{ 231 struct gl_context *ctx = &intel->ctx; 232 struct gl_renderbuffer *depth_rb = intel_image->depth_rb; 233 struct gl_renderbuffer *stencil_rb = intel_image->stencil_rb; 234 int w, h, d; 235 236 intel_miptree_get_dimensions_for_image(&intel_image->base.Base, &w, &h, &d); 237 assert(d == 1); /* FINISHME */ 238 239 uint32_t depth_row[w]; 240 uint8_t stencil_row[w]; 241 242 intel_renderbuffer_map(intel, depth_rb); 243 intel_renderbuffer_map(intel, stencil_rb); 244 245 if (scatter) { 246 for (int y = 0; y < h; ++y) { 247 depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); 248 for (int x = 0; x < w; ++x) { 249 stencil_row[x] = depth_row[x] >> 24; 250 } 251 stencil_rb->PutRow(ctx, stencil_rb, w, 0, y, stencil_row, NULL); 252 } 253 } else { /* gather */ 254 for (int y = 0; y < h; ++y) { 255 depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); 256 stencil_rb->GetRow(ctx, stencil_rb, w, 0, y, stencil_row); 257 for (int x = 0; x < w; ++x) { 258 uint32_t s8_x24 = stencil_row[x] << 24; 259 uint32_t x8_z24 = depth_row[x] & 0x00ffffff; 260 depth_row[x] = s8_x24 | x8_z24; 261 } 262 depth_rb->PutRow(ctx, depth_rb, w, 0, y, depth_row, NULL); 263 } 264 } 265 266 intel_renderbuffer_unmap(intel, depth_rb); 267 intel_renderbuffer_unmap(intel, stencil_rb); 268} 269 270/** 271 * Copy the x8 bits from intel_image->depth_rb to intel_image->stencil_rb. 272 */ 273void 274intel_tex_image_s8z24_scatter(struct intel_context *intel, 275 struct intel_texture_image *intel_image) 276{ 277 intel_tex_image_s8z24_scattergather(intel, intel_image, true); 278} 279 280/** 281 * Copy the data in intel_image->stencil_rb to the x8 bits in 282 * intel_image->depth_rb. 283 */ 284void 285intel_tex_image_s8z24_gather(struct intel_context *intel, 286 struct intel_texture_image *intel_image) 287{ 288 intel_tex_image_s8z24_scattergather(intel, intel_image, false); 289} 290 291bool 292intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, 293 struct intel_texture_image *image) 294{ 295 struct gl_context *ctx = &intel->ctx; 296 bool ok = true; 297 int width, height, depth; 298 struct gl_renderbuffer *drb; 299 struct gl_renderbuffer *srb; 300 struct intel_renderbuffer *idrb; 301 struct intel_renderbuffer *isrb; 302 303 intel_miptree_get_dimensions_for_image(&image->base.Base, 304 &width, &height, &depth); 305 assert(depth == 1); /* FINISHME */ 306 307 assert(intel->has_separate_stencil); 308 assert(image->base.Base.TexFormat == MESA_FORMAT_S8_Z24); 309 assert(image->mt != NULL); 310 311 drb = intel_create_wrapped_renderbuffer(ctx, width, height, 312 MESA_FORMAT_X8_Z24); 313 srb = intel_create_wrapped_renderbuffer(ctx, width, height, 314 MESA_FORMAT_S8); 315 316 if (!drb || !srb) { 317 if (drb) { 318 drb->Delete(drb); 319 } 320 if (srb) { 321 srb->Delete(srb); 322 } 323 return false; 324 } 325 326 idrb = intel_renderbuffer(drb); 327 isrb = intel_renderbuffer(srb); 328 329 intel_region_reference(&idrb->region, image->mt->region); 330 ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8, 331 width, height); 332 333 if (!ok) { 334 drb->Delete(drb); 335 srb->Delete(srb); 336 return false; 337 } 338 339 intel_renderbuffer_set_draw_offset(idrb, image, 0); 340 intel_renderbuffer_set_draw_offset(isrb, image, 0); 341 342 _mesa_reference_renderbuffer(&image->depth_rb, drb); 343 _mesa_reference_renderbuffer(&image->stencil_rb, srb); 344 345 return true; 346} 347 348static void 349intelTexImage(struct gl_context * ctx, 350 GLint dims, 351 GLenum target, GLint level, 352 GLint internalFormat, 353 GLint width, GLint height, GLint depth, 354 GLint border, 355 GLenum format, GLenum type, const void *pixels, 356 const struct gl_pixelstore_attrib *unpack, 357 struct gl_texture_object *texObj, 358 struct gl_texture_image *texImage, GLsizei imageSize) 359{ 360 DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, 361 _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); 362 363 /* Attempt to use the blitter for PBO image uploads. 364 */ 365 if (dims <= 2 && 366 try_pbo_upload(ctx, texImage, unpack, format, type, 367 width, height, pixels)) { 368 return; 369 } 370 371 DBG("%s: upload image %dx%dx%d pixels %p\n", 372 __FUNCTION__, width, height, depth, pixels); 373 374 _mesa_store_teximage3d(ctx, target, level, internalFormat, 375 width, height, depth, border, 376 format, type, pixels, 377 unpack, texObj, texImage); 378} 379 380 381static void 382intelTexImage3D(struct gl_context * ctx, 383 GLenum target, GLint level, 384 GLint internalFormat, 385 GLint width, GLint height, GLint depth, 386 GLint border, 387 GLenum format, GLenum type, const void *pixels, 388 const struct gl_pixelstore_attrib *unpack, 389 struct gl_texture_object *texObj, 390 struct gl_texture_image *texImage) 391{ 392 intelTexImage(ctx, 3, target, level, 393 internalFormat, width, height, depth, border, 394 format, type, pixels, unpack, texObj, texImage, 0); 395} 396 397 398static void 399intelTexImage2D(struct gl_context * ctx, 400 GLenum target, GLint level, 401 GLint internalFormat, 402 GLint width, GLint height, GLint border, 403 GLenum format, GLenum type, const void *pixels, 404 const struct gl_pixelstore_attrib *unpack, 405 struct gl_texture_object *texObj, 406 struct gl_texture_image *texImage) 407{ 408 intelTexImage(ctx, 2, target, level, 409 internalFormat, width, height, 1, border, 410 format, type, pixels, unpack, texObj, texImage, 0); 411} 412 413 414static void 415intelTexImage1D(struct gl_context * ctx, 416 GLenum target, GLint level, 417 GLint internalFormat, 418 GLint width, GLint border, 419 GLenum format, GLenum type, const void *pixels, 420 const struct gl_pixelstore_attrib *unpack, 421 struct gl_texture_object *texObj, 422 struct gl_texture_image *texImage) 423{ 424 intelTexImage(ctx, 1, target, level, 425 internalFormat, width, 1, 1, border, 426 format, type, pixels, unpack, texObj, texImage, 0); 427} 428 429 430/** 431 * Binds a region to a texture image, like it was uploaded by glTexImage2D(). 432 * 433 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, 434 */ 435static void 436intel_set_texture_image_region(struct gl_context *ctx, 437 struct gl_texture_image *image, 438 struct intel_region *region, 439 GLenum target, 440 GLenum internalFormat, 441 gl_format format) 442{ 443 struct intel_context *intel = intel_context(ctx); 444 struct intel_texture_image *intel_image = intel_texture_image(image); 445 446 _mesa_init_teximage_fields(&intel->ctx, target, image, 447 region->width, region->height, 1, 448 0, internalFormat, format); 449 450 ctx->Driver.FreeTextureImageBuffer(ctx, image); 451 452 intel_image->mt = intel_miptree_create_for_region(intel, target, 453 image->TexFormat, 454 region); 455 if (intel_image->mt == NULL) 456 return; 457 458 intel_image->base.RowStride = region->pitch; 459} 460 461void 462intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 463 GLint texture_format, 464 __DRIdrawable *dPriv) 465{ 466 struct gl_framebuffer *fb = dPriv->driverPrivate; 467 struct intel_context *intel = pDRICtx->driverPrivate; 468 struct gl_context *ctx = &intel->ctx; 469 struct intel_texture_object *intelObj; 470 struct intel_renderbuffer *rb; 471 struct gl_texture_object *texObj; 472 struct gl_texture_image *texImage; 473 int level = 0, internalFormat; 474 gl_format texFormat; 475 476 texObj = _mesa_get_current_tex_object(ctx, target); 477 intelObj = intel_texture_object(texObj); 478 479 if (!intelObj) 480 return; 481 482 if (dPriv->lastStamp != dPriv->dri2.stamp || 483 !pDRICtx->driScreenPriv->dri2.useInvalidate) 484 intel_update_renderbuffers(pDRICtx, dPriv); 485 486 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); 487 /* If the region isn't set, then intel_update_renderbuffers was unable 488 * to get the buffers for the drawable. 489 */ 490 if (rb->region == NULL) 491 return; 492 493 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { 494 internalFormat = GL_RGB; 495 texFormat = MESA_FORMAT_XRGB8888; 496 } 497 else { 498 internalFormat = GL_RGBA; 499 texFormat = MESA_FORMAT_ARGB8888; 500 } 501 502 _mesa_lock_texture(&intel->ctx, texObj); 503 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 504 intel_set_texture_image_region(ctx, texImage, rb->region, target, 505 internalFormat, texFormat); 506 _mesa_unlock_texture(&intel->ctx, texObj); 507} 508 509void 510intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) 511{ 512 /* The old interface didn't have the format argument, so copy our 513 * implementation's behavior at the time. 514 */ 515 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 516} 517 518#if FEATURE_OES_EGL_image 519static void 520intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, 521 struct gl_texture_object *texObj, 522 struct gl_texture_image *texImage, 523 GLeglImageOES image_handle) 524{ 525 struct intel_context *intel = intel_context(ctx); 526 __DRIscreen *screen; 527 __DRIimage *image; 528 529 screen = intel->intelScreen->driScrnPriv; 530 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 531 screen->loaderPrivate); 532 if (image == NULL) 533 return; 534 535 intel_set_texture_image_region(ctx, texImage, image->region, 536 target, image->internal_format, image->format); 537} 538#endif 539 540void 541intelInitTextureImageFuncs(struct dd_function_table *functions) 542{ 543 functions->TexImage1D = intelTexImage1D; 544 functions->TexImage2D = intelTexImage2D; 545 functions->TexImage3D = intelTexImage3D; 546 547#if FEATURE_OES_EGL_image 548 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; 549#endif 550} 551