summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Nieminen <pauli.nieminen@linux.intel.com>2012-05-09 23:15:22 +0300
committerPauli Nieminen <pauli.nieminen@linux.intel.com>2012-06-05 18:33:46 +0300
commit5010a5d1a469f7963aa333cb54d06642d4cf10ce (patch)
tree7a976d16e51ccaaa9cbe9b165c07fc0477e75bcf
parent47b64c9290d54f78e5a20e378593977cd47e285f (diff)
HACK v3: EGL_KHR_gl_texture_* supportKHR_gl_texture_image2
Now it works all except smallest levels. The smallest level samples white only so I suspect it is some bug in my fake miptree setup. Unless of course white while I tough rgbw should be linear filter of rgbw values resulting to gray. Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
-rw-r--r--include/GL/internal/dri_interface.h13
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c84
-rw-r--r--src/mesa/drivers/dri/i915/i915_texstate.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c17
-rw-r--r--src/mesa/drivers/dri/i965/gen6_blorp.cpp14
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c72
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h20
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c153
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c23
10 files changed, 383 insertions, 23 deletions
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index e37917eda9..aacf5e2f95 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -963,6 +963,19 @@ struct __DRIimageExtensionRec {
* \since 4
*/
int (*write)(__DRIimage *image, const void *buf, size_t count);
+
+ /**
+ * Create image from texture.
+ *
+ * \since 5
+ */
+ __DRIimage *(*createImageFromTexture)(__DRIcontext *context,
+ int target,
+ unsigned texture,
+ int level,
+ int depth,
+ void *loaderPrivate);
+
};
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 4a02838383..206c960ccb 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -503,6 +503,12 @@ dri2_setup_screen(_EGLDisplay *disp)
disp->Extensions.MESA_drm_image = EGL_TRUE;
disp->Extensions.KHR_image_base = EGL_TRUE;
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
+ if (dri2_dpy->image->base.version >= 5 &&
+ dri2_dpy->image->createImageFromTexture) {
+ disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
+ disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
+ disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
+ }
}
}
@@ -993,6 +999,75 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
}
static _EGLImage *
+dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attr_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
+ struct dri2_egl_image *dri2_img;
+ GLuint texture = (GLuint) (uintptr_t) buffer;
+ _EGLImageAttribs attrs;
+ GLuint depth;
+ GLenum gl_target;
+
+ if (texture == 0) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
+ return EGL_NO_IMAGE_KHR;
+
+ switch (target) {
+ case EGL_GL_TEXTURE_2D_KHR:
+ depth = 0;
+ gl_target = GL_TEXTURE_2D;
+ break;
+ case EGL_GL_TEXTURE_3D_KHR:
+ depth = attrs.GLTextureZOffset;
+ gl_target = GL_TEXTURE_3D;
+ break;
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+ depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
+ gl_target = GL_TEXTURE_CUBE_MAP;
+ break;
+ }
+
+ dri2_img = malloc(sizeof *dri2_img);
+ if (!dri2_img) {
+ _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ if (!_eglInitImage(&dri2_img->base, disp)) {
+ _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+ free(dri2_img);
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ dri2_img->dri_image =
+ dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
+ gl_target,
+ texture,
+ depth,
+ attrs.GLTextureLevel,
+ dri2_img);
+
+ if (!dri2_img->dri_image) {
+ free(dri2_img);
+ return EGL_NO_IMAGE_KHR;
+ }
+ return &dri2_img->base;
+}
+
+static _EGLImage *
dri2_create_image_drm_name(_EGLDisplay *disp, _EGLContext *ctx,
EGLint name,
const _EGLImageAttribs *attrs,
@@ -1120,6 +1195,15 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
(void) drv;
switch (target) {
+ case EGL_GL_TEXTURE_2D_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+ case EGL_GL_TEXTURE_3D_KHR:
+ return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
case EGL_GL_RENDERBUFFER_KHR:
return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
case EGL_DRM_BUFFER_MESA:
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index fd63a69151..3c24ff5488 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -145,6 +145,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
GLint lodbias, aniso = 0;
GLubyte border[4];
GLfloat maxlod;
+ uint32_t tile_x, tile_y;
memset(state, 0, sizeof(state));
@@ -165,7 +166,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
drm_intel_bo_reference(intelObj->mt->region->bo);
i915->state.tex_buffer[unit] = intelObj->mt->region->bo;
- i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */
+ i915->state.tex_offset[unit] = intel_miptree_tile_offsets(intelObj->mt,
+ &tile_x, &tile_y);
+
+ assert(tile_x == 0 && tile_y == 0);
format = translate_texture_format(firstImage->TexFormat,
sampler->DepthMode);
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 6e745cf71a..1f81e4a3c5 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -656,6 +656,7 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
uint32_t *surf;
int width, height, depth;
+ uint32_t tile_x, tile_y;
intel_miptree_get_dimensions_for_image(firstImage, &width, &height, &depth);
@@ -671,7 +672,8 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
sampler->sRGBDecode) <<
BRW_SURFACE_FORMAT_SHIFT));
- surf[1] = intelObj->mt->region->bo->offset; /* reloc */
+ surf[1] = (intel_miptree_tile_offsets(mt, &tile_x, &tile_y) +
+ intelObj->mt->region->bo->offset); /* reloc */
surf[2] = ((intelObj->_MaxLevel - tObj->BaseLevel) << BRW_SURFACE_LOD_SHIFT |
(width - 1) << BRW_SURFACE_WIDTH_SHIFT |
@@ -684,12 +686,21 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
surf[4] = 0;
- surf[5] = (mt->align_h == 4) ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0;
+ assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0));
+ /* Note that the low bits of these fields are missing, so
+ * there's the possibility of getting in trouble.
+ */
+ assert(tile_x % 4 == 0);
+ assert(tile_y % 2 == 0);
+ surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT |
+ (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT |
+ (mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0));
/* Emit relocation to surface contents */
drm_intel_bo_emit_reloc(brw->intel.batch.bo,
brw->wm.surf_offset[surf_index] + 4,
- intelObj->mt->region->bo, 0,
+ intelObj->mt->region->bo,
+ surf[1] - mt->region->bo->offset,
I915_GEM_DOMAIN_SAMPLER, 0);
}
diff --git a/src/mesa/drivers/dri/i965/gen6_blorp.cpp b/src/mesa/drivers/dri/i965/gen6_blorp.cpp
index 601bc9bbcd..d066af28d8 100644
--- a/src/mesa/drivers/dri/i965/gen6_blorp.cpp
+++ b/src/mesa/drivers/dri/i965/gen6_blorp.cpp
@@ -415,6 +415,7 @@ gen6_blorp_emit_surface_state(struct brw_context *brw,
{
uint32_t wm_surf_offset;
uint32_t width, height;
+ uint32_t tile_x, tile_y;
surface->get_miplevel_dims(&width, &height);
if (surface->num_samples > 0) { /* TODO: seems clumsy */
width /= 2;
@@ -440,7 +441,8 @@ gen6_blorp_emit_surface_state(struct brw_context *brw,
format << BRW_SURFACE_FORMAT_SHIFT);
/* reloc */
- surf[1] = region->bo->offset; /* No tile offsets needed */
+ surf[1] = (intel_miptree_tile_offsets(surface->mt, &tile_x, &tile_y) +
+ region->bo->offset); /* reloc */
surf[2] = (0 << BRW_SURFACE_LOD_SHIFT |
(width - 1) << BRW_SURFACE_WIDTH_SHIFT |
@@ -458,8 +460,14 @@ gen6_blorp_emit_surface_state(struct brw_context *brw,
surf[4] = brw_get_surface_num_multisamples(surface->num_samples);
- surf[5] = (0 << BRW_SURFACE_X_OFFSET_SHIFT |
- 0 << BRW_SURFACE_Y_OFFSET_SHIFT |
+ assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0));
+ /* Note that the low bits of these fields are missing, so
+ * there's the possibility of getting in trouble.
+ */
+ assert(tile_x % 4 == 0);
+ assert(tile_y % 2 == 0);
+ surf[5] = (tile_x << BRW_SURFACE_X_OFFSET_SHIFT |
+ tile_y << BRW_SURFACE_Y_OFFSET_SHIFT |
(surface->mt->align_h == 4 ?
BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0));
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 7018c3732b..fef8976aa3 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -242,18 +242,24 @@ intel_miptree_create(struct intel_context *intel,
return mt;
}
-
+/**
+ * Create miptree for region based on offset and size
+ */
struct intel_mipmap_tree *
-intel_miptree_create_for_region(struct intel_context *intel,
+intel_miptree_create_for_offset(struct intel_context *intel,
GLenum target,
gl_format format,
- struct intel_region *region)
+ struct intel_region *region,
+ GLuint width,
+ GLuint height,
+ GLuint offset_x,
+ GLuint offset_y)
{
struct intel_mipmap_tree *mt;
mt = intel_miptree_create_internal(intel, target, format,
0, 0,
- region->width, region->height, 1,
+ width, height, 1,
true, 0 /* num_samples */,
false /* msaa_is_interleaved */);
if (!mt)
@@ -261,10 +267,34 @@ intel_miptree_create_for_region(struct intel_context *intel,
intel_region_reference(&mt->region, region);
+ /* Fixup tree to include correct offsets */
+ mt->total_width = mt->region->width;
+ mt->total_height = mt->region->height;
+ mt->level[0].level_x = offset_x;
+ mt->level[0].level_y = offset_y;
+ mt->level[0].slice[0].x_offset = offset_x;
+ mt->level[0].slice[0].y_offset = offset_y;
+
return mt;
}
/**
+ * Convince for common case where we use whole region.
+ *
+ * See also \c intel_miptree_create_for_region_offset
+ */
+struct intel_mipmap_tree *
+intel_miptree_create_for_region(struct intel_context *intel,
+ GLenum target,
+ gl_format format,
+ struct intel_region *region)
+{
+ return intel_miptree_create_for_offset(intel, target, format, region,
+ 0, 0,
+ 0, 0);
+}
+
+/**
* Determine whether the MSAA surface being created should use an interleaved
* layout or a sliced layout, based on the chip generation and the surface
* type.
@@ -428,6 +458,24 @@ intel_miptree_get_dimensions_for_image(struct gl_texture_image *image,
}
}
+uint32_t
+intel_miptree_tile_offsets(struct intel_mipmap_tree *mt,
+ uint32_t *tile_x,
+ uint32_t *tile_y)
+{
+ struct intel_region *region = mt->region;
+ uint32_t mask_x, mask_y;
+ int fl = mt->first_level;
+
+ intel_region_get_tile_masks(region, &mask_x, &mask_y);
+
+ *tile_x = mt->level[fl].level_x & mask_x;
+ *tile_y = mt->level[fl].level_y & mask_y;
+ return intel_region_get_aligned_offset(region,
+ mt->level[fl].level_x & ~mask_x,
+ mt->level[fl].level_y & ~mask_y);
+}
+
/**
* Can the image be pulled into a unified mipmap tree? This mirrors
* the completeness test in a lot of ways.
@@ -629,6 +677,22 @@ intel_miptree_copy_teximage(struct intel_context *intel,
intel_miptree_reference(&intelImage->mt, dst_mt);
}
+/**
+ * Copies all image data in from src miptree to dst miptree.
+ */
+void
+intel_miptree_copy(struct intel_context *intel,
+ struct intel_mipmap_tree *dst_mt,
+ struct intel_mipmap_tree *src_mt)
+{
+ for (GLuint level = src_mt->first_level; level < src_mt->last_level + 1; level++) {
+ GLuint depth = src_mt->level[level].depth;
+ for (GLuint slice = 0; slice < depth; slice++) {
+ intel_miptree_copy_slice(intel, dst_mt, src_mt, level, 0, slice);
+ }
+ }
+}
+
bool
intel_miptree_alloc_hiz(struct intel_context *intel,
struct intel_mipmap_tree *mt,
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 5c57e02f03..a4473c0c48 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -267,6 +267,16 @@ intel_miptree_create_for_region(struct intel_context *intel,
gl_format format,
struct intel_region *region);
+struct intel_mipmap_tree *
+intel_miptree_create_for_offset(struct intel_context *intel,
+ GLenum target,
+ gl_format format,
+ struct intel_region *region,
+ GLuint width,
+ GLuint height,
+ GLuint offset_x,
+ GLuint offset_y);
+
/**
* Create a miptree appropriate as the storage for a non-texture renderbuffer.
* The miptree has the following properties:
@@ -316,6 +326,11 @@ void
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image,
int *width, int *height, int *depth);
+uint32_t
+intel_miptree_tile_offsets(struct intel_mipmap_tree *mt,
+ uint32_t *tile_x,
+ uint32_t *tile_y);
+
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
GLuint x, GLuint y,
@@ -330,6 +345,11 @@ intel_miptree_copy_teximage(struct intel_context *intel,
struct intel_texture_image *intelImage,
struct intel_mipmap_tree *dst_mt);
+void
+intel_miptree_copy(struct intel_context *intel,
+ struct intel_mipmap_tree *dst_mt,
+ struct intel_mipmap_tree *src_mt);
+
/**
* Copy the stencil data from \c mt->stencil_mt->region to \c mt->region for
* the given miptree slice.
diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h
index 2fb30eb48f..b8d4eb398f 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.h
+++ b/src/mesa/drivers/dri/intel/intel_regions.h
@@ -148,6 +148,10 @@ struct __DRIimageRec {
uint32_t dri_format;
GLuint format;
GLenum data_type;
+ GLuint width;
+ GLuint height;
+ GLuint offset_x;
+ GLuint offset_y;
void *data;
};
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 458178fe92..7a2c5b7463 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -30,11 +30,13 @@
#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"
#include "main/version.h"
#include "swrast/s_renderbuffer.h"
+#include "egl/main/eglcurrent.h"
#include "utils.h"
#include "xmlpool.h"
@@ -102,6 +104,10 @@ const GLuint __driNConfigOptions = 14;
#include "intel_tex.h"
#include "intel_regions.h"
+#ifndef I915
+#include "brw_context.h"
+#endif
+
#include "i915_drm.h"
#ifdef USE_NEW_INTERFACE
@@ -175,6 +181,65 @@ static const struct __DRI2flushExtensionRec intelFlushExtension = {
dri2InvalidateDrawable,
};
+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->offset_x = mt->level[level].slice[zoffset].x_offset;
+ image->offset_y = mt->level[level].slice[zoffset].y_offset;
+
+ intel_region_get_tile_masks(mt->region, &mask_x, &mask_y);
+
+#ifndef I915
+ has_surface_tile_offset = brw_context(&intel->ctx)->has_surface_tile_offset;
+#endif
+
+ if (!has_surface_tile_offset && (image->offset_x & mask_x) &&
+ (image->offset_y & 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.
+ *
+ * If application didn't pass EGL_IMAGE_PRESERVED_KHR, EGL_TRUE but
+ * current internal interface assumes preserve is always set.
+ */
+ 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_is_interleaved);
+
+ intel->use_texture_tiling = texture_tiling;
+ intel_miptree_copy(intel, new_mt, mt);
+ intel_miptree_reference(pmt, new_mt);
+ image->offset_x = new_mt->level[level].slice[zoffset].x_offset;
+ image->offset_y = 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->offset_x = 0;
+ image->offset_y = 0;
+}
+
static __DRIimage *
intel_create_image_from_name(__DRIscreen *screen,
int width, int height, int format,
@@ -232,6 +297,8 @@ intel_create_image_from_name(__DRIscreen *screen,
return NULL;
}
+ intel_setup_image_from_dimensions(image);
+
return image;
}
@@ -246,21 +313,88 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer);
if (!rb) {
- _mesa_error(&intel->ctx,
- GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
+ _eglError(EGL_BAD_PARAMETER, __func__);
return NULL;
}
irb = intel_renderbuffer(rb);
image = CALLOC(sizeof *image);
- if (image == NULL)
+ if (image == NULL) {
+ _eglError(EGL_BAD_ALLOC, __func__);
return NULL;
+ }
image->internal_format = rb->InternalFormat;
image->format = rb->Format;
image->data_type = GL_UNSIGNED_BYTE;
image->data = loaderPrivate;
- intel_region_reference(&image->region, irb->mt->region);
+ intel_setup_image_from_mipmap_tree(intel, image, &irb->mt, 0, 0);
+
+ 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;
+ }
+
+ 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) {
+ _eglError(EGL_BAD_PARAMETER, __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)) {
+ _eglError(EGL_BAD_PARAMETER, __func__);
+ return NULL;
+ }
+
+ if (level < obj->BaseLevel || level > obj->_MaxLevel) {
+ _eglError(EGL_BAD_MATCH, __func__);
+ return NULL;
+ }
+
+ if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) {
+ _eglError(EGL_BAD_MATCH, __func__);
+ return NULL;
+ }
+ image = CALLOC(sizeof *image);
+ if (image == NULL) {
+ _eglError(EGL_BAD_ALLOC, __func__);
+ return NULL;
+ }
+
+ image->internal_format = obj->Image[face][level]->InternalFormat;
+ image->format = obj->Image[face][level]->TexFormat;
+ image->data_type = GL_UNSIGNED_BYTE;
+ image->data = loaderPrivate;
+ intel_setup_image_from_mipmap_tree(intel, image, &iobj->mt, level, zoffset);
switch (image->format) {
case MESA_FORMAT_RGB565:
@@ -358,6 +492,8 @@ intel_create_image(__DRIscreen *screen,
FREE(image);
return NULL;
}
+
+ intel_setup_image_from_dimensions(image);
return image;
}
@@ -402,6 +538,10 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
image->dri_format = orig_image->dri_format;
image->format = orig_image->format;
image->data_type = orig_image->data_type;
+ image->width = orig_image->width;
+ image->height = orig_image->height;
+ image->offset_x = orig_image->offset_x;
+ image->offset_y = orig_image->offset_y;
image->data = loaderPrivate;
return image;
@@ -439,7 +579,7 @@ intel_image_write(__DRIimage *image, const void *buf, size_t count)
}
static struct __DRIimageExtensionRec intelImageExtension = {
- { __DRI_IMAGE, 4 },
+ { __DRI_IMAGE, 5 },
intel_create_image_from_name,
intel_create_image_from_renderbuffer,
intel_destroy_image,
@@ -447,7 +587,8 @@ static struct __DRIimageExtensionRec intelImageExtension = {
intel_query_image,
intel_dup_image,
intel_validate_usage,
- intel_image_write
+ intel_image_write,
+ intel_create_image_from_texture,
};
static const __DRIextension *intelScreenExtensions[] = {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index abd75c51d2..c1ed822242 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -286,7 +286,11 @@ intel_set_texture_image_region(struct gl_context *ctx,
struct intel_region *region,
GLenum target,
GLenum internalFormat,
- gl_format format)
+ gl_format format,
+ GLuint width,
+ GLuint height,
+ GLuint offset_x,
+ GLuint offset_y)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(image);
@@ -294,14 +298,16 @@ intel_set_texture_image_region(struct gl_context *ctx,
struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
_mesa_init_teximage_fields(&intel->ctx, image,
- region->width, region->height, 1,
+ width, height, 1,
0, internalFormat, format);
ctx->Driver.FreeTextureImageBuffer(ctx, image);
- intel_image->mt = intel_miptree_create_for_region(intel, target,
+ intel_image->mt = intel_miptree_create_for_offset(intel, target,
image->TexFormat,
- region);
+ region,
+ width, height,
+ offset_x, offset_y);
if (intel_image->mt == NULL)
return;
@@ -360,7 +366,10 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
_mesa_lock_texture(&intel->ctx, texObj);
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
- internalFormat, texFormat);
+ internalFormat, texFormat,
+ rb->mt->region->width,
+ rb->mt->region->height,
+ 0, 0);
_mesa_unlock_texture(&intel->ctx, texObj);
}
@@ -391,7 +400,9 @@ intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
return;
intel_set_texture_image_region(ctx, texImage, image->region,
- target, image->internal_format, image->format);
+ target, image->internal_format, image->format,
+ image->width, image->height,
+ image->offset_x, image->offset_y);
}
#endif