blob: cc2e52ab2796acab2960bfe089d8ff8d099ed401 [file] [log] [blame]
/*
* 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;
}