/* GGI-Driver for MESA
*
* Copyright (C) 1997-1998 Uwe Maurer - uwe_maurer@t-online.de
+ * 2002 Filip Spacek
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include "conf.h"
#endif
-#ifdef GGI
-
#include <ggi/mesa/ggimesa_int.h>
#include <ggi/mesa/debug.h>
+#include "main/extensions.h"
+#include "main/buffers.h"
+#include "main/colormac.h"
+#include "main/imports.h"
+#include "main/matrix.h"
+#include "main/teximage.h"
+#include "main/texformat.h"
+#include "main/texstore.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "vbo/vbo.h"
+
+/* We use LibGG to manage config files */
+#include <ggi/gg.h>
+
+
+/* XXX: Those #defines should be provided via
+ * config.h
+ */
+#define GGIMESAPATHTAG "pAtHTAg"
+#define GGIMESACONFDIR "pAtHTAg/usr/local/etc/ggi"
+#define GGIMESATAGLEN 7
+#define GGIMESACONFFILE "ggimesa.conf"
-#undef VIS
-#undef FLIP
-#define VIS (GGIMesa->ggi_vis)
-#define FLIP(y) (GGIMesa->flip_y-(y))
-
-GGIMesaContext GGIMesa = NULL; /* the current context */
-ggi_extid ggiMesaID = -1;
+/* Static variables
+ */
static int _ggimesaLibIsUp = 0;
static void *_ggimesaConfigHandle;
+static char _ggimesaconfstub[512] = GGIMESACONFDIR;
+static char *_ggimesaconfdir = _ggimesaconfstub+GGIMESATAGLEN;
-/* FIXME: These should really be defined in the make system using -Dxxx */
-#define GGIMESACONFFILE "/usr/local/etc/ggi/ggimesa.conf"
-#define GGIMESATAGLEN 0
-static char ggimesaconfstub[512] = GGIMESACONFFILE;
-static char *ggimesaconffile = ggimesaconfstub + GGIMESATAGLEN;
+int _ggimesaDebugSync = 0;
+uint32 _ggimesaDebugState = 0;
-int gl_ggi_init = GL_FALSE;
-int gl_ggi_debug = GL_FALSE;
-static void gl_ggiUpdateState(GLcontext *ctx);
-static int changed(ggi_visual_t vis, int whatchanged);
-#if 0
-/* FIXME: Move this debugging stuff to include/ggi/mesa/internal/ */
-void gl_ggiPrint(char *format,...)
-{
- va_list args;
- va_start(args,format);
- fprintf(stderr,"GGIMesa: ");
- vfprintf(stderr,format,args);
- va_end(args);
-}
+/* Extension ID. Defaulting to -1 should make segfault on abuse more likely...
+ */
+ggi_extid _ggiMesaID = -1;
-void gl_ggiDEBUG(char *format,...)
-{
- va_list args;
- if (gl_ggi_debug)
- {
- va_start(args,format);
- fprintf(stderr,"GGIMesa: ");
- vfprintf(stderr,format,args);
- va_end(args);
- }
-}
-#endif
-static void gl_ggiGetSize(GLcontext *ctx, GLuint *width, GLuint *height)
-{
- *width = GGIMesa->width;
- *height = GGIMesa->height;
-}
+#define SUBLIB_PREFIX "MesaGGIdl_"
-static void gl_ggiSetIndex(GLcontext *ctx, GLuint ci)
-{
- ggiSetGCForeground(VIS, ci);
- GGICTX->color = (ggi_pixel)ci;
-}
-static void gl_ggiSetClearIndex(GLcontext *ctx, GLuint ci)
+/*
+ * Returns the directory where global config files are kept
+ */
+
+const char *ggiMesaGetConfDir(void)
{
- ggiSetGCForeground(VIS, ci);
- GGICTX->clearcolor = (ggi_pixel)ci;
+#ifdef __WIN32__
+ /* On Win32 we allow overriding of the compiled in path. */
+ const char *envdir = getenv("GGI_CONFDIR");
+ if (envdir) return envdir;
+#endif
+ return _ggimesaconfdir;
}
-static void gl_ggiSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
- GLubyte blue, GLubyte alpha)
+
+/* Dummy function which returns -1
+ We use this to reset the function pointers */
+static int _ggi_error(void)
{
- ggi_color rgb;
- ggi_pixel col;
+ GGIMESADPRINT_CORE("_ggi_error() called\n");
- rgb.r = (uint16)red << SHIFT;
- rgb.g = (uint16)green << SHIFT;
- rgb.b = (uint16)blue << SHIFT;
- col = ggiMapColor(VIS, &rgb);
- ggiSetGCForeground(VIS, col);
- GGICTX->color = col;
+ return -1;
}
-static void gl_ggiSetClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
- GLubyte blue, GLubyte alpha)
-{
- ggi_color rgb;
- ggi_pixel col;
- rgb.r = (uint16)red << SHIFT;
- rgb.g = (uint16)green << SHIFT;
- rgb.b = (uint16)blue << SHIFT;
- col = ggiMapColor(VIS, &rgb);
- ggiSetGCForeground(VIS, col);
- GGICTX->clearcolor = col;
-}
-static GLbitfield gl_ggiClear(GLcontext *ctx,GLbitfield mask, GLboolean all,
- GLint x, GLint y, GLint width, GLint height)
+static int changed(ggi_visual_t vis, int whatchanged)
{
+ GLcontext *ctx;
+ ctx = _mesa_get_current_context();
- if (mask & GL_COLOR_BUFFER_BIT)
+ GGIMESADPRINT_CORE("changed() called\n");
+
+ switch (whatchanged) {
+ case GGI_CHG_APILIST:
{
- ggiSetGCForeground(VIS, GGICTX->clearcolor);
-
- if (all)
- {
- ggiDrawBox(VIS, 0, GGIMesa->origin.y,
- GGIMesa->width, GGIMesa->height);
- }
- else
- {
- ggiDrawBox(VIS, x, FLIP(y), width, height);
+ char api[GGI_MAX_APILEN];
+ char args[GGI_MAX_APILEN];
+ int i;
+ const char *fname;
+ ggi_dlhandle *lib;
+
+ GLvisual *gl_vis = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ GLframebuffer *gl_fb = &(LIBGGI_MESAEXT(vis)->mesa_buffer);
+
+ /* Initialize the framebuffer to provide all necessary
+ buffers in software. The target libraries that are loaded
+ next are free to modify this according to their
+ capabilities.
+ */
+ /* FIXME: if the target changes capabilities we'll leak
+ swrast's memory !!! Need to deallocate first */
+ _mesa_initialize_framebuffer(gl_fb, gl_vis,
+ gl_vis->depthBits > 0,
+ gl_vis->stencilBits > 0,
+ gl_vis->accumRedBits > 0,
+ gl_vis->alphaBits > 0);
+
+ for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++) {
+ strcat(api, "-mesa");
+ GGIMESADPRINT_CORE("GGIMesa: looking for"
+ "a sublib named %s\n", api);
+ fname = ggMatchConfig(_ggimesaConfigHandle, api, NULL);
+ if (fname == NULL) {
+ /* No special implementation for this sublib */
+ continue;
+ }
+ lib = ggiExtensionLoadDL(vis, fname, args, NULL,
+ SUBLIB_PREFIX);
}
- ggiSetGCForeground(VIS, GGICTX->color);
- }
- return mask & (~GL_COLOR_BUFFER_BIT);
-}
-
-#if 0
-static GLboolean gl_ggiSetBuffer(GLcontext *ctx, GLenum mode)
-{
- if (mode == GL_FRONT)
- GGICTX->active_buffer = 1;
- else
- GGICTX->active_buffer = 0;
-
- return GL_TRUE;
-}
-#endif
-
-/* Set the buffer used for drawing */
-static GLboolean gl_ggiSetDrawBuffer(GLcontext *ctx, GLenum mode)
-{
- if (mode == GL_FRONT_LEFT)
- {
- GGICTX->active_buffer = 1;
- return GL_TRUE;
- }
- else if (mode == GL_BACK_LEFT)
- {
- GGICTX->active_buffer = 0;
- return GL_TRUE;
- }
- else
- {
- return GL_FALSE;
- }
-}
-
-
-/* Set the buffer used for reading */
-/* XXX support for separate read/draw buffers hasn't been tested */
-static void gl_ggiSetReadBuffer(GLcontext *ctx, GLframebuffer *buffer, GLenum mode)
-{
- if (mode == GL_FRONT_LEFT)
- {
- GGICTX->active_buffer = 1;
- }
- else if (mode == GL_BACK_LEFT)
- {
- GGICTX->active_buffer = 0;
+ /* The targets have cleared everything they can do from
+ the framebuffer structure so we provide the rest in sw
+ */
+ /*_swrast_alloc_buffers(gl_fb);*/
+
+ break;
+ }
}
+ return 0;
}
-static const char * gl_ggiRendererString(void)
-{
- return "GGI";
-}
-
-static void gl_ggiFlush(GLcontext *ctx)
-{
- ggiFlush(VIS);
-}
-
-static void gl_ggiSetupPointers( GLcontext *ctx )
+int ggiMesaInit()
{
- /* Initialize all the pointers in the DD struct. Do this whenever */
- /* a new context is made current or we change buffers via set_buffer! */
-
- ctx->Driver.RendererString = gl_ggiRendererString;
- ctx->Driver.UpdateState = gl_ggiUpdateState;
-
- ctx->Driver.ClearIndex = gl_ggiSetClearIndex;
- ctx->Driver.ClearColor = gl_ggiSetClearColor;
- ctx->Driver.Clear = gl_ggiClear;
- ctx->Driver.Index = gl_ggiSetIndex;
- ctx->Driver.Color = gl_ggiSetColor;
+ int err;
+ char *str;
+ char *conffile;
- ctx->Driver.SetDrawBuffer = gl_ggiSetDrawBuffer;
- ctx->Driver.SetReadBuffer = gl_ggiSetReadBuffer;
+ GGIMESADPRINT_CORE("ggiMesaInit() called\n");
- ctx->Driver.GetBufferSize = gl_ggiGetSize;
- ctx->Driver.Finish = gl_ggiFlush;
- ctx->Driver.Flush = gl_ggiFlush;
-
-}
-
-static int gl_ggiInitInfo(GGIMesaContext ctx, struct ggi_mesa_info *info)
-{
- ggi_mode mode;
-
- ggiGetMode(ctx->ggi_vis, &mode);
+ _ggimesaLibIsUp++;
+ if (_ggimesaLibIsUp > 1) return 0; /* Initialize only at first call */
- info->depth_bits = DEPTH_BITS;
- info->stencil_bits = STENCIL_BITS;
- info->accum_bits = ACCUM_BITS;
-
- if (info->rgb_flag)
- {
- info->rgb_flag = GL_TRUE;
- info->alpha_flag = GL_FALSE;
- info->index_bits = 0;
-
- info->red_bits = 8;
- info->green_bits = 8;
- info->blue_bits = 8;
-
- info->alpha_bits = 0;
- }
- else
- {
- info->alpha_flag = GL_FALSE;
-
- info->index_bits = GT_SIZE(mode.graphtype);
- info->red_bits = info->green_bits =
- info->blue_bits = info->alpha_bits = 0;
+ str = getenv("GGIMESA_DEBUGSYNC");
+ if (str != NULL) {
+ _ggimesaDebugSync = 1;
}
-
- return 0;
-}
-
-int ggiMesaInit()
-{
- int err;
- _ggimesaLibIsUp++;
- if (_ggimesaLibIsUp > 1)
- return 0; /* Initialize only at first call */
+ str = getenv("GGIMESA_DEBUG");
+ if (str != NULL) {
+ _ggimesaDebugState = atoi(str);
+ GGIMESADPRINT_CORE("%s Debugging=%d\n",
+ _ggimesaDebugSync ? "sync" : "async",
+ _ggimesaDebugState);
+ }
- err = ggLoadConfig(ggimesaconffile, &_ggimesaConfigHandle);
- if (err != GGI_OK)
- {
- fprintf(stderr, "GGIMesa: Couldn't open %s\n", ggimesaconffile);
+
+ conffile = malloc(strlen(ggiMesaGetConfDir()) + 1
+ + strlen(GGIMESACONFFILE) +1);
+ if (conffile == NULL) {
+ fprintf(stderr, "GGIMesa: unable to allocate memory for config filename.\n");
+ return GGI_ENOMEM;
+ }
+ sprintf(conffile, "%s%c%s",
+ ggiMesaGetConfDir(), '/', GGIMESACONFFILE);
+ err = ggLoadConfig(conffile, &_ggimesaConfigHandle);
+ if (err != GGI_OK) {
+ fprintf(stderr, "GGIMesa: Couldn't open %s\n",
+ conffile);
+ free(conffile);
_ggimesaLibIsUp--;
return err;
}
+ free(conffile);
- ggiMesaID = ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext), changed);
-
- if (ggiMesaID < 0)
- {
+ _ggiMesaID = ggiExtensionRegister("GGIMesa",
+ sizeof(struct ggi_mesa_ext), changed);
+ if (_ggiMesaID < 0) {
fprintf(stderr, "GGIMesa: failed to register as extension\n");
_ggimesaLibIsUp--;
ggFreeConfig(_ggimesaConfigHandle);
- return ggiMesaID;
+ return _ggiMesaID;
}
return 0;
}
-
-GGIMesaContext GGIMesaCreateContext(void)
+int ggiMesaExit(void)
{
- GGIMesaContext ctx;
- char *s;
+ int rc;
- s = getenv("GGIMESA_DEBUG");
- gl_ggi_debug = (s && atoi(s));
+ GGIMESADPRINT_CORE("ggiMesaExit() called\n");
- if (ggiMesaInit() < 0) /* register extensions*/
- {
- return NULL;
- }
+ if (!_ggimesaLibIsUp) return -1;
- ctx = (GGIMesaContext)calloc(1, sizeof(struct ggi_mesa_context));
- if (!ctx)
- return NULL;
+ if (_ggimesaLibIsUp > 1) {
+ /* Exit only at last call */
+ _ggimesaLibIsUp--;
+ return 0;
+ }
- ctx->gl_vis = (GLvisual *)calloc(1, sizeof(GLvisual));
- if (!ctx->gl_vis)
- return NULL;
+ rc = ggiExtensionUnregister(_ggiMesaID);
+ ggFreeConfig(_ggimesaConfigHandle);
- ctx->viewport_init = GL_FALSE;
- ctx->gl_vis->DBflag = GL_FALSE;
+ _ggimesaLibIsUp = 0;
- ctx->gl_ctx = gl_create_context(ctx->gl_vis, NULL, (void *)ctx, GL_TRUE);
- if (!ctx->gl_ctx)
- return NULL;
-
- return ctx;
+ return rc;
}
-void GGIMesaDestroyContext(GGIMesaContext ctx)
+
+
+
+static void gl_ggiUpdateState(GLcontext *ctx, GLuint new_state);
+
+
+static void gl_ggiGetSize(GLframebuffer *fb, GLuint *width, GLuint *height)
{
- if (ctx)
- {
- gl_destroy_visual(ctx->gl_vis);
- gl_destroy_context(ctx->gl_ctx);
- gl_destroy_framebuffer(ctx->gl_buffer);
- if (ctx == GGIMesa)
- GGIMesa = NULL;
- if (ctx->ggi_vis)
- ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
- ggiExtensionUnregister(ggiMesaID);
- free(ctx);
- }
+ /* FIXME: this is a hack to work around the new interface */
+ GLcontext *ctx;
+ ggi_mesa_context_t ggi_ctx;
+ ctx = _mesa_get_current_context();
+ ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
+
+ *width = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ *height = LIBGGI_VIRTY(ggi_ctx->ggi_visual);
+ printf("returning %d, %d\n", *width, *height);
}
-int GGIMesaSetVisual(GGIMesaContext ctx, ggi_visual_t vis,
- GLboolean rgb_flag, GLboolean db_flag)
+/**
+ * We only implement this function as a mechanism to check if the
+ * framebuffer size has changed (and update corresponding state).
+ */
+static void gl_ggiViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
- struct ggi_mesa_info info;
- int err;
- uint16 r,g,b;
- ggi_color pal[256];
- int i;
- void *func;
- ggi_mode mode;
- int num_buf;
-
- if (!ctx) return -1;
- if (!vis) return -1;
-
- if (ctx->ggi_vis)
- ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
+ GLuint newWidth, newHeight;
+ GLframebuffer *buffer = ctx->WinSysDrawBuffer;
+ gl_ggiGetSize( buffer, &newWidth, &newHeight );
+ if (buffer->Width != newWidth || buffer->Height != newHeight) {
+ _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight );
+ }
+}
- ctx->ggi_vis=vis;
- err = ggiExtensionAttach(vis, ggiMesaID);
- if (err < 0)
- return -1;
- if (err == 0)
- changed(vis, GGI_CHG_APILIST);
+static void gl_ggiSetIndex(GLcontext *ctx, GLuint ci)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
- if (ctx->gl_vis)
- gl_destroy_visual(ctx->gl_vis);
+ GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
+
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ci);
+ ggi_ctx->color = (ggi_pixel)ci;
+}
- if (ctx->gl_buffer)
- gl_destroy_framebuffer(ctx->gl_buffer);
+static void gl_ggiSetClearIndex(GLcontext *ctx, GLuint ci)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
- info.rgb_flag = rgb_flag;
- info.db_flag = db_flag;
+ GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
- err = gl_ggiInitInfo(ctx, &info);
- if (err)
- return -1;
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ci);
+ ggi_ctx->clearcolor = (ggi_pixel)ci;
+}
- gl_ggiSetupPointers(ctx->gl_ctx);
+static void gl_ggiSetClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+ GLubyte byteColor[3];
- func = (void *)LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver;
+ GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
+
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[2], color[2]);
+
+ rgb.r = (uint16)byteColor[0] << SHIFT;
+ rgb.g = (uint16)byteColor[1] << SHIFT;
+ rgb.b = (uint16)byteColor[2] << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiSetGCForeground(ggi_ctx->ggi_visual, col);
+ ggi_ctx->clearcolor = col;
+}
- if (!func)
- {
- fprintf(stderr, "setup_driver==NULL!\n");
- fprintf(stderr, "Please check your config files!\n");
- return -1;
- }
+static void gl_ggiClear(GLcontext *ctx, GLbitfield mask)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int x = ctx->DrawBuffer->_Xmin;
+ int y = ctx->DrawBuffer->_Ymin;
+ int w = ctx->DrawBuffer->_Xmax - x;
+ int h = ctx->DrawBuffer->_Ymax - y;
+ GLboolean all = (w == ctx->DrawBuffer->Width && h == ctx->DrawBuffer->height)
+
+ GGIMESADPRINT_CORE("gl_ggiClear() called\n");
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ggi_ctx->clearcolor);
+
+ if (all) {
+ int w, h;
+ w = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ h = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ ggiDrawBox(ggi_ctx->ggi_visual, 0, 0, w, h);
+ } else {
+ ggiDrawBox(ggi_ctx->ggi_visual, x, y, //FLIP(y),
+ width, height);
+ }
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ggi_ctx->color);
- err = LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver(ctx, &info);
- if (err)
- return -1;
-
- ctx->gl_vis = gl_create_visual(info.rgb_flag,
- info.alpha_flag,
- info.db_flag,
- GL_FALSE,
- info.depth_bits,
- info.stencil_bits,
- info.accum_bits,
- info.index_bits,
- info.red_bits, info.green_bits,
- info.blue_bits, info.alpha_bits);
- if (!ctx->gl_vis)
- {
- fprintf(stderr, "Can't create gl_visual!\n");
- return -1;
+ mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
}
+ _swrast_Clear(ctx, mask);
+
+}
- ctx->gl_buffer = gl_create_framebuffer(ctx->gl_vis,
- ctx->gl_vis->DepthBits > 0,
- ctx->gl_vis->StencilBits > 0,
- ctx->gl_vis->AccumBits > 0,
- ctx->gl_vis->AlphaBits > 0);
-
- if (!ctx->gl_buffer)
- {
- fprintf(stderr, "Can't create gl_buffer!\n");
- return -1;
- }
-
- ggiGetMode(ctx->ggi_vis, &mode);
- ctx->width = mode.visible.x;
- ctx->height = mode.visible.y;
- ctx->stride = mode.virt.x;
- ctx->origin.x = 0;
- ctx->origin.y = 0;
- ctx->flip_y = ctx->origin.y + ctx->height - 1;
+/* Set the buffer used for reading */
+/* XXX support for separate read/draw buffers hasn't been tested */
+static GLboolean gl_ggiSetBuffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
- ctx->color = 0;
+ printf("set read %d\n", bufferBit);
+ GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
- ctx->lfb[0] = ctx->lfb[1] = NULL;
- num_buf = ggiDBGetNumBuffers(ctx->ggi_vis);
-
- for (i = 0; i < num_buf; i++)
+ if (bufferBit == DD_FRONT_LEFT_BIT)
{
- if (ggiDBGetBuffer(ctx->ggi_vis,i)->layout == blPixelLinearBuffer)
- {
- ctx->stride = ggiDBGetBuffer(ctx->ggi_vis, i)->buffer.plb.stride /
- (ggiDBGetBuffer(ctx->ggi_vis, i)->buffer.plb.pixelformat->size / 8);
- ctx->lfb[0] = ggiDBGetBuffer(ctx->ggi_vis, i)->write;
- }
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ return GL_TRUE;
}
-
- if (ctx->lfb[0] == NULL)
+ else if (bufferBit == DD_BACK_LEFT_BIT)
{
- fprintf(stderr, "No linear frame buffer!\n");
- return -1;
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual)?0 : 1);
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual)?0 : 1);
+ return GL_TRUE;
}
-
- /* FIXME: Use separate buffers */
- ctx->lfb[1] = malloc(ctx->stride * ctx->height);
- ctx->bufsize = (ctx->stride * ctx->height);
-
- ctx->gl_ctx->Visual = ctx->gl_vis;
- ctx->gl_ctx->Pixel.ReadBuffer =
- ctx->gl_ctx->Color.DrawBuffer = (db_flag) ? GL_BACK : GL_FRONT;
+ else
+ return GL_FALSE;
+}
- if (GGIMesa == ctx)
- gl_make_current(ctx->gl_ctx, ctx->gl_buffer);
- if (rgb_flag && mode.graphtype==GT_8BIT)
- {
- for (i = r = 0; r < 8; r++)
- for (g = 0; g < 8; g++)
- for (b = 0; b < 4; b++, i++)
- {
- pal[i].r = r << (GGI_COLOR_PRECISION - 3);
- pal[i].g = g << (GGI_COLOR_PRECISION - 3);
- pal[i].b = b << (GGI_COLOR_PRECISION - 2);
- }
- ggiSetPalette(ctx->ggi_vis, 0, 256, pal);
- }
+static const GLubyte * gl_ggiGetString(GLcontext *ctx, GLenum name)
+{
+ GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
- return 0;
+ if (name == GL_RENDERER) {
+ return (GLubyte *) "Mesa GGI";
+ } else {
+ return NULL;
+ }
}
-void GGIMesaMakeCurrent(GGIMesaContext ctx)
+static void gl_ggiFlush(GLcontext *ctx)
{
- if (!ctx->ggi_vis)
- return;
-
- GGIMesa = ctx;
- gl_make_current(ctx->gl_ctx, ctx->gl_buffer);
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
- if (!ctx->viewport_init)
- {
- gl_Viewport(ctx->gl_ctx, 0, 0, ctx->width, ctx->height);
- ctx->viewport_init = GL_TRUE;
- }
+ ggiFlush(ggi_ctx->ggi_visual);
}
+static void gl_ggiIndexMask(GLcontext *ctx, GLuint mask)
+{
+ GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
+}
-GGIMesaContext GGIMesaGetCurrentContext(void)
+static void gl_ggiColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
{
- return GGIMesa;
+ GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
}
-/*
- * Swap front/back buffers for current context if double buffered.
- */
-void GGIMesaSwapBuffers(void)
+static void gl_ggiEnable(GLcontext *ctx, GLenum pname, GLboolean state)
{
- GGIMESADPRINT_CORE("GGIMesaSwapBuffers\n");
-
- FLUSH_VB(GGIMesa->gl_ctx, "swap buffers");
- gl_ggiFlush(GGIMesa->gl_ctx);
-
- if (GGIMesa->gl_vis->DBflag)
- {
- memcpy(GGIMesa->lfb[0], GGIMesa->lfb[1], GGIMesa->bufsize);
- }
+ GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
}
-static void gl_ggiUpdateState(GLcontext *ctx)
+static void gl_ggiSetupPointers(GLcontext *ctx)
{
- void *func;
+ TNLcontext *tnl;
- func = (void *)CTX_OPMESA(ctx)->update_state;
+ GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
- if (!func) {
- fprintf(stderr, "update_state == NULL!\n");
- fprintf(stderr, "Please check your config files!\n");
- ggiPanic("");
- }
+ /* Plug in default driver functions */
+ _mesa_init_driver_functions(&ctx->Driver);
- CTX_OPMESA(ctx)->update_state(ctx);
-}
+ /* Plug in ggi-specific functions */
+ ctx->Driver.GetString = gl_ggiGetString;
+ ctx->Driver.GetBufferSize = gl_ggiGetSize;
+ ctx->Driver.Viewport = gl_ggiViewport;
+ ctx->Driver.Finish = gl_ggiFlush;
+ ctx->Driver.Flush = gl_ggiFlush;
+ ctx->Driver.Clear = gl_ggiClear;
+ ctx->Driver.ClearIndex = gl_ggiSetClearIndex;
+ ctx->Driver.ClearColor = gl_ggiSetClearColor;
+ ctx->Driver.IndexMask = gl_ggiIndexMask;
+ ctx->Driver.ColorMask = gl_ggiColorMask;
+ ctx->Driver.Enable = gl_ggiEnable;
+ ctx->Driver.UpdateState = gl_ggiUpdateState;
-static int changed(ggi_visual_t vis, int whatchanged)
-{
- switch (whatchanged)
- {
- case GGI_CHG_APILIST:
- {
- char api[256];
- char args[256];
- int i;
- const char *fname;
- ggi_dlhandle *lib;
-
- for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++)
- {
- strcat(api, "-mesa");
- fname = ggMatchConfig(_ggimesaConfigHandle, api, NULL);
- if (fname == NULL)
- {
- /* No special implementation for this sublib */
- continue;
- }
- lib = ggiExtensionLoadDL(vis, fname, args, NULL);
- }
- }
- break;
- }
- return 0;
+ /* Initialize TNL driver interface */
+ tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ /* Install setup for tnl */
+ _swsetup_Wakeup(ctx);
}
-
-int ggiMesaExit(void)
+static void get_mode_info(ggi_visual_t vis, int *r, int *g, int *b,
+ GLboolean *rgb, GLboolean *db, int *ci)
{
- int rc;
-
- if (!_ggimesaLibIsUp)
- return -1;
+ unsigned int i;
- if (_ggimesaLibIsUp > 1)
- {
- /* Exit only at last call */
- _ggimesaLibIsUp--;
- return 0;
+ *r = 0;
+ *g = 0;
+ *b = 0;
+
+ for(i = 0; i < sizeof(ggi_pixel)*8; ++i) {
+ int mask = 1 << i;
+ if (LIBGGI_PIXFMT(vis)->red_mask & mask)
+ ++(*r);
+ if (LIBGGI_PIXFMT(vis)->green_mask & mask)
+ ++(*g);
+ if (LIBGGI_PIXFMT(vis)->blue_mask & mask)
+ ++(*b);
}
-
- rc = ggiExtensionUnregister(ggiMesaID);
- ggFreeConfig(_ggimesaConfigHandle);
-
- _ggimesaLibIsUp = 0;
-
- return rc;
-}
-static int _ggi_error(void)
-{
- return -1;
+ *rgb = GT_SCHEME(LIBGGI_MODE(vis)->graphtype) == GT_TRUECOLOR;
+ *db = LIBGGI_MODE(vis)->frames > 1;
+ *ci = GT_SIZE(LIBGGI_MODE(vis)->graphtype);
+
+ printf("rgb (%d, %d, %d) db %d, rgb %d ci %d\n",*r,*g,*b,*db,*rgb,*ci);
}
+
int ggiMesaAttach(ggi_visual_t vis)
{
int rc;
-
- rc = ggiExtensionAttach(vis, ggiMesaID);
+
+ GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
+
+ rc = ggiExtensionAttach(vis, _ggiMesaID);
if (rc == 0)
{
+ int r, g, b, ci;
+ GLboolean rgb, db;
+ GLvisual *gl_visual;
+
/* We are creating the primary instance */
- memset(LIBGGI_MESAEXT(vis), 0, sizeof(mesaext));
+ memset(LIBGGI_MESAEXT(vis), 0, sizeof(struct ggi_mesa_ext));
LIBGGI_MESAEXT(vis)->update_state = (void *)_ggi_error;
LIBGGI_MESAEXT(vis)->setup_driver = (void *)_ggi_error;
+
+ /* Initialize default mesa visual */
+ get_mode_info(vis, &r, &g, &b, &rgb, &db, &ci);
+ gl_visual = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ _mesa_initialize_visual(gl_visual,
+ rgb, db, 0 /* No stereo */,
+ r, g, b, 0 /* No alpha */, ci,
+ 0 /* No depth */, 0 /* No stencil */,
+ 0, 0, 0, 0 /* No accum */, 0);
/* Now fake an "API change" so the right libs get loaded */
changed(vis, GGI_CHG_APILIST);
int ggiMesaDetach(ggi_visual_t vis)
{
- return ggiExtensionDetach(vis, ggiMesaID);
+ GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
+
+ return ggiExtensionDetach(vis, _ggiMesaID);
+}
+
+int ggiMesaExtendVisual(ggi_visual_t vis, GLboolean alpha_flag,
+ GLboolean stereo_flag, GLint depth_size,
+ GLint stencil_size, GLint accum_red_size,
+ GLint accum_green_size, GLint accum_blue_size,
+ GLint accum_alpha_size, GLint num_samples)
+{
+ GLvisual *gl_vis = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ int r, g, b, ci;
+ GLboolean db, rgb;
+
+ get_mode_info(vis, &r, &g, &b, &rgb, &db, &ci);
+
+ /* Initialize the visual with the provided information */
+ _mesa_initialize_visual(gl_vis,
+ rgb, db, stereo_flag,
+ r, g, b, 0 /* FIXME */, ci,
+ depth_size, stencil_size,
+ accum_red_size, accum_green_size,
+ accum_blue_size, accum_alpha_size, 0);
+
+ /* Now fake an "API change" so the right libs get loaded. After all,
+ extending the visual by all these new buffers could be considered
+ a "mode change" which requires an "API change".
+ */
+ changed(vis, GGI_CHG_APILIST);
+
+ return 0;
+}
+
+
+ggi_mesa_context_t ggiMesaCreateContext(ggi_visual_t vis)
+{
+ ggi_mesa_context_t ctx;
+ int err;
+
+ GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
+
+ ctx = (ggi_mesa_context_t)malloc(sizeof(struct ggi_mesa_context));
+ if (!ctx)
+ return NULL;
+
+ ctx->ggi_visual = vis;
+ ctx->color = 0;
+
+ ctx->gl_ctx =
+ _mesa_create_context(&(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual),
+ NULL, (void *) ctx, GL_FALSE);
+ if (!ctx->gl_ctx)
+ goto free_context;
+
+ _mesa_enable_sw_extensions(ctx->gl_ctx);
+
+ _swrast_CreateContext(ctx->gl_ctx);
+ _vbo_CreateContext(ctx->gl_ctx);
+ _tnl_CreateContext(ctx->gl_ctx);
+ _swsetup_CreateContext(ctx->gl_ctx);
+
+ gl_ggiSetupPointers(ctx->gl_ctx);
+
+ /* Make sure that an appropriate sublib has been loaded */
+ if (!LIBGGI_MESAEXT(ctx->ggi_visual)->setup_driver){
+ GGIMESADPRINT_CORE("setup_driver==NULL!\n");
+ GGIMESADPRINT_CORE("Please check your config files!\n");
+ goto free_context;
+ }
+
+ /* Set up the sublib driver */
+ err = LIBGGI_MESAEXT(ctx->ggi_visual)->setup_driver(ctx);
+ if (err){
+ GGIMESADPRINT_CORE("setup_driver failed (err = %d)", err);
+ goto free_gl_context;
+ }
+
+ return ctx;
+
+free_gl_context:
+ _mesa_destroy_context(ctx->gl_ctx);
+free_context:
+ free(ctx);
+
+ return NULL;
+}
+
+void ggiMesaDestroyContext(ggi_mesa_context_t ctx)
+{
+ GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
+
+ if(!ctx)
+ return;
+
+ _mesa_destroy_context(ctx->gl_ctx);
+ free(ctx);
+}
+
+void ggiMesaMakeCurrent(ggi_mesa_context_t ctx, ggi_visual_t vis)
+{
+ GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx);
+
+ /* FIXME: clean up where are ggi_vis */
+ if (ctx->ggi_visual != vis) {
+ GGIMESADPRINT_CORE("Cannot migrate GL contexts\n");
+ return;
+ }
+
+ _mesa_make_current(ctx->gl_ctx, &LIBGGI_MESAEXT(vis)->mesa_buffer);
}
-#else
/*
- * Need this to provide at least one external definition when GGI is
- * not defined on the compiler command line.
+ * Swap front/back buffers for current context if double buffered.
*/
+void ggiMesaSwapBuffers(void)
+{
+ GLcontext *ctx;
+ ggi_mesa_context_t ggi_ctx;
+ ctx = _mesa_get_current_context();
+ ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
+
+ _mesa_notifySwapBuffers(ctx);
+ gl_ggiFlush(ctx);
+
+ ggiSetDisplayFrame(ggi_ctx->ggi_visual,
+ !ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ !ggiGetWriteFrame(ggi_ctx->ggi_visual));
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ !ggiGetReadFrame(ggi_ctx->ggi_visual));
+
+ GGIMESADPRINT_CORE("swap disp: %d, write %d\n",
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual),
+ ggiGetWriteFrame(ggi_ctx->ggi_visual));
+}
-int gl_ggi_dummy_function(void)
+static void gl_ggiUpdateState(GLcontext *ctx, GLuint new_state)
{
- return 0;
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
+
+ /* Propogate statechange information to swrast and swrast_setup
+ * modules. The GGI driver has no internal GL-dependent state.
+ */
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /* XXX: Better use an assertion that bails out here on failure */
+ if (!LIBGGI_MESAEXT(ggi_ctx->ggi_visual)->update_state) {
+ GGIMESADPRINT_CORE("update_state == NULL!\n");
+ GGIMESADPRINT_CORE("Please check your config files!\n");
+ ggiPanic("");
+ }
+
+ LIBGGI_MESAEXT(ggi_ctx->ggi_visual)->update_state(ggi_ctx);
}
-#endif