| /* |
| * 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, <alanh@fairlite.demon.co.uk> |
| * |
| * 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; |
| } |