blob: f3da4a5ba259c5fcafaa2bec5653f89b89d86b47 [file] [log] [blame]
/*
* 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 "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 "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
#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;
};
/**********************************************************************/
/* 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 );
_vbo_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;
*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(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
GLuint newWidth, newHeight;
GLframebuffer *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 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"
/* 8-bit color index */
#define NAME(PREFIX) PREFIX##_CI8
#define CI_MODE
#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)
#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_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 (_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;
case GLFBDEV_MULTISAMPLE:
numSamples = attrib[1];
attrib++;
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) {
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");
_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, 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;
}
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;
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_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 = _mesa_malloc(size);
if (!backBuffer) {
_mesa_free_framebuffer_data(&buf->glframebuffer);
_mesa_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_unreference_framebuffer(&fb);
}
}
}
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 );
_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) {
GLcontext *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);
_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 /* USE_GLFBDEV_DRIVER */