-/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c,v 1.4 2002/12/17 00:32:56 dawes Exp $ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
#include <sched.h>
#include <errno.h>
-#include "glheader.h"
-#include "imports.h"
-#include "macros.h"
-#include "context.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/context.h"
#include "swrast/swrast.h"
#include "r200_context.h"
#include "r200_sanity.h"
#include "radeon_reg.h"
+#include "drirenderbuffer.h"
#include "vblank.h"
-
#define R200_TIMEOUT 512
#define R200_IDLE_RETRY 16
static void r200WaitForIdle( r200ContextPtr rmesa );
+/* 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;
+}
+
int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
{
int ret, i;
- drmRadeonCmdBuffer cmd;
+ drm_radeon_cmd_buffer_t cmd;
+
+ if (rmesa->lost_context)
+ r200BackUpAndEmitLostStateLocked( rmesa );
if (R200_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (rmesa->state.scissor.enabled) {
cmd.nbox = rmesa->state.scissor.numClipRects;
- cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects;
+ cmd.boxes = (drm_clip_rect_t *)rmesa->state.scissor.pClipRects;
} else {
cmd.nbox = rmesa->numClipRects;
- cmd.boxes = (drmClipRect *)rmesa->pClipRects;
+ cmd.boxes = (drm_clip_rect_t *)rmesa->pClipRects;
}
ret = drmCommandWrite( rmesa->dri.fd,
rmesa->store.statenr = 0;
rmesa->store.cmd_used = 0;
rmesa->dma.nr_released_bufs = 0;
- rmesa->lost_context = 1;
+ rmesa->save_on_next_emit = 1;
+
return ret;
}
rmesa->dma.flush( rmesa );
if (--region->buf->refcount == 0) {
- drmRadeonCmdHeader *cmd;
+ 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 = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sizeof(*cmd),
+ 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;
rmesa->dma.nr_released_bufs++;
}
- region->buf = 0;
+ region->buf = NULL;
region->start = 0;
}
assert( rmesa->dma.current.ptr <= rmesa->dma.current.end );
}
-void r200AllocDmaRegionVerts( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- int numverts,
- int vertsize,
- int alignment )
-{
- r200AllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
-}
-
/* ================================================================
* SwapBuffers with client-side throttling
*/
-static CARD32 r200GetLastFrame(r200ContextPtr rmesa)
+static uint32_t r200GetLastFrame(r200ContextPtr rmesa)
{
- drmRadeonGetParam gp;
+ drm_radeon_getparam_t gp;
int ret;
- CARD32 frame;
+ uint32_t frame;
gp.param = RADEON_PARAM_LAST_FRAME;
gp.value = (int *)&frame;
static void r200EmitIrqLocked( r200ContextPtr rmesa )
{
- drmRadeonIrqEmit ie;
+ drm_radeon_irq_emit_t ie;
int ret;
ie.irq_seq = &rmesa->iw.irq_seq;
do {
ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
&rmesa->iw, sizeof(rmesa->iw) );
- } while (ret && (errno == EINTR || errno == EAGAIN));
+ } while (ret && (errno == EINTR || errno == EBUSY));
if ( ret ) {
fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
{
- RADEONSAREAPrivPtr sarea = rmesa->sarea;
+ drm_radeon_sarea_t *sarea = rmesa->sarea;
if (rmesa->do_irqs) {
if (r200GetLastFrame(rmesa) < sarea->last_frame) {
/* Copy the back color buffer to the front color buffer.
*/
-void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
+void r200CopyBuffer( __DRIdrawablePrivate *dPriv,
+ const drm_clip_rect_t *rect)
{
r200ContextPtr rmesa;
GLint nbox, i, ret;
GLboolean missed_target;
- int64_t ust;
+ int64_t ust;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
assert(dPriv);
assert(dPriv->driContextPriv);
* request at a time.
*/
r200WaitForFrameCompletion( rmesa );
- UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
- LOCK_HARDWARE( rmesa );
+ if (!rect)
+ {
+ UNLOCK_HARDWARE( rmesa );
+ driWaitForVBlank( dPriv, & missed_target );
+ LOCK_HARDWARE( rmesa );
+ }
nbox = dPriv->numClipRects; /* must be in locked region */
for ( i = 0 ; i < nbox ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
- XF86DRIClipRectPtr box = dPriv->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t *b = rmesa->sarea->boxes;
GLint n = 0;
for ( ; i < nr ; i++ ) {
- *b++ = box[i];
- n++;
+
+ *b = box[i];
+
+ if (rect)
+ {
+ if (rect->x1 > b->x1)
+ b->x1 = rect->x1;
+ if (rect->y1 > b->y1)
+ b->y1 = rect->y1;
+ if (rect->x2 < b->x2)
+ b->x2 = rect->x2;
+ if (rect->y2 < b->y2)
+ b->y2 = rect->y2;
+
+ if (b->x1 >= b->x2 || b->y1 >= b->y2)
+ continue;
+ }
+
+ b++;
+ n++;
}
rmesa->sarea->nbox = n;
+ if (!n)
+ continue;
+
ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
if ( ret ) {
}
UNLOCK_HARDWARE( rmesa );
- rmesa->lost_context = 1;
+ if (!rect)
+ {
+ rmesa->hw.all_dirty = GL_TRUE;
- rmesa->swap_count++;
- (*rmesa->get_ust)( & ust );
- if ( missed_target ) {
- rmesa->swap_missed_count++;
- rmesa->swap_missed_ust = ust - rmesa->swap_ust;
- }
+ rmesa->swap_count++;
+ (*psp->systemTime->getUST)( & ust );
+ if ( missed_target ) {
+ rmesa->swap_missed_count++;
+ rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+ }
- rmesa->swap_ust = ust;
+ rmesa->swap_ust = ust;
- sched_yield();
+ sched_yield();
+ }
}
-void r200PageFlip( const __DRIdrawablePrivate *dPriv )
+void r200PageFlip( __DRIdrawablePrivate *dPriv )
{
r200ContextPtr rmesa;
GLint ret;
GLboolean missed_target;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
assert(dPriv);
assert(dPriv->driContextPriv);
/* Need to do this for the perf box placement:
*/
{
- XF86DRIClipRectPtr box = dPriv->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t *b = rmesa->sarea->boxes;
b[0] = box[0];
rmesa->sarea->nbox = 1;
}
*/
r200WaitForFrameCompletion( rmesa );
UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+ driWaitForVBlank( dPriv, & missed_target );
if ( missed_target ) {
rmesa->swap_missed_count++;
- (void) (*rmesa->get_ust)( & rmesa->swap_missed_ust );
+ (void) (*psp->systemTime->getUST)( & rmesa->swap_missed_ust );
}
LOCK_HARDWARE( rmesa );
}
rmesa->swap_count++;
- (void) (*rmesa->get_ust)( & rmesa->swap_ust );
+ (void) (*psp->systemTime->getUST)( & rmesa->swap_ust );
+#if 000
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
+ rmesa->r200Screen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+ if (rmesa->sarea->tiling_enabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
+ }
+#else
+ /* Get ready for drawing next frame. Update the renderbuffers'
+ * flippedOffset/Pitch fields so we draw into the right place.
+ */
+ driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
+ rmesa->sarea->pfCurrentPage);
+
+
+ r200UpdateDrawBuffer(rmesa->glCtx);
+#endif
}
/* ================================================================
* Buffer clear
*/
-static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
- GLint cx, GLint cy, GLint cw, GLint ch )
+static void r200Clear( GLcontext *ctx, GLbitfield mask )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLuint flags = 0;
GLuint color_mask = 0;
GLint ret, i;
+ GLint cx, cy, cw, ch;
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 );
+ fprintf( stderr, "r200Clear\n");
}
{
return;
}
- r200EmitState( rmesa );
-
- /* Need to cope with lostcontext here as kernel relies on
- * some residual state:
- */
- R200_FIREVERTICES( rmesa );
+ r200Flush( ctx );
- if ( mask & DD_FRONT_LEFT_BIT ) {
+ if ( mask & BUFFER_BIT_FRONT_LEFT ) {
flags |= RADEON_FRONT;
color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~DD_FRONT_LEFT_BIT;
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
}
- if ( mask & DD_BACK_LEFT_BIT ) {
+ if ( mask & BUFFER_BIT_BACK_LEFT ) {
flags |= RADEON_BACK;
color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~DD_BACK_LEFT_BIT;
+ mask &= ~BUFFER_BIT_BACK_LEFT;
}
- if ( mask & DD_DEPTH_BIT ) {
- if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
- mask &= ~DD_DEPTH_BIT;
+ if ( mask & BUFFER_BIT_DEPTH ) {
+ flags |= RADEON_DEPTH;
+ mask &= ~BUFFER_BIT_DEPTH;
}
- if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
+ if ( (mask & BUFFER_BIT_STENCIL) && rmesa->state.stencil.hwBuffer ) {
flags |= RADEON_STENCIL;
- mask &= ~DD_STENCIL_BIT;
+ 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, all, cx, cy, cw, ch );
+ _swrast_Clear( ctx, mask );
}
if ( !flags )
return;
+ if (rmesa->using_hyperz) {
+ flags |= RADEON_USE_COMP_ZBUF;
+/* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_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;
+ }
+ }
+
+ LOCK_HARDWARE( rmesa );
+
+ /* 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;
- LOCK_HARDWARE( rmesa );
-
/* Throttle the number of clear ioctls we do.
*/
while ( 1 ) {
- drmRadeonGetParam gp;
+ drm_radeon_getparam_t gp;
int ret;
int clear;
}
}
+ /* 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 );
- XF86DRIClipRectPtr box = dPriv->pClipRects;
- XF86DRIClipRectPtr b = rmesa->sarea->boxes;
- drmRadeonClearType clear;
- drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+ 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 ) {
+ if (cw != dPriv->w || ch != dPriv->h) {
+ /* clear subregion */
for ( ; i < nr ; i++ ) {
GLint x = box[i].x1;
GLint y = box[i].y1;
n++;
}
} else {
+ /* clear whole window */
for ( ; i < nr ; i++ ) {
*b++ = box[i];
n++;
clear.flags = flags;
clear.clear_color = rmesa->state.color.clear;
- clear.clear_depth = 0; /* not used */
+ 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[RADEON_CLEAR_X1] = (float)b[n].x1;
- depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1;
- depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2;
- depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2;
- depth_boxes[n].f[RADEON_CLEAR_DEPTH] = ctx->Depth.Clear;
+ 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(drmRadeonClearType));
+ &clear, sizeof(clear));
if ( ret ) {
}
UNLOCK_HARDWARE( rmesa );
- rmesa->lost_context = 1;
+ rmesa->hw.all_dirty = GL_TRUE;
}
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
- if (!is_empty_list(&rmesa->hw.dirty))
- r200EmitState( rmesa );
+ r200EmitState( rmesa );
if (rmesa->store.cmd_used)
r200FlushCmdBuf( rmesa, __FUNCTION__ );
* the kernel data structures, and the current context to get the
* device fd.
*/
-void *r200AllocateMemoryMESA(GLsizei size,
+void *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size,
GLfloat readfreq, GLfloat writefreq,
GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
int region_offset;
- drmRadeonMemAlloc alloc;
+ drm_radeon_mem_alloc_t alloc;
int ret;
if (R200_DEBUG & DEBUG_IOCTL)
if (getenv("R200_NO_ALLOC"))
return NULL;
-
- if (rmesa->dri.drmMinor < 6)
- return NULL;
-
+
alloc.region = RADEON_MEM_REGION_GART;
alloc.alignment = 0;
alloc.size = size;
/* Called via glXFreeMemoryMESA() */
-void r200FreeMemoryMESA(GLvoid *pointer)
+void r200FreeMemoryMESA(__DRIscreen *screen, GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
- int region_offset;
- drmRadeonMemFree memfree;
+ ptrdiff_t region_offset;
+ drm_radeon_mem_free_t memfree;
int ret;
if (R200_DEBUG & DEBUG_IOCTL)
return;
}
- if (rmesa->dri.drmMinor < 6)
- return;
-
region_offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
if (region_offset < 0 ||
}
/* Called via glXGetMemoryOffsetMESA() */
-GLuint r200GetMemoryOffsetMESA(const GLvoid *pointer)
+GLuint r200GetMemoryOffsetMESA(__DRIscreen *screen, const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
if (!r200IsGartMemory( rmesa, pointer, 0 ))
return ~0;
- if (rmesa->dri.drmMinor < 6)
- return ~0;
-
card_offset = r200GartOffsetFromVirtual( rmesa, pointer );
return card_offset - rmesa->r200Screen->gart_base;
}
-
GLboolean r200IsGartMemory( r200ContextPtr rmesa, const GLvoid *pointer,
GLint size )
{
- int offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
+ ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
int valid = (size >= 0 &&
offset >= 0 &&
offset + size < rmesa->r200Screen->gartTextures.size);
GLuint r200GartOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer )
{
- int offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
+ ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
if (offset < 0 || offset > rmesa->r200Screen->gartTextures.size)
return ~0;
-void r200InitIoctlFuncs( GLcontext *ctx )
+void r200InitIoctlFuncs( struct dd_function_table *functions )
{
- ctx->Driver.Clear = r200Clear;
- ctx->Driver.Finish = r200Finish;
- ctx->Driver.Flush = r200Flush;
+ functions->Clear = r200Clear;
+ functions->Finish = r200Finish;
+ functions->Flush = r200Flush;
}