diff options
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/fbdev/glfbdev.c')
-rw-r--r-- | nx-X11/extras/Mesa/src/mesa/drivers/fbdev/glfbdev.c | 861 |
1 files changed, 861 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/fbdev/glfbdev.c b/nx-X11/extras/Mesa/src/mesa/drivers/fbdev/glfbdev.c new file mode 100644 index 000000000..c8d9375b6 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/fbdev/glfbdev.c @@ -0,0 +1,861 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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 "buffers.h" +#include "context.h" +#include "extensions.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "imports.h" +#include "renderbuffer.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" +#include "drivers/common/driverfuncs.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; + size_t size; /* color buffer size in bytes */ + GLuint bytesPerPixel; +}; + +/* + * Derived from Mesa's GLcontext class. + */ +struct GLFBDevContextRec { + GLcontext glcontext; /* base class */ + GLFBDevVisualPtr visual; + GLFBDevBufferPtr drawBuffer; + GLFBDevBufferPtr readBuffer; + GLFBDevBufferPtr curBuffer; +}; + +/* + * Derived from Mesa's gl_renderbuffer class. + */ +struct GLFBDevRenderbufferRec { + struct gl_renderbuffer Base; + GLubyte *bottom; /* pointer to last row */ + GLuint rowStride; /* in bytes */ + GLboolean mallocedBuffer; +}; + + + +#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 = GLFBDEV_BUFFER(buffer); + *width = fbdevbuffer->var.xres_virtual; + *height = fbdevbuffer->var.yres_virtual; +} + + +static void +viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + /* poll for window size change and realloc software Z/stencil/etc if needed */ + _mesa_ResizeBuffersMESA(); +} + + +/* specifies the buffer for swrast span rendering/reading */ +static void +set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) +{ + /* this is a no-op when using the new gl_renderbuffer span functions. */ +} + + +/* + * Generate code for span functions. + */ + +/* 24-bit BGR */ +#define NAME(PREFIX) PREFIX##_B8G8R8 +#define FORMAT GL_RGBA8 +#define SPAN_VARS \ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 3 +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[BCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[RCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = CHAN_MAX + +#include "swrast/s_spantemp2.h" + + +/* 32-bit BGRA */ +#define NAME(PREFIX) PREFIX##_B8G8R8A8 +#define FORMAT GL_RGBA8 +#define SPAN_VARS \ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 4 +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[BCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[RCOMP]; \ + DST[3] = VALUE[ACOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = SRC[3] + +#include "swrast/s_spantemp2.h" + + +/* 16-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G6R5 +#define FORMAT GL_RGBA8 +#define SPAN_VARS \ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) ) +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \ + DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \ + DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \ + DST[ACOMP] = CHAN_MAX + +#include "swrast/s_spantemp2.h" + + +/* 15-bit BGR (XXX implement dithering someday) */ +#define NAME(PREFIX) PREFIX##_B5G5R5 +#define FORMAT GL_RGBA8 +#define SPAN_VARS \ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) ) +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \ + DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \ + DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \ + DST[ACOMP] = CHAN_MAX + +#include "swrast/s_spantemp2.h" + + +/* 8-bit color index */ +#define NAME(PREFIX) PREFIX##_CI8 +#define FORMAT GL_COLOR_INDEX8_EXT +#define SPAN_VARS \ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) +#define INC_PIXEL_PTR(P) P += 1 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + *DST = VALUE[0] +#define FETCH_PIXEL(DST, SRC) \ + DST = SRC[0] + +#include "swrast/s_spantemp2.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 GLFBDevProc +glFBDevGetProcAddress( const char *procName ) +{ + struct name_address { + const char *name; + const GLFBDevProc func; + }; + static const struct name_address functions[] = { + { "glFBDevGetString", (GLFBDevProc) glFBDevGetString }, + { "glFBDevGetProcAddress", (GLFBDevProc) glFBDevGetProcAddress }, + { "glFBDevCreateVisual", (GLFBDevProc) glFBDevCreateVisual }, + { "glFBDevDestroyVisual", (GLFBDevProc) glFBDevDestroyVisual }, + { "glFBDevGetVisualAttrib", (GLFBDevProc) glFBDevGetVisualAttrib }, + { "glFBDevCreateBuffer", (GLFBDevProc) glFBDevCreateBuffer }, + { "glFBDevDestroyBuffer", (GLFBDevProc) glFBDevDestroyBuffer }, + { "glFBDevGetBufferAttrib", (GLFBDevProc) glFBDevGetBufferAttrib }, + { "glFBDevGetCurrentDrawBuffer", (GLFBDevProc) glFBDevGetCurrentDrawBuffer }, + { "glFBDevGetCurrentReadBuffer", (GLFBDevProc) glFBDevGetCurrentReadBuffer }, + { "glFBDevSwapBuffers", (GLFBDevProc) glFBDevSwapBuffers }, + { "glFBDevCreateContext", (GLFBDevProc) glFBDevCreateContext }, + { "glFBDevDestroyContext", (GLFBDevProc) glFBDevDestroyContext }, + { "glFBDevGetContextAttrib", (GLFBDevProc) glFBDevGetContextAttrib }, + { "glFBDevGetCurrentContext", (GLFBDevProc) glFBDevGetCurrentContext }, + { "glFBDevMakeCurrent", (GLFBDevProc) 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) +{ + /* XXX unfinished */ + (void) visual; + (void) attrib; + return -1; +} + + +static void +delete_renderbuffer(struct gl_renderbuffer *rb) +{ + struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb; + if (frb->mallocedBuffer) { + _mesa_free(frb->Base.Data); + } + _mesa_free(frb); +} + + +static GLboolean +renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + /* no-op: the renderbuffer storage is allocated just once when it's + * created. Never resized or reallocated. + */ + return GL_TRUE; +} + + +static struct GLFBDevRenderbufferRec * +new_glfbdev_renderbuffer(void *bufferStart, int pixelFormat) +{ + struct GLFBDevRenderbufferRec *rb = CALLOC_STRUCT(GLFBDevRenderbufferRec); + if (rb) { + GLuint name = 0; + _mesa_init_renderbuffer(&rb->Base, name); + + rb->Base.Delete = delete_renderbuffer; + rb->Base.AllocStorage = renderbuffer_storage; + + if (pixelFormat == PF_B8G8R8) { + rb->Base.GetRow = get_row_B8G8R8; + rb->Base.GetValues = get_values_B8G8R8; + rb->Base.PutRow = put_row_B8G8R8; + rb->Base.PutMonoRow = put_mono_row_B8G8R8; + rb->Base.PutValues = put_values_B8G8R8; + rb->Base.PutMonoValues = put_mono_values_B8G8R8; + } + else if (pixelFormat == PF_B8G8R8A8) { + rb->Base.GetRow = get_row_B8G8R8A8; + rb->Base.GetValues = get_values_B8G8R8A8; + rb->Base.PutRow = put_row_B8G8R8A8; + rb->Base.PutMonoRow = put_mono_row_B8G8R8A8; + rb->Base.PutValues = put_values_B8G8R8A8; + rb->Base.PutMonoValues = put_mono_values_B8G8R8A8; + } + else if (pixelFormat == PF_B5G6R5) { + rb->Base.GetRow = get_row_B5G6R5; + rb->Base.GetValues = get_values_B5G6R5; + rb->Base.PutRow = put_row_B5G6R5; + rb->Base.PutMonoRow = put_mono_row_B5G6R5; + rb->Base.PutValues = put_values_B5G6R5; + rb->Base.PutMonoValues = put_mono_values_B5G6R5; + } + else if (pixelFormat == PF_B5G5R5) { + rb->Base.GetRow = get_row_B5G5R5; + rb->Base.GetValues = get_values_B5G5R5; + rb->Base.PutRow = put_row_B5G5R5; + rb->Base.PutMonoRow = put_mono_row_B5G5R5; + rb->Base.PutValues = put_values_B5G5R5; + rb->Base.PutMonoValues = put_mono_values_B5G5R5; + } + else if (pixelFormat == PF_CI8) { + rb->Base.GetRow = get_row_CI8; + rb->Base.GetValues = get_values_CI8; + rb->Base.PutRow = put_row_CI8; + rb->Base.PutMonoRow = put_mono_row_CI8; + rb->Base.PutValues = put_values_CI8; + rb->Base.PutMonoValues = put_mono_values_CI8; + } + + if (pixelFormat == PF_CI8) { + rb->Base.InternalFormat = GL_COLOR_INDEX8_EXT; + rb->Base._BaseFormat = GL_COLOR_INDEX; + } + else { + rb->Base.InternalFormat = GL_RGBA; + rb->Base._BaseFormat = GL_RGBA; + } + rb->Base.DataType = GL_UNSIGNED_BYTE; + rb->Base.Data = bufferStart; + } + return rb; +} + + +GLFBDevBufferPtr +glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo, + const struct fb_var_screeninfo *varInfo, + const GLFBDevVisualPtr visual, + void *frontBuffer, void *backBuffer, size_t size ) +{ + struct GLFBDevRenderbufferRec *frontrb, *backrb; + 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; + + /* basic framebuffer setup */ + _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual); + /* add front renderbuffer */ + frontrb = new_glfbdev_renderbuffer(frontBuffer, visual->pixelFormat); + _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_FRONT_LEFT, + &frontrb->Base); + /* add back renderbuffer */ + if (visual->glvisual.doubleBufferMode) { + backrb = new_glfbdev_renderbuffer(backBuffer, visual->pixelFormat); + _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_BACK_LEFT, + &backrb->Base); + } + /* add software renderbuffers */ + _mesa_add_soft_renderbuffers(&buf->glframebuffer, + GL_FALSE, /* color */ + visual->glvisual.haveDepthBuffer, + visual->glvisual.haveStencilBuffer, + visual->glvisual.haveAccumBuffer, + GL_FALSE, /* alpha */ + GL_FALSE /* aux bufs */); + + + + buf->fix = *fixInfo; /* struct assignment */ + buf->var = *varInfo; /* struct assignment */ + buf->visual = visual; /* ptr assignment */ + buf->size = size; + buf->bytesPerPixel = visual->var.bits_per_pixel / 8; + frontrb->rowStride = visual->var.xres_virtual * buf->bytesPerPixel; + frontrb->bottom = (GLubyte *) frontrb->Base.Data + + (visual->var.yres_virtual - 1) * frontrb->rowStride; + + if (visual->glvisual.doubleBufferMode) { + if (!backBuffer) { + /* malloc a back buffer */ + backrb->Base.Data = _mesa_malloc(size); + if (!backrb->Base.Data) { + _mesa_free_framebuffer_data(&buf->glframebuffer); + _mesa_free(buf); + return NULL; + } + backrb->mallocedBuffer = GL_TRUE; + } + backrb->rowStride = frontrb->rowStride; + backrb->bottom = (GLubyte *) backrb->Base.Data + + (visual->var.yres_virtual - 1) * backrb->rowStride; + } + else { + backrb->bottom = NULL; + backrb->rowStride = 0; + } + + 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); + } + /* 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(); + struct GLFBDevRenderbufferRec *frontrb = (struct GLFBDevRenderbufferRec *) + buffer->glframebuffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + struct GLFBDevRenderbufferRec *backrb = (struct GLFBDevRenderbufferRec *) + buffer->glframebuffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer; + + 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(frontrb->Base.Data); + ASSERT(backrb->Base.Data); + _mesa_memcpy(frontrb->Base.Data, backrb->Base.Data, buffer->size); +} + + +GLFBDevContextPtr +glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ) +{ + GLFBDevContextPtr ctx; + GLcontext *glctx; + struct dd_function_table functions; + + ASSERT(visual); + + ctx = CALLOC_STRUCT(GLFBDevContextRec); + if (!ctx) + return NULL; + + /* build table of device driver functions */ + _mesa_init_driver_functions(&functions); + functions.GetString = get_string; + functions.UpdateState = update_state; + functions.GetBufferSize = get_buffer_size; + functions.Viewport = viewport; + + if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual, + share ? &share->glcontext : NULL, + &functions, (void *) ctx)) { + _mesa_free(ctx); + return NULL; + } + + ctx->visual = visual; + + /* Create module contexts */ + glctx = (GLcontext *) &ctx->glcontext; + _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; + + /* no longer used */ + swdd->WriteRGBASpan = NULL; + swdd->WriteRGBSpan = NULL; + swdd->WriteMonoRGBASpan = NULL; + swdd->WriteRGBAPixels = NULL; + swdd->WriteMonoRGBAPixels = NULL; + swdd->ReadRGBASpan = NULL; + swdd->ReadRGBAPixels = NULL; + } + + /* 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_current(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_current( &context->glcontext, + &drawBuffer->glframebuffer, + &readBuffer->glframebuffer ); + context->drawBuffer = drawBuffer; + context->readBuffer = readBuffer; + context->curBuffer = drawBuffer; + } + else { + /* unbind */ + _mesa_make_current( NULL, NULL, NULL ); + } + + return 1; +} + +#endif |