blob: 3bcec50cf81e1ea793ad3134da0301dfd96a984c [file] [log] [blame]
/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
/*
* Copyright 2000 Gareth Hughes
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Leif Delgass <ldelgass@retinalburn.net>
* Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
*/
#include <errno.h>
#include "mach64_context.h"
#include "mach64_state.h"
#include "mach64_ioctl.h"
#include "mach64_tex.h"
#include "imports.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "vblank.h"
#define MACH64_TIMEOUT 10 /* the DRM already has a timeout, so keep this small */
/* =============================================================
* Hardware vertex buffer handling
*/
/* Get a new VB from the pool of vertex buffers in AGP space.
*/
drmBufPtr mach64GetBufferLocked( mach64ContextPtr mmesa )
{
int fd = mmesa->mach64Screen->driScreen->fd;
int index = 0;
int size = 0;
drmDMAReq dma;
drmBufPtr buf = NULL;
int to = 0;
int ret;
dma.context = mmesa->hHWContext;
dma.send_count = 0;
dma.send_list = NULL;
dma.send_sizes = NULL;
dma.flags = 0;
dma.request_count = 1;
dma.request_size = MACH64_BUFFER_SIZE;
dma.request_list = &index;
dma.request_sizes = &size;
dma.granted_count = 0;
while ( !buf && ( to++ < MACH64_TIMEOUT ) ) {
ret = drmDMA( fd, &dma );
if ( ret == 0 ) {
buf = &mmesa->mach64Screen->buffers->list[index];
buf->used = 0;
#if ENABLE_PERF_BOXES
/* Bump the performance counter */
mmesa->c_vertexBuffers++;
#endif
return buf;
}
}
if ( !buf ) {
drmCommandNone( fd, DRM_MACH64_RESET );
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "Error: Could not get new VB... exiting\n" );
exit( -1 );
}
return buf;
}
void mach64FlushVerticesLocked( mach64ContextPtr mmesa )
{
drm_clip_rect_t *pbox = mmesa->pClipRects;
int nbox = mmesa->numClipRects;
void *buffer = mmesa->vert_buf;
int count = mmesa->vert_used;
int prim = mmesa->hw_primitive;
int fd = mmesa->driScreen->fd;
drm_mach64_vertex_t vertex;
int i;
mmesa->num_verts = 0;
mmesa->vert_used = 0;
if ( !count )
return;
if ( mmesa->dirty & ~MACH64_UPLOAD_CLIPRECTS )
mach64EmitHwStateLocked( mmesa );
if ( !nbox )
count = 0;
if ( nbox > MACH64_NR_SAREA_CLIPRECTS )
mmesa->dirty |= MACH64_UPLOAD_CLIPRECTS;
if ( !count || !(mmesa->dirty & MACH64_UPLOAD_CLIPRECTS) ) {
int to = 0;
int ret;
/* FIXME: Is this really necessary */
if ( nbox == 1 )
mmesa->sarea->nbox = 0;
else
mmesa->sarea->nbox = nbox;
vertex.prim = prim;
vertex.buf = buffer;
vertex.used = count;
vertex.discard = 1;
do {
ret = drmCommandWrite( fd, DRM_MACH64_VERTEX,
&vertex, sizeof(drm_mach64_vertex_t) );
} while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );
exit( -1 );
}
} else {
for ( i = 0 ; i < nbox ; ) {
int nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS, nbox );
drm_clip_rect_t *b = mmesa->sarea->boxes;
int discard = 0;
int to = 0;
int ret;
mmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++ ) {
*b++ = pbox[i];
}
/* Finished with the buffer?
*/
if ( nr == nbox ) {
discard = 1;
}
mmesa->sarea->dirty |= MACH64_UPLOAD_CLIPRECTS;
vertex.prim = prim;
vertex.buf = buffer;
vertex.used = count;
vertex.discard = discard;
do {
ret = drmCommandWrite( fd, DRM_MACH64_VERTEX,
&vertex, sizeof(drm_mach64_vertex_t) );
} while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );
exit( -1 );
}
}
}
mmesa->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
}
/* ================================================================
* Texture uploads
*/
void mach64FireBlitLocked( mach64ContextPtr mmesa, void *buffer,
GLint offset, GLint pitch, GLint format,
GLint x, GLint y, GLint width, GLint height )
{
drm_mach64_blit_t blit;
int to = 0;
int ret;
blit.buf = buffer;
blit.offset = offset;
blit.pitch = pitch;
blit.format = format;
blit.x = x;
blit.y = y;
blit.width = width;
blit.height = height;
do {
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_BLIT,
&blit, sizeof(drm_mach64_blit_t) );
} while ( ( ret == -EAGAIN ) && ( to++ < MACH64_TIMEOUT ) );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_BLIT: return = %d\n", ret );
exit( -1 );
}
}
/* ================================================================
* SwapBuffers with client-side throttling
*/
static void delay( void ) {
/* Prevent an optimizing compiler from removing a spin loop */
}
/* Throttle the frame rate -- only allow MACH64_MAX_QUEUED_FRAMES
* pending swap buffers requests at a time.
*
* GH: We probably don't want a timeout here, as we can wait as
* long as we want for a frame to complete. If it never does, then
* the card has locked.
*/
static int mach64WaitForFrameCompletion( mach64ContextPtr mmesa )
{
int fd = mmesa->driFd;
int i;
int wait = 0;
int frames;
while ( 1 ) {
drm_mach64_getparam_t gp;
int ret;
if ( mmesa->sarea->frames_queued < MACH64_MAX_QUEUED_FRAMES ) {
break;
}
if (MACH64_DEBUG & DEBUG_NOWAIT) {
return 1;
}
gp.param = MACH64_PARAM_FRAMES_QUEUED;
gp.value = &frames; /* also copied into sarea->frames_queued by DRM */
ret = drmCommandWriteRead( fd, DRM_MACH64_GETPARAM, &gp, sizeof(gp) );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_GETPARAM: return = %d\n", ret );
exit( -1 );
}
/* Spin in place a bit so we aren't hammering the register */
wait++;
for ( i = 0 ; i < 1024 ; i++ ) {
delay();
}
}
return wait;
}
/* Copy the back color buffer to the front color buffer.
*/
void mach64CopyBuffer( __DRIdrawablePrivate *dPriv )
{
mach64ContextPtr mmesa;
GLint nbox, i, ret;
drm_clip_rect_t *pbox;
GLboolean missed_target;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;
if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "\n********************************\n" );
fprintf( stderr, "\n%s( %p )\n\n",
__FUNCTION__, mmesa->glCtx );
fflush( stderr );
}
/* Flush any outstanding vertex buffers */
FLUSH_BATCH( mmesa );
LOCK_HARDWARE( mmesa );
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.
*/
if ( !mach64WaitForFrameCompletion( mmesa ) ) {
mmesa->hardwareWentIdle = 1;
} else {
mmesa->hardwareWentIdle = 0;
}
#if ENABLE_PERF_BOXES
if ( mmesa->boxes ) {
mach64PerformanceBoxesLocked( mmesa );
}
#endif
UNLOCK_HARDWARE( mmesa );
driWaitForVBlank( dPriv, &missed_target );
LOCK_HARDWARE( mmesa );
/* use front buffer cliprects */
nbox = dPriv->numClipRects;
pbox = dPriv->pClipRects;
for ( i = 0 ; i < nbox ; ) {
GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox );
drm_clip_rect_t *b = mmesa->sarea->boxes;
GLint n = 0;
for ( ; i < nr ; i++ ) {
*b++ = pbox[i];
n++;
}
mmesa->sarea->nbox = n;
ret = drmCommandNone( mmesa->driFd, DRM_MACH64_SWAP );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_SWAP: return = %d\n", ret );
exit( -1 );
}
}
if ( MACH64_DEBUG & DEBUG_ALWAYS_SYNC ) {
mach64WaitForIdleLocked( mmesa );
}
UNLOCK_HARDWARE( mmesa );
mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
MACH64_UPLOAD_MISC |
MACH64_UPLOAD_CLIPRECTS);
#if ENABLE_PERF_BOXES
/* Log the performance counters if necessary */
mach64PerformanceCounters( mmesa );
#endif
}
#if ENABLE_PERF_BOXES
/* ================================================================
* Performance monitoring
*/
void mach64PerformanceCounters( mach64ContextPtr mmesa )
{
if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {
/* report performance counters */
fprintf( stderr, "mach64CopyBuffer: vertexBuffers:%i drawWaits:%i clears:%i\n",
mmesa->c_vertexBuffers, mmesa->c_drawWaits, mmesa->c_clears );
}
mmesa->c_vertexBuffers = 0;
mmesa->c_drawWaits = 0;
mmesa->c_clears = 0;
if ( mmesa->c_textureSwaps || mmesa->c_textureBytes || mmesa->c_agpTextureBytes ) {
if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {
fprintf( stderr, " textureSwaps:%i textureBytes:%i agpTextureBytes:%i\n",
mmesa->c_textureSwaps, mmesa->c_textureBytes, mmesa->c_agpTextureBytes );
}
mmesa->c_textureSwaps = 0;
mmesa->c_textureBytes = 0;
mmesa->c_agpTextureBytes = 0;
}
mmesa->c_texsrc_agp = 0;
mmesa->c_texsrc_card = 0;
if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT)
fprintf( stderr, "---------------------------------------------------------\n" );
}
void mach64PerformanceBoxesLocked( mach64ContextPtr mmesa )
{
GLint ret;
drm_mach64_clear_t clear;
GLint x, y, w, h;
GLuint color;
GLint nbox;
GLint x1, y1, x2, y2;
drm_clip_rect_t *b = mmesa->sarea->boxes;
/* save cliprects */
nbox = mmesa->sarea->nbox;
x1 = b[0].x1;
y1 = b[0].y1;
x2 = b[0].x2;
y2 = b[0].y2;
/* setup a single cliprect and call the clear ioctl for each box */
mmesa->sarea->nbox = 1;
w = h = 8;
x = mmesa->drawX;
y = mmesa->drawY;
b[0].x1 = x;
b[0].x2 = x + w;
b[0].y1 = y;
b[0].y2 = y + h;
clear.flags = MACH64_BACK;
clear.clear_depth = 0;
/* Red box if DDFinish was called to wait for rendering to complete */
if ( mmesa->c_drawWaits ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 0, 0 );
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
x += w;
b[0].x1 = x;
b[0].x2 = x + w;
/* draw a green box if we had to wait for previous frame(s) to complete */
if ( !mmesa->hardwareWentIdle ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 255, 0, 0 );
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
x += w;
w = 20;
b[0].x1 = x;
/* show approx. ratio of AGP/card textures used - Blue = AGP, Purple = Card */
if ( mmesa->c_texsrc_agp || mmesa->c_texsrc_card ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 0, 255, 0 );
w = ((GLfloat)mmesa->c_texsrc_agp / (GLfloat)(mmesa->c_texsrc_agp + mmesa->c_texsrc_card))*20;
if (w > 1) {
b[0].x2 = x + w;
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
x += w;
w = 20 - w;
if (w > 1) {
b[0].x1 = x;
b[0].x2 = x + w;
color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 255, 0 );
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
}
x += w;
w = 8;
b[0].x1 = x;
b[0].x2 = x + w;
/* Yellow box if we swapped textures */
if ( mmesa->c_textureSwaps ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 255, 0, 0 );
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
h = 4;
x += 8;
b[0].x1 = x;
b[0].y2 = y + h;
/* Purple bar for card memory texture blits/uploads */
if ( mmesa->c_textureBytes ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 255, 0 );
w = mmesa->c_textureBytes / 16384;
if ( w <= 0 )
w = 1;
if (w > (mmesa->driDrawable->w - 44))
w = mmesa->driDrawable->w - 44;
b[0].x2 = x + w;
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
/* Blue bar for AGP memory texture blits/uploads */
if ( mmesa->c_agpTextureBytes ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 0, 255, 0 );
w = mmesa->c_agpTextureBytes / 16384;
if ( w <= 0 )
w = 1;
if (w > (mmesa->driDrawable->w - 44))
w = mmesa->driDrawable->w - 44;
y += 4;
b[0].x2 = x + w;
b[0].y1 = y;
b[0].y2 = y + h;
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
/* Pink bar for number of vertex buffers used */
if ( mmesa->c_vertexBuffers ) {
color = mach64PackColor( mmesa->mach64Screen->cpp, 196, 128, 128, 0 );
w = mmesa->c_vertexBuffers;
if (w > (mmesa->driDrawable->w))
w = mmesa->driDrawable->w;
h = 8;
x = mmesa->drawX;
y = mmesa->drawY + 8;
b[0].x1 = x;
b[0].x2 = x + w;
b[0].y1 = y;
b[0].y2 = y + h;
clear.x = x;
clear.y = y;
clear.w = w;
clear.h = h;
clear.clear_color = color;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if (ret < 0) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
/* restore cliprects */
mmesa->sarea->nbox = nbox;
b[0].x1 = x1;
b[0].y1 = y1;
b[0].x2 = x2;
b[0].y2 = y2;
}
#endif
/* ================================================================
* Buffer clear
*/
static void mach64DDClear( GLcontext *ctx, GLbitfield mask )
{
mach64ContextPtr mmesa = MACH64_CONTEXT( ctx );
__DRIdrawablePrivate *dPriv = mmesa->driDrawable;
drm_mach64_clear_t clear;
GLuint flags = 0;
GLint i;
GLint ret;
GLint cx, cy, cw, ch;
if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "mach64DDClear\n");
}
#if ENABLE_PERF_BOXES
/* Bump the performance counter */
mmesa->c_clears++;
#endif
FLUSH_BATCH( mmesa );
/* The only state changes we care about here are the RGBA colormask
* and scissor/clipping. We'll just update that state, if needed.
*/
if ( mmesa->new_state & (MACH64_NEW_MASKS | MACH64_NEW_CLIP) ) {
const GLuint save_state = mmesa->new_state;
mmesa->new_state &= (MACH64_NEW_MASKS | MACH64_NEW_CLIP);
mach64DDUpdateHWState( ctx );
mmesa->new_state = save_state & ~(MACH64_NEW_MASKS | MACH64_NEW_CLIP);
}
if ( mask & BUFFER_BIT_FRONT_LEFT ) {
flags |= MACH64_FRONT;
mask &= ~BUFFER_BIT_FRONT_LEFT;
}
if ( mask & BUFFER_BIT_BACK_LEFT ) {
flags |= MACH64_BACK;
mask &= ~BUFFER_BIT_BACK_LEFT;
}
if ( ( mask & BUFFER_BIT_DEPTH ) && ctx->Depth.Mask ) {
flags |= MACH64_DEPTH;
mask &= ~BUFFER_BIT_DEPTH;
}
if ( mask )
_swrast_Clear( ctx, mask );
if ( !flags )
return;
LOCK_HARDWARE( mmesa );
/* 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 += mmesa->drawX;
cy = mmesa->drawY + dPriv->h - cy - ch;
/* HACK?
*/
if ( mmesa->dirty & ~MACH64_UPLOAD_CLIPRECTS ) {
mach64EmitHwStateLocked( mmesa );
}
for ( i = 0 ; i < mmesa->numClipRects ; ) {
int nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS, mmesa->numClipRects );
drm_clip_rect_t *box = mmesa->pClipRects;
drm_clip_rect_t *b = mmesa->sarea->boxes;
GLint n = 0;
if (cw != dPriv->w || ch != dPriv->h) {
/* clear subregion */
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 {
/* clear whole window */
for ( ; i < nr ; i++ ) {
*b++ = box[i];
n++;
}
}
mmesa->sarea->nbox = n;
if ( MACH64_DEBUG & DEBUG_VERBOSE_IOCTL ) {
fprintf( stderr,
"DRM_MACH64_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
flags,
(GLuint)mmesa->ClearColor,
(GLuint)mmesa->ClearDepth,
mmesa->sarea->nbox );
}
clear.flags = flags;
clear.x = cx;
clear.y = cy;
clear.w = cw;
clear.h = ch;
clear.clear_color = mmesa->ClearColor;
clear.clear_depth = mmesa->ClearDepth;
ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
&clear, sizeof(drm_mach64_clear_t) );
if ( ret ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
exit( -1 );
}
}
UNLOCK_HARDWARE( mmesa );
mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
MACH64_UPLOAD_MISC |
MACH64_UPLOAD_CLIPRECTS);
}
void mach64WaitForIdleLocked( mach64ContextPtr mmesa )
{
int fd = mmesa->driFd;
int to = 0;
int ret;
do {
ret = drmCommandNone( fd, DRM_MACH64_IDLE );
} while ( ( ret == -EBUSY ) && ( to++ < MACH64_TIMEOUT ) );
if ( ret < 0 ) {
drmCommandNone( fd, DRM_MACH64_RESET );
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "Error: Mach64 timed out... exiting\n" );
exit( -1 );
}
}
/* Flush the DMA queue to the hardware */
void mach64FlushDMALocked( mach64ContextPtr mmesa )
{
int fd = mmesa->driFd;
int ret;
ret = drmCommandNone( fd, DRM_MACH64_FLUSH );
if ( ret < 0 ) {
drmCommandNone( fd, DRM_MACH64_RESET );
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "Error flushing DMA... exiting\n" );
exit( -1 );
}
mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
MACH64_UPLOAD_MISC |
MACH64_UPLOAD_CLIPRECTS);
}
/* For client-side state emits - currently unused */
void mach64UploadHwStateLocked( mach64ContextPtr mmesa )
{
drm_mach64_sarea_t *sarea = mmesa->sarea;
drm_mach64_context_regs_t *regs = &sarea->context_state;
unsigned int dirty = sarea->dirty;
CARD32 offset = ((regs->tex_size_pitch & 0xf0) >> 2);
DMALOCALS;
DMAGETPTR( 19*2 );
if ( dirty & MACH64_UPLOAD_MISC ) {
DMAOUTREG( MACH64_DP_MIX, regs->dp_mix );
DMAOUTREG( MACH64_DP_SRC, regs->dp_src );
DMAOUTREG( MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl );
DMAOUTREG( MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl );
DMAOUTREG( MACH64_SC_LEFT_RIGHT, regs->sc_left_right );
DMAOUTREG( MACH64_SC_TOP_BOTTOM, regs->sc_top_bottom );
sarea->dirty &= ~MACH64_UPLOAD_MISC;
}
if ( dirty & MACH64_UPLOAD_DST_OFF_PITCH ) {
DMAOUTREG( MACH64_DST_OFF_PITCH, regs->dst_off_pitch );
sarea->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH;
}
if ( dirty & MACH64_UPLOAD_Z_OFF_PITCH ) {
DMAOUTREG( MACH64_Z_OFF_PITCH, regs->z_off_pitch );
sarea->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH;
}
if ( dirty & MACH64_UPLOAD_Z_ALPHA_CNTL ) {
DMAOUTREG( MACH64_Z_CNTL, regs->z_cntl );
DMAOUTREG( MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl );
sarea->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL;
}
if ( dirty & MACH64_UPLOAD_SCALE_3D_CNTL ) {
DMAOUTREG( MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl );
sarea->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL;
}
if ( dirty & MACH64_UPLOAD_DP_FOG_CLR ) {
DMAOUTREG( MACH64_DP_FOG_CLR, regs->dp_fog_clr );
sarea->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR;
}
if ( dirty & MACH64_UPLOAD_DP_WRITE_MASK ) {
DMAOUTREG( MACH64_DP_WRITE_MASK, regs->dp_write_mask );
sarea->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK;
}
if ( dirty & MACH64_UPLOAD_DP_PIX_WIDTH ) {
DMAOUTREG( MACH64_DP_PIX_WIDTH, regs->dp_pix_width );
sarea->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH;
}
if ( dirty & MACH64_UPLOAD_SETUP_CNTL ) {
DMAOUTREG( MACH64_SETUP_CNTL, regs->setup_cntl );
sarea->dirty &= ~MACH64_UPLOAD_SETUP_CNTL;
}
if ( dirty & MACH64_UPLOAD_TEXTURE ) {
DMAOUTREG( MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch );
DMAOUTREG( MACH64_TEX_CNTL, regs->tex_cntl );
DMAOUTREG( MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off );
DMAOUTREG( MACH64_TEX_0_OFF + offset, regs->tex_offset );
sarea->dirty &= ~MACH64_UPLOAD_TEXTURE;
}
#if 0
if ( dirty & MACH64_UPLOAD_CLIPRECTS ) {
DMAOUTREG( MACH64_SC_LEFT_RIGHT, regs->sc_left_right );
DMAOUTREG( MACH64_SC_TOP_BOTTOM, regs->sc_top_bottom );
sarea->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
}
#endif
sarea->dirty = 0;
DMAADVANCE();
}
void mach64InitIoctlFuncs( struct dd_function_table *functions )
{
functions->Clear = mach64DDClear;
}