/* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_xmesa.c,v 1.14 2002/10/30 12:51:30 alanh Exp $ */ /* * Copyright 2001 by Alan Hourihane. * * 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, * * 3DLabs Gamma driver */ #include "gamma_context.h" #include "gamma_vb.h" #include "context.h" #include "mmath.h" #include "matrix.h" #include "glint_dri.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" #include "array_cache/acache.h" static GLboolean gammaInitDriver(__DRIscreenPrivate *sPriv) { sPriv->private = (void *) gammaCreateScreen( sPriv ); if (!sPriv->private) { gammaDestroyScreen( sPriv ); return GL_FALSE; } return GL_TRUE; } static void gammaDestroyContext(__DRIcontextPrivate *driContextPriv) { gammaContextPtr gmesa = (gammaContextPtr)driContextPriv->driverPrivate; if (gmesa) { _swsetup_DestroyContext( gmesa->glCtx ); _tnl_DestroyContext( gmesa->glCtx ); _ac_DestroyContext( gmesa->glCtx ); _swrast_DestroyContext( gmesa->glCtx ); gammaFreeVB( gmesa->glCtx ); /* free the Mesa context */ gmesa->glCtx->DriverCtx = NULL; _mesa_destroy_context(gmesa->glCtx); Xfree(gmesa); driContextPriv->driverPrivate = NULL; } } static GLboolean gammaCreateBuffer( Display *dpy, __DRIscreenPrivate *driScrnPriv, __DRIdrawablePrivate *driDrawPriv, const __GLcontextModes *mesaVis, GLboolean isPixmap ) { if (isPixmap) { return GL_FALSE; /* not implemented */ } else { driDrawPriv->driverPrivate = (void *) _mesa_create_framebuffer(mesaVis, GL_FALSE, /* software depth buffer? */ mesaVis->stencilBits > 0, mesaVis->accumRedBits > 0, mesaVis->alphaBits > 0 ); return (driDrawPriv->driverPrivate != NULL); } } static void gammaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) { _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); } static void gammaSwapBuffers(Display *dpy, void *drawablePrivate) { __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; (void) dpy; if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { gammaContextPtr gmesa; __DRIscreenPrivate *driScrnPriv; GLcontext *ctx; gmesa = (gammaContextPtr) dPriv->driContextPriv->driverPrivate; ctx = gmesa->glCtx; driScrnPriv = gmesa->driScreen; VALIDATE_DRAWABLE_INFO(gmesa); /* Flush any partially filled buffers */ FLUSH_DMA_BUFFER(gmesa); DRM_SPINLOCK(&driScrnPriv->pSAREA->drawable_lock, driScrnPriv->drawLockID); VALIDATE_DRAWABLE_INFO_NO_LOCK(gmesa); if (gmesa->EnabledFlags & GAMMA_BACK_BUFFER) { int src, dst, x0, y0, x1, h; int i; int nRect = dPriv->numClipRects; XF86DRIClipRectPtr pRect = dPriv->pClipRects; __DRIscreenPrivate *driScrnPriv = gmesa->driScreen; GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)driScrnPriv->pDevPriv; CHECK_DMA_BUFFER(gmesa, 2); WRITE(gmesa->buf, FBReadMode, (gmesa->FBReadMode | FBReadSrcEnable)); WRITE(gmesa->buf, LBWriteMode, LBWriteModeDisable); for (i = 0; i < nRect; i++, pRect++) { x0 = pRect->x1; x1 = pRect->x2; h = pRect->y2 - pRect->y1; y0 = driScrnPriv->fbHeight - (pRect->y1+h); if (gDRIPriv->numMultiDevices == 2) src = (y0/2)*driScrnPriv->fbWidth+x0; else src = y0*driScrnPriv->fbWidth+x0; y0 += driScrnPriv->fbHeight; if (gDRIPriv->numMultiDevices == 2) dst = (y0/2)*driScrnPriv->fbWidth+x0; else dst = y0*driScrnPriv->fbWidth+x0; CHECK_DMA_BUFFER(gmesa, 9); WRITE(gmesa->buf, StartXDom, x0<<16); /* X0dest */ WRITE(gmesa->buf, StartY, y0<<16); /* Y0dest */ WRITE(gmesa->buf, StartXSub, x1<<16); /* X1dest */ WRITE(gmesa->buf, GLINTCount, h); /* H */ WRITE(gmesa->buf, dY, 1<<16); /* ydir */ WRITE(gmesa->buf, dXDom, 0<<16); WRITE(gmesa->buf, dXSub, 0<<16); WRITE(gmesa->buf, FBSourceOffset, (dst-src)); WRITE(gmesa->buf, Render, 0x00040048); /* NOT_DONE */ } /* ** NOTE: FBSourceOffset (above) is backwards from what is ** described in the manual (i.e., dst-src instead of src-dst) ** due to our using the bottom-left window origin instead of the ** top-left window origin. */ /* Restore FBReadMode */ CHECK_DMA_BUFFER(gmesa, 2); WRITE(gmesa->buf, FBReadMode, (gmesa->FBReadMode | gmesa->AB_FBReadMode)); WRITE(gmesa->buf, LBWriteMode, LBWriteModeEnable); } if (gmesa->EnabledFlags & GAMMA_BACK_BUFFER) PROCESS_DMA_BUFFER_TOP_HALF(gmesa); DRM_SPINUNLOCK(&driScrnPriv->pSAREA->drawable_lock, driScrnPriv->drawLockID); VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(gmesa); if (gmesa->EnabledFlags & GAMMA_BACK_BUFFER) PROCESS_DMA_BUFFER_BOTTOM_HALF(gmesa); } else { _mesa_problem(NULL, "gammaSwapBuffers: drawable has no context!\n"); } } static GLboolean gammaMakeCurrent(__DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv) { if (driContextPriv) { GET_CURRENT_CONTEXT(ctx); gammaContextPtr oldGammaCtx = ctx ? GAMMA_CONTEXT(ctx) : NULL; gammaContextPtr newGammaCtx = (gammaContextPtr) driContextPriv->driverPrivate; if ( newGammaCtx != oldGammaCtx ) { newGammaCtx->dirty = ~0; } if (newGammaCtx->driDrawable != driDrawPriv) { newGammaCtx->driDrawable = driDrawPriv; gammaUpdateWindow ( newGammaCtx->glCtx ); gammaUpdateViewportOffset( newGammaCtx->glCtx ); } #if 0 newGammaCtx->Window &= ~W_GIDMask; newGammaCtx->Window |= (driDrawPriv->index << 5); CHECK_DMA_BUFFER(newGammaCtx,1); WRITE(newGammaCtx->buf, GLINTWindow, newGammaCtx->Window); #endif newGammaCtx->new_state |= GAMMA_NEW_WINDOW; /* FIXME */ _mesa_make_current2( newGammaCtx->glCtx, (GLframebuffer *) driDrawPriv->driverPrivate, (GLframebuffer *) driReadPriv->driverPrivate ); if (!newGammaCtx->glCtx->Viewport.Width) { _mesa_set_viewport(newGammaCtx->glCtx, 0, 0, driDrawPriv->w, driDrawPriv->h); } } else { _mesa_make_current( 0, 0 ); } return GL_TRUE; } static GLboolean gammaUnbindContext( __DRIcontextPrivate *driContextPriv ) { return GL_TRUE; } static GLboolean gammaOpenFullScreen(__DRIcontextPrivate *driContextPriv) { return GL_TRUE; } static GLboolean gammaCloseFullScreen(__DRIcontextPrivate *driContextPriv) { return GL_TRUE; } static struct __DriverAPIRec gammaAPI = { gammaInitDriver, gammaDestroyScreen, gammaCreateContext, gammaDestroyContext, gammaCreateBuffer, gammaDestroyBuffer, gammaSwapBuffers, gammaMakeCurrent, gammaUnbindContext, gammaOpenFullScreen, gammaCloseFullScreen }; /* * This is the bootstrap function for the driver. * The __driCreateScreen name is the symbol that libGL.so fetches. * Return: pointer to a __DRIscreenPrivate. */ void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, int numConfigs, __GLXvisualConfig *config) { __DRIscreenPrivate *psp; psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &gammaAPI); return (void *) psp; } void __driRegisterExtensions(void) { /* No extensions */ }