#ifdef GLX_DIRECT_RENDERING
#include "ffb_xmesa.h"
#include "context.h"
#include "matrix.h"
#include "simple_list.h"
#include "imports.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "array_cache/acache.h"
#include "ffb_context.h"
#include "ffb_dd.h"
#include "ffb_span.h"
#include "ffb_depth.h"
#include "ffb_stencil.h"
#include "ffb_clear.h"
#include "ffb_vb.h"
#include "ffb_tris.h"
#include "ffb_lines.h"
#include "ffb_points.h"
#include "ffb_state.h"
#include "ffb_tex.h"
#include "ffb_lock.h"
#include "ffb_vtxfmt.h"
#include "ffb_bitmap.h"
static GLboolean
ffbInitDriver(__DRIscreenPrivate *sPriv)
{
ffbScreenPrivate *ffbScreen;
FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
if (getenv("LIBGL_FORCE_XSERVER"))
return GL_FALSE;
ffbScreen = (ffbScreenPrivate *) Xmalloc(sizeof(ffbScreenPrivate));
if (!ffbScreen)
return GL_FALSE;
if (drmMap(sPriv->fd,
gDRIPriv->hFbcRegs,
gDRIPriv->sFbcRegs,
&gDRIPriv->mFbcRegs)) {
Xfree(ffbScreen);
return GL_FALSE;
}
ffbScreen->regs = (ffb_fbcPtr) gDRIPriv->mFbcRegs;
if (drmMap(sPriv->fd,
gDRIPriv->hDacRegs,
gDRIPriv->sDacRegs,
&gDRIPriv->mDacRegs)) {
drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
Xfree(ffbScreen);
return GL_FALSE;
}
ffbScreen->dac = (ffb_dacPtr) gDRIPriv->mDacRegs;
if (drmMap(sPriv->fd,
gDRIPriv->hSfb8r,
gDRIPriv->sSfb8r,
&gDRIPriv->mSfb8r)) {
drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
Xfree(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb8r = (volatile char *) gDRIPriv->mSfb8r;
if (drmMap(sPriv->fd,
gDRIPriv->hSfb32,
gDRIPriv->sSfb32,
&gDRIPriv->mSfb32)) {
drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
Xfree(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb32 = (volatile char *) gDRIPriv->mSfb32;
if (drmMap(sPriv->fd,
gDRIPriv->hSfb64,
gDRIPriv->sSfb64,
&gDRIPriv->mSfb64)) {
drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
Xfree(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb64 = (volatile char *) gDRIPriv->mSfb64;
ffbScreen->fifo_cache = 0;
ffbScreen->rp_active = 0;
ffbScreen->sPriv = sPriv;
sPriv->private = (void *) ffbScreen;
ffbDDLinefuncInit();
ffbDDPointfuncInit();
return GL_TRUE;
}
static void
ffbDestroyScreen(__DRIscreenPrivate *sPriv)
{
ffbScreenPrivate *ffbScreen = sPriv->private;
FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
drmUnmap(gDRIPriv->mSfb64, gDRIPriv->sSfb64);
Xfree(ffbScreen);
}
static const struct gl_pipeline_stage *ffb_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
&_tnl_render_stage,
0,
};
static GLboolean
ffbCreateContext(const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
ffbContextPtr fmesa;
GLcontext *ctx, *shareCtx;
__DRIscreenPrivate *sPriv;
ffbScreenPrivate *ffbScreen;
char *debug;
fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec));
if (!fmesa)
return GL_FALSE;
if (sharedContextPrivate)
shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, fmesa, GL_TRUE);
if (!fmesa->glCtx) {
FREE(fmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = fmesa;
ctx = fmesa->glCtx;
sPriv = driContextPriv->driScreenPriv;
ffbScreen = (ffbScreenPrivate *) sPriv->private;
fmesa->hHWContext = driContextPriv->hHWContext;
fmesa->driFd = sPriv->fd;
fmesa->driHwLock = &sPriv->pSAREA->lock;
fmesa->ffbScreen = ffbScreen;
fmesa->driScreen = sPriv;
fmesa->ffb_sarea = FFB_DRISHARE(sPriv->pSAREA);
fmesa->regs = ffbScreen->regs;
fmesa->sfb32 = ffbScreen->sfb32;
ffbDDInitContextHwState(ctx);
{
GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
fmesa->clear_pixel = ((r << 0) |
(g << 8) |
(b << 16));
}
fmesa->clear_depth = Z_FROM_MESA(ctx->Depth.Clear * 4294967295.0f);
fmesa->clear_stencil = ctx->Stencil.Clear & 0xf;
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 1.0;
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
fmesa->ffb_2_30_fixed_scale = __FFB_2_30_FIXED_SCALE;
fmesa->ffb_one_over_2_30_fixed_scale = (1.0 / __FFB_2_30_FIXED_SCALE);
fmesa->ffb_16_16_fixed_scale = __FFB_16_16_FIXED_SCALE;
fmesa->ffb_one_over_16_16_fixed_scale = (1.0 / __FFB_16_16_FIXED_SCALE);
fmesa->ffb_ubyte_color_scale = 255.0f;
fmesa->ffb_zero = 0.0f;
fmesa->debugFallbacks = GL_FALSE;
debug = getenv("LIBGL_DEBUG");
if (debug && strstr(debug, "fallbacks"))
fmesa->debugFallbacks = GL_TRUE;
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
ffbDDExtensionsInit(ctx);
ffbDDInitDriverFuncs(ctx);
ffbDDInitStateFuncs(ctx);
ffbDDInitSpanFuncs(ctx);
ffbDDInitDepthFuncs(ctx);
ffbDDInitStencilFuncs(ctx);
ffbDDInitRenderFuncs(ctx);
ffbDDInitTexFuncs(ctx);
ffbDDInitBitmapFuncs(ctx);
ffbInitVB(ctx);
ffbInitTnlModule(ctx);
_tnl_destroy_pipeline(ctx);
_tnl_install_pipeline(ctx, ffb_pipeline);
return GL_TRUE;
}
static void
ffbDestroyContext(__DRIcontextPrivate *driContextPriv)
{
ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
if (fmesa) {
ffbFreeVB(fmesa->glCtx);
_swsetup_DestroyContext( fmesa->glCtx );
_tnl_DestroyContext( fmesa->glCtx );
_ac_DestroyContext( fmesa->glCtx );
_swrast_DestroyContext( fmesa->glCtx );
fmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(fmesa->glCtx);
FREE(fmesa);
}
}
static GLboolean
ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap) {
return GL_FALSE;
}
else {
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer(mesaVis,
GL_FALSE,
mesaVis->stencilBits > 0,
mesaVis->accumRedBits > 0,
mesaVis->alphaBits > 0);
return (driDrawPriv->driverPrivate != NULL);
}
}
static void
ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}
#define USE_FAST_SWAP
static void
ffbSwapBuffers( __DRIdrawablePrivate *dPriv )
{
ffbContextPtr fmesa = (ffbContextPtr) dPriv->driContextPriv->driverPrivate;
unsigned int fbc, wid, wid_reg_val, dac_db_bit;
unsigned int shadow_dac_addr, active_dac_addr;
ffb_fbcPtr ffb;
ffb_dacPtr dac;
if (fmesa == NULL ||
fmesa->glCtx->Visual.doubleBufferMode == 0)
return;
_mesa_notifySwapBuffers(fmesa->glCtx);
ffb = fmesa->regs;
dac = fmesa->ffbScreen->dac;
fbc = fmesa->fbc;
wid = fmesa->wid;
fmesa->back_buffer ^= 1;
if ((fbc & FFB_FBC_WB_AB) != FFB_FBC_WB_AB) {
if ((fbc & FFB_FBC_WB_A) != 0)
fbc = (fbc & ~FFB_FBC_WB_A) | FFB_FBC_WB_B;
else
fbc = (fbc & ~FFB_FBC_WB_B) | FFB_FBC_WB_A;
}
if ((fbc & FFB_FBC_RB_A) != 0)
fbc = (fbc & ~FFB_FBC_RB_A) | FFB_FBC_RB_B;
else
fbc = (fbc & ~FFB_FBC_RB_B) | FFB_FBC_RB_A;
LOCK_HARDWARE(fmesa);
if (fmesa->fbc != fbc) {
FFBFifo(fmesa, 1);
ffb->fbc = fmesa->fbc = fbc;
fmesa->ffbScreen->rp_active = 1;
}
if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
dac_db_bit = FFBDAC_PAC1_WLUT_DB;
} else {
shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
dac_db_bit = FFBDAC_PAC2_WLUT_DB;
}
FFBWait(fmesa, ffb);
wid_reg_val = DACCFG_READ(dac, active_dac_addr);
if (fmesa->back_buffer == 0)
wid_reg_val |= dac_db_bit;
else
wid_reg_val &= ~dac_db_bit;
#ifdef USE_FAST_SWAP
DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
#else
DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
(FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
{
int limit = 1000000;
while (limit--) {
unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
break;
}
}
#endif
UNLOCK_HARDWARE(fmesa);
}
static void ffb_init_wid(ffbContextPtr fmesa, unsigned int wid)
{
ffb_dacPtr dac = fmesa->ffbScreen->dac;
unsigned int wid_reg_val, dac_db_bit, active_dac_addr;
unsigned int shadow_dac_addr;
if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
dac_db_bit = FFBDAC_PAC1_WLUT_DB;
} else {
shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
dac_db_bit = FFBDAC_PAC2_WLUT_DB;
}
wid_reg_val = DACCFG_READ(dac, active_dac_addr);
wid_reg_val &= ~dac_db_bit;
#ifdef USE_FAST_SWAP
DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
#else
DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
(FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
{
int limit = 1000000;
while (limit--) {
unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
break;
}
}
#endif
}
static GLboolean
ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv)
{
if (driContextPriv) {
ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
int first_time;
fmesa->driDrawable = driDrawPriv;
_mesa_make_current2(fmesa->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate);
if (!fmesa->glCtx->Viewport.Width)
_mesa_set_viewport(fmesa->glCtx,
0, 0,
driDrawPriv->w,
driDrawPriv->h);
first_time = 0;
if (fmesa->wid == ~0) {
first_time = 1;
if (getenv("LIBGL_SOFTWARE_RENDERING"))
FALLBACK( fmesa->glCtx, FFB_BADATTR_SWONLY, GL_TRUE );
}
LOCK_HARDWARE(fmesa);
if (first_time) {
fmesa->wid = fmesa->ffb_sarea->wid_table[driDrawPriv->index];
ffb_init_wid(fmesa, fmesa->wid);
}
fmesa->state_dirty |= FFB_STATE_ALL;
fmesa->state_fifo_ents = fmesa->state_all_fifo_ents;
ffbSyncHardware(fmesa);
UNLOCK_HARDWARE(fmesa);
if (first_time) {
ffbDDClear(fmesa->glCtx,
(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
DD_DEPTH_BIT | DD_STENCIL_BIT),
1, 0, 0, 0, 0);
}
} else {
_mesa_make_current(NULL, NULL);
}
return GL_TRUE;
}
static GLboolean
ffbUnbindContext(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
static GLboolean
ffbOpenFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
static GLboolean
ffbCloseFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
void ffbXMesaUpdateState(ffbContextPtr fmesa)
{
__DRIdrawablePrivate *dPriv = fmesa->driDrawable;
__DRIscreenPrivate *sPriv = fmesa->driScreen;
int stamp = dPriv->lastStamp;
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
if (dPriv->lastStamp != stamp) {
GLcontext *ctx = fmesa->glCtx;
ffbCalcViewport(ctx);
if (ctx->Polygon.StippleFlag)
ffbXformAreaPattern(fmesa,
(const GLubyte *)ctx->PolygonStipple);
}
}
static struct __DriverAPIRec ffbAPI = {
ffbInitDriver,
ffbDestroyScreen,
ffbCreateContext,
ffbDestroyContext,
ffbCreateBuffer,
ffbDestroyBuffer,
ffbSwapBuffers,
ffbMakeCurrent,
ffbUnbindContext,
ffbOpenFullScreen,
ffbCloseFullScreen
};
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &ffbAPI);
return (void *) psp;
}
#endif