| /* $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 |
| }; |