/* 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); } }
/* 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; }
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 ); }
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; }
/* ================================================================ * 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; }
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; }