summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/tdfx/tdfx_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/tdfx/tdfx_screen.c')
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_screen.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_screen.c b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
new file mode 100644
index 0000000000..26de09503a
--- /dev/null
+++ b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
@@ -0,0 +1,450 @@
+/* -*- mode: c; c-basic-offset: 3 -*-
+ *
+ * Copyright 2000 VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS 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.
+ */
+
+/*
+ * Original rewrite:
+ * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "tdfx_dri.h"
+#include "tdfx_context.h"
+#include "tdfx_lock.h"
+#include "tdfx_span.h"
+
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "xmlpool.h"
+
+#include "utils.h"
+
+#ifdef DEBUG_LOCKING
+char *prevLockFile = 0;
+int prevLockLine = 0;
+#endif
+
+#ifndef TDFX_DEBUG
+int TDFX_DEBUG = 0;
+#endif
+
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+ DRI_CONF_SECTION_DEBUG
+ DRI_CONF_NO_RAST(false)
+ DRI_CONF_SECTION_END
+DRI_CONF_END;
+
+static const __DRIextension *tdfxExtensions[] = {
+ &driReadDrawableExtension,
+ NULL
+};
+
+static const GLuint __driNConfigOptions = 1;
+
+static GLboolean
+tdfxCreateScreen( __DRIscreen *sPriv )
+{
+ tdfxScreenPrivate *fxScreen;
+ TDFXDRIPtr fxDRIPriv = (TDFXDRIPtr) sPriv->pDevPriv;
+
+ if (sPriv->devPrivSize != sizeof(TDFXDRIRec)) {
+ fprintf(stderr,"\nERROR! sizeof(TDFXDRIRec) does not match passed size from device driver\n");
+ return GL_FALSE;
+ }
+
+ /* Allocate the private area */
+ fxScreen = (tdfxScreenPrivate *) CALLOC( sizeof(tdfxScreenPrivate) );
+ if ( !fxScreen )
+ return GL_FALSE;
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo (&fxScreen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ fxScreen->driScrnPriv = sPriv;
+ sPriv->private = (void *) fxScreen;
+
+ fxScreen->regs.handle = fxDRIPriv->regs;
+ fxScreen->regs.size = fxDRIPriv->regsSize;
+ fxScreen->deviceID = fxDRIPriv->deviceID;
+ fxScreen->width = fxDRIPriv->width;
+ fxScreen->height = fxDRIPriv->height;
+ fxScreen->mem = fxDRIPriv->mem;
+ fxScreen->cpp = fxDRIPriv->cpp;
+ fxScreen->stride = fxDRIPriv->stride;
+ fxScreen->fifoOffset = fxDRIPriv->fifoOffset;
+ fxScreen->fifoSize = fxDRIPriv->fifoSize;
+ fxScreen->fbOffset = fxDRIPriv->fbOffset;
+ fxScreen->backOffset = fxDRIPriv->backOffset;
+ fxScreen->depthOffset = fxDRIPriv->depthOffset;
+ fxScreen->textureOffset = fxDRIPriv->textureOffset;
+ fxScreen->textureSize = fxDRIPriv->textureSize;
+ fxScreen->sarea_priv_offset = fxDRIPriv->sarea_priv_offset;
+
+ if ( drmMap( sPriv->fd, fxScreen->regs.handle,
+ fxScreen->regs.size, &fxScreen->regs.map ) ) {
+ return GL_FALSE;
+ }
+
+ sPriv->extensions = tdfxExtensions;
+
+ return GL_TRUE;
+}
+
+
+static void
+tdfxDestroyScreen( __DRIscreen *sPriv )
+{
+ tdfxScreenPrivate *fxScreen = (tdfxScreenPrivate *) sPriv->private;
+
+ if (!fxScreen)
+ return;
+
+ drmUnmap( fxScreen->regs.map, fxScreen->regs.size );
+
+ /* free all option information */
+ driDestroyOptionInfo (&fxScreen->optionCache);
+
+ FREE( fxScreen );
+ sPriv->private = NULL;
+}
+
+
+static GLboolean
+tdfxInitDriver( __DRIscreen *sPriv )
+{
+ if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
+ fprintf( stderr, "%s( %p )\n", __FUNCTION__, (void *)sPriv );
+ }
+
+ if ( !tdfxCreateScreen( sPriv ) ) {
+ tdfxDestroyScreen( sPriv );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+tdfxCreateBuffer( __DRIscreen *driScrnPriv,
+ __DRIdrawable *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ tdfxScreenPrivate *screen = (tdfxScreenPrivate *) driScrnPriv->private;
+
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+
+ {
+ driRenderbuffer *frontRb
+ = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL, screen->cpp,
+ screen->fbOffset, screen->width, driDrawPriv);
+ tdfxSetSpanFunctions(frontRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
+ }
+
+ if (mesaVis->doubleBufferMode) {
+ driRenderbuffer *backRb
+ = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL, screen->cpp,
+ screen->backOffset, screen->width,
+ driDrawPriv);
+ tdfxSetSpanFunctions(backRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
+ backRb->backBuffer = GL_TRUE;
+ }
+
+ if (mesaVis->depthBits == 16) {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(MESA_FORMAT_Z16, NULL, screen->cpp,
+ screen->depthOffset, screen->width,
+ driDrawPriv);
+ tdfxSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+ else if (mesaVis->depthBits == 24) {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(MESA_FORMAT_Z24_S8, NULL, screen->cpp,
+ screen->depthOffset, screen->width,
+ driDrawPriv);
+ tdfxSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+
+ if (mesaVis->stencilBits > 0) {
+ driRenderbuffer *stencilRb
+ = driNewRenderbuffer(MESA_FORMAT_S8, NULL, screen->cpp,
+ screen->depthOffset, screen->width,
+ driDrawPriv);
+ tdfxSetSpanFunctions(stencilRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
+ }
+
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ GL_FALSE, /* depth */
+ GL_FALSE, /*swStencil,*/
+ mesaVis->accumRedBits > 0,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */);
+ driDrawPriv->driverPrivate = (void *) fb;
+
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+tdfxDestroyBuffer(__DRIdrawable *driDrawPriv)
+{
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
+}
+
+
+static void
+tdfxSwapBuffers( __DRIdrawable *driDrawPriv )
+
+{
+ GET_CURRENT_CONTEXT(ctx);
+ tdfxContextPtr fxMesa = 0;
+ GLframebuffer *mesaBuffer;
+
+ if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
+ fprintf( stderr, "%s( %p )\n", __FUNCTION__, (void *)driDrawPriv );
+ }
+
+ mesaBuffer = (GLframebuffer *) driDrawPriv->driverPrivate;
+ if ( !mesaBuffer->Visual.doubleBufferMode )
+ return; /* can't swap a single-buffered window */
+
+ /* If the current context's drawable matches the given drawable
+ * we have to do a glFinish (per the GLX spec).
+ */
+ if ( ctx ) {
+ __DRIdrawable *curDrawPriv;
+ fxMesa = TDFX_CONTEXT(ctx);
+ curDrawPriv = fxMesa->driContext->driDrawablePriv;
+
+ if ( curDrawPriv == driDrawPriv ) {
+ /* swapping window bound to current context, flush first */
+ _mesa_notifySwapBuffers( ctx );
+ LOCK_HARDWARE( fxMesa );
+ }
+ else {
+ /* find the fxMesa context previously bound to the window */
+ fxMesa = (tdfxContextPtr) driDrawPriv->driContextPriv->driverPrivate;
+ if (!fxMesa)
+ return;
+ LOCK_HARDWARE( fxMesa );
+ fxMesa->Glide.grSstSelect( fxMesa->Glide.Board );
+#ifdef DEBUG
+ printf("SwapBuf SetState 1\n");
+#endif
+ fxMesa->Glide.grGlideSetState(fxMesa->Glide.State );
+ }
+ }
+
+#ifdef STATS
+ {
+ int stalls;
+ static int prevStalls = 0;
+
+ stalls = fxMesa->Glide.grFifoGetStalls();
+
+ fprintf( stderr, "%s:\n", __FUNCTION__ );
+ if ( stalls != prevStalls ) {
+ fprintf( stderr, " %d stalls occurred\n",
+ stalls - prevStalls );
+ prevStalls = stalls;
+ }
+ if ( fxMesa && fxMesa->texSwaps ) {
+ fprintf( stderr, " %d texture swaps occurred\n",
+ fxMesa->texSwaps );
+ fxMesa->texSwaps = 0;
+ }
+ }
+#endif
+
+ assert(fxMesa);
+
+ if (fxMesa->scissoredClipRects) {
+ /* restore clip rects without scissor box */
+ fxMesa->Glide.grDRIPosition( driDrawPriv->x, driDrawPriv->y,
+ driDrawPriv->w, driDrawPriv->h,
+ driDrawPriv->numClipRects,
+ driDrawPriv->pClipRects );
+ }
+
+ fxMesa->Glide.grDRIBufferSwap( fxMesa->Glide.SwapInterval );
+
+ if (fxMesa->scissoredClipRects) {
+ /* restore clip rects WITH scissor box */
+ fxMesa->Glide.grDRIPosition( driDrawPriv->x, driDrawPriv->y,
+ driDrawPriv->w, driDrawPriv->h,
+ fxMesa->numClipRects, fxMesa->pClipRects );
+ }
+
+
+#if 0
+ {
+ FxI32 result;
+ do {
+ FxI32 result;
+ fxMesa->Glide.grGet(GR_PENDING_BUFFERSWAPS, 4, &result);
+ } while ( result > fxMesa->maxPendingSwapBuffers );
+ }
+#endif
+
+ fxMesa->stats.swapBuffer++;
+
+ if (ctx) {
+ if (ctx->DriverCtx != fxMesa) {
+ fxMesa = TDFX_CONTEXT(ctx);
+ fxMesa->Glide.grSstSelect( fxMesa->Glide.Board );
+#ifdef DEBUG
+ printf("SwapBuf SetState 2\n");
+#endif
+ fxMesa->Glide.grGlideSetState(fxMesa->Glide.State );
+ }
+ UNLOCK_HARDWARE( fxMesa );
+ }
+}
+
+static const __DRIconfig **
+tdfxFillInModes(__DRIscreen *psp,
+ unsigned pixel_bits,
+ unsigned depth_bits,
+ unsigned stencil_bits,
+ GLboolean have_back_buffer)
+{
+ unsigned deep = (depth_bits > 17);
+
+ /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
+ * enough to add support. Basically, if a context is created with an
+ * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
+ * will never be used.
+ */
+
+ static const GLenum db_modes[2] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML };
+ uint8_t depth_bits_array[4];
+ uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
+ if(deep) {
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = 24;
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 8;
+ } else {
+ depth_bits_array[0] = depth_bits;
+ depth_bits_array[1] = 0;
+ depth_bits_array[2] = depth_bits;
+ depth_bits_array[3] = 0;
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 0;
+ stencil_bits_array[2] = 8;
+ stencil_bits_array[3] = 8;
+ }
+
+ msaa_samples_array[0] = 0;
+
+ return (const __DRIconfig **)
+ driCreateConfigs(deep ? GL_RGBA : GL_RGB,
+ deep ? GL_UNSIGNED_INT_8_8_8_8 :
+ GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array,
+ stencil_bits_array,
+ deep ? 2 : 4,
+ db_modes, 2,
+ msaa_samples_array, 1,
+ GL_TRUE);
+}
+
+/**
+ * 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 **
+tdfxInitScreen(__DRIscreen *psp)
+{
+ static const __DRIversion ddx_expected = { 1, 1, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 1, 0, 0 };
+
+ /* divined from tdfx_dri.c, sketchy */
+ TDFXDRIPtr dri_priv = (TDFXDRIPtr) psp->pDevPriv;
+
+ /* XXX i wish it was like this */
+ /* bpp = dri_priv->bpp */
+ int bpp = (dri_priv->cpp > 2) ? 24 : 16;
+
+ if ( ! driCheckDriDdxDrmVersions2( "tdfx",
+ &psp->dri_version, & dri_expected,
+ &psp->ddx_version, & ddx_expected,
+ &psp->drm_version, & drm_expected ) )
+ return NULL;
+
+ if (!tdfxInitDriver(psp))
+ return NULL;
+
+ return tdfxFillInModes(psp,
+ bpp, (bpp == 16) ? 16 : 24,
+ (bpp == 16) ? 0 : 8,
+ (dri_priv->backOffset!=dri_priv->depthOffset));
+}
+
+const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = tdfxInitScreen,
+ .DestroyScreen = tdfxDestroyScreen,
+ .CreateContext = tdfxCreateContext,
+ .DestroyContext = tdfxDestroyContext,
+ .CreateBuffer = tdfxCreateBuffer,
+ .DestroyBuffer = tdfxDestroyBuffer,
+ .SwapBuffers = tdfxSwapBuffers,
+ .MakeCurrent = tdfxMakeCurrent,
+ .UnbindContext = tdfxUnbindContext,
+ .GetSwapInfo = NULL,
+ .GetDrawableMSC = NULL,
+ .WaitForMSC = NULL,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+ &driCoreExtension.base,
+ &driLegacyExtension.base,
+ NULL
+};