* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
+
#include <sched.h>
#include <errno.h>
#include "main/context.h"
#include "swrast/swrast.h"
+
+
+#include "radeon_common.h"
+#include "radeon_lock.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#define R200_TIMEOUT 512
#define R200_IDLE_RETRY 16
-
-/* 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 radeon_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->radeon.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;
-}
-
-int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
-{
- int ret, i;
- drm_radeon_cmd_buffer_t cmd;
-
- if (rmesa->radeon.lost_context)
- r200BackUpAndEmitLostStateLocked( rmesa );
-
- if (R200_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (0 & R200_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
- fprintf(stderr, "%d: %x\n", i/4,
- *(int *)(&rmesa->store.cmd_buf[i]));
- }
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
- rmesa->dma.nr_released_bufs);
-
-
- if (R200_DEBUG & DEBUG_SANITY) {
- if (rmesa->radeon.state.scissor.enabled)
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->radeon.state.scissor.numClipRects,
- rmesa->radeon.state.scissor.pClipRects);
- else
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->radeon.numClipRects,
- rmesa->radeon.pClipRects);
- if (ret) {
- fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
- goto out;
- }
- }
-
-
- if (R200_DEBUG & DEBUG_MEMORY) {
- if (! driValidateTextureHeaps( rmesa->radeon.texture_heaps, rmesa->radeon.nr_heaps,
- & rmesa->radeon.swapped ) ) {
- fprintf( stderr, "%s: texture memory is inconsistent - expect "
- "mangled textures\n", __FUNCTION__ );
- }
- }
-
-
- cmd.bufsz = rmesa->store.cmd_used;
- cmd.buf = rmesa->store.cmd_buf;
-
- if (rmesa->radeon.state.scissor.enabled) {
- cmd.nbox = rmesa->radeon.state.scissor.numClipRects;
- cmd.boxes = (drm_clip_rect_t *)rmesa->radeon.state.scissor.pClipRects;
- } else {
- cmd.nbox = rmesa->radeon.numClipRects;
- cmd.boxes = (drm_clip_rect_t *)rmesa->radeon.pClipRects;
- }
-
- ret = drmCommandWrite( rmesa->radeon.dri.fd,
- DRM_RADEON_CMDBUF,
- &cmd, sizeof(cmd) );
-
- if (ret)
- fprintf(stderr, "drmCommandWrite: %d\n", ret);
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
- radeonWaitForIdleLocked( &rmesa->radeon );
- }
-
-
- out:
- rmesa->store.primnr = 0;
- rmesa->store.statenr = 0;
- rmesa->store.cmd_used = 0;
- rmesa->dma.nr_released_bufs = 0;
- rmesa->save_on_next_emit = 1;
-
- return ret;
-}
-
-
-/* Note: does not emit any commands to avoid recursion on
- * r200AllocCmdBuf.
- */
-void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller )
-{
- int ret;
-
- LOCK_HARDWARE( &rmesa->radeon );
-
- ret = r200FlushCmdBufLocked( rmesa, caller );
-
- UNLOCK_HARDWARE( &rmesa->radeon );
-
- if (ret) {
- fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
- exit(ret);
- }
-}
-
-
-/* =============================================================
- * Hardware vertex buffer handling
- */
-
-
-void r200RefillCurrentDmaRegion( r200ContextPtr rmesa )
-{
- struct radeon_dma_buffer *dmabuf;
- int fd = rmesa->radeon.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->radeon.glCtx );
- }
-
- if (rmesa->dma.current.buf)
- r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
-
- if (rmesa->dma.nr_released_bufs > 4)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
-
- dma.context = rmesa->radeon.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->radeon); /* 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->radeon.do_usleeps) {
- UNLOCK_HARDWARE( &rmesa->radeon );
- DO_USLEEP( 1 );
- LOCK_HARDWARE( &rmesa->radeon );
- }
- }
-
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
- dmabuf->buf = &rmesa->radeon.radeonScreen->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;
-}
-
-void r200ReleaseDmaRegion( r200ContextPtr rmesa,
- struct radeon_dma_region *region,
- const char *caller )
-{
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa->radeon.glCtx );
-
- if (--region->buf->refcount == 0) {
- drm_radeon_cmd_header_t *cmd;
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
- region->buf->buf->idx);
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sizeof(*cmd),
- __FUNCTION__ );
- cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = NULL;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void r200AllocDmaRegion( r200ContextPtr rmesa,
- struct radeon_dma_region *region,
- int bytes,
- int alignment )
-{
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa->radeon.glCtx );
-
- if (region->buf)
- r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ );
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- r200RefillCurrentDmaRegion( rmesa );
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert( rmesa->dma.current.ptr <= rmesa->dma.current.end );
-}
-
-
-/* ================================================================
- * Buffer clear
- */
-static void r200Clear( GLcontext *ctx, GLbitfield mask )
+static void r200KernelClear(GLcontext *ctx, GLuint flags)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
- GLuint flags = 0;
- GLuint color_mask = 0;
- GLint ret, i;
- GLint cx, cy, cw, ch;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "r200Clear\n");
- }
-
- {
- LOCK_HARDWARE( &rmesa->radeon );
- UNLOCK_HARDWARE( &rmesa->radeon );
- if ( dPriv->numClipRects == 0 )
- return;
- }
-
- r200Flush( ctx );
-
- if ( mask & BUFFER_BIT_FRONT_LEFT ) {
- flags |= RADEON_FRONT;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_FRONT_LEFT;
- }
-
- if ( mask & BUFFER_BIT_BACK_LEFT ) {
- flags |= RADEON_BACK;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_BACK_LEFT;
- }
-
- if ( mask & BUFFER_BIT_DEPTH ) {
- flags |= RADEON_DEPTH;
- mask &= ~BUFFER_BIT_DEPTH;
- }
-
- if ( (mask & BUFFER_BIT_STENCIL) && rmesa->radeon.state.stencil.hwBuffer ) {
- flags |= RADEON_STENCIL;
- mask &= ~BUFFER_BIT_STENCIL;
- }
-
- if ( mask ) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
- _swrast_Clear( ctx, mask );
- }
-
- if ( !flags )
- return;
-
- if (rmesa->using_hyperz) {
- flags |= RADEON_USE_COMP_ZBUF;
-/* if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200)
- flags |= RADEON_USE_HIERZ; */
- if (!(rmesa->radeon.state.stencil.hwBuffer) ||
- ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
- ((rmesa->radeon.state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) {
- flags |= RADEON_CLEAR_FASTZ;
- }
- }
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLint cx, cy, cw, ch, ret;
+ GLuint i;
LOCK_HARDWARE( &rmesa->radeon );
- /* compute region after locking: */
- cx = ctx->DrawBuffer->_Xmin;
- cy = ctx->DrawBuffer->_Ymin;
- cw = ctx->DrawBuffer->_Xmax - cx;
- ch = ctx->DrawBuffer->_Ymax - cy;
-
- /* Flip top to bottom */
- cx += dPriv->x;
- cy = dPriv->y + dPriv->h - cy - ch;
-
/* Throttle the number of clear ioctls we do.
*/
while ( 1 ) {
if ( rmesa->radeon.sarea->last_clear - clear <= 25 ) {
break;
}
-
+
if (rmesa->radeon.do_usleeps) {
UNLOCK_HARDWARE( &rmesa->radeon );
DO_USLEEP( 1 );
}
/* Send current state to the hardware */
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
+
+
+ /* compute region after locking: */
+ cx = ctx->DrawBuffer->_Xmin;
+ cy = ctx->DrawBuffer->_Ymin;
+ cw = ctx->DrawBuffer->_Xmax - cx;
+ ch = ctx->DrawBuffer->_Ymax - cy;
+ /* Flip top to bottom */
+ cx += dPriv->x;
+ cy = dPriv->y + dPriv->h - cy - ch;
for ( i = 0 ; i < dPriv->numClipRects ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
drm_clip_rect_t *box = dPriv->pClipRects;
exit( 1 );
}
}
-
UNLOCK_HARDWARE( &rmesa->radeon );
- rmesa->hw.all_dirty = GL_TRUE;
}
+/* ================================================================
+ * Buffer clear
+ */
+static void r200Clear( GLcontext *ctx, GLbitfield mask )
+{
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLuint flags = 0;
+ GLuint color_mask = 0;
+ GLuint orig_mask = mask;
+ if ( R200_DEBUG & RADEON_IOCTL ) {
+ if (rmesa->radeon.sarea)
+ fprintf( stderr, "r200Clear %x %d\n", mask, rmesa->radeon.sarea->pfCurrentPage);
+ else
+ fprintf( stderr, "r200Clear %x radeon->sarea is NULL\n", mask);
+ }
-void r200Flush( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
+ {
+ LOCK_HARDWARE( &rmesa->radeon );
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ if ( dPriv->numClipRects == 0 )
+ return;
+ }
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ radeonFlush( ctx );
- if (rmesa->dma.flush)
- rmesa->dma.flush( ctx );
+ if ( mask & BUFFER_BIT_FRONT_LEFT ) {
+ flags |= RADEON_FRONT;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ }
- r200EmitState( rmesa );
-
- if (rmesa->store.cmd_used)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
-}
+ if ( mask & BUFFER_BIT_BACK_LEFT ) {
+ flags |= RADEON_BACK;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ }
-/* Make sure all commands have been sent to the hardware and have
- * completed processing.
- */
-void r200Finish( GLcontext *ctx )
-{
- r200Flush( ctx );
- radeon_common_finish(ctx);
-}
+ if ( mask & BUFFER_BIT_DEPTH ) {
+ flags |= RADEON_DEPTH;
+ mask &= ~BUFFER_BIT_DEPTH;
+ }
+ if ( (mask & BUFFER_BIT_STENCIL) ) {
+ flags |= RADEON_STENCIL;
+ mask &= ~BUFFER_BIT_STENCIL;
+ }
+
+ if ( mask ) {
+ if (R200_DEBUG & RADEON_FALLBACKS)
+ fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
+ _swrast_Clear( ctx, mask );
+ }
+
+ if ( !flags )
+ return;
+
+ if (rmesa->using_hyperz) {
+ flags |= RADEON_USE_COMP_ZBUF;
+/* if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200)
+ flags |= RADEON_USE_HIERZ; */
+ if (!((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
+ ((rmesa->radeon.state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) {
+ flags |= RADEON_CLEAR_FASTZ;
+ }
+ }
+
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ radeonUserClear(ctx, orig_mask);
+ else {
+ r200KernelClear(ctx, flags);
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
+ }
+}
/* This version of AllocateMemoryMESA allocates only GART memory, and
* only does so after the point at which the driver has been
* device fd.
*/
void *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size,
- GLfloat readfreq, GLfloat writefreq,
+ GLfloat readfreq, GLfloat writefreq,
GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
drm_radeon_mem_alloc_t alloc;
int ret;
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
+ if (R200_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->radeon.radeonScreen->gartTextures.map)
ret = drmCommandWriteRead( rmesa->radeon.radeonScreen->driScreen->fd,
DRM_RADEON_ALLOC,
&alloc, sizeof(alloc));
-
+
if (ret) {
fprintf(stderr, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__, ret);
return NULL;
}
-
+
{
char *region_start = (char *)rmesa->radeon.radeonScreen->gartTextures.map;
return (void *)(region_start + region_offset);
drm_radeon_mem_free_t memfree;
int ret;
- if (R200_DEBUG & DEBUG_IOCTL)
+ if (R200_DEBUG & RADEON_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->radeon.radeonScreen->gartTextures.map) {
region_offset = (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- if (region_offset < 0 ||
+ if (region_offset < 0 ||
region_offset > rmesa->radeon.radeonScreen->gartTextures.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
rmesa->radeon.radeonScreen->gartTextures.size);
memfree.region = RADEON_MEM_REGION_GART;
memfree.region_offset = region_offset;
-
+
ret = drmCommandWrite( rmesa->radeon.radeonScreen->driScreen->fd,
DRM_RADEON_FREE,
&memfree, sizeof(memfree));
-
- if (ret)
+
+ if (ret)
fprintf(stderr, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__, ret);
}
offset >= 0 &&
offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
- if (R200_DEBUG & DEBUG_IOCTL)
+ if (R200_DEBUG & RADEON_IOCTL)
fprintf(stderr, "r200IsGartMemory( %p ) : %d\n", pointer, valid );
-
+
return valid;
}
void r200InitIoctlFuncs( struct dd_function_table *functions )
{
functions->Clear = r200Clear;
- functions->Finish = r200Finish;
- functions->Flush = r200Flush;
+ functions->Finish = radeonFinish;
+ functions->Flush = radeonFlush;
}