Ejemplo n.º 1
0
/* Note: does not emit any commands to avoid recursion on
 * r200AllocCmdBuf.
 */
void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller )
{
   int ret;

   LOCK_HARDWARE( rmesa );

   ret = r200FlushCmdBufLocked( rmesa, caller );

   UNLOCK_HARDWARE( rmesa );

   if (ret) {
      fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
      exit(ret);
   }
}
Ejemplo n.º 2
0
/* At this point we were in FlushCmdBufLocked but we had lost our context, so
 * we need to unwire our current cmdbuf, hook the one with the saved state in
 * it, flush it, and then put the current one back.  This is so commands at the
 * start of a cmdbuf can rely on the state being kept from the previous one.
 */
static void r200BackUpAndEmitLostStateLocked( r200ContextPtr rmesa )
{
   GLuint nr_released_bufs;
   struct r200_store saved_store;

   if (rmesa->backup_store.cmd_used == 0)
      return;

   if (R200_DEBUG & DEBUG_STATE)
      fprintf(stderr, "Emitting backup state on lost context\n");

   rmesa->lost_context = GL_FALSE;

   nr_released_bufs = rmesa->dma.nr_released_bufs;
   saved_store = rmesa->store;
   rmesa->dma.nr_released_bufs = 0;
   rmesa->store = rmesa->backup_store;
   r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
   rmesa->dma.nr_released_bufs = nr_released_bufs;
   rmesa->store = saved_store;
}
Ejemplo n.º 3
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 );
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
/* ================================================================
 * Buffer clear
 */
