/** * Binds a region to a texture image, like it was uploaded by glTexImage2D(). * * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, */ static void intel_set_texture_image_region(struct gl_context *ctx, struct gl_texture_image *image, struct intel_region *region, GLenum target, GLenum internalFormat, gl_format format, uint32_t offset, GLuint width, GLuint height, GLuint tile_x, GLuint tile_y) { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(image); struct gl_texture_object *texobj = image->TexObject; struct intel_texture_object *intel_texobj = intel_texture_object(texobj); bool has_surface_tile_offset = false; uint32_t draw_x, draw_y; _mesa_init_teximage_fields(&intel->ctx, image, width, height, 1, 0, internalFormat, format); ctx->Driver.FreeTextureImageBuffer(ctx, image); intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat, 0, 0, width, height, 1, true); if (intel_image->mt == NULL) return; intel_region_reference(&intel_image->mt->region, region); intel_image->mt->total_width = width; intel_image->mt->total_height = height; intel_image->mt->level[0].slice[0].x_offset = tile_x; intel_image->mt->level[0].slice[0].y_offset = tile_y; intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y); /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has * trouble resolving back to destination image due to alignment issues. */ if (!has_surface_tile_offset && (draw_x != 0 || draw_y != 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, __func__); intel_miptree_release(&intel_image->mt); return; } intel_texobj->needs_validate = true; intel_image->mt->offset = offset; assert(region->pitch % region->cpp == 0); intel_image->base.RowStride = region->pitch / region->cpp; /* Immediately validate the image to the object. */ intel_miptree_reference(&intel_texobj->mt, intel_image->mt); }
struct intel_mipmap_tree * intel_miptree_create_for_bo(struct intel_context *intel, drm_intel_bo *bo, mesa_format format, uint32_t offset, uint32_t width, uint32_t height, int pitch, uint32_t tiling) { struct intel_mipmap_tree *mt; struct intel_region *region = calloc(1, sizeof(*region)); if (!region) return NULL; /* Nothing will be able to use this miptree with the BO if the offset isn't * aligned. */ if (tiling != I915_TILING_NONE) assert(offset % 4096 == 0); /* miptrees can't handle negative pitch. If you need flipping of images, * that's outside of the scope of the mt. */ assert(pitch >= 0); mt = intel_miptree_create_layout(intel, GL_TEXTURE_2D, format, 0, 0, width, height, 1, true); if (!mt) { free(region); return mt; } region->cpp = mt->cpp; region->width = width; region->height = height; region->pitch = pitch; region->refcount = 1; drm_intel_bo_reference(bo); region->bo = bo; region->tiling = tiling; mt->region = region; mt->offset = offset; return mt; }
struct intel_mipmap_tree * intel_miptree_create(struct intel_context *intel, GLenum target, mesa_format format, GLuint first_level, GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, bool expect_accelerated_upload, enum intel_miptree_tiling_mode requested_tiling) { struct intel_mipmap_tree *mt; GLuint total_width, total_height; mt = intel_miptree_create_layout(intel, target, format, first_level, last_level, width0, height0, depth0, false); /* * pitch == 0 || height == 0 indicates the null texture */ if (!mt || !mt->total_width || !mt->total_height) { intel_miptree_release(&mt); return NULL; } total_width = mt->total_width; total_height = mt->total_height; uint32_t tiling = intel_miptree_choose_tiling(intel, format, width0, requested_tiling, mt); bool y_or_x = tiling == (I915_TILING_Y | I915_TILING_X); mt->region = intel_region_alloc(intel->intelScreen, y_or_x ? I915_TILING_Y : tiling, mt->cpp, total_width, total_height, expect_accelerated_upload); /* If the region is too large to fit in the aperture, we need to use the * BLT engine to support it. The BLT paths can't currently handle Y-tiling, * so we need to fall back to X. */ if (y_or_x && mt->region->bo->size >= intel->max_gtt_map_object_size) { perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n", mt->total_width, mt->total_height); intel_region_release(&mt->region); mt->region = intel_region_alloc(intel->intelScreen, I915_TILING_X, mt->cpp, total_width, total_height, expect_accelerated_upload); } mt->offset = 0; if (!mt->region) { intel_miptree_release(&mt); return NULL; } return mt; }