blob: 7fd4e570d3372b049850d6bdca2b1db042320def [file] [log] [blame]
/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.c,v 1.4 2002/02/22 21:32:59 dawes Exp $
*
* GLX Hardware Device Driver for Sun Creator/Creator3D
* Copyright (C) 2000, 2001 David S. Miller
*
* 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 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
* DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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.
*
*
* David S. Miller <davem@redhat.com>
*/
#include "ffb_xmesa.h"
#include "context.h"
#include "framebuffer.h"
#include "matrix.h"
#include "renderbuffer.h"
#include "simple_list.h"
#include "imports.h"
#include "utils.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "vbo/vbo.h"
#include "drivers/common/driverfuncs.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"
#include "drm_sarea.h"
#include "drirenderbuffer.h"
static GLboolean
ffbInitDriver(__DRIscreenPrivate *sPriv)
{
ffbScreenPrivate *ffbScreen;
FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
drmAddress map;
if (getenv("LIBGL_FORCE_XSERVER"))
return GL_FALSE;
if (sPriv->devPrivSize != sizeof(FFBDRIRec)) {
fprintf(stderr,"\nERROR! sizeof(FFBDRIRec) does not match passed size from device driver\n");
return GL_FALSE;
}
/* Allocate the private area. */
ffbScreen = (ffbScreenPrivate *) MALLOC(sizeof(ffbScreenPrivate));
if (!ffbScreen)
return GL_FALSE;
/* Map FBC registers. */
if (drmMap(sPriv->fd,
gDRIPriv->hFbcRegs,
gDRIPriv->sFbcRegs,
&map)) {
FREE(ffbScreen);
return GL_FALSE;
}
ffbScreen->regs = (ffb_fbcPtr) map;
/* Map ramdac registers. */
if (drmMap(sPriv->fd,
gDRIPriv->hDacRegs,
gDRIPriv->sDacRegs,
&map)) {
drmUnmap((drmAddress)ffbScreen->regs, gDRIPriv->sFbcRegs);
FREE(ffbScreen);
return GL_FALSE;
}
ffbScreen->dac = (ffb_dacPtr) map;
/* Map "Smart" framebuffer views. */
if (drmMap(sPriv->fd,
gDRIPriv->hSfb8r,
gDRIPriv->sSfb8r,
&map)) {
drmUnmap((drmAddress)ffbScreen->regs, gDRIPriv->sFbcRegs);
drmUnmap((drmAddress)ffbScreen->dac, gDRIPriv->sDacRegs);
FREE(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb8r = (volatile char *) map;
if (drmMap(sPriv->fd,
gDRIPriv->hSfb32,
gDRIPriv->sSfb32,
&map)) {
drmUnmap((drmAddress)ffbScreen->regs, gDRIPriv->sFbcRegs);
drmUnmap((drmAddress)ffbScreen->dac, gDRIPriv->sDacRegs);
drmUnmap((drmAddress)ffbScreen->sfb8r, gDRIPriv->sSfb8r);
FREE(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb32 = (volatile char *) map;
if (drmMap(sPriv->fd,
gDRIPriv->hSfb64,
gDRIPriv->sSfb64,
&map)) {
drmUnmap((drmAddress)ffbScreen->regs, gDRIPriv->sFbcRegs);
drmUnmap((drmAddress)ffbScreen->dac, gDRIPriv->sDacRegs);
drmUnmap((drmAddress)ffbScreen->sfb8r, gDRIPriv->sSfb8r);
drmUnmap((drmAddress)ffbScreen->sfb32, gDRIPriv->sSfb32);
FREE(ffbScreen);
return GL_FALSE;
}
ffbScreen->sfb64 = (volatile char *) map;
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((drmAddress)ffbScreen->regs, gDRIPriv->sFbcRegs);
drmUnmap((drmAddress)ffbScreen->dac, gDRIPriv->sDacRegs);
drmUnmap((drmAddress)ffbScreen->sfb8r, gDRIPriv->sSfb8r);
drmUnmap((drmAddress)ffbScreen->sfb32, gDRIPriv->sSfb32);
drmUnmap((drmAddress)ffbScreen->sfb64, gDRIPriv->sSfb64);
FREE(ffbScreen);
}
static const struct tnl_pipeline_stage *ffb_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
/* REMOVE: fog coord stage */
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
/* REMOVE: point attenuation stage */
&_tnl_render_stage,
0,
};
/* Create and initialize the Mesa and driver specific context data */
static GLboolean
ffbCreateContext(const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
ffbContextPtr fmesa;
GLcontext *ctx, *shareCtx;
__DRIscreenPrivate *sPriv;
ffbScreenPrivate *ffbScreen;
char *debug;
struct dd_function_table functions;
/* Allocate ffb context */
fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec));
if (!fmesa)
return GL_FALSE;
_mesa_init_driver_functions(&functions);
/* Allocate Mesa context */
if (sharedContextPrivate)
shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
&functions, fmesa);
if (!fmesa->glCtx) {
FREE(fmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = fmesa;
ctx = fmesa->glCtx;
sPriv = driContextPriv->driScreenPriv;
ffbScreen = (ffbScreenPrivate *) sPriv->private;
/* Dri stuff. */
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);
/* Register and framebuffer hw pointers. */
fmesa->regs = ffbScreen->regs;
fmesa->sfb32 = ffbScreen->sfb32;
ffbDDInitContextHwState(ctx);
/* Default clear and depth colors. */
{
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;
/* No wide points. */
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
/* Disable wide lines as we can't antialias them correctly in
* hardware.
*/
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;
/* Instead of having GCC emit these constants a zillion times
* everywhere in the driver, put them here.
*/
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;
/* Initialize the software rasterizer and helper modules. */
_swrast_CreateContext( ctx );
_vbo_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
/* All of this need only be done once for a new context. */
/* XXX these should be moved right after the
* _mesa_init_driver_functions() call above.
*/
ffbDDExtensionsInit(ctx);
ffbDDInitDriverFuncs(ctx);
ffbDDInitStateFuncs(ctx);
ffbDDInitRenderFuncs(ctx);
/*ffbDDInitTexFuncs(ctx); not needed */
ffbDDInitBitmapFuncs(ctx);
ffbInitVB(ctx);
#if 0
ffbInitTnlModule(ctx);
#endif
_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 );
_vbo_DestroyContext( fmesa->glCtx );
_swrast_DestroyContext( fmesa->glCtx );
/* free the Mesa context */
fmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(fmesa->glCtx);
FREE(fmesa);
}
}
/* Create and initialize the Mesa and driver specific pixmap buffer data */
static GLboolean
ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
/* Mesa checks for pitch > 0, but ffb doesn't use pitches */
int bogusPitch = 1;
int bpp = 4; /* we've always got a 32bpp framebuffer */
int offset = 0; /* always at 0 for offset */
if (isPixmap) {
return GL_FALSE; /* not implemented */
} else {
GLboolean swStencil = (mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24);
struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
{
driRenderbuffer *frontRb
= driNewRenderbuffer(GL_RGBA, NULL, bpp, offset, bogusPitch,
driDrawPriv);
ffbSetSpanFunctions(frontRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
}
if (mesaVis->doubleBufferMode) {
driRenderbuffer *backRb
= driNewRenderbuffer(GL_RGBA, NULL, bpp, offset, bogusPitch,
driDrawPriv);
ffbSetSpanFunctions(backRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
}
if (mesaVis->depthBits == 16) {
driRenderbuffer *depthRb
= driNewRenderbuffer(GL_DEPTH_COMPONENT16, NULL, bpp, offset,
bogusPitch, driDrawPriv);
ffbSetDepthFunctions(depthRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
}
if (mesaVis->stencilBits > 0 && !swStencil) {
driRenderbuffer *stencilRb
= driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, NULL, bpp, offset,
bogusPitch, driDrawPriv);
ffbSetStencilFunctions(stencilRb, mesaVis);
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
}
_mesa_add_soft_renderbuffers(fb,
GL_FALSE, /* color */
GL_FALSE, /* depth */
swStencil,
mesaVis->accumRedBits > 0,
GL_FALSE, /* alpha */
GL_FALSE /* aux */);
driDrawPriv->driverPrivate = (void *) fb;
return (driDrawPriv->driverPrivate != NULL);
}
}
static void
ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_unreference_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;
/* Flush pending rendering commands */
_mesa_notifySwapBuffers(fmesa->glCtx);
ffb = fmesa->regs;
dac = fmesa->ffbScreen->dac;
fbc = fmesa->fbc;
wid = fmesa->wid;
/* Swap the buffer we render into and read pixels from. */
fmesa->back_buffer ^= 1;
/* If we are writing into both buffers, don't mess with
* the WB setting.
*/
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;
}
/* But either way, we must flip the read buffer setting. */
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;
}
/* And swap the buffer displayed in the WID. */
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);
/* Schedule the window transfer. */
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);
/* Schedule the window transfer. */
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
}
/* Force the context `c' to be the current context and associate with it
buffer `b' */
static GLboolean
ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv)
{
if (driContextPriv) {
ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
int first_time;
fmesa->driDrawable = driDrawPriv;
_mesa_make_current(fmesa->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate);
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) {
/* Also, at the first switch to a new context,
* we need to clear all the hw buffers.
*/
ffbDDClear(fmesa->glCtx,
(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL));
}
} else {
_mesa_make_current(NULL, NULL, NULL);
}
return GL_TRUE;
}
/* Force the context `c' to be unbound from its buffer */
static GLboolean
ffbUnbindContext(__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);
driUpdateFramebufferSize(ctx, dPriv);
if (ctx->Polygon.StippleFlag) {
ffbXformAreaPattern(fmesa,
(const GLubyte *)ctx->PolygonStipple);
}
}
}
static const __DRIconfig **
ffbFillInModes( __DRIscreenPrivate *psp,
unsigned pixel_bits, unsigned depth_bits,
unsigned stencil_bits, GLboolean have_back_buffer )
{
__DRIconfig **configs;
__GLcontextModes *m;
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
GLenum fb_format;
GLenum fb_type;
int i;
/* GLX_SWAP_COPY_OML is only supported because the FFB driver doesn't
* support pageflipping at all.
*/
static const GLenum back_buffer_modes[] = {
GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
};
u_int8_t depth_bits_array[3];
u_int8_t stencil_bits_array[3];
depth_bits_array[0] = 0;
depth_bits_array[1] = depth_bits;
depth_bits_array[2] = depth_bits;
/* Just like with the accumulation buffer, always provide some modes
* with a stencil buffer. It will be a sw fallback, but some apps won't
* care about that.
*/
stencil_bits_array[0] = 0;
stencil_bits_array[1] = 0;
stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
back_buffer_factor = (have_back_buffer) ? 3 : 1;
if ( pixel_bits == 16 ) {
fb_format = GL_RGB;
fb_type = GL_UNSIGNED_SHORT_5_6_5;
}
else {
fb_format = GL_BGRA;
fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
back_buffer_factor);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
return NULL;
}
/* Mark the visual as slow if there are "fake" stencil bits.
*/
for (i = 0; configs[i]; i++) {
m = &configs[i]->modes;
if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
m->visualRating = GLX_SLOW_CONFIG;
}
}
return (const __DRIconfig **) configs;
}
/**
* This is the driver specific part of the createNewScreen entry point.
*
* \todo maybe fold this into intelInitDriver
*
* \return the __GLcontextModes supported by this driver
*/
static const __DRIconfig **
ffbInitScreen(__DRIscreen *psp)
{
static const __DRIversion ddx_expected = { 0, 1, 1 };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 0, 0, 1 };
if ( ! driCheckDriDdxDrmVersions2( "ffb",
&psp->dri_version, & dri_expected,
&psp->ddx_version, & ddx_expected,
&psp->drm_version, & drm_expected ) )
return NULL;
if (!ffbInitDriver(psp))
return NULL;
return ffbFillInModes( psp, 32, 16, 0, GL_TRUE );
}
const struct __DriverAPIRec driDriverAPI = {
.InitScreen = ffbInitScreen,
.DestroyScreen = ffbDestroyScreen,
.CreateContext = ffbCreateContext,
.DestroyContext = ffbDestroyContext,
.CreateBuffer = ffbCreateBuffer,
.DestroyBuffer = ffbDestroyBuffer,
.SwapBuffers = ffbSwapBuffers,
.MakeCurrent = ffbMakeCurrent,
.UnbindContext = ffbUnbindContext,
.GetSwapInfo = NULL,
.GetDrawableMSC = NULL,
.WaitForMSC = NULL,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL
};