diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 50f1d1a765c..b83aff18f97 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -64,6 +64,7 @@ typedef struct __DRIallocateExtensionRec __DRIallocateExtension; typedef struct __DRIframeTrackingExtensionRec __DRIframeTrackingExtension; typedef struct __DRImediaStreamCounterExtensionRec __DRImediaStreamCounterExtension; typedef struct __DRItexOffsetExtensionRec __DRItexOffsetExtension; +typedef struct __DRItexBufferExtensionRec __DRItexBufferExtension; /*@}*/ @@ -221,6 +222,25 @@ struct __DRItexOffsetExtensionRec { }; +#define __DRI_TEX_BUFFER "DRI_TexBuffer" +#define __DRI_TEX_BUFFER_VERSION 1 +struct __DRItexBufferExtensionRec { + __DRIextension base; + + /** + * Method to override base texture image with a DRM memory manager + * buffer object. The depth passed in allows e.g. to ignore the + * alpha channel of texture images where the non-alpha components + * don't occupy a whole texel. + * + * For GLX_EXT_texture_from_pixmap with AIGLX. + */ + void (*setTexBuffer)(__DRIcontext *pDRICtx, + GLint target, unsigned long handle, + GLint cpp, GLuint pitch, GLuint height); +}; + + /** * Macros for building symbol and strings. Standard CPP two step... */ diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 97a82fe9d0f..d446b2b392a 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -49,17 +49,15 @@ target_to_target(GLenum target) } } -struct intel_mipmap_tree * -intel_miptree_create(struct intel_context *intel, - GLenum target, - GLenum internal_format, - GLuint first_level, - GLuint last_level, - GLuint width0, - GLuint height0, - GLuint depth0, - GLuint cpp, - GLuint compress_byte) +static struct intel_mipmap_tree * +intel_miptree_create_internal(struct intel_context *intel, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + GLuint width0, + GLuint height0, + GLuint depth0, GLuint cpp, GLuint compress_byte) { GLboolean ok; struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); @@ -89,14 +87,7 @@ intel_miptree_create(struct intel_context *intel, ok = brw_miptree_layout(intel, mt); #endif - if (ok) { - assert (mt->pitch); - - mt->region = intel_region_alloc(intel, - mt->cpp, mt->pitch, mt->total_height); - } - - if (!mt->region) { + if (!ok) { free(mt); return NULL; } @@ -104,6 +95,74 @@ intel_miptree_create(struct intel_context *intel, return mt; } +struct intel_mipmap_tree * +intel_miptree_create(struct intel_context *intel, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + GLuint width0, + GLuint height0, + GLuint depth0, GLuint cpp, GLuint compress_byte) +{ + struct intel_mipmap_tree *mt; + + mt = intel_miptree_create_internal(intel, target, internal_format, + first_level, last_level, width0, + height0, depth0, cpp, compress_byte); + if (!mt) + return NULL; + + assert (mt->pitch); + mt->region = intel_region_alloc(intel, + mt->cpp, mt->pitch, mt->total_height); + + if (!mt->region) { + free(mt); + return NULL; + } + + return mt; +} + +struct intel_mipmap_tree * +intel_miptree_create_for_region(struct intel_context *intel, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + struct intel_region *region, + GLuint depth0, + GLuint compress_byte) +{ + struct intel_mipmap_tree *mt; + + mt = intel_miptree_create_internal(intel, target, internal_format, + first_level, last_level, + region->pitch, region->height, depth0, + region->cpp, compress_byte); + if (!mt) + return mt; +#if 0 + if (mt->pitch != region->pitch) { + fprintf(stderr, + "region pitch (%d) doesn't match mipmap tree pitch (%d)\n", + region->pitch, mt->pitch); + free(mt); + return NULL; + } +#else + /* The mipmap tree pitch is aligned to 64 bytes to make sure render + * to texture works, but we don't need that for texturing from a + * pixmap. Just override it here. */ + mt->pitch = region->pitch; +#endif + + mt->region = region; + + return mt; + } + /** * intel_miptree_pitch_align: * diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index e3b31f9c6e5..3c1a6ffa2a8 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -124,6 +124,16 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, GLuint cpp, GLuint compress_byte); +struct intel_mipmap_tree * +intel_miptree_create_for_region(struct intel_context *intel, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + struct intel_region *region, + GLuint depth0, + GLuint compress_byte); + int intel_miptree_pitch_align (struct intel_context *intel, struct intel_mipmap_tree *mt, int pitch); diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 7e0c52005de..2392c2c49cc 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -398,6 +398,11 @@ static const __DRItexOffsetExtension intelTexOffsetExtension = { intelSetTexOffset, }; +static const __DRItexBufferExtension intelTexBufferExtension = { + { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, + intelSetTexBuffer, +}; + static const __DRIextension *intelExtensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, @@ -405,6 +410,7 @@ static const __DRIextension *intelExtensions[] = { &driFrameTrackingExtension.base, &driMediaStreamCounterExtension.base, &intelTexOffsetExtension.base, + &intelTexBufferExtension.base, NULL }; diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 2973e0ceb9f..d1055be93e6 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -137,6 +137,9 @@ void intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, unsigned long long offset, GLint depth, GLuint pitch); +void intelSetTexBuffer(__DRIcontext *pDRICtx, + GLint target, unsigned long handle, + GLint cpp, GLuint pitch, GLuint height); GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit); diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 0500829f4b6..4cbc453c704 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -14,6 +14,7 @@ #include "texformat.h" #include "texobj.h" #include "texstore.h" +#include "teximage.h" #include "intel_context.h" #include "intel_mipmap_tree.h" @@ -692,3 +693,69 @@ intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, if (offset) intelObj->textureOffset = offset; } + +void +intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, + unsigned long handle, GLint cpp, GLuint pitch, GLuint height) +{ + __DRIcontextPrivate *driContext = pDRICtx->private; + struct intel_context *intel = driContext->driverPrivate; + struct intel_texture_object *intelObj; + struct intel_texture_image *intelImage; + struct intel_mipmap_tree *mt; + struct intel_region *region; + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + int level = 0; + + /* FIXME: type, format, internalFormat */ + int type = GL_BGRA; + int format = GL_UNSIGNED_BYTE; + int internalFormat = (cpp == 3 ? 3 : 4); + cpp = 4; + pitch /= 4; + + texUnit = &intel->ctx.Texture.Unit[intel->ctx.Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(&intel->ctx, texUnit, target); + intelObj = intel_texture_object(texObj); + + if (!intelObj) + return; + + region = intel_region_alloc_for_handle(intel, cpp, pitch, height, + 0, handle); + + mt = intel_miptree_create_for_region(intel, target, + internalFormat, + 0, 0, region, 1, 0); + if (mt == NULL) + return; + + _mesa_lock_texture(&intel->ctx, texObj); + + if (intelObj->mt) + intel_miptree_release(intel, &intelObj->mt); + + intelObj->mt = mt; + texImage = _mesa_get_tex_image(&intel->ctx, texObj, target, level); + _mesa_init_teximage_fields(&intel->ctx, target, texImage, + pitch, height, 1, + 0, internalFormat); + + intelImage = intel_texture_image(texImage); + intelImage->face = target_to_face(target); + intelImage->level = level; + texImage->TexFormat = intelChooseTextureFormat(&intel->ctx, internalFormat, + type, format); + _mesa_set_fetch_functions(texImage, 2); + texImage->RowStride = pitch; + intel_miptree_reference(&intelImage->mt, intelObj->mt); + + if (!intel_miptree_match_image(intelObj->mt, &intelImage->base, + intelImage->face, intelImage->level)) { + fprintf(stderr, "miptree doesn't match image\n"); + } + + _mesa_unlock_texture(&intel->ctx, texObj); +}