/* * Mesa 3-D graphics library * Version: 7.1 * * Copyright (C) 1999-2007 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 "GL/glfbdev.h" #include #include "main/glheader.h" #include "main/buffers.h" #include "main/context.h" #include "main/extensions.h" #include "main/fbobject.h" #include "main/framebuffer.h" #include "main/imports.h" #include "main/renderbuffer.h" #include "main/texformat.h" #include "main/teximage.h" #include "main/texstore.h" #include "vbo/vbo.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" /** * Pixel formats we support: */ #define PF_B8G8R8 1 #define PF_B8G8R8A8 2 #define PF_B5G6R5 3 #define PF_B5G5R5 4 /** * Derived from Mesa's struct gl_config class. */ struct GLFBDevVisualRec { struct gl_config glvisual; /* base class */ struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; int pixelFormat; }; /** * Derived from Mesa's struct gl_framebuffer class. */ struct GLFBDevBufferRec { struct gl_framebuffer 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 struct gl_context class. */ struct GLFBDevContextRec { struct gl_context 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; }; /**********************************************************************/ /* Internal device driver functions */ /**********************************************************************/ static const GLubyte * get_string(struct gl_context *ctx, GLenum pname) { (void) ctx; switch (pname) { case GL_RENDERER: return (const GLubyte *) "Mesa glfbdev"; default: return NULL; } } static void update_state( struct gl_context *ctx, GLuint new_state ) { /* not much to do here - pass it on */ _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); } static void get_buffer_size( struct gl_framebuffer *buffer, GLuint *width, GLuint *height ) { const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer; *width = fbdevbuffer->var.xres; *height = fbdevbuffer->var.yres; } /** * We only implement this function as a mechanism to check if the * framebuffer size has changed (and update corresponding state). */ static void viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) { GLuint newWidth, newHeight; struct gl_framebuffer *buffer; buffer = ctx->WinSysDrawBuffer; get_buffer_size( buffer, &newWidth, &newHeight ); if (buffer->Width != newWidth || buffer->Height != newHeight) { _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight ); } buffer = ctx->WinSysReadBuffer; get_buffer_size( buffer, &newWidth, &newHeight ); if (buffer->Width != newWidth || buffer->Height != newHeight) { _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight ); } } /* * Generate code for span functions. */ /* 24-bit BGR */ #define NAME(PREFIX) PREFIX##_B8G8R8 #define RB_TYPE GLubyte #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_spantemp.h" /* 32-bit BGRA */ #define NAME(PREFIX) PREFIX##_B8G8R8A8 #define RB_TYPE GLubyte #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 STORE_PIXEL_RGB(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] = SRC[3] #include "swrast/s_spantemp.h" /* 16-bit BGR (XXX implement dithering someday) */ #define NAME(PREFIX) PREFIX##_B5G6R5 #define RB_TYPE GLubyte #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_spantemp.h" /* 15-bit BGR (XXX implement dithering someday) */ #define NAME(PREFIX) PREFIX##_B5G5R5 #define RB_TYPE GLubyte #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_spantemp.h" /**********************************************************************/ /* Public API functions */ /**********************************************************************/ const char * glFBDevGetString( int str ) { switch (str) { case GLFBDEV_VENDOR: return "Mesa Project"; case GLFBDEV_VERSION: return "1.0.1"; default: return NULL; } } 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 (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 dbFlag = GL_FALSE, stereoFlag = GL_FALSE; GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0; GLint 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_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; case GLFBDEV_MULTISAMPLE: numSamples = attrib[1]; attrib++; break; case GLFBDEV_COLOR_INDEX: /* Mesa no longer supports color-index rendering. */ default: /* unexpected token */ free(vis); return NULL; } } 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) { if (varInfo->bits_per_pixel == 24 && varInfo->red.offset == 16 && varInfo->green.offset == 8 && varInfo->blue.offset == 0) { vis->pixelFormat = PF_B8G8R8; } else if (varInfo->bits_per_pixel == 32 && varInfo->red.offset == 16 && varInfo->green.offset == 8 && varInfo->blue.offset == 0) { vis->pixelFormat = PF_B8G8R8A8; } else if (varInfo->bits_per_pixel == 16 && varInfo->red.offset == 11 && varInfo->green.offset == 5 && varInfo->blue.offset == 0) { vis->pixelFormat = PF_B5G6R5; } else if (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"); free(vis); return NULL; } } if (!_mesa_initialize_visual(&vis->glvisual, dbFlag, stereoFlag, redBits, greenBits, blueBits, alphaBits, depthBits, stencilBits, accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits, numSamples)) { /* something was invalid */ free(vis); return NULL; } return vis; } void glFBDevDestroyVisual( GLFBDevVisualPtr visual ) { if (visual) 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) { free(frb->Base.Data); } free(frb); } static GLboolean renderbuffer_storage(struct gl_context *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, const GLFBDevVisualPtr visual) { struct GLFBDevRenderbufferRec *rb = CALLOC_STRUCT(GLFBDevRenderbufferRec); if (rb) { GLuint name = 0; int pixelFormat = visual->pixelFormat; _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.PutRowRGB = put_row_rgb_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.PutRowRGB = put_row_rgb_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.PutRowRGB = put_row_rgb_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.PutRowRGB = put_row_rgb_B5G5R5; rb->Base.PutMonoRow = put_mono_row_B5G5R5; rb->Base.PutValues = put_values_B5G5R5; rb->Base.PutMonoValues = put_mono_values_B5G5R5; } rb->Base.InternalFormat = GL_RGBA; rb->Base._BaseFormat = GL_RGBA; rb->Base.DataType = GL_UNSIGNED_BYTE; rb->Base.Data = bufferStart; rb->rowStride = visual->var.xres_virtual * visual->var.bits_per_pixel / 8; rb->bottom = (GLubyte *) bufferStart + (visual->var.yres - 1) * rb->rowStride; rb->Base.Width = visual->var.xres; rb->Base.Height = visual->var.yres; /* rb->Base.RedBits = visual->var.red.length; rb->Base.GreenBits = visual->var.green.length; rb->Base.BlueBits = visual->var.blue.length; rb->Base.AlphaBits = visual->var.transp.length; */ rb->Base.InternalFormat = pixelFormat; } 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); /* this is to update the visual if there was a resize and the buffer is created again */ visual->var = *varInfo; visual->fix = *fixInfo; 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_window_framebuffer(&buf->glframebuffer, &visual->glvisual); /* add front renderbuffer */ frontrb = new_glfbdev_renderbuffer(frontBuffer, visual); _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_FRONT_LEFT, &frontrb->Base); /* add back renderbuffer */ if (visual->glvisual.doubleBufferMode) { const int malloced = !backBuffer; if (malloced) { /* malloc a back buffer */ backBuffer = malloc(size); if (!backBuffer) { _mesa_free_framebuffer_data(&buf->glframebuffer); free(buf); return NULL; } } backrb = new_glfbdev_renderbuffer(backBuffer, visual); if (!backrb) { /* out of mem */ return NULL; } backrb->mallocedBuffer = malloced; _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; 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); } { struct gl_framebuffer *fb = &buffer->glframebuffer; _mesa_reference_framebuffer(&fb, NULL); } } } 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); memcpy(frontrb->Base.Data, backrb->Base.Data, buffer->size); } GLFBDevContextPtr glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ) { GLFBDevContextPtr ctx; struct gl_context *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, API_OPENGL, &visual->glvisual, share ? &share->glcontext : NULL, &functions, (void *) ctx)) { free(ctx); return NULL; } ctx->visual = visual; /* Create module contexts */ glctx = (struct gl_context *) &ctx->glcontext; _swrast_CreateContext( glctx ); _vbo_CreateContext( glctx ); _tnl_CreateContext( glctx ); _swsetup_CreateContext( glctx ); _swsetup_Wakeup( glctx ); /* use default TCL pipeline */ { TNLcontext *tnl = TNL_CONTEXT(glctx); tnl->Driver.RunPipeline = _tnl_run_pipeline; } _mesa_enable_sw_extensions(glctx); _mesa_enable_1_3_extensions(glctx); _mesa_enable_1_4_extensions(glctx); _mesa_enable_1_5_extensions(glctx); _mesa_enable_2_0_extensions(glctx); _mesa_enable_2_1_extensions(glctx); return ctx; } void glFBDevDestroyContext( GLFBDevContextPtr context ) { GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); if (context) { struct gl_context *mesaCtx = &context->glcontext; _swsetup_DestroyContext( mesaCtx ); _swrast_DestroyContext( mesaCtx ); _tnl_DestroyContext( mesaCtx ); _vbo_DestroyContext( mesaCtx ); if (fbdevctx == context) { /* destroying current context */ _mesa_make_current(NULL, NULL, NULL); } _mesa_free_context_data(&context->glcontext); 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 /* USE_GLFBDEV_DRIVER */