Beispiel #1
0
static void do_draw_pix( GLcontext *ctx,
			 GLint x, GLint y, GLsizei width, GLsizei height,
			 GLint pitch,
			 const void *pixels,
			 GLuint dest )
{
   intelContextPtr intel = INTEL_CONTEXT(ctx);
   __DRIdrawablePrivate *dPriv = intel->driDrawable;
   drm_clip_rect_t *box = dPriv->pClipRects;
   int nbox = dPriv->numClipRects;
   int i;
   int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
   int src_pitch = pitch;

   assert(src_offset != ~0);  /* should be caught earlier */

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   intelFlush( &intel->ctx );
   LOCK_HARDWARE( intel );
   if (ctx->DrawBuffer)
   {
      y -= height;			/* cope with pixel zoom */
   
      if (!clip_pixelrect(ctx, ctx->DrawBuffer,
			  &x, &y, &width, &height)) {
	 UNLOCK_HARDWARE( intel );
	 return;
      }

      y = dPriv->h - y - height; 	/* convert from gl to hardware coords */
      x += dPriv->x;
      y += dPriv->y;

      for (i = 0 ; i < nbox ; i++ )
      {
	 GLint bx, by, bw, bh;
	 if (intersect_region(box + i, x, y, width, height,
			      &bx, &by, &bw, &bh)) {
            intelEmitCopyBlitLocked( intel,
                                     intel->intelScreen->cpp,
                                     src_pitch, src_offset,
                                     intel->intelScreen->front.pitch,
                                     intel->drawRegion->offset,
                                     bx - x, by - y,
                                     bx, by,
                                     bw, bh );
         }
      }
   }
   UNLOCK_HARDWARE( intel );
   intelFinish( &intel->ctx );
}
Beispiel #2
0
static void do_draw_pix( GLcontext *ctx,
                         GLint x, GLint y, GLsizei width, GLsizei height,
                         GLint pitch,
                         const void *pixels,
                         GLuint planemask)
{
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
    drm_clip_rect_t *box = dPriv->pClipRects;
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorDrawBuffers[0][0];
    driRenderbuffer *drb = (driRenderbuffer *) rb;
    int nbox = dPriv->numClipRects;
    int i;
    int blit_format;
    int size;
    int src_offset = r200GartOffsetFromVirtual( rmesa, pixels );
    int src_pitch = pitch * rmesa->r200Screen->cpp;

    if (R200_DEBUG & DEBUG_PIXEL)
        fprintf(stderr, "%s\n", __FUNCTION__);

    switch ( rmesa->r200Screen->cpp ) {
    case 2:
        blit_format = R200_CP_COLOR_FORMAT_RGB565;
        break;
    case 4:
        blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
        break;
    default:
        return;
    }


    LOCK_HARDWARE( rmesa );

    if (rmesa->store.cmd_used)
        r200FlushCmdBufLocked( rmesa, __FUNCTION__ );

    y -= height;			/* cope with pixel zoom */

    if (!clip_pixelrect(ctx, ctx->DrawBuffer,
                        &x, &y, &width, &height,
                        &size)) {
        UNLOCK_HARDWARE( rmesa );
        return;
    }

    y = dPriv->h - y - height; 	/* convert from gl to hardware coords */
    x += dPriv->x;
    y += dPriv->y;


    r200EmitWait( rmesa, RADEON_WAIT_3D );

    for (i = 0 ; i < nbox ; i++ )
    {
        GLint bx = box[i].x1;
        GLint by = box[i].y1;
        GLint bw = box[i].x2 - bx;
        GLint bh = box[i].y2 - by;

        if (bx < x) bw -= x - bx, bx = x;
        if (by < y) bh -= y - by, by = y;
        if (bx + bw > x + width) bw = x + width - bx;
        if (by + bh > y + height) bh = y + height - by;
        if (bw <= 0) continue;
        if (bh <= 0) continue;

        r200EmitBlit( rmesa,
                      blit_format,
                      src_pitch, src_offset,
                      drb->pitch * drb->cpp,
                      drb->offset + rmesa->r200Screen->fbLocation,
                      bx - x, by - y,
                      bx, by,
                      bw, bh );
    }

    r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
    r200WaitForIdleLocked( rmesa ); /* required by GL */
    UNLOCK_HARDWARE( rmesa );
}
Beispiel #3
0
static GLboolean
r200TryReadPixels( GLcontext *ctx,
                   GLint x, GLint y, GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *pack,
                   GLvoid *pixels )
{
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    GLint pitch = pack->RowLength ? pack->RowLength : width;
    GLint blit_format;
    GLuint cpp = rmesa->r200Screen->cpp;
    GLint size = width * height * cpp;

    if (R200_DEBUG & DEBUG_PIXEL)
        fprintf(stderr, "%s\n", __FUNCTION__);

    /* Only accelerate reading to GART buffers.
     */
    if ( !r200IsGartMemory(rmesa, pixels,
                           pitch * height * rmesa->r200Screen->cpp ) ) {
        if (R200_DEBUG & DEBUG_PIXEL)
            fprintf(stderr, "%s: dest not GART\n", __FUNCTION__);
        return GL_FALSE;
    }

    /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
     * blitter:
     */
    if (!pack->Invert) {
        if (R200_DEBUG & DEBUG_PIXEL)
            fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
        return GL_FALSE;
    }

    if (!check_color(ctx, type, format, pack, pixels, size, pitch))
        return GL_FALSE;

    switch ( rmesa->r200Screen->cpp ) {
    case 4:
        blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
        break;
    default:
        return GL_FALSE;
    }


    /* Although the blits go on the command buffer, need to do this and
     * fire with lock held to guarentee cliprects and drawOffset are
     * correct.
     *
     * This is an unusual situation however, as the code which flushes
     * a full command buffer expects to be called unlocked.  As a
     * workaround, immediately flush the buffer on aquiring the lock.
     */
    LOCK_HARDWARE( rmesa );

    if (rmesa->store.cmd_used)
        r200FlushCmdBufLocked( rmesa, __FUNCTION__ );

    if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
                        &size)) {
        UNLOCK_HARDWARE( rmesa );
        if (R200_DEBUG & DEBUG_PIXEL)
            fprintf(stderr, "%s totally clipped -- nothing to do\n",
                    __FUNCTION__);
        return GL_TRUE;
    }

    {
        __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
        driRenderbuffer *drb = (driRenderbuffer *) ctx->ReadBuffer->_ColorReadBuffer;
        int nbox = dPriv->numClipRects;
        int src_offset = drb->offset
                         + rmesa->r200Screen->fbLocation;
        int src_pitch = drb->pitch * drb->cpp;
        int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels );
        int dst_pitch = pitch * rmesa->r200Screen->cpp;
        drm_clip_rect_t *box = dPriv->pClipRects;
        int i;

        r200EmitWait( rmesa, RADEON_WAIT_3D );

        y = dPriv->h - y - height;
        x += dPriv->x;
        y += dPriv->y;


        if (R200_DEBUG & DEBUG_PIXEL)
            fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
                    src_pitch, dst_pitch);

        for (i = 0 ; i < nbox ; i++)
        {
            GLint bx = box[i].x1;
            GLint by = box[i].y1;
            GLint bw = box[i].x2 - bx;
            GLint bh = box[i].y2 - by;

            if (bx < x) bw -= x - bx, bx = x;
            if (by < y) bh -= y - by, by = y;
            if (bx + bw > x + width) bw = x + width - bx;
            if (by + bh > y + height) bh = y + height - by;
            if (bw <= 0) continue;
            if (bh <= 0) continue;

            r200EmitBlit( rmesa,
                          blit_format,
                          src_pitch, src_offset,
                          dst_pitch, dst_offset,
                          bx, by,
                          bx - x, by - y,
                          bw, bh );
        }

        r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
    }
    UNLOCK_HARDWARE( rmesa );

    r200Finish( ctx ); /* required by GL */

    return GL_TRUE;
}
Beispiel #4
0
static GLboolean
intelTryReadPixels( GLcontext *ctx,
		  GLint x, GLint y, GLsizei width, GLsizei height,
		  GLenum format, GLenum type,
		  const struct gl_pixelstore_attrib *pack,
		  GLvoid *pixels )
{
   intelContextPtr intel = INTEL_CONTEXT(ctx);
   GLint size = 0; /* not really used */
   GLint pitch = pack->RowLength ? pack->RowLength : width;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   /* Only accelerate reading to agp buffers.
    */
   if ( !intelIsAgpMemory(intel, pixels, 
			pitch * height * intel->intelScreen->cpp ) ) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
      return GL_FALSE;
   }

   /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
    * blitter:
    */
   if (!pack->Invert) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!check_color(ctx, type, format, pack, pixels, size, pitch))
      return GL_FALSE;

   switch ( intel->intelScreen->cpp ) {
   case 4:
      break;
   default:
      return GL_FALSE;
   }


   /* Although the blits go on the command buffer, need to do this and
    * fire with lock held to guarentee cliprects and drawing offset are
    * correct.
    *
    * This is an unusual situation however, as the code which flushes
    * a full command buffer expects to be called unlocked.  As a
    * workaround, immediately flush the buffer on aquiring the lock.
    */
   intelFlush( &intel->ctx );
   LOCK_HARDWARE( intel );
   {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      int nbox = dPriv->numClipRects;
      int src_offset = intel->readRegion->offset;
      int src_pitch = intel->intelScreen->front.pitch;
      int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
      drm_clip_rect_t *box = dPriv->pClipRects;
      int i;

      assert(dst_offset != ~0);  /* should have been caught above */

      if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) {
	 UNLOCK_HARDWARE( intel );
	 if (INTEL_DEBUG & DEBUG_PIXEL)
	    fprintf(stderr, "%s totally clipped -- nothing to do\n",
		    __FUNCTION__);
	 return GL_TRUE;
      }

      /* convert to screen coords (y=0=top) */
      y = dPriv->h - y - height;
      x += dPriv->x;
      y += dPriv->y;

      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
		 src_pitch, pitch);

      /* We don't really have to do window clipping for readpixels.
       * The OpenGL spec says that pixels read from outside the
       * visible window region (pixel ownership) have undefined value.
       */
      for (i = 0 ; i < nbox ; i++)
      {
         GLint bx, by, bw, bh;
         if (intersect_region(box+i, x, y, width, height,
                              &bx, &by, &bw, &bh)) {
            intelEmitCopyBlitLocked( intel,
                                     intel->intelScreen->cpp,
                                     src_pitch, src_offset,
                                     pitch, dst_offset,
                                     bx, by,
                                     bx - x, by - y,
                                     bw, bh );
         }
      }
   }
   UNLOCK_HARDWARE( intel );
   intelFinish( &intel->ctx );

   return GL_TRUE;
}
Beispiel #5
0
static void do_draw_pix( GLcontext *ctx,
			 GLint x, GLint y, GLsizei width, GLsizei height,
			 GLint pitch,
			 const void *pixels,
			 GLuint dest )
{
   intelContextPtr intel = INTEL_CONTEXT(ctx);
   __DRIdrawablePrivate *dPriv = intel->driDrawable;
   drm_clip_rect_t *box = dPriv->pClipRects;
   int nbox = dPriv->numClipRects;
   int i;
   int size;
   int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
   int src_pitch = pitch;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   intelFlush( &intel->ctx );
   LOCK_HARDWARE( intel );
   if (ctx->DrawBuffer)
   {
      y -= height;			/* cope with pixel zoom */
   
      if (!clip_pixelrect(ctx, ctx->DrawBuffer,
			  &x, &y, &width, &height,
			  &size)) {
	 UNLOCK_HARDWARE( intel );
	 return;
      }

      y = dPriv->h - y - height; 	/* convert from gl to hardware coords */
      x += dPriv->x;
      y += dPriv->y;


      for (i = 0 ; i < nbox ; i++ )
      {
	 GLint bx = box[i].x1;
	 GLint by = box[i].y1;
	 GLint bw = box[i].x2 - bx;
	 GLint bh = box[i].y2 - by;

	 if (bx < x) bw -= x - bx, bx = x;
	 if (by < y) bh -= y - by, by = y;
	 if (bx + bw > x + width) bw = x + width - bx;
	 if (by + bh > y + height) bh = y + height - by;
	 if (bw <= 0) continue;
	 if (bh <= 0) continue;

	 intelEmitCopyBlitLocked( intel,
			    intel->intelScreen->cpp,
			    src_pitch, src_offset,
			    intel->intelScreen->frontPitch,
			      intel->drawOffset,
			    bx - x, by - y,
			    bx, by,
			    bw, bh );
      }
   }
   UNLOCK_HARDWARE( intel );
   intelFinish( &intel->ctx );
}
Beispiel #6
0
static GLboolean
intelTryReadPixels( GLcontext *ctx,
		  GLint x, GLint y, GLsizei width, GLsizei height,
		  GLenum format, GLenum type,
		  const struct gl_pixelstore_attrib *pack,
		  GLvoid *pixels )
{
   intelContextPtr intel = INTEL_CONTEXT(ctx);
   GLint size = 0;
   GLint pitch = pack->RowLength ? pack->RowLength : width;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   /* Only accelerate reading to agp buffers.
    */
   if ( !intelIsAgpMemory(intel, pixels, 
			pitch * height * intel->intelScreen->cpp ) ) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
      return GL_FALSE;
   }

   /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
    * blitter:
    */
   if (!pack->Invert) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!check_color(ctx, type, format, pack, pixels, size, pitch))
      return GL_FALSE;

   switch ( intel->intelScreen->cpp ) {
   case 4:
      break;
   default:
      return GL_FALSE;
   }


   /* Although the blits go on the command buffer, need to do this and
    * fire with lock held to guarentee cliprects and drawOffset are
    * correct.
    *
    * This is an unusual situation however, as the code which flushes
    * a full command buffer expects to be called unlocked.  As a
    * workaround, immediately flush the buffer on aquiring the lock.
    */
   intelFlush( &intel->ctx );
   LOCK_HARDWARE( intel );
   {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      int nbox = dPriv->numClipRects;
      int src_offset = intel->drawOffset;
      int src_pitch = intel->intelScreen->frontPitch;
      int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
      drm_clip_rect_t *box = dPriv->pClipRects;
      int i;

      if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
			  &size)) {
	 UNLOCK_HARDWARE( intel );
	 if (INTEL_DEBUG & DEBUG_PIXEL)
	    fprintf(stderr, "%s totally clipped -- nothing to do\n",
		    __FUNCTION__);
	 return GL_TRUE;
      }


      y = dPriv->h - y - height;
      x += dPriv->x;
      y += dPriv->y;


      if (INTEL_DEBUG & DEBUG_PIXEL)
	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
		 src_pitch, pitch);

      for (i = 0 ; i < nbox ; i++)
      {
	 GLint bx = box[i].x1;
	 GLint by = box[i].y1;
	 GLint bw = box[i].x2 - bx;
	 GLint bh = box[i].y2 - by;
	 
	 if (bx < x) bw -= x - bx, bx = x;
	 if (by < y) bh -= y - by, by = y;
	 if (bx + bw > x + width) bw = x + width - bx;
	 if (by + bh > y + height) bh = y + height - by;
	 if (bw <= 0) continue;
	 if (bh <= 0) continue;

	 intelEmitCopyBlitLocked( intel,
			    intel->intelScreen->cpp,
			    src_pitch, src_offset,
			    pitch, dst_offset,
			    bx, by,
			    bx - x, by - y,
			    bw, bh );
      }
   }
   UNLOCK_HARDWARE( intel );
   intelFinish( &intel->ctx );

   return GL_TRUE;
}
Beispiel #7
0
static GLboolean
mgaTryDrawPixels( GLcontext *ctx,
		  GLint x, GLint y, GLsizei width, GLsizei height,
		  GLenum format, GLenum type,
		  const struct gl_pixelstore_attrib *unpack,
		  const GLvoid *pixels )
{
   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
   GLint size, skipPixels, skipRows;
   GLint pitch = unpack->RowLength ? unpack->RowLength : width;
   GLuint dest, planemask;
   GLuint cpp = mmesa->mgaScreen->cpp;

   if (!clip_pixelrect(ctx, ctx->DrawBuffer,
		       &x, &y, &width, &height,
		       &skipPixels, &skipRows, &size)) {
      return GL_TRUE;
   }


   switch (format) {
#if defined(MESA_packed_depth_stencil)
   case GL_DEPTH_STENCIL_MESA:
      dest = mmesa->mgaScreen->depthOffset;
      planemask = ~0;
      if (!check_depth_stencil_24_8(ctx, type, unpack, pixels, size, pitch) ||
	  !check_depth_per_fragment_ops(ctx) ||
	  !check_stencil_per_fragment_ops(ctx))
	 return GL_FALSE;
      break;
#endif

   case GL_DEPTH_COMPONENT:
      dest = mmesa->mgaScreen->depthOffset;

      if (ctx->Visual.depthBits == 24)
	 planemask = ~0xff;
      else
	 planemask = ~0;

      if (!check_depth(ctx, type, unpack, pixels, size, pitch) ||
	  !check_depth_per_fragment_ops(ctx))
	 return GL_FALSE;
      break;

   case GL_RGB:
   case GL_BGRA:
      dest = (mmesa->draw_buffer == MGA_FRONT ?
	      mmesa->mgaScreen->frontOffset :
	      mmesa->mgaScreen->backOffset);

      planemask = mgaPackColor(cpp,
			       ctx->Color.ColorMask[RCOMP],
			       ctx->Color.ColorMask[GCOMP],
			       ctx->Color.ColorMask[BCOMP],
			       ctx->Color.ColorMask[ACOMP]);

      if (cpp == 2)
	 planemask |= planemask << 16;

      if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
	 return GL_FALSE;
      }
      if (!check_color_per_fragment_ops(ctx)) {
	 return GL_FALSE;
      }
      break;

   default:
      return GL_FALSE;
   }

   LOCK_HARDWARE_QUIESCENT( mmesa );

   if (mmesa->dirty_cliprects & MGA_FRONT)
      mgaUpdateRects( mmesa, MGA_FRONT );

   if ( IS_AGP_MEM(mmesa, (char *)pixels) &&
	IS_AGP_MEM(mmesa, (char *)pixels + size) )
   {
      do_draw_pix( ctx, x, y, width, height, pitch, pixels,
		   dest, planemask );
      UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
   }
   else
   {
      /* Pixels is in regular memory -- get dma buffers and perform
       * upload through them.
       */
/*        drmBufPtr buf = mgaGetBufferLocked(mmesa); */
      GLuint bufferpitch = (width*cpp+31)&~31;

      char *address = 0; /*  mmesa->mgaScreen->agp.map; */

      do {
/*  	 GLuint rows = MIN2( height, MGA_DMA_BUF_SZ / bufferpitch ); */
	 GLuint rows = height;


	 if (0) fprintf(stderr, "trying to upload %d rows (pitch %d)\n",
			rows, bufferpitch);

	 /* The texture conversion code is so slow that there is only
	  * negligble speedup when the buffers/images don't exactly
	  * match:
	  */
#if 0
	 if (cpp == 2) {
	    if (!_mesa_convert_texsubimage2d( MESA_FORMAT_RGB565,
					      0, 0, width, rows,
					      bufferpitch, format, type,
					      unpack, pixels, address )) {
/*  	       mgaReleaseBufLocked( mmesa, buf ); */
	       UNLOCK_HARDWARE(mmesa);
	       return GL_FALSE;
	    }
	 } else {
	    if (!_mesa_convert_texsubimage2d( MESA_FORMAT_ARGB8888,
					      0, 0, width, rows,
					      bufferpitch, format, type,
					      unpack, pixels, address )) {
/*  	       mgaReleaseBufLocked( mmesa, buf ); */
	       UNLOCK_HARDWARE(mmesa);
	       return GL_FALSE;
	    }
	 }
#else
	 MEMCPY( address, pixels, rows*bufferpitch );
#endif

	 do_draw_pix( ctx, x, y, width, rows,
		      bufferpitch/cpp, address, dest, planemask );

	 /* Fix me -- use multiple buffers to avoid flush.
	  */
	 UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );

	 pixels = (void *)((char *) pixels + rows * pitch);
	 height -= rows;
	 y += rows;
      } while (height);