static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
			 GLint cx, GLint cy, GLint cw, GLint ch )
{
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
   GLuint flags = 0;
   GLuint color_mask = 0;
   GLint ret, i;

   if ( R200_DEBUG & DEBUG_IOCTL ) {
      fprintf( stderr, "%s:  all=%d cx=%d cy=%d cw=%d ch=%d\n",
	       __FUNCTION__, all, cx, cy, cw, ch );
   }

   {
      LOCK_HARDWARE( rmesa );
      UNLOCK_HARDWARE( rmesa );
      if ( dPriv->numClipRects == 0 ) 
	 return;
   }

   r200Flush( ctx );

   if ( mask & DD_FRONT_LEFT_BIT ) {
      flags |= RADEON_FRONT;
      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
      mask &= ~DD_FRONT_LEFT_BIT;
   }

   if ( mask & DD_BACK_LEFT_BIT ) {
      flags |= RADEON_BACK;
      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
      mask &= ~DD_BACK_LEFT_BIT;
   }

   if ( mask & DD_DEPTH_BIT ) {
      flags |= RADEON_DEPTH;
      mask &= ~DD_DEPTH_BIT;
   }

   if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
      flags |= RADEON_STENCIL;
      mask &= ~DD_STENCIL_BIT;
   }

   if ( mask ) {
      if (R200_DEBUG & DEBUG_FALLBACKS)
	 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
      _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
   }

   if ( !flags ) 
      return;

   if (rmesa->using_hyperz) {
      flags |= RADEON_USE_COMP_ZBUF;
/*      if (rmesa->r200Screen->chipset & R200_CHIPSET_REAL_R200)
	 flags |= RADEON_USE_HIERZ; */
      if (!(rmesa->state.stencil.hwBuffer) ||
	 ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
	    ((rmesa->state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) {
	  flags |= RADEON_CLEAR_FASTZ;
      }
   }

   /* Flip top to bottom */
   cx += dPriv->x;
   cy  = dPriv->y + dPriv->h - cy - ch;

   LOCK_HARDWARE( rmesa );

   /* Throttle the number of clear ioctls we do.
    */
   while ( 1 ) {
      drm_radeon_getparam_t gp;
      int ret;
      int clear;

      gp.param = RADEON_PARAM_LAST_CLEAR;
      gp.value = (int *)&clear;
      ret = drmCommandWriteRead( rmesa->dri.fd,
		      DRM_RADEON_GETPARAM, &gp, sizeof(gp) );

      if ( ret ) {
	 fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
	 exit(1);
      }

      /* Clear throttling needs more thought.
       */
      if ( rmesa->sarea->last_clear - clear <= 25 ) {
	 break;
      }
      
      if (rmesa->do_usleeps) {
	 UNLOCK_HARDWARE( rmesa );
	 DO_USLEEP( 1 );
	 LOCK_HARDWARE( rmesa );
      }
   }

   /* Send current state to the hardware */
   r200FlushCmdBufLocked( rmesa, __FUNCTION__ );

   for ( i = 0 ; i < dPriv->numClipRects ; ) {
      GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
      drm_clip_rect_t *box = dPriv->pClipRects;
      drm_clip_rect_t *b = rmesa->sarea->boxes;
      drm_radeon_clear_t clear;
      drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
      GLint n = 0;

      if ( !all ) {
	 for ( ; i < nr ; i++ ) {
	    GLint x = box[i].x1;
	    GLint y = box[i].y1;
	    GLint w = box[i].x2 - x;
	    GLint h = box[i].y2 - y;

	    if ( x < cx ) w -= cx - x, x = cx;
	    if ( y < cy ) h -= cy - y, y = cy;
	    if ( x + w > cx + cw ) w = cx + cw - x;
	    if ( y + h > cy + ch ) h = cy + ch - y;
	    if ( w <= 0 ) continue;
	    if ( h <= 0 ) continue;

	    b->x1 = x;
	    b->y1 = y;
	    b->x2 = x + w;
	    b->y2 = y + h;
	    b++;
	    n++;
	 }
      } else {
	 for ( ; i < nr ; i++ ) {
	    *b++ = box[i];
	    n++;
	 }
      }

      rmesa->sarea->nbox = n;

      clear.flags       = flags;
      clear.clear_color = rmesa->state.color.clear;
      clear.clear_depth = rmesa->state.depth.clear;	/* needed for hyperz */
      clear.color_mask  = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
      clear.depth_mask  = rmesa->state.stencil.clear;
      clear.depth_boxes = depth_boxes;

      n--;
      b = rmesa->sarea->boxes;
      for ( ; n >= 0 ; n-- ) {
	 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
	 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
	 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
	 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
	 depth_boxes[n].f[CLEAR_DEPTH] = ctx->Depth.Clear;
      }

      ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
			     &clear, sizeof(clear));


      if ( ret ) {
	 UNLOCK_HARDWARE( rmesa );
	 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
	 exit( 1 );
      }
   }

   UNLOCK_HARDWARE( rmesa );
   rmesa->hw.all_dirty = GL_TRUE;
}
Ejemplo n.º 6
0
void r200RefillCurrentDmaRegion( r200ContextPtr rmesa )
{
   struct r200_dma_buffer *dmabuf;
   int fd = rmesa->dri.fd;
   int index = 0;
   int size = 0;
   drmDMAReq dma;
   int ret;

   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
      fprintf(stderr, "%s\n", __FUNCTION__);  

   if (rmesa->dma.flush) {
      rmesa->dma.flush( rmesa );
   }

   if (rmesa->dma.current.buf)
      r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );

   if (rmesa->dma.nr_released_bufs > 4)
      r200FlushCmdBuf( rmesa, __FUNCTION__ );

   dma.context = rmesa->dri.hwContext;
   dma.send_count = 0;
   dma.send_list = NULL;
   dma.send_sizes = NULL;
   dma.flags = 0;
   dma.request_count = 1;
   dma.request_size = RADEON_BUFFER_SIZE;
   dma.request_list = &index;
   dma.request_sizes = &size;
   dma.granted_count = 0;

   LOCK_HARDWARE(rmesa);	/* no need to validate */

   while (1) {
      ret = drmDMA( fd, &dma );
      if (ret == 0)
	 break;
   
      if (rmesa->dma.nr_released_bufs) {
	 r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
      }

      if (rmesa->do_usleeps) {
	 UNLOCK_HARDWARE( rmesa );
	 DO_USLEEP( 1 );
	 LOCK_HARDWARE( rmesa );
      }
   }

   UNLOCK_HARDWARE(rmesa);

   if (R200_DEBUG & DEBUG_DMA)
      fprintf(stderr, "Allocated buffer %d\n", index);

   dmabuf = CALLOC_STRUCT( r200_dma_buffer );
   dmabuf->buf = &rmesa->r200Screen->buffers->list[index];
   dmabuf->refcount = 1;

   rmesa->dma.current.buf = dmabuf;
   rmesa->dma.current.address = dmabuf->buf->address;
   rmesa->dma.current.end = dmabuf->buf->total;
   rmesa->dma.current.start = 0;
   rmesa->dma.current.ptr = 0;
}