[Mesa-dev] [PATCH 5/6] intel: implement create image from texture
Abdiel Janulgue
abdiel.janulgue at linux.intel.com
Fri Dec 14 05:28:17 PST 2012
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.janulgue at 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
More information about the mesa-dev
mailing list