[Intel-gfx] [RFC] libdrm_intel: Add support for userptr objects

Chris Wilson chris at chris-wilson.co.uk
Wed Jul 9 16:47:56 CEST 2014


On Wed, Jul 09, 2014 at 04:25:55PM +0200, Daniel Vetter wrote:
> On Wed, Jul 09, 2014 at 02:16:59PM +0100, Damien Lespiau wrote:
> > On Wed, Jul 09, 2014 at 02:08:08PM +0100, Tvrtko Ursulin wrote:
> > > 
> > > On 06/19/2014 12:13 PM, Damien Lespiau wrote:
> > > >On Wed, Feb 26, 2014 at 04:41:41PM +0000, Tvrtko Ursulin wrote:
> > > >>From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> > > >>
> > > >>Allow userptr objects to be created and used via libdrm_intel.
> > > >>
> > > >>At the moment tiling and mapping to GTT aperture is not supported
> > > >>due hardware limitations across different generations and uncertainty
> > > >>about its usefulness.
> > > >>
> > > >>Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> > > >>---
> > > >>  include/drm/i915_drm.h    |  16 +++++
> > > >>  intel/intel_bufmgr.c      |  13 ++++
> > > >>  intel/intel_bufmgr.h      |   5 ++
> > > >>  intel/intel_bufmgr_gem.c  | 154 +++++++++++++++++++++++++++++++++++++++++++++-
> > > >>  intel/intel_bufmgr_priv.h |  12 +++-
> > > >>  5 files changed, 198 insertions(+), 2 deletions(-)
> > > >
> > > >Apart from couple of remarks below I couldn't find anything that would
> > > >prevent merging this. Well, except maybe that it'd be very nice to have
> > > >some feedback from someone using it, we do have an API/ABI guarantee on
> > > >libdrm after all.
> > > 
> > > Looks like I've forgotten to reply to this. I did address the other
> > > review comments and sent out a v2 back then.
> > > 
> > > But for what users are concerned, apart from internal ones who have
> > > been using this API for some years now, I don't know of any.
> > 
> > Well, considering this is only a wrapper of an ioctl() already
> > upstreamed, I'm inclined to just push it as is. Daniel any thoughts?
> 
> Since both igt and sna have their own wrappers and the beinget patch for
> this hasn't surfaced yet we don't really have a public open-source user
> for this yet. My understanding of Dave's stance is that we should hold off
> with committing until this is requirement is fulfilled.

The interface is fairly ugly since it combines the tiling into the
create, which is just as convenient as a second step.

But if you want a user, just wire up an accelerated glReadPixels. Now,
this is only really beneficial as the current ReadPixels is not well
optimised and it assumes that userptr drm_intel_bo is automatically
synced on destruction:

diff --git a/src/mesa/drivers/dri/i965/intel_pixel_read.c b/src/mesa/drivers/dri/i965/intel_pixel_read.c
index beb3152..1b1f7e4 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_read.c
@@ -161,6 +161,103 @@ do_blit_readpixels(struct gl_context * ctx,
    return true;
 }
 
+static bool
+do_userptr_readpixels(struct gl_context * ctx,
+                     GLint x, GLint y, GLsizei width, GLsizei height,
+                     GLenum format, GLenum type,
+                     const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
+{
+   struct brw_context *brw = brw_context(ctx);
+   GLuint dst_offset;
+   drm_intel_bo *dst_buffer;
+   GLint dst_x, dst_y;
+   GLuint dirty;
+
+   DBG("%s\n", __FUNCTION__);
+
+   assert(_mesa_is_bufferobj(pack->BufferObj));
+
+   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+   uintptr_t start, end;
+
+   /* Currently this function only supports reading from color buffers. */
+   if (!_mesa_is_color_format(format))
+      return false;
+
+   assert(irb != NULL);
+
+   if (ctx->_ImageTransferState ||
+       !_mesa_format_matches_format_and_type(irb->mt->format, format, type,
+                                             false)) {
+      DBG("%s - bad format for blit\n", __FUNCTION__);
+      return false;
+   }
+
+   if (pack->SwapBytes || pack->LsbFirst) {
+      DBG("%s: bad packing params\n", __FUNCTION__);
+      return false;
+   }
+
+   int dst_stride = _mesa_image_row_stride(pack, width, format, type);
+   bool dst_flip = false;
+   /* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a
+    * normal dst_stride.
+    */
+   struct gl_pixelstore_attrib uninverted_pack = *pack;
+   if (pack->Invert) {
+      dst_stride = -dst_stride;
+      dst_flip = true;
+      uninverted_pack.Invert = false;
+   }
+
+   dst_offset = (GLintptr)pixels;
+   dst_offset += _mesa_image_offset(2, &uninverted_pack, width, height,
+                                   format, type, 0, 0, 0);
+
+   if (!_mesa_clip_copytexsubimage(ctx,
+                                  &dst_x, &dst_y,
+                                  &x, &y,
+                                  &width, &height)) {
+      return true;
+   }
+
+   dirty = brw->front_buffer_dirty;
+   intel_prepare_render(brw);
+   brw->front_buffer_dirty = dirty;
+
+   start = (uintptr_t)(pixel + dst_offset) & ~4095;
+   end = (uintptr_t)(pixel + dst_offset + dst_stride * height + 4095) & ~4095;
+
+   dst_buffer = drm_intel_bo_alloc_userptr(bufmgr, "glReadPixels",
+                                          (void *)start,
+                                          I915_TILING_NONE, dst_stride,
+                                          end - start, 0);
+
+   struct intel_mipmap_tree *pbo_mt =
+      intel_miptree_create_for_bo(brw,
+                                  dst_buffer,
+                                  irb->mt->format,
+                                  (uintptr_t)(pixel + dst_offset) - start,
+                                  width, height,
+                                  dst_stride);
+
+   if (!intel_miptree_blit(brw,
+                           irb->mt, irb->mt_level, irb->mt_layer,
+                           x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer),
+                           pbo_mt, 0, 0,
+                           0, 0, dst_flip,
+                           width, height, GL_COPY)) {
+      return false;
+   }
+
+   intel_miptree_release(&pbo_mt);
+   drm_intel_bo_unreference(dst_buffer);
+
+   DBG("%s - DONE\n", __FUNCTION__);
+
+   return true;
+}
+
 void
 intelReadPixels(struct gl_context * ctx,
                 GLint x, GLint y, GLsizei width, GLsizei height,
@@ -182,6 +280,13 @@ intelReadPixels(struct gl_context * ctx,
       perf_debug("%s: fallback to CPU mapping in PBO case\n", __FUNCTION__);
    }
 
+   if (do_userptr_readpixels(ctx,
+                            x, y, width, height,
+                            format, type,
+                            pack, pixels)) {
+      return;
+   }
+
    /* glReadPixels() wont dirty the front buffer, so reset the dirty
     * flag after calling intel_prepare_render(). */
    dirty = brw->front_buffer_dirty;



-- 
Chris Wilson, Intel Open Source Technology Centre



More information about the Intel-gfx mailing list