diff options
| author | Brian Paul <brian.paul@tungstengraphics.com> | 2003-12-06 17:20:10 +0000 | 
|---|---|---|
| committer | Brian Paul <brian.paul@tungstengraphics.com> | 2003-12-06 17:20:10 +0000 | 
| commit | a763123b35ac4f7bd1b3a47b5b3180f217a3b81d (patch) | |
| tree | e8338cbbb386bf7a92cd5ae3d6f90a5e0578a3d7 /src | |
| parent | fde2b9750ea9f37b018aaa26c9bbb6454cd1c016 (diff) | |
glFBDev driver from embedded-2 branch.
Probably won't be actively used/maintained, but bring it to the trunk so
it doesn't get lost.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/drivers/fbdev/glfbdev.c | 828 | 
1 files changed, 828 insertions, 0 deletions
| diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c new file mode 100644 index 0000000000..6d3ed01d7b --- /dev/null +++ b/src/mesa/drivers/fbdev/glfbdev.c @@ -0,0 +1,828 @@ +/* + * Mesa 3-D graphics library + * Version:  5.1 + * + * Copyright (C) 1999-2003  Brian Paul   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 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 + * BRIAN PAUL 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. + */ + + +/* + * OpenGL (Mesa) interface for fbdev. + * For info about fbdev: + * http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html + * + * known VGA modes + * Colours   640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200 + * --------+-------------------------------------------------------------- + *  4 bits |    ?       ?     0x302      ?        ?        ?         ? + *  8 bits |  0x300   0x301   0x303    0x305    0x161    0x307     0x31C + * 15 bits |    ?     0x310   0x313    0x316    0x162    0x319     0x31D + * 16 bits |    ?     0x311   0x314    0x317    0x163    0x31A     0x31E + * 24 bits |    ?     0x312   0x315    0x318      ?      0x31B     0x31F + * 32 bits |    ?       ?       ?        ?      0x164      ? + */ + + +#ifdef USE_GLFBDEV_DRIVER + +#include "glheader.h" +#include <linux/fb.h> +#include "GL/glfbdev.h" +#include "context.h" +#include "extensions.h" +#include "imports.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" +#include "array_cache/acache.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" + + +#define PF_B8G8R8     1 +#define PF_B8G8R8A8   2 +#define PF_B5G6R5     3 +#define PF_B5G5R5     4 +#define PF_CI8        5 + + +/* + * Derived from Mesa's GLvisual class. + */ +struct GLFBDevVisualRec { +   GLvisual glvisual;              /* base class */ +   struct fb_fix_screeninfo fix; +   struct fb_var_screeninfo var; +   int pixelFormat; +}; + +/* + * Derived from Mesa's GLframebuffer class. + */ +struct GLFBDevBufferRec { +   GLframebuffer glframebuffer;    /* base class */ +   GLFBDevVisualPtr visual; +   struct fb_fix_screeninfo fix; +   struct fb_var_screeninfo var; +   void *frontStart; +   void *backStart; +   size_t size; +   GLuint bytesPerPixel; +   GLuint rowStride;               /* in bytes */ +   GLubyte *frontBottom;           /* pointer to last row */ +   GLubyte *backBottom;            /* pointer to last row */ +   GLubyte *curBottom;             /* = frontBottom or backBottom */ +   GLboolean mallocBackBuffer; +}; + +/* + * Derived from Mesa's GLcontext class. + */ +struct GLFBDevContextRec { +   GLcontext glcontext;            /* base class */ +   GLFBDevVisualPtr visual; +   GLFBDevBufferPtr drawBuffer; +   GLFBDevBufferPtr readBuffer; +   GLFBDevBufferPtr curBuffer; +}; + + + +#define GLFBDEV_CONTEXT(CTX)  ((GLFBDevContextPtr) (CTX)) +#define GLFBDEV_BUFFER(BUF)  ((GLFBDevBufferPtr) (BUF)) + + +/**********************************************************************/ +/* Internal device driver functions                                   */ +/**********************************************************************/ + + +static const GLubyte * +get_string(GLcontext *ctx, GLenum pname) +{ +   (void) ctx; +   switch (pname) { +      case GL_RENDERER: +         return (const GLubyte *) "Mesa glfbdev"; +      default: +         return NULL; +   } +} + + +static void +update_state( GLcontext *ctx, GLuint new_state ) +{ +   /* not much to do here - pass it on */ +   _swrast_InvalidateState( ctx, new_state ); +   _swsetup_InvalidateState( ctx, new_state ); +   _ac_InvalidateState( ctx, new_state ); +   _tnl_InvalidateState( ctx, new_state ); +} + + +static void +get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +{ +   const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer; +   *width = fbdevbuffer->var.xres_virtual; +   *height = fbdevbuffer->var.yres_virtual; +} + + +/* specifies the buffer for swrast span rendering/reading */ +static void +set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) +{ +   GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); +   GLFBDevBufferPtr fbdevbuf = GLFBDEV_BUFFER(buffer); +   fbdevctx->curBuffer = fbdevbuf; +   switch (bufferBit) { +   case FRONT_LEFT_BIT: +      fbdevbuf->curBottom = fbdevbuf->frontBottom; +      break; +   case BACK_LEFT_BIT: +      fbdevbuf->curBottom = fbdevbuf->backBottom; +      break; +   default: +      _mesa_problem(ctx, "bad bufferBit in set_buffer()"); +   } +} + + +static void +init_core_functions( GLcontext *ctx ) +{ +   ctx->Driver.GetString = get_string; +   ctx->Driver.UpdateState = update_state; +   ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; +   ctx->Driver.GetBufferSize = get_buffer_size; + +   ctx->Driver.Accum = _swrast_Accum; +   ctx->Driver.Bitmap = _swrast_Bitmap; +   ctx->Driver.Clear = _swrast_Clear;  /* would be good to optimize */ +   ctx->Driver.CopyPixels = _swrast_CopyPixels; +   ctx->Driver.DrawPixels = _swrast_DrawPixels; +   ctx->Driver.ReadPixels = _swrast_ReadPixels; +   ctx->Driver.DrawBuffer = _swrast_DrawBuffer; + +   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; +   ctx->Driver.TexImage1D = _mesa_store_teximage1d; +   ctx->Driver.TexImage2D = _mesa_store_teximage2d; +   ctx->Driver.TexImage3D = _mesa_store_teximage3d; +   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; +   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; +   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; +   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + +   ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; +   ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; +   ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; +   ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; +   ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; +   ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; + +   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; +   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; +   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; +   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; +   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; +   ctx->Driver.CopyColorTable = _swrast_CopyColorTable; +   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; +   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; +   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; +} + + +/* + * Generate code for span functions. + */ + +/* 24-bit BGR */ +#define NAME(PREFIX) PREFIX##_B8G8R8 +#define SPAN_VARS \ +   const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \ +   const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer; +#define INIT_PIXEL_PTR(P, X, Y) \ +   GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 3 +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ +   P[0] = B;  P[1] = G;  P[2] = R +#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ +   P[0] = B;  P[1] = G;  P[2] = R +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ +   R = P[2];  G = P[1];  B = P[0];  A = CHAN_MAX + +#include "swrast/s_spantemp.h" + + +/* 32-bit BGRA */ +#define NAME(PREFIX) PREFIX##_B8G8R8A8 +#define SPAN_VARS \ +   const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \ +   const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer; +#define INIT_PIXEL_PTR(P, X, Y) \ +   GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 4 +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ +   P[0] = B;  P[1] = G;  P[2] = R;  P[3] = 255 +#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ +   P[0] = B;  P[1] = G;  P[2] = R;  P[3] = A +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ +   R = P[2];  G = P[1];  B = P[0];  A = P[3] + +#include "swrast/s_spantemp.h" + + +/* 16-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G6R5 +#define SPAN_VARS \ +   const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \ +   const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer; +#define INIT_PIXEL_PTR(P, X, Y) \ +   GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ +   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) +#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ +   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ +   R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \ +   G = ( (((*P) >> 3) & 0xfc) | (((*P) >>  5) & 0x3) ); \ +   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \ +   A = CHAN_MAX + +#include "swrast/s_spantemp.h" + + +/* 15-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G5R5 +#define SPAN_VARS \ +   const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \ +   const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer; +#define INIT_PIXEL_PTR(P, X, Y) \ +   GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ +   *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) ) +#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ +   *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) ) +#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ +   R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \ +   G = ( (((*P) >> 2) & 0xf8) | (((*P) >>  5) & 0x7) ); \ +   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \ +   A = CHAN_MAX + +#include "swrast/s_spantemp.h" + + +/* 8-bit color index */ +#define NAME(PREFIX) PREFIX##_CI8 +#define SPAN_VARS \ +   const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \ +   const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer; +#define INIT_PIXEL_PTR(P, X, Y) \ +   GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_CI_PIXEL(P, CI) \ +   P[0] = CI +#define FETCH_CI_PIXEL(CI, P) \ +   CI = P[0] + +#include "swrast/s_spantemp.h" + +/**********************************************************************/ +/* Public API functions                                               */ +/**********************************************************************/ + + +const char * +glFBDevGetString( int str ) +{ +   switch (str) { +   case GLFBDEV_VENDOR: +      return "Mesa Project"; +   case GLFBDEV_VERSION: +      return "1.0.0"; +   default: +      return NULL; +   } +} + + +const void * +glFBDevGetProcAddress( const char *procName ) +{ +   struct name_address { +      const char *name; +      const void *func; +   }; +   static const struct name_address functions[] = { +      { "glFBDevGetString", (void *) glFBDevGetString }, +      { "glFBDevGetProcAddress", (void *) glFBDevGetProcAddress }, +      { "glFBDevCreateVisual", (void *) glFBDevCreateVisual }, +      { "glFBDevDestroyVisual", (void *) glFBDevDestroyVisual }, +      { "glFBDevGetVisualAttrib", (void *) glFBDevGetVisualAttrib }, +      { "glFBDevCreateBuffer", (void *) glFBDevCreateBuffer }, +      { "glFBDevDestroyBuffer", (void *) glFBDevDestroyBuffer }, +      { "glFBDevGetBufferAttrib", (void *) glFBDevGetBufferAttrib }, +      { "glFBDevGetCurrentDrawBuffer", (void *) glFBDevGetCurrentDrawBuffer }, +      { "glFBDevGetCurrentReadBuffer", (void *) glFBDevGetCurrentReadBuffer }, +      { "glFBDevSwapBuffers", (void *) glFBDevSwapBuffers }, +      { "glFBDevCreateContext", (void *) glFBDevCreateContext }, +      { "glFBDevDestroyContext", (void *) glFBDevDestroyContext }, +      { "glFBDevGetContextAttrib", (void *) glFBDevGetContextAttrib }, +      { "glFBDevGetCurrentContext", (void *) glFBDevGetCurrentContext }, +      { "glFBDevMakeCurrent", (void *) glFBDevMakeCurrent }, +      { NULL, NULL } +   }; +   const struct name_address *entry; +   for (entry = functions; entry->name; entry++) { +      if (_mesa_strcmp(entry->name, procName) == 0) { +         return entry->func; +      } +   } +   return _glapi_get_proc_address(procName); +} + + +GLFBDevVisualPtr +glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo, +                     const struct fb_var_screeninfo *varInfo, +                     const int *attribs ) +{ +   GLFBDevVisualPtr vis; +   const int *attrib; +   GLboolean rgbFlag = GL_TRUE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE; +   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0; +   GLint indexBits = 0, depthBits = 0, stencilBits = 0; +   GLint accumRedBits = 0, accumGreenBits = 0; +   GLint accumBlueBits = 0, accumAlphaBits = 0; +   GLint numSamples = 0; + +   ASSERT(fixInfo); +   ASSERT(varInfo); + +   vis = CALLOC_STRUCT(GLFBDevVisualRec); +   if (!vis) +      return NULL; + +   vis->fix = *fixInfo;  /* struct assignment */ +   vis->var = *varInfo;  /* struct assignment */ + +   for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) { +      switch (*attrib) { +      case GLFBDEV_DOUBLE_BUFFER: +         dbFlag = GL_TRUE; +         break; +      case GLFBDEV_COLOR_INDEX: +         rgbFlag = GL_FALSE; +         break; +      case GLFBDEV_DEPTH_SIZE: +         depthBits = attrib[1]; +         attrib++; +         break; +      case GLFBDEV_STENCIL_SIZE: +         stencilBits = attrib[1]; +         attrib++; +         break; +      case GLFBDEV_ACCUM_SIZE: +         accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits +            = attrib[1]; +         attrib++; +         break; +      case GLFBDEV_LEVEL: +         /* ignored for now */ +         break; +      default: +         /* unexpected token */ +         _mesa_free(vis); +         return NULL; +      } +   } + +   if (rgbFlag) { +      redBits   = varInfo->red.length; +      greenBits = varInfo->green.length; +      blueBits  = varInfo->blue.length; +      alphaBits = varInfo->transp.length; + +      if ((fixInfo->visual == FB_VISUAL_TRUECOLOR || +           fixInfo->visual == FB_VISUAL_DIRECTCOLOR) +          && varInfo->bits_per_pixel == 24 +          && varInfo->red.offset == 16 +          && varInfo->green.offset == 8 +          && varInfo->blue.offset == 0) { +         vis->pixelFormat = PF_B8G8R8; +      } +      else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR || +                fixInfo->visual == FB_VISUAL_DIRECTCOLOR) +               && varInfo->bits_per_pixel == 32 +               && varInfo->red.offset == 16 +               && varInfo->green.offset == 8 +               && varInfo->blue.offset == 0 +               && varInfo->transp.offset == 24) { +         vis->pixelFormat = PF_B8G8R8A8; +      } +      else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR || +                fixInfo->visual == FB_VISUAL_DIRECTCOLOR) +               && varInfo->bits_per_pixel == 16 +               && varInfo->red.offset == 11 +               && varInfo->green.offset == 5 +               && varInfo->blue.offset == 0) { +         vis->pixelFormat = PF_B5G6R5; +      } +      else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR || +                fixInfo->visual == FB_VISUAL_DIRECTCOLOR) +               && varInfo->bits_per_pixel == 16 +               && varInfo->red.offset == 10 +               && varInfo->green.offset == 5 +               && varInfo->blue.offset == 0) { +         vis->pixelFormat = PF_B5G5R5; +      } +      else { +         _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n"); +         /* +         printf("fixInfo->visual = 0x%x\n", fixInfo->visual); +         printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel); +         printf("varInfo->red.offset = %d\n", varInfo->red.offset); +         printf("varInfo->green.offset = %d\n", varInfo->green.offset); +         printf("varInfo->blue.offset = %d\n", varInfo->blue.offset); +         */ +         _mesa_free(vis); +         return NULL; +      } +   } +   else { +      indexBits = varInfo->bits_per_pixel; +      if ((fixInfo->visual == FB_VISUAL_PSEUDOCOLOR || +           fixInfo->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) +          && varInfo->bits_per_pixel == 8) { +         vis->pixelFormat = PF_CI8; +      } +      else { +         _mesa_problem(NULL, "Unsupported fbdev CI visual/bitdepth!\n"); +         _mesa_free(vis); +         return NULL; +      } +   } + +   if (!_mesa_initialize_visual(&vis->glvisual, rgbFlag, dbFlag, stereoFlag, +                                redBits, greenBits, blueBits, alphaBits, +                                indexBits, depthBits, stencilBits, +                                accumRedBits, accumGreenBits, +                                accumBlueBits, accumAlphaBits, +                                numSamples)) { +      /* something was invalid */ +      _mesa_free(vis); +      return NULL; +   } + +   return vis; +} + + +void +glFBDevDestroyVisual( GLFBDevVisualPtr visual ) +{ +   if (visual) +      _mesa_free(visual); +} + + +int +glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib) +{ +   (void) visual; +   (void) attrib; +   return -1; +} + + + +GLFBDevBufferPtr +glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo, +                     const struct fb_var_screeninfo *varInfo, +                     const GLFBDevVisualPtr visual, +                     void *frontBuffer, void *backBuffer, size_t size ) +{ +   GLFBDevBufferPtr buf; + +   ASSERT(visual); +   ASSERT(frontBuffer); +   ASSERT(size > 0); + +   if (visual->fix.visual != fixInfo->visual || +       visual->fix.type != fixInfo->type || +       visual->var.bits_per_pixel != varInfo->bits_per_pixel || +       visual->var.grayscale != varInfo->grayscale || +       visual->var.red.offset != varInfo->red.offset || +       visual->var.green.offset != varInfo->green.offset || +       visual->var.blue.offset != varInfo->blue.offset || +       visual->var.transp.offset != varInfo->transp.offset) { +      /* visual mismatch! */ +      return NULL; +   } + +   buf = CALLOC_STRUCT(GLFBDevBufferRec); +   if (!buf) +      return NULL; + +   _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual, +                                visual->glvisual.haveDepthBuffer, +                                visual->glvisual.haveStencilBuffer, +                                visual->glvisual.haveAccumBuffer, +                                GL_FALSE); + +   buf->fix = *fixInfo;   /* struct assignment */ +   buf->var = *varInfo;   /* struct assignment */ +   buf->visual = visual;  /* ptr assignment */ +   buf->frontStart = frontBuffer; +   buf->size = size; +   buf->bytesPerPixel = visual->var.bits_per_pixel / 8; +   buf->rowStride = visual->var.xres_virtual * buf->bytesPerPixel; +   buf->frontBottom = (GLubyte *) buf->frontStart +                    + (visual->var.yres_virtual - 1) * buf->rowStride; + +   if (visual->glvisual.doubleBufferMode) { +      if (backBuffer) { +         buf->backStart = backBuffer; +         buf->mallocBackBuffer = GL_FALSE; +      } +      else { +         buf->backStart = _mesa_malloc(size); +         if (!buf->backStart) { +            _mesa_free_framebuffer_data(&buf->glframebuffer); +            _mesa_free(buf); +            return NULL; +         } +         buf->mallocBackBuffer = GL_TRUE; +      } +      buf->backBottom = (GLubyte *) buf->backStart +                      + (visual->var.yres_virtual - 1) * buf->rowStride; +      buf->curBottom = buf->backBottom; +   } +   else { +      buf->backStart = NULL; +      buf->mallocBackBuffer = GL_FALSE; +      buf->backBottom = NULL; +      buf->curBottom = buf->frontBottom; +   } + +   return buf; +} + + +void +glFBDevDestroyBuffer( GLFBDevBufferPtr buffer ) +{ +   if (buffer) { +      /* check if destroying the current buffer */ +      GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer(); +      GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer(); +      if (buffer == curDraw || buffer == curRead) { +         glFBDevMakeCurrent( NULL, NULL, NULL); +      } +      if (buffer->mallocBackBuffer) { +         _mesa_free(buffer->backStart); +      } +      /* free the software depth, stencil, accum buffers */ +      _mesa_free_framebuffer_data(&buffer->glframebuffer); +      _mesa_free(buffer); +   } +} + + +int +glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib) +{ +   (void) buffer; +   (void) attrib; +   return -1; +} + + +GLFBDevBufferPtr +glFBDevGetCurrentDrawBuffer( void ) +{ +   GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); +   if (fbdevctx) +      return fbdevctx->drawBuffer; +   else +      return NULL; +} + + +GLFBDevBufferPtr +glFBDevGetCurrentReadBuffer( void ) +{ +   GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); +   if (fbdevctx) +      return fbdevctx->readBuffer; +   else +      return NULL; +} + + +void +glFBDevSwapBuffers( GLFBDevBufferPtr buffer ) +{ +   GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); + +   if (!buffer || !buffer->visual->glvisual.doubleBufferMode) +      return; + +   /* check if swapping currently bound buffer */ +   if (fbdevctx->drawBuffer == buffer) { +      /* flush pending rendering */ +      _mesa_notifySwapBuffers(&fbdevctx->glcontext); +   } + +   ASSERT(buffer->frontStart); +   ASSERT(buffer->backStart); +   _mesa_memcpy(buffer->frontStart, buffer->backStart, buffer->size); +} + + +GLFBDevContextPtr +glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ) +{ +   GLFBDevContextPtr ctx; +   GLcontext *glctx; + +   ASSERT(visual); + +   ctx = CALLOC_STRUCT(GLFBDevContextRec); +   if (!ctx) +      return NULL; + +   if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual, +                                 share ? &share->glcontext : NULL, +                                 (void *) ctx, GL_FALSE)) { +      _mesa_free(ctx); +      return NULL; +   } + +   ctx->visual = visual; + +   /* Create module contexts */ +   glctx = (GLcontext *) &ctx->glcontext; +   init_core_functions( glctx ); +   _swrast_CreateContext( glctx ); +   _ac_CreateContext( glctx ); +   _tnl_CreateContext( glctx ); +   _swsetup_CreateContext( glctx ); +   _swsetup_Wakeup( glctx ); + +   /* swrast init */ +   { +      struct swrast_device_driver *swdd; +      swdd = _swrast_GetDeviceDriverReference( glctx ); +      swdd->SetBuffer = set_buffer; +      if (visual->pixelFormat == PF_B8G8R8) { +         swdd->WriteRGBASpan = write_rgba_span_B8G8R8; +         swdd->WriteRGBSpan = write_rgb_span_B8G8R8; +         swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8; +         swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8; +         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8; +         swdd->ReadRGBASpan = read_rgba_span_B8G8R8; +         swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8; +      } +      else if (visual->pixelFormat == PF_B8G8R8A8) { +         swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8; +         swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8; +         swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8; +         swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8; +         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8; +         swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8; +         swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8; +      } +      else if (visual->pixelFormat == PF_B5G6R5) { +         swdd->WriteRGBASpan = write_rgba_span_B5G6R5; +         swdd->WriteRGBSpan = write_rgb_span_B5G6R5; +         swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5; +         swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5; +         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5; +         swdd->ReadRGBASpan = read_rgba_span_B5G6R5; +         swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5; +      } +      else if (visual->pixelFormat == PF_B5G5R5) { +         swdd->WriteRGBASpan = write_rgba_span_B5G5R5; +         swdd->WriteRGBSpan = write_rgb_span_B5G5R5; +         swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5; +         swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5; +         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5; +         swdd->ReadRGBASpan = read_rgba_span_B5G5R5; +         swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5; +      } +      else if (visual->pixelFormat == PF_CI8) { +         swdd->WriteCI32Span = write_index32_span_CI8; +         swdd->WriteCI8Span = write_index8_span_CI8; +         swdd->WriteMonoCISpan = write_monoindex_span_CI8; +         swdd->WriteCI32Pixels = write_index_pixels_CI8; +         swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8; +         swdd->ReadCI32Span = read_index_span_CI8; +         swdd->ReadCI32Pixels = read_index_pixels_CI8; +      } +      else { +         _mesa_printf("bad pixelformat: %d\n", visual->pixelFormat); +      } +   } + +   /* use default TCL pipeline */ +   { +      TNLcontext *tnl = TNL_CONTEXT(glctx); +      tnl->Driver.RunPipeline = _tnl_run_pipeline; +   } + +   _mesa_enable_sw_extensions(glctx); + +   return ctx; +} + + +void +glFBDevDestroyContext( GLFBDevContextPtr context ) +{ +   GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); + +   if (context) { +      if (fbdevctx == context) { +         /* destroying current context */ +         _mesa_make_current2(NULL, NULL, NULL); +         _mesa_notifyDestroy(&context->glcontext); +      } +      _mesa_free_context_data(&context->glcontext); +      _mesa_free(context); +   } +} + + +int +glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib) +{ +   (void) context; +   (void) attrib; +   return -1; +} + + +GLFBDevContextPtr +glFBDevGetCurrentContext( void ) +{ +   GET_CURRENT_CONTEXT(ctx); +   return (GLFBDevContextPtr) ctx; +} + + +int +glFBDevMakeCurrent( GLFBDevContextPtr context, +                    GLFBDevBufferPtr drawBuffer, +                    GLFBDevBufferPtr readBuffer ) +{ +   if (context && drawBuffer && readBuffer) { +      /* Make sure the context's visual and the buffers' visuals match. +       * XXX we might do this by comparing specific fields like bits_per_pixel, +       * visual, etc. in the future. +       */ +      if (context->visual != drawBuffer->visual || +          context->visual != readBuffer->visual) { +         return 0; +      } +      _mesa_make_current2( &context->glcontext, +                           &drawBuffer->glframebuffer, +                           &readBuffer->glframebuffer ); +      context->drawBuffer = drawBuffer; +      context->readBuffer = readBuffer; +      context->curBuffer = drawBuffer; +   } +   else { +      /* unbind */ +      _mesa_make_current2( NULL, NULL, NULL ); +   } + +   return 1; +} + +#endif /* USE_GLFBDEV_DRIVER */ + | 
