/* * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Alan Hourihane not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Alan Hourihane makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: Alan Hourihane, * * Trident CyberBladeXP driver. * */ #include "trident_context.h" #include "trident_lock.h" #include "vbo/vbo.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" #include "framebuffer.h" #define TRIDENTPACKCOLOR332(r, g, b) \ (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6)) #define TRIDENTPACKCOLOR1555(r, g, b, a) \ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ ((a) ? 0x8000 : 0)) #define TRIDENTPACKCOLOR565(r, g, b) \ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) #define TRIDENTPACKCOLOR888(r, g, b) \ (((r) << 16) | ((g) << 8) | (b)) #define TRIDENTPACKCOLOR8888(r, g, b, a) \ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) #define TRIDENTPACKCOLOR4444(r, g, b, a) \ ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) static __inline__ GLuint tridentPackColor( GLuint cpp, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) { switch ( cpp ) { case 2: return TRIDENTPACKCOLOR565( r, g, b ); case 4: return TRIDENTPACKCOLOR8888( r, g, b, a ); default: return 0; } } void tridentUploadHwStateLocked( tridentContextPtr tmesa ) { unsigned char *MMIO = tmesa->tridentScreen->mmio.map; #if 0 ATISAREAPrivPtr sarea = tmesa->sarea; trident_context_regs_t *regs = &(sarea->ContextState); #endif if ( tmesa->dirty & TRIDENT_UPLOAD_COMMAND_D ) { MMIO_OUT32(MMIO, 0x00281C, tmesa->commandD ); tmesa->dirty &= ~TRIDENT_UPLOAD_COMMAND_D; } if ( tmesa->dirty & TRIDENT_UPLOAD_CLIPRECTS ) { /* XXX FIX ME ! */ MMIO_OUT32(MMIO, 0x002C80 , 0x20008000 | tmesa->tridentScreen->height ); MMIO_OUT32(MMIO, 0x002C84 , 0x20000000 | tmesa->tridentScreen->width ); tmesa->dirty &= ~TRIDENT_UPLOAD_CLIPRECTS; } tmesa->dirty = 0; } /* Copy the back color buffer to the front color buffer. */ void tridentCopyBuffer( const __DRIdrawablePrivate *dPriv ) { unsigned char *MMIO; tridentContextPtr tmesa; GLint nbox, i; int busy; drm_clip_rect_t *pbox; assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate; MMIO = tmesa->tridentScreen->mmio.map; LOCK_HARDWARE( tmesa ); /* use front buffer cliprects */ nbox = dPriv->numClipRects; pbox = dPriv->pClipRects; for ( i = 0 ; i < nbox ; i++ ) { #if 0 GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox ); drm_clip_rect_t *b = tmesa->sarea->boxes; GLint n = 0; for ( ; i < nr ; i++ ) { *b++ = pbox[i]; n++; } tmesa->sarea->nbox = n; #endif MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4); MMIO_OUT32(MMIO, 0x2154, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4); MMIO_OUT8(MMIO, 0x2127, 0xCC); /* Copy Rop */ MMIO_OUT32(MMIO, 0x2128, 0x4); /* scr2scr */ MMIO_OUT32(MMIO, 0x2138, (pbox->x1 << 16) | pbox->y1); MMIO_OUT32(MMIO, 0x213C, (pbox->x1 << 16) | pbox->y1); MMIO_OUT32(MMIO, 0x2140, (pbox->x2 - pbox->x1) << 16 | (pbox->y2 - pbox->y1) ); MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ #define GE_BUSY 0x80 for (;;) { busy = MMIO_IN8(MMIO, 0x2120); if ( !(busy & GE_BUSY) ) break; } } UNLOCK_HARDWARE( tmesa ); #if 0 tmesa->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS); #endif } static void tridentDDClear( GLcontext *ctx, GLbitfield mask ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); unsigned char *MMIO = tmesa->tridentScreen->mmio.map; int busy; GLuint flags = 0; GLint i; GLint cx, cy, cw, ch; #define DRM_TRIDENT_FRONT 0x01 #define DRM_TRIDENT_BACK 0x02 #define DRM_TRIDENT_DEPTH 0x04 if ( tmesa->new_state ) tridentDDUpdateHWState( ctx ); if ( mask & BUFFER_BIT_FRONT_LEFT ) { flags |= DRM_TRIDENT_FRONT; mask &= ~BUFFER_BIT_FRONT_LEFT; } if ( mask & BUFFER_BIT_BACK_LEFT ) { flags |= DRM_TRIDENT_BACK; mask &= ~BUFFER_BIT_BACK_LEFT; } if ( ( mask & BUFFER_BIT_DEPTH ) && ctx->Depth.Mask ) { flags |= DRM_TRIDENT_DEPTH; mask &= ~BUFFER_BIT_DEPTH; } LOCK_HARDWARE(tmesa); /* get region after locking: */ cx = ctx->DrawBuffer->_Xmin; cy = ctx->DrawBuffer->_Ymin; cw = ctx->DrawBuffer->_Xmax - cx; ch = ctx->DrawBuffer->_Ymax - cy; if ( flags ) { cx += tmesa->drawX; cy += tmesa->drawY; /* HACK!!! */ if ( tmesa->dirty & ~TRIDENT_UPLOAD_CLIPRECTS ) { tridentUploadHwStateLocked( tmesa ); } for ( i = 0 ; i < tmesa->numClipRects ; i++ ) { #if 0 int nr = MIN2( i + TRIDENT_NR_SAREA_CLIPRECTS, tmesa->numClipRects ); drm_clip_rect_t *box = tmesa->pClipRects; drm_clip_rect_t *b = tmesa->sarea->boxes; 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++; } } tmesa->sarea->nbox = n; #endif if (flags & DRM_TRIDENT_BACK) { MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4); MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ #define GE_BUSY 0x80 for (;;) { busy = MMIO_IN8(MMIO, 0x2120); if ( !(busy & GE_BUSY) ) break; } } if (flags & DRM_TRIDENT_DEPTH) { MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->depthPitch << 20 | tmesa->tridentScreen->depthOffset>>4); MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ #define GE_BUSY 0x80 for (;;) { busy = MMIO_IN8(MMIO, 0x2120); if ( !(busy & GE_BUSY) ) break; } } MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4); if (flags & DRM_TRIDENT_FRONT) { MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ #define GE_BUSY 0x80 for (;;) { busy = MMIO_IN8(MMIO, 0x2120); if ( !(busy & GE_BUSY) ) break; } } } #if 0 tmesa->dirty |= (TRIDENT_UPLOAD_CONTEXT | TRIDENT_UPLOAD_MISC | TRIDENT_UPLOAD_CLIPRECTS); #endif } UNLOCK_HARDWARE(tmesa); if ( mask ) _swrast_Clear( ctx, mask ); } static void tridentDDShadeModel( GLcontext *ctx, GLenum mode ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); GLuint s = tmesa->commandD; #define TRIDENT_FLAT_SHADE 0x000000E0 #define TRIDENT_FLAT_SHADE_VERTEX_C 0x00000060 #define TRIDENT_FLAT_SHADE_GOURAUD 0x00000080 s &= ~TRIDENT_FLAT_SHADE; switch ( mode ) { case GL_FLAT: s |= TRIDENT_FLAT_SHADE_VERTEX_C; break; case GL_SMOOTH: s |= TRIDENT_FLAT_SHADE_GOURAUD; break; default: return; } if ( tmesa->commandD != s ) { tmesa->commandD = s; tmesa->dirty |= TRIDENT_UPLOAD_COMMAND_D; } } static void tridentCalcViewport( GLcontext *ctx ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); const GLfloat *v = ctx->Viewport._WindowMap.m; GLfloat *m = tmesa->hw_viewport; /* See also trident_translate_vertex. */ m[MAT_SX] = v[MAT_SX]; m[MAT_TX] = v[MAT_TX] + tmesa->drawX + SUBPIXEL_X; m[MAT_SY] = - v[MAT_SY]; m[MAT_TY] = - v[MAT_TY] + tmesa->driDrawable->h + tmesa->drawY + SUBPIXEL_Y; #if 0 m[MAT_SZ] = v[MAT_SZ] * tmesa->depth_scale; m[MAT_TZ] = v[MAT_TZ] * tmesa->depth_scale; #else m[MAT_SZ] = v[MAT_SZ]; m[MAT_TZ] = v[MAT_TZ]; #endif tmesa->SetupNewInputs = ~0; } static void tridentDDViewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height ) { tridentCalcViewport( ctx ); } static void tridentDDDepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval ) { tridentCalcViewport( ctx ); } static void tridentSetCliprects( tridentContextPtr tmesa, GLenum mode ) { __DRIdrawablePrivate *dPriv = tmesa->driDrawable; switch ( mode ) { case GL_FRONT_LEFT: if (dPriv->numClipRects == 0) { static drm_clip_rect_t zeroareacliprect = {0,0,0,0}; tmesa->numClipRects = 1; tmesa->pClipRects = &zeroareacliprect; } else { tmesa->numClipRects = dPriv->numClipRects; tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects; } tmesa->drawX = dPriv->x; tmesa->drawY = dPriv->y; break; case GL_BACK_LEFT: if ( dPriv->numBackClipRects == 0 ) { if (dPriv->numClipRects == 0) { static drm_clip_rect_t zeroareacliprect = {0,0,0,0}; tmesa->numClipRects = 1; tmesa->pClipRects = &zeroareacliprect; } else { tmesa->numClipRects = dPriv->numClipRects; tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects; tmesa->drawX = dPriv->x; tmesa->drawY = dPriv->y; } } else { tmesa->numClipRects = dPriv->numBackClipRects; tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pBackClipRects; tmesa->drawX = dPriv->backX; tmesa->drawY = dPriv->backY; } break; default: return; } #if 0 tmesa->dirty |= TRIDENT_UPLOAD_CLIPRECTS; #endif } #if 0 static GLboolean tridentDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); int found = GL_TRUE; if ( tmesa->DrawBuffer != mode ) { tmesa->DrawBuffer = mode; switch ( mode ) { case GL_FRONT_LEFT: tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE ); tmesa->drawOffset = tmesa->tridentScreen->frontOffset; tmesa->drawPitch = tmesa->tridentScreen->frontPitch; tridentSetCliprects( tmesa, GL_FRONT_LEFT ); break; case GL_BACK_LEFT: tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE ); tmesa->drawOffset = tmesa->tridentScreen->backOffset; tmesa->drawPitch = tmesa->tridentScreen->backPitch; tridentSetCliprects( tmesa, GL_BACK_LEFT ); break; default: tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_TRUE ); found = GL_FALSE; break; } #if 0 tmesa->setup.dst_off_pitch = (((tmesa->drawPitch/8) << 22) | (tmesa->drawOffset >> 3)); tmesa->dirty |= MACH64_UPLOAD_DST_OFF_PITCH | MACH64_UPLOAD_CONTEXT; #endif } return found; } static void tridentDDClearColor( GLcontext *ctx, const GLchan color[4] ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); tmesa->ClearColor = tridentPackColor( tmesa->tridentScreen->cpp, color[0], color[1], color[2], color[3] ); } #endif static void tridentDDUpdateState( GLcontext *ctx, GLuint new_state ) { _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); TRIDENT_CONTEXT(ctx)->new_gl_state |= new_state; } /* Initialize the context's hardware state. */ void tridentDDInitState( tridentContextPtr tmesa ) { tmesa->new_state = 0; switch ( tmesa->glCtx->Visual.depthBits ) { case 16: tmesa->depth_scale = 1.0 / (GLfloat)0xffff; break; case 24: tmesa->depth_scale = 1.0 / (GLfloat)0xffffff; break; } } void tridentDDUpdateHWState( GLcontext *ctx ) { tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); int new_state = tmesa->new_state; if ( new_state ) { tmesa->new_state = 0; #if 0 /* Update the various parts of the context's state. */ if ( new_state & GAMMA_NEW_ALPHA ) tridentUpdateAlphaMode( ctx ); if ( new_state & GAMMA_NEW_DEPTH ) tridentUpdateZMode( ctx ); if ( new_state & GAMMA_NEW_FOG ) gammaUpdateFogAttrib( ctx ); if ( new_state & GAMMA_NEW_CLIP ) gammaUpdateClipping( ctx ); if ( new_state & GAMMA_NEW_POLYGON ) gammaUpdatePolygon( ctx ); if ( new_state & GAMMA_NEW_CULL ) gammaUpdateCull( ctx ); if ( new_state & GAMMA_NEW_MASKS ) gammaUpdateMasks( ctx ); if ( new_state & GAMMA_NEW_STIPPLE ) gammaUpdateStipple( ctx ); #endif } /* HACK ! */ #if 0 gammaEmitHwState( tmesa ); #endif } /* Initialize the driver's state functions. */ void tridentDDInitStateFuncs( GLcontext *ctx ) { ctx->Driver.UpdateState = tridentDDUpdateState; ctx->Driver.Clear = tridentDDClear; ctx->Driver.DepthRange = tridentDDDepthRange; ctx->Driver.ShadeModel = tridentDDShadeModel; ctx->Driver.Viewport = tridentDDViewport; }