Save miptree level info to DRIImage, taking offsets into consideration. For <= gen4 hw which doesn't support non-tile aligned offset, re-create the mipmap tree internally before exporting the updated offsets to avoid alignment problems.
Signed-off-by: Abdiel Janulgue <abdiel.janul...@linux.intel.com> --- src/mesa/drivers/dri/intel/intel_screen.c | 175 +++++++++++++++++++++++++---- 1 file changed, 155 insertions(+), 20 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 4e2742f..f6a524a 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -31,6 +31,7 @@ #include "main/context.h" #include "main/framebuffer.h" #include "main/renderbuffer.h" +#include "main/texobj.h" #include "main/hash.h" #include "main/fbobject.h" #include "main/mfeatures.h" @@ -104,6 +105,10 @@ const GLuint __driNConfigOptions = 15; #include "intel_tex.h" #include "intel_regions.h" +#ifndef I915 +#include "brw_context.h" +#endif + #include "i915_drm.h" #ifdef USE_NEW_INTERFACE @@ -295,6 +300,95 @@ intel_allocate_image(int dri_format, void *loaderPrivate) return image; } +static void +intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *image, + struct intel_mipmap_tree **pmt, GLuint level, GLuint zoffset) +{ + struct intel_mipmap_tree *mt = *pmt; + bool has_surface_tile_offset = false; + uint32_t mask_x, mask_y; + + intel_miptree_check_level_layer(mt, level, zoffset); + + intel_region_reference(&image->region, mt->region); + image->width = mt->level[level].width; + image->height = mt->level[level].height; + image->level_x = mt->level[level].level_x; + image->level_y = mt->level[level].level_y; + image->slice_x_offset = mt->level[level].slice[zoffset].x_offset; + image->slice_y_offset = mt->level[level].slice[zoffset].y_offset; + + intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false); + image->offset = intel_region_get_aligned_offset(mt->region, + mt->level[level].level_x & ~mask_x, + mt->level[level].level_y & ~mask_y, + false); +#ifndef I915 + has_surface_tile_offset = brw_context(&intel->ctx)->has_surface_tile_offset; +#endif + + if (!has_surface_tile_offset && (image->slice_x_offset & mask_x) && + (image->slice_y_offset & mask_y)) { + /* Driver doesn't support non-tile aligned texture offset for gen4 + * and earlier. To avoid problems with unaligned texture offset we make + * linear copy of the texture. + * + * Linear image will lose in performance but at least correct stuff + * ends to screen. + */ + bool texture_tiling = intel->use_texture_tiling; + intel->use_texture_tiling = false; + + struct intel_mipmap_tree *new_mt = intel_miptree_create(intel, + mt->target, mt->format, + mt->first_level, mt->last_level, + mt->width0, mt->height0, + mt->depth0, true, + mt->num_samples, + mt->msaa_layout); + + intel->use_texture_tiling = texture_tiling; + intel_miptree_copy(intel, new_mt, mt); + intel_miptree_reference(pmt, new_mt); + image->level_x = new_mt->level[level].level_x; + image->level_y = new_mt->level[level].level_y; + image->slice_x_offset = new_mt->level[level].slice[zoffset].x_offset; + image->slice_y_offset = new_mt->level[level].slice[zoffset].y_offset; + } +} + +static void +intel_setup_image_from_dimensions(__DRIimage *image) +{ + image->width = image->region->width; + image->height = image->region->height; + image->level_x = 0; + image->level_y = 0; + image->slice_x_offset = 0; + image->slice_y_offset = 0; +} + +static inline uint32_t +intel_dri_format(GLuint format) +{ + switch (format) { + case MESA_FORMAT_RGB565: + return __DRI_IMAGE_FORMAT_RGB565; + case MESA_FORMAT_XRGB8888: + return __DRI_IMAGE_FORMAT_XRGB8888; + case MESA_FORMAT_ARGB8888: + return __DRI_IMAGE_FORMAT_ARGB8888; + case MESA_FORMAT_RGBA8888_REV: + return __DRI_IMAGE_FORMAT_ABGR8888; + case MESA_FORMAT_R8: + return __DRI_IMAGE_FORMAT_R8; + case MESA_FORMAT_RG88: + return __DRI_IMAGE_FORMAT_GR88; + } + + return 0; +} + static __DRIimage * intel_create_image_from_name(__DRIscreen *screen, int width, int height, int format, @@ -317,6 +411,8 @@ intel_create_image_from_name(__DRIscreen *screen, return NULL; } + intel_setup_image_from_dimensions(image); + return image; } @@ -346,27 +442,57 @@ intel_create_image_from_renderbuffer(__DRIcontext *context, image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); + intel_setup_image_from_dimensions(image); + image->dri_format = intel_dri_format(image->format); - switch (image->format) { - case MESA_FORMAT_RGB565: - image->dri_format = __DRI_IMAGE_FORMAT_RGB565; - break; - case MESA_FORMAT_XRGB8888: - image->dri_format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case MESA_FORMAT_ARGB8888: - image->dri_format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - case MESA_FORMAT_RGBA8888_REV: - image->dri_format = __DRI_IMAGE_FORMAT_ABGR8888; - break; - case MESA_FORMAT_R8: - image->dri_format = __DRI_IMAGE_FORMAT_R8; - break; - case MESA_FORMAT_RG88: - image->dri_format = __DRI_IMAGE_FORMAT_GR88; - break; + return image; +} + +static __DRIimage * +intel_create_image_from_texture(__DRIcontext *context, int target, + unsigned texture, int zoffset, int level, + void *loaderPrivate) +{ + __DRIimage *image; + struct intel_context *intel = context->driverPrivate; + struct gl_texture_object *obj; + struct intel_texture_object *iobj; + GLuint face = 0; + + obj = _mesa_lookup_texture(&intel->ctx, texture); + if (!obj || obj->Target != target) { + _mesa_warning(NULL, "%s: invalid texture", __func__); + return NULL; + } + + if (target == GL_TEXTURE_CUBE_MAP) + face = zoffset; + + _mesa_test_texobj_completeness(&intel->ctx, obj); + iobj = intel_texture_object(obj); + if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { + _mesa_warning(NULL, "%s: texture object incomplete", __func__); + return NULL; + } + + if (level < obj->BaseLevel || level > obj->_MaxLevel) { + _mesa_warning(NULL, "%s: invalid mipmap level", __func__); + return NULL; + } + + if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) { + _mesa_warning(NULL, "%s: invalid Z offset", __func__); + return NULL; } + image = calloc(1, sizeof *image); + if (image == NULL) + return NULL; + + image->internal_format = obj->Image[face][level]->InternalFormat; + image->format = obj->Image[face][level]->TexFormat; + image->data = loaderPrivate; + intel_setup_image_from_mipmap_tree(intel, image, &iobj->mt, level, zoffset); + image->dri_format = intel_dri_format(image->format); return image; } @@ -405,6 +531,8 @@ intel_create_image(__DRIscreen *screen, return NULL; } + intel_setup_image_from_dimensions(image); + return image; } @@ -459,6 +587,12 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) image->dri_format = orig_image->dri_format; image->format = orig_image->format; image->offset = orig_image->offset; + image->width = orig_image->width; + image->height = orig_image->height; + image->level_x = orig_image->level_x; + image->level_y = orig_image->level_y; + image->slice_x_offset = orig_image->slice_x_offset; + image->slice_y_offset = orig_image->slice_y_offset; image->data = loaderPrivate; memcpy(image->strides, orig_image->strides, sizeof(image->strides)); @@ -587,7 +721,8 @@ static struct __DRIimageExtensionRec intelImageExtension = { .dupImage = intel_dup_image, .validateUsage = intel_validate_usage, .createImageFromNames = intel_create_image_from_names, - .fromPlanar = intel_from_planar + .fromPlanar = intel_from_planar, + .createImageFromTexture = intel_create_image_from_texture }; static const __DRIextension *intelScreenExtensions[] = { -- 1.7.9.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev