Add TTM buffer object based texture from pixmap implementation.
authorKristian Høgsberg <krh@redhat.com>
Fri, 15 Feb 2008 03:12:51 +0000 (22:12 -0500)
committerKristian Høgsberg <krh@redhat.com>
Fri, 15 Feb 2008 03:12:51 +0000 (22:12 -0500)
Currently only implemented for intel hw.

include/GL/internal/dri_interface.h
src/mesa/drivers/dri/intel/intel_mipmap_tree.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.h
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_tex.h
src/mesa/drivers/dri/intel/intel_tex_image.c

index 50f1d1a765c4a463953cb1024d1f4c498976f5f9..b83aff18f9738ca4fa2673ab250998874c618601 100644 (file)
@@ -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...
  */
index 97a82fe9d0f3be86d57eaad07ea51502ac8cfa9f..d446b2b392ab10feed2ed0fdf92624600f071334 100644 (file)
@@ -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,20 +87,81 @@ 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 (!ok) {
+      free(mt);
+      return NULL;
    }
 
+   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:
index e3b31f9c6e5f0c0d63a9b05e2a137283f7a7583e..3c1a6ffa2a81cca42eaad9048cbc6d9a84c22c9c 100644 (file)
@@ -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);
index 7e0c52005dee3dde98210278f9f2edc085f51202..2392c2c49ccc0cecdca48e94003b673e09a3d647 100644 (file)
@@ -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
 };
 
index 2973e0ceb9feb8ce21011005fac93606ab119fc8..d1055be93e6879f56c664d2953ef915716adb75a 100644 (file)
@@ -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);
 
index 0500829f4b6c3cabc556eba31fdd6db66e6a681e..4cbc453c704d9b1f8921becd3803340b2b59f5fe 100644 (file)
@@ -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);
+}