intel_tex_image.c revision 02ebad900db4ef1ac42cbfb41b433919a4c857a2
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/texgetimage.h" 14#include "main/texobj.h" 15#include "main/teximage.h" 16#include "main/texstore.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/* Work back from the specified level of the image to the baselevel and create a 30 * miptree of that size. 31 */ 32struct intel_mipmap_tree * 33intel_miptree_create_for_teximage(struct intel_context *intel, 34 struct intel_texture_object *intelObj, 35 struct intel_texture_image *intelImage, 36 bool expect_accelerated_upload) 37{ 38 GLuint firstLevel; 39 GLuint lastLevel; 40 int width, height, depth; 41 GLuint i; 42 43 intel_miptree_get_dimensions_for_image(&intelImage->base.Base, 44 &width, &height, &depth); 45 46 DBG("%s\n", __FUNCTION__); 47 48 if (intelImage->base.Base.Level > intelObj->base.BaseLevel && 49 (width == 1 || 50 (intelObj->base.Target != GL_TEXTURE_1D && height == 1) || 51 (intelObj->base.Target == GL_TEXTURE_3D && depth == 1))) { 52 /* For this combination, we're at some lower mipmap level and 53 * some important dimension is 1. We can't extrapolate up to a 54 * likely base level width/height/depth for a full mipmap stack 55 * from this info, so just allocate this one level. 56 */ 57 firstLevel = intelImage->base.Base.Level; 58 lastLevel = intelImage->base.Base.Level; 59 } else { 60 /* If this image disrespects BaseLevel, allocate from level zero. 61 * Usually BaseLevel == 0, so it's unlikely to happen. 62 */ 63 if (intelImage->base.Base.Level < intelObj->base.BaseLevel) 64 firstLevel = 0; 65 else 66 firstLevel = intelObj->base.BaseLevel; 67 68 /* Figure out image dimensions at start level. */ 69 for (i = intelImage->base.Base.Level; i > firstLevel; i--) { 70 width <<= 1; 71 if (height != 1) 72 height <<= 1; 73 if (depth != 1) 74 depth <<= 1; 75 } 76 77 /* Guess a reasonable value for lastLevel. This is probably going 78 * to be wrong fairly often and might mean that we have to look at 79 * resizable buffers, or require that buffers implement lazy 80 * pagetable arrangements. 81 */ 82 if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || 83 intelObj->base.Sampler.MinFilter == GL_LINEAR) && 84 intelImage->base.Base.Level == firstLevel && 85 (intel->gen < 4 || firstLevel == 0)) { 86 lastLevel = firstLevel; 87 } else if (intelObj->base.Target == GL_TEXTURE_EXTERNAL_OES) { 88 lastLevel = firstLevel; 89 } else { 90 lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); 91 } 92 } 93 94 return intel_miptree_create(intel, 95 intelObj->base.Target, 96 intelImage->base.Base.TexFormat, 97 firstLevel, 98 lastLevel, 99 width, 100 height, 101 depth, 102 expect_accelerated_upload, 103 0 /* num_samples */, 104 false /* msaa_is_interleaved */); 105} 106 107/* There are actually quite a few combinations this will work for, 108 * more than what I've listed here. 109 */ 110static bool 111check_pbo_format(GLenum format, GLenum type, 112 gl_format mesa_format) 113{ 114 switch (mesa_format) { 115 case MESA_FORMAT_ARGB8888: 116 return (format == GL_BGRA && (type == GL_UNSIGNED_BYTE || 117 type == GL_UNSIGNED_INT_8_8_8_8_REV)); 118 case MESA_FORMAT_RGB565: 119 return (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5); 120 case MESA_FORMAT_L8: 121 return (format == GL_LUMINANCE && type == GL_UNSIGNED_BYTE); 122 case MESA_FORMAT_YCBCR: 123 return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE); 124 default: 125 return false; 126 } 127} 128 129 130/* XXX: Do this for TexSubImage also: 131 */ 132static bool 133try_pbo_upload(struct gl_context *ctx, 134 struct gl_texture_image *image, 135 const struct gl_pixelstore_attrib *unpack, 136 GLenum format, GLenum type, 137 GLint width, GLint height, const void *pixels) 138{ 139 struct intel_texture_image *intelImage = intel_texture_image(image); 140 struct intel_context *intel = intel_context(ctx); 141 struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); 142 GLuint src_offset, src_stride; 143 GLuint dst_x, dst_y, dst_stride; 144 drm_intel_bo *dst_buffer, *src_buffer; 145 146 if (!_mesa_is_bufferobj(unpack->BufferObj)) 147 return false; 148 149 DBG("trying pbo upload\n"); 150 151 if (intel->ctx._ImageTransferState || 152 unpack->SkipPixels || unpack->SkipRows) { 153 DBG("%s: image transfer\n", __FUNCTION__); 154 return false; 155 } 156 157 if (!check_pbo_format(format, type, intelImage->base.Base.TexFormat)) { 158 DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", 159 __FUNCTION__, _mesa_get_format_name(intelImage->base.Base.TexFormat), 160 format, type); 161 return false; 162 } 163 164 ctx->Driver.AllocTextureImageBuffer(ctx, image, image->TexFormat, 165 width, height, 1); 166 167 if (!intelImage->mt) { 168 DBG("%s: no miptree\n", __FUNCTION__); 169 return false; 170 } 171 172 dst_buffer = intelImage->mt->region->bo; 173 src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset); 174 /* note: potential 64-bit ptr to 32-bit int cast */ 175 src_offset += (GLuint) (unsigned long) pixels; 176 177 if (unpack->RowLength > 0) 178 src_stride = unpack->RowLength; 179 else 180 src_stride = width; 181 182 intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level, 183 intelImage->base.Base.Face, 0, 184 &dst_x, &dst_y); 185 186 dst_stride = intelImage->mt->region->pitch; 187 188 if (!intelEmitCopyBlit(intel, 189 intelImage->mt->cpp, 190 src_stride, src_buffer, 191 src_offset, false, 192 dst_stride, dst_buffer, 0, 193 intelImage->mt->region->tiling, 194 0, 0, dst_x, dst_y, width, height, 195 GL_COPY)) { 196 DBG("%s: blit failed\n", __FUNCTION__); 197 return false; 198 } 199 200 DBG("%s: success\n", __FUNCTION__); 201 return true; 202} 203 204static void 205intelTexImage(struct gl_context * ctx, 206 GLuint dims, 207 struct gl_texture_image *texImage, 208 GLint internalFormat, 209 GLint width, GLint height, GLint depth, GLint border, 210 GLenum format, GLenum type, const void *pixels, 211 const struct gl_pixelstore_attrib *unpack) 212{ 213 DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__, 214 _mesa_lookup_enum_by_nr(texImage->TexObject->Target), 215 texImage->Level, width, height, depth); 216 217 /* Attempt to use the blitter for PBO image uploads. 218 */ 219 if (dims <= 2 && 220 try_pbo_upload(ctx, texImage, unpack, format, type, 221 width, height, pixels)) { 222 return; 223 } 224 225 DBG("%s: upload image %dx%dx%d pixels %p\n", 226 __FUNCTION__, width, height, depth, pixels); 227 228 _mesa_store_teximage(ctx, dims, texImage, internalFormat, 229 width, height, depth, 0, 230 format, type, pixels, unpack); 231} 232 233 234/** 235 * Binds a region to a texture image, like it was uploaded by glTexImage2D(). 236 * 237 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, 238 */ 239static void 240intel_set_texture_image_region(struct gl_context *ctx, 241 struct gl_texture_image *image, 242 struct intel_region *region, 243 GLenum target, 244 GLenum internalFormat, 245 gl_format format, 246 uint32_t offset) 247{ 248 struct intel_context *intel = intel_context(ctx); 249 struct intel_texture_image *intel_image = intel_texture_image(image); 250 struct gl_texture_object *texobj = image->TexObject; 251 struct intel_texture_object *intel_texobj = intel_texture_object(texobj); 252 253 _mesa_init_teximage_fields(&intel->ctx, image, 254 region->width, region->height, 1, 255 0, internalFormat, format); 256 257 ctx->Driver.FreeTextureImageBuffer(ctx, image); 258 259 intel_image->mt = intel_miptree_create_for_region(intel, target, 260 image->TexFormat, 261 region); 262 if (intel_image->mt == NULL) 263 return; 264 265 intel_image->mt->offset = offset; 266 intel_image->base.RowStride = region->pitch; 267 268 /* Immediately validate the image to the object. */ 269 intel_miptree_reference(&intel_texobj->mt, intel_image->mt); 270} 271 272void 273intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 274 GLint texture_format, 275 __DRIdrawable *dPriv) 276{ 277 struct gl_framebuffer *fb = dPriv->driverPrivate; 278 struct intel_context *intel = pDRICtx->driverPrivate; 279 struct gl_context *ctx = &intel->ctx; 280 struct intel_texture_object *intelObj; 281 struct intel_renderbuffer *rb; 282 struct gl_texture_object *texObj; 283 struct gl_texture_image *texImage; 284 int level = 0, internalFormat = 0; 285 gl_format texFormat = MESA_FORMAT_NONE; 286 287 texObj = _mesa_get_current_tex_object(ctx, target); 288 intelObj = intel_texture_object(texObj); 289 290 if (!intelObj) 291 return; 292 293 if (dPriv->lastStamp != dPriv->dri2.stamp || 294 !pDRICtx->driScreenPriv->dri2.useInvalidate) 295 intel_update_renderbuffers(pDRICtx, dPriv); 296 297 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); 298 /* If the region isn't set, then intel_update_renderbuffers was unable 299 * to get the buffers for the drawable. 300 */ 301 if (!rb || !rb->mt) 302 return; 303 304 if (rb->mt->cpp == 4) { 305 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { 306 internalFormat = GL_RGB; 307 texFormat = MESA_FORMAT_XRGB8888; 308 } 309 else { 310 internalFormat = GL_RGBA; 311 texFormat = MESA_FORMAT_ARGB8888; 312 } 313 } else if (rb->mt->cpp == 2) { 314 internalFormat = GL_RGB; 315 texFormat = MESA_FORMAT_RGB565; 316 } 317 318 _mesa_lock_texture(&intel->ctx, texObj); 319 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 320 intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, 321 internalFormat, texFormat, 0); 322 _mesa_unlock_texture(&intel->ctx, texObj); 323} 324 325void 326intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) 327{ 328 /* The old interface didn't have the format argument, so copy our 329 * implementation's behavior at the time. 330 */ 331 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 332} 333 334#if FEATURE_OES_EGL_image 335static void 336intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, 337 struct gl_texture_object *texObj, 338 struct gl_texture_image *texImage, 339 GLeglImageOES image_handle) 340{ 341 struct intel_context *intel = intel_context(ctx); 342 __DRIscreen *screen; 343 __DRIimage *image; 344 345 screen = intel->intelScreen->driScrnPriv; 346 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 347 screen->loaderPrivate); 348 if (image == NULL) 349 return; 350 351 intel_set_texture_image_region(ctx, texImage, image->region, 352 target, image->internal_format, 353 image->format, 0); 354} 355#endif 356 357void 358intelInitTextureImageFuncs(struct dd_function_table *functions) 359{ 360 functions->TexImage = intelTexImage; 361 362#if FEATURE_OES_EGL_image 363 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; 364#endif 365} 366