/* -*- 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 * Leif Delgass * Jos�Fonseca */ #include #include "mach64_context.h" #include "mach64_state.h" #include "mach64_ioctl.h" #include "mach64_tex.h" #include "main/imports.h" #include "main/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( __DRIdrawable *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( struct gl_context *ctx, GLbitfield mask ) { mach64ContextPtr mmesa = MACH64_CONTEXT( ctx ); __DRIdrawable *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; }