/*        mgaReleaseBufLocked( mmesa, buf ); */
   }

   UNLOCK_HARDWARE( mmesa );
   mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;

   return GL_TRUE;
}
Beispiel #8
0
static GLboolean
mgaTryReadPixels( GLcontext *ctx,
		  GLint x, GLint y, GLsizei width, GLsizei height,
		  GLenum format, GLenum type,
		  const struct gl_pixelstore_attrib *pack,
		  GLvoid *pixels )
{
   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
   GLint size, skipPixels, skipRows;
   GLint pitch = pack->RowLength ? pack->RowLength : width;
   GLboolean ok;

   GLuint planemask;
   GLuint source;
#if 0
   drmMGABlit blit;
   GLuint dest;
   GLint source_pitch, dest_pitch;
   GLint delta_sx, delta_sy;
   GLint delta_dx, delta_dy;
   GLint blit_height, ydir;
#endif

   if (!clip_pixelrect(ctx, ctx->ReadBuffer,
		       &x, &y, &width, &height,
		       &skipPixels, &skipRows, &size)) {
      return GL_TRUE;
   }

   /* Only accelerate reading to agp buffers.
    */
   if ( !IS_AGP_MEM(mmesa, (char *)pixels) ||
	!IS_AGP_MEM(mmesa, (char *)pixels + size) )
      return GL_FALSE;

   switch (format) {
#if defined(MESA_packed_depth_stencil)
   case GL_DEPTH_STENCIL_MESA:
      ok = check_depth_stencil_24_8(ctx, type, pack, pixels, size, pitch);
      planemask = ~0;
      source = mmesa->mgaScreen->depthOffset;
      break;
#endif

   case GL_DEPTH_COMPONENT:
      ok = check_depth(ctx, type, pack, pixels, size, pitch);

      /* Can't accelerate at this depth -- planemask does the wrong
       * thing; it doesn't clear the low order bits in the
       * destination, instead it leaves them untouched.
       *
       * Could get the acclerator to solid fill the destination with
       * zeros first...  Or get the cpu to do it...
       */
      if (ctx->Visual.depthBits == 24)
	 return GL_FALSE;

      planemask = ~0;
      source = mmesa->mgaScreen->depthOffset;
      break;

   case GL_RGB:
   case GL_BGRA:
      ok = check_color(ctx, type, format, pack, pixels, size, pitch);
      planemask = ~0;
      source = (mmesa->draw_buffer == MGA_FRONT ?
		mmesa->mgaScreen->frontOffset :
		mmesa->mgaScreen->backOffset);
      break;

   default:
      return GL_FALSE;
   }

   if (!ok) {
      return GL_FALSE;
   }


   LOCK_HARDWARE( mmesa );

#if 0
   {
      __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
      int nbox, retcode, i;

      UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );

      if (mmesa->dirty_cliprects & MGA_FRONT)
	 mgaUpdateRects( mmesa, MGA_FRONT );

      nbox = dPriv->numClipRects;

      y = dPriv->h - y - height;
      x += mmesa->drawX;
      y += mmesa->drawY;

      dest = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) |
	      DO_dstmap_sys | DO_dstacc_agp);
      source_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp;
      dest_pitch = pitch;
      delta_sx = 0;
      delta_sy = 0;
      delta_dx = -x;
      delta_dy = -y;
      blit_height = 2*y + height;
      ydir = -1;

      if (0) fprintf(stderr, "XX doing readpixel blit src_pitch %d dst_pitch %d\n",
		     source_pitch, dest_pitch);



      for (i = 0 ; i < nbox ; )
      {
	 int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
	 XF86DRIClipRectRec *box = dPriv->pClipRects;
	 drm_clip_rect_t *b = mmesa->sarea->boxes;
	 int n = 0;

	 for ( ; i < nr ; i++) {
	    GLint bx = box[i].x1;
	    GLint by = box[i].y1;
	    GLint bw = box[i].x2 - bx;
	    GLint bh = box[i].y2 - by;

	    if (bx < x) bw -= x - bx, bx = x;
	    if (by < y) bh -= y - by, by = y;
	    if (bx + bw > x + width) bw = x + width - bx;
	    if (by + bh > y + height) bh = y + height - by;
	    if (bw <= 0) continue;
	    if (bh <= 0) continue;

	    b->x1 = bx;
	    b->y1 = by;
	    b->x2 = bx + bw;
	    b->y2 = by + bh;
	    b++;
	    n++;
	 }

	 mmesa->sarea->nbox = n;

	 if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT,
                                              &blit, sizeof(drmMGABlit)))) {
	    fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode);
	    UNLOCK_HARDWARE( mmesa );
	    exit(1);
	 }
      }

      UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
   }
#endif

   UNLOCK_HARDWARE( mmesa );

   return GL_TRUE;
}