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 INTEL_MSAA_LAYOUT_NONE); 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, const void *pixels) 137{ 138 struct intel_texture_image *intelImage = intel_texture_image(image); 139 struct intel_context *intel = intel_context(ctx); 140 struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); 141 GLuint src_offset, src_stride; 142 GLuint dst_x, dst_y, dst_stride; 143 drm_intel_bo *dst_buffer, *src_buffer; 144 145 if (!_mesa_is_bufferobj(unpack->BufferObj)) 146 return false; 147 148 DBG("trying pbo upload\n"); 149 150 if (intel->ctx._ImageTransferState || 151 unpack->SkipPixels || unpack->SkipRows) { 152 DBG("%s: image transfer\n", __FUNCTION__); 153 return false; 154 } 155 156 if (!check_pbo_format(format, type, intelImage->base.Base.TexFormat)) { 157 DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", 158 __FUNCTION__, _mesa_get_format_name(intelImage->base.Base.TexFormat), 159 format, type); 160 return false; 161 } 162 163 ctx->Driver.AllocTextureImageBuffer(ctx, image); 164 165 if (!intelImage->mt) { 166 DBG("%s: no miptree\n", __FUNCTION__); 167 return false; 168 } 169 170 dst_buffer = intelImage->mt->region->bo; 171 src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset); 172 /* note: potential 64-bit ptr to 32-bit int cast */ 173 src_offset += (GLuint) (unsigned long) pixels; 174 175 if (unpack->RowLength > 0) 176 src_stride = unpack->RowLength; 177 else 178 src_stride = image->Width; 179 180 intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level, 181 intelImage->base.Base.Face, 0, 182 &dst_x, &dst_y); 183 184 dst_stride = intelImage->mt->region->pitch; 185 186 if (!intelEmitCopyBlit(intel, 187 intelImage->mt->cpp, 188 src_stride, src_buffer, 189 src_offset, false, 190 dst_stride, dst_buffer, 0, 191 intelImage->mt->region->tiling, 192 0, 0, dst_x, dst_y, image->Width, image->Height, 193 GL_COPY)) { 194 DBG("%s: blit failed\n", __FUNCTION__); 195 return false; 196 } 197 198 DBG("%s: success\n", __FUNCTION__); 199 return true; 200} 201 202static void 203intelTexImage(struct gl_context * ctx, 204 GLuint dims, 205 struct gl_texture_image *texImage, 206 GLenum format, GLenum type, const void *pixels, 207 const struct gl_pixelstore_attrib *unpack) 208{ 209 DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__, 210 _mesa_lookup_enum_by_nr(texImage->TexObject->Target), 211 texImage->Level, texImage->Width, texImage->Height, texImage->Depth); 212 213 /* Attempt to use the blitter for PBO image uploads. 214 */ 215 if (dims <= 2 && 216 try_pbo_upload(ctx, texImage, unpack, format, type, pixels)) { 217 return; 218 } 219 220 DBG("%s: upload image %dx%dx%d pixels %p\n", 221 __FUNCTION__, texImage->Width, texImage->Height, texImage->Depth, 222 pixels); 223 224 _mesa_store_teximage(ctx, dims, texImage, 225 format, type, pixels, unpack); 226} 227 228 229/** 230 * Binds a region to a texture image, like it was uploaded by glTexImage2D(). 231 * 232 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, 233 */ 234static void 235intel_set_texture_image_region(struct gl_context *ctx, 236 struct gl_texture_image *image, 237 struct intel_region *region, 238 GLenum target, 239 GLenum internalFormat, 240 gl_format format, 241 uint32_t offset) 242{ 243 struct intel_context *intel = intel_context(ctx); 244 struct intel_texture_image *intel_image = intel_texture_image(image); 245 struct gl_texture_object *texobj = image->TexObject; 246 struct intel_texture_object *intel_texobj = intel_texture_object(texobj); 247 248 _mesa_init_teximage_fields(&intel->ctx, image, 249 region->width, region->height, 1, 250 0, internalFormat, format); 251 252 ctx->Driver.FreeTextureImageBuffer(ctx, image); 253 254 intel_image->mt = intel_miptree_create_for_region(intel, target, 255 image->TexFormat, 256 region); 257 if (intel_image->mt == NULL) 258 return; 259 260 intel_image->mt->offset = offset; 261 intel_image->base.RowStride = region->pitch; 262 263 /* Immediately validate the image to the object. */ 264 intel_miptree_reference(&intel_texobj->mt, intel_image->mt); 265} 266 267void 268intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 269 GLint texture_format, 270 __DRIdrawable *dPriv) 271{ 272 struct gl_framebuffer *fb = dPriv->driverPrivate; 273 struct intel_context *intel = pDRICtx->driverPrivate; 274 struct gl_context *ctx = &intel->ctx; 275 struct intel_texture_object *intelObj; 276 struct intel_renderbuffer *rb; 277 struct gl_texture_object *texObj; 278 struct gl_texture_image *texImage; 279 int level = 0, internalFormat = 0; 280 gl_format texFormat = MESA_FORMAT_NONE; 281 282 texObj = _mesa_get_current_tex_object(ctx, target); 283 intelObj = intel_texture_object(texObj); 284 285 if (!intelObj) 286 return; 287 288 if (dPriv->lastStamp != dPriv->dri2.stamp || 289 !pDRICtx->driScreenPriv->dri2.useInvalidate) 290 intel_update_renderbuffers(pDRICtx, dPriv); 291 292 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); 293 /* If the region isn't set, then intel_update_renderbuffers was unable 294 * to get the buffers for the drawable. 295 */ 296 if (!rb || !rb->mt) 297 return; 298 299 if (rb->mt->cpp == 4) { 300 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { 301 internalFormat = GL_RGB; 302 texFormat = MESA_FORMAT_XRGB8888; 303 } 304 else { 305 internalFormat = GL_RGBA; 306 texFormat = MESA_FORMAT_ARGB8888; 307 } 308 } else if (rb->mt->cpp == 2) { 309 internalFormat = GL_RGB; 310 texFormat = MESA_FORMAT_RGB565; 311 } 312 313 _mesa_lock_texture(&intel->ctx, texObj); 314 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 315 intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, 316 internalFormat, texFormat, 0); 317 _mesa_unlock_texture(&intel->ctx, texObj); 318} 319 320void 321intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) 322{ 323 /* The old interface didn't have the format argument, so copy our 324 * implementation's behavior at the time. 325 */ 326 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 327} 328 329#if FEATURE_OES_EGL_image 330static void 331intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, 332 struct gl_texture_object *texObj, 333 struct gl_texture_image *texImage, 334 GLeglImageOES image_handle) 335{ 336 struct intel_context *intel = intel_context(ctx); 337 __DRIscreen *screen; 338 __DRIimage *image; 339 340 screen = intel->intelScreen->driScrnPriv; 341 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 342 screen->loaderPrivate); 343 if (image == NULL) 344 return; 345 346 intel_set_texture_image_region(ctx, texImage, image->region, 347 target, image->internal_format, 348 image->format, image->offset); 349} 350#endif 351 352void 353intelInitTextureImageFuncs(struct dd_function_table *functions) 354{ 355 functions->TexImage = intelTexImage; 356 357#if FEATURE_OES_EGL_image 358 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; 359#endif 360} 361