From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c | 753 +++++++++++++++++++++ 1 file changed, 753 insertions(+) create mode 100644 nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c') diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c new file mode 100644 index 000000000..530c5373a --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_xmesa.c @@ -0,0 +1,753 @@ +/* $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 + */ + +#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 "array_cache/acache.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" + +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 ); + _ac_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 ); + _ac_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); +#if 0 + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + mesaVis->stencilBits > 0, + mesaVis->accumRedBits > 0, + mesaVis->alphaBits > 0); +#else + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch); + ffbSetSpanFunctions(frontRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch); + ffbSetSpanFunctions(backRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, bpp, offset, bogusPitch); + ffbSetDepthFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, bpp, offset,bogusPitch); + 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; +#endif + 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; + + /* 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), + 1, 0, 0, 0, 0); + } + } 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); + if (ctx->Polygon.StippleFlag) + ffbXformAreaPattern(fmesa, + (const GLubyte *)ctx->PolygonStipple); + } +} + +static const struct __DriverAPIRec ffbAPI = { + .InitDriver = ffbInitDriver, + .DestroyScreen = ffbDestroyScreen, + .CreateContext = ffbCreateContext, + .DestroyContext = ffbDestroyContext, + .CreateBuffer = ffbCreateBuffer, + .DestroyBuffer = ffbDestroyBuffer, + .SwapBuffers = ffbSwapBuffers, + .MakeCurrent = ffbMakeCurrent, + .UnbindContext = ffbUnbindContext, + .GetSwapInfo = NULL, + .GetMSC = NULL, + .WaitForMSC = NULL, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL +}; + + +static __GLcontextModes * +ffbFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* 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; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + 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; + } + + modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); + m = modes; + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_DIRECT_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for ( m = modes ; m != NULL ; m = m->next ) { + if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes ) + +{ + __DRIscreenPrivate *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 }; + + dri_interface = interface; + + if ( ! driCheckDriDdxDrmVersions2( "ffb", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected ) ) { + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &ffbAPI); + if ( psp != NULL ) { + *driver_modes = ffbFillInModes( 32, 16, 0, GL_TRUE ); + } + + return (void *) psp; +} -- cgit v1.2.3