Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / fbdev / glfbdev.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25
26 /*
27  * OpenGL (Mesa) interface for fbdev.
28  * For info about fbdev:
29  * http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html
30  *
31  * known VGA modes
32  * Colours   640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
33  * --------+--------------------------------------------------------------
34  *  4 bits |    ?       ?     0x302      ?        ?        ?         ?
35  *  8 bits |  0x300   0x301   0x303    0x305    0x161    0x307     0x31C
36  * 15 bits |    ?     0x310   0x313    0x316    0x162    0x319     0x31D
37  * 16 bits |    ?     0x311   0x314    0x317    0x163    0x31A     0x31E
38  * 24 bits |    ?     0x312   0x315    0x318      ?      0x31B     0x31F
39  * 32 bits |    ?       ?       ?        ?      0x164      ?
40  */
41
42 #ifdef USE_GLFBDEV_DRIVER
43
44 #include "GL/glfbdev.h"
45 #include <linux/fb.h>
46 #include "main/glheader.h"
47 #include "main/buffers.h"
48 #include "main/context.h"
49 #include "main/extensions.h"
50 #include "main/fbobject.h"
51 #include "main/framebuffer.h"
52 #include "main/imports.h"
53 #include "main/renderbuffer.h"
54 #include "main/texformat.h"
55 #include "main/teximage.h"
56 #include "main/texstore.h"
57 #include "vbo/vbo.h"
58 #include "swrast/swrast.h"
59 #include "swrast_setup/swrast_setup.h"
60 #include "tnl/tnl.h"
61 #include "tnl/t_context.h"
62 #include "tnl/t_pipeline.h"
63 #include "drivers/common/driverfuncs.h"
64
65
66 /**
67  * Pixel formats we support:
68  */
69 #define PF_B8G8R8     1
70 #define PF_B8G8R8A8   2
71 #define PF_B5G6R5     3
72 #define PF_B5G5R5     4
73
74
75 /**
76  * Derived from Mesa's struct gl_config class.
77  */
78 struct GLFBDevVisualRec {
79    struct gl_config glvisual;              /* base class */
80    struct fb_fix_screeninfo fix;
81    struct fb_var_screeninfo var;
82    int pixelFormat;
83 };
84
85 /**
86  * Derived from Mesa's struct gl_framebuffer class.
87  */
88 struct GLFBDevBufferRec {
89    struct gl_framebuffer glframebuffer;    /* base class */
90    GLFBDevVisualPtr visual;
91    struct fb_fix_screeninfo fix;
92    struct fb_var_screeninfo var;
93    size_t size;                    /* color buffer size in bytes */
94    GLuint bytesPerPixel;
95 };
96
97 /**
98  * Derived from Mesa's struct gl_context class.
99  */
100 struct GLFBDevContextRec {
101    struct gl_context glcontext;            /* base class */
102    GLFBDevVisualPtr visual;
103    GLFBDevBufferPtr drawBuffer;
104    GLFBDevBufferPtr readBuffer;
105    GLFBDevBufferPtr curBuffer;
106 };
107
108 /**
109  * Derived from Mesa's gl_renderbuffer class.
110  */
111 struct GLFBDevRenderbufferRec {
112    struct gl_renderbuffer Base;
113    GLubyte *bottom;                /* pointer to last row */
114    GLuint rowStride;               /* in bytes */
115    GLboolean mallocedBuffer;
116 };
117
118
119 /**********************************************************************/
120 /* Internal device driver functions                                   */
121 /**********************************************************************/
122
123
124 static const GLubyte *
125 get_string(struct gl_context *ctx, GLenum pname)
126 {
127    (void) ctx;
128    switch (pname) {
129       case GL_RENDERER:
130          return (const GLubyte *) "Mesa glfbdev";
131       default:
132          return NULL;
133    }
134 }
135
136
137 static void
138 update_state( struct gl_context *ctx, GLuint new_state )
139 {
140    /* not much to do here - pass it on */
141    _swrast_InvalidateState( ctx, new_state );
142    _swsetup_InvalidateState( ctx, new_state );
143    _vbo_InvalidateState( ctx, new_state );
144    _tnl_InvalidateState( ctx, new_state );
145 }
146
147
148 static void
149 get_buffer_size( struct gl_framebuffer *buffer, GLuint *width, GLuint *height )
150 {
151    const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer;
152    *width = fbdevbuffer->var.xres;
153    *height = fbdevbuffer->var.yres;
154 }
155
156
157 /**
158  * We only implement this function as a mechanism to check if the
159  * framebuffer size has changed (and update corresponding state).
160  */
161 static void
162 viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
163 {
164    GLuint newWidth, newHeight;
165    struct gl_framebuffer *buffer;
166
167    buffer = ctx->WinSysDrawBuffer;
168    get_buffer_size( buffer, &newWidth, &newHeight );
169    if (buffer->Width != newWidth || buffer->Height != newHeight) {
170       _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight );
171    }
172
173    buffer = ctx->WinSysReadBuffer;
174    get_buffer_size( buffer, &newWidth, &newHeight );
175    if (buffer->Width != newWidth || buffer->Height != newHeight) {
176       _mesa_resize_framebuffer(ctx, buffer, newWidth, newHeight );
177    }
178 }
179
180
181 /*
182  * Generate code for span functions.
183  */
184
185 /* 24-bit BGR */
186 #define NAME(PREFIX) PREFIX##_B8G8R8
187 #define RB_TYPE GLubyte
188 #define SPAN_VARS \
189    struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
190 #define INIT_PIXEL_PTR(P, X, Y) \
191    GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 3
192 #define INC_PIXEL_PTR(P) P += 3
193 #define STORE_PIXEL(DST, X, Y, VALUE) \
194    DST[0] = VALUE[BCOMP];  \
195    DST[1] = VALUE[GCOMP];  \
196    DST[2] = VALUE[RCOMP]
197 #define FETCH_PIXEL(DST, SRC) \
198    DST[RCOMP] = SRC[2];  \
199    DST[GCOMP] = SRC[1];  \
200    DST[BCOMP] = SRC[0];  \
201    DST[ACOMP] = CHAN_MAX
202
203 #include "swrast/s_spantemp.h"
204
205
206 /* 32-bit BGRA */
207 #define NAME(PREFIX) PREFIX##_B8G8R8A8
208 #define RB_TYPE GLubyte
209 #define SPAN_VARS \
210    struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
211 #define INIT_PIXEL_PTR(P, X, Y) \
212    GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 4
213 #define INC_PIXEL_PTR(P) P += 4
214 #define STORE_PIXEL(DST, X, Y, VALUE) \
215    DST[0] = VALUE[BCOMP];  \
216    DST[1] = VALUE[GCOMP];  \
217    DST[2] = VALUE[RCOMP];  \
218    DST[3] = VALUE[ACOMP]
219 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
220    DST[0] = VALUE[BCOMP];  \
221    DST[1] = VALUE[GCOMP];  \
222    DST[2] = VALUE[RCOMP];
223 #define FETCH_PIXEL(DST, SRC) \
224    DST[RCOMP] = SRC[2];  \
225    DST[GCOMP] = SRC[1];  \
226    DST[BCOMP] = SRC[0];  \
227    DST[ACOMP] = SRC[3]
228
229 #include "swrast/s_spantemp.h"
230
231
232 /* 16-bit BGR (XXX implement dithering someday) */
233 #define NAME(PREFIX) PREFIX##_B5G6R5
234 #define RB_TYPE GLubyte
235 #define SPAN_VARS \
236    struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
237 #define INIT_PIXEL_PTR(P, X, Y) \
238    GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2)
239 #define INC_PIXEL_PTR(P) P += 1
240 #define STORE_PIXEL(DST, X, Y, VALUE) \
241    DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
242 #define FETCH_PIXEL(DST, SRC) \
243    DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \
244    DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >>  5) & 0x3) ); \
245    DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0])      ) & 0x7) ); \
246    DST[ACOMP] = CHAN_MAX
247
248 #include "swrast/s_spantemp.h"
249
250
251 /* 15-bit BGR (XXX implement dithering someday) */
252 #define NAME(PREFIX) PREFIX##_B5G5R5
253 #define RB_TYPE GLubyte
254 #define SPAN_VARS \
255    struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
256 #define INIT_PIXEL_PTR(P, X, Y) \
257    GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2)
258 #define INC_PIXEL_PTR(P) P += 1
259 #define STORE_PIXEL(DST, X, Y, VALUE) \
260    DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) )
261 #define FETCH_PIXEL(DST, SRC) \
262    DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \
263    DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >>  5) & 0x7) ); \
264    DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0])      ) & 0x7) ); \
265    DST[ACOMP] = CHAN_MAX
266
267 #include "swrast/s_spantemp.h"
268
269
270 /**********************************************************************/
271 /* Public API functions                                               */
272 /**********************************************************************/
273
274
275 const char *
276 glFBDevGetString( int str )
277 {
278    switch (str) {
279    case GLFBDEV_VENDOR:
280       return "Mesa Project";
281    case GLFBDEV_VERSION:
282       return "1.0.1";
283    default:
284       return NULL;
285    }
286 }
287
288
289 GLFBDevProc
290 glFBDevGetProcAddress( const char *procName )
291 {
292    struct name_address {
293       const char *name;
294       const GLFBDevProc func;
295    };
296    static const struct name_address functions[] = {
297       { "glFBDevGetString", (GLFBDevProc) glFBDevGetString },
298       { "glFBDevGetProcAddress", (GLFBDevProc) glFBDevGetProcAddress },
299       { "glFBDevCreateVisual", (GLFBDevProc) glFBDevCreateVisual },
300       { "glFBDevDestroyVisual", (GLFBDevProc) glFBDevDestroyVisual },
301       { "glFBDevGetVisualAttrib", (GLFBDevProc) glFBDevGetVisualAttrib },
302       { "glFBDevCreateBuffer", (GLFBDevProc) glFBDevCreateBuffer },
303       { "glFBDevDestroyBuffer", (GLFBDevProc) glFBDevDestroyBuffer },
304       { "glFBDevGetBufferAttrib", (GLFBDevProc) glFBDevGetBufferAttrib },
305       { "glFBDevGetCurrentDrawBuffer", (GLFBDevProc) glFBDevGetCurrentDrawBuffer },
306       { "glFBDevGetCurrentReadBuffer", (GLFBDevProc) glFBDevGetCurrentReadBuffer },
307       { "glFBDevSwapBuffers", (GLFBDevProc) glFBDevSwapBuffers },
308       { "glFBDevCreateContext", (GLFBDevProc) glFBDevCreateContext },
309       { "glFBDevDestroyContext", (GLFBDevProc) glFBDevDestroyContext },
310       { "glFBDevGetContextAttrib", (GLFBDevProc) glFBDevGetContextAttrib },
311       { "glFBDevGetCurrentContext", (GLFBDevProc) glFBDevGetCurrentContext },
312       { "glFBDevMakeCurrent", (GLFBDevProc) glFBDevMakeCurrent },
313       { NULL, NULL }
314    };
315    const struct name_address *entry;
316    for (entry = functions; entry->name; entry++) {
317       if (strcmp(entry->name, procName) == 0) {
318          return entry->func;
319       }
320    }
321    return _glapi_get_proc_address(procName);
322 }
323
324
325 GLFBDevVisualPtr
326 glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
327                      const struct fb_var_screeninfo *varInfo,
328                      const int *attribs )
329 {
330    GLFBDevVisualPtr vis;
331    const int *attrib;
332    GLboolean dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
333    GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
334    GLint depthBits = 0, stencilBits = 0;
335    GLint accumRedBits = 0, accumGreenBits = 0;
336    GLint accumBlueBits = 0, accumAlphaBits = 0;
337    GLint numSamples = 0;
338
339    ASSERT(fixInfo);
340    ASSERT(varInfo);
341
342    vis = CALLOC_STRUCT(GLFBDevVisualRec);
343    if (!vis)
344       return NULL;
345
346    vis->fix = *fixInfo;  /* struct assignment */
347    vis->var = *varInfo;  /* struct assignment */
348
349    for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) {
350       switch (*attrib) {
351       case GLFBDEV_DOUBLE_BUFFER:
352          dbFlag = GL_TRUE;
353          break;
354       case GLFBDEV_DEPTH_SIZE:
355          depthBits = attrib[1];
356          attrib++;
357          break;
358       case GLFBDEV_STENCIL_SIZE:
359          stencilBits = attrib[1];
360          attrib++;
361          break;
362       case GLFBDEV_ACCUM_SIZE:
363          accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits
364             = attrib[1];
365          attrib++;
366          break;
367       case GLFBDEV_LEVEL:
368          /* ignored for now */
369          break;
370       case GLFBDEV_MULTISAMPLE:
371          numSamples = attrib[1];
372          attrib++;
373          break;
374       case GLFBDEV_COLOR_INDEX:
375          /* Mesa no longer supports color-index rendering. */
376       default:
377          /* unexpected token */
378          free(vis);
379          return NULL;
380       }
381    }
382
383    redBits   = varInfo->red.length;
384    greenBits = varInfo->green.length;
385    blueBits  = varInfo->blue.length;
386    alphaBits = varInfo->transp.length;
387
388    if (fixInfo->visual == FB_VISUAL_TRUECOLOR ||
389        fixInfo->visual == FB_VISUAL_DIRECTCOLOR) {
390       if (varInfo->bits_per_pixel == 24
391           && varInfo->red.offset == 16
392           && varInfo->green.offset == 8
393           && varInfo->blue.offset == 0) {
394          vis->pixelFormat = PF_B8G8R8;
395       }
396       else if (varInfo->bits_per_pixel == 32
397                && varInfo->red.offset == 16
398                && varInfo->green.offset == 8
399                && varInfo->blue.offset == 0) {
400          vis->pixelFormat = PF_B8G8R8A8;
401       }
402       else if (varInfo->bits_per_pixel == 16
403                && varInfo->red.offset == 11
404                && varInfo->green.offset == 5
405                && varInfo->blue.offset == 0) {
406          vis->pixelFormat = PF_B5G6R5;
407       }
408       else if (varInfo->bits_per_pixel == 16
409                && varInfo->red.offset == 10
410                && varInfo->green.offset == 5
411                && varInfo->blue.offset == 0) {
412          vis->pixelFormat = PF_B5G5R5;
413       }
414       else {
415          _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
416          free(vis);
417          return NULL;
418       }
419    }
420
421    if (!_mesa_initialize_visual(&vis->glvisual, dbFlag, stereoFlag,
422                                 redBits, greenBits, blueBits, alphaBits,
423                                 depthBits, stencilBits,
424                                 accumRedBits, accumGreenBits,
425                                 accumBlueBits, accumAlphaBits,
426                                 numSamples)) {
427       /* something was invalid */
428       free(vis);
429       return NULL;
430    }
431
432    return vis;
433 }
434
435
436 void
437 glFBDevDestroyVisual( GLFBDevVisualPtr visual )
438 {
439    if (visual)
440       free(visual);
441 }
442
443
444 int
445 glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib)
446 {
447    /* XXX unfinished */
448    (void) visual;
449    (void) attrib;
450    return -1;
451 }
452
453
454 static void
455 delete_renderbuffer(struct gl_renderbuffer *rb)
456 {
457    struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
458    if (frb->mallocedBuffer) {
459       free(frb->Base.Data);
460    }
461    free(frb);
462 }
463
464
465 static GLboolean
466 renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
467                      GLenum internalFormat, GLuint width, GLuint height)
468 {
469    /* no-op: the renderbuffer storage is allocated just once when it's
470     * created.  Never resized or reallocated.
471     */
472    return GL_TRUE;
473 }
474
475
476 static struct GLFBDevRenderbufferRec *
477 new_glfbdev_renderbuffer(void *bufferStart, const GLFBDevVisualPtr visual)
478 {
479    struct GLFBDevRenderbufferRec *rb = CALLOC_STRUCT(GLFBDevRenderbufferRec);
480    if (rb) {
481       GLuint name = 0;
482       int pixelFormat = visual->pixelFormat;
483
484       _mesa_init_renderbuffer(&rb->Base, name);
485
486       rb->Base.Delete = delete_renderbuffer;
487       rb->Base.AllocStorage = renderbuffer_storage;
488
489       if (pixelFormat == PF_B8G8R8) {
490          rb->Base.GetRow = get_row_B8G8R8;
491          rb->Base.GetValues = get_values_B8G8R8;
492          rb->Base.PutRow = put_row_B8G8R8;
493          rb->Base.PutRowRGB = put_row_rgb_B8G8R8;
494          rb->Base.PutMonoRow = put_mono_row_B8G8R8;
495          rb->Base.PutValues = put_values_B8G8R8;
496          rb->Base.PutMonoValues = put_mono_values_B8G8R8;
497       }
498       else if (pixelFormat == PF_B8G8R8A8) {
499          rb->Base.GetRow = get_row_B8G8R8A8;
500          rb->Base.GetValues = get_values_B8G8R8A8;
501          rb->Base.PutRow = put_row_B8G8R8A8;
502          rb->Base.PutRowRGB = put_row_rgb_B8G8R8A8;
503          rb->Base.PutMonoRow = put_mono_row_B8G8R8A8;
504          rb->Base.PutValues = put_values_B8G8R8A8;
505          rb->Base.PutMonoValues = put_mono_values_B8G8R8A8;
506       }
507       else if (pixelFormat == PF_B5G6R5) {
508          rb->Base.GetRow = get_row_B5G6R5;
509          rb->Base.GetValues = get_values_B5G6R5;
510          rb->Base.PutRow = put_row_B5G6R5;
511          rb->Base.PutRowRGB = put_row_rgb_B5G6R5;
512          rb->Base.PutMonoRow = put_mono_row_B5G6R5;
513          rb->Base.PutValues = put_values_B5G6R5;
514          rb->Base.PutMonoValues = put_mono_values_B5G6R5;
515       }
516       else if (pixelFormat == PF_B5G5R5) {
517          rb->Base.GetRow = get_row_B5G5R5;
518          rb->Base.GetValues = get_values_B5G5R5;
519          rb->Base.PutRow = put_row_B5G5R5;
520          rb->Base.PutRowRGB = put_row_rgb_B5G5R5;
521          rb->Base.PutMonoRow = put_mono_row_B5G5R5;
522          rb->Base.PutValues = put_values_B5G5R5;
523          rb->Base.PutMonoValues = put_mono_values_B5G5R5;
524       }
525
526       rb->Base.InternalFormat = GL_RGBA;
527       rb->Base._BaseFormat = GL_RGBA;
528       rb->Base.DataType = GL_UNSIGNED_BYTE;
529       rb->Base.Data = bufferStart;
530
531       rb->rowStride = visual->var.xres_virtual * visual->var.bits_per_pixel / 8;
532       rb->bottom = (GLubyte *) bufferStart
533                  + (visual->var.yres - 1) * rb->rowStride;
534
535       rb->Base.Width = visual->var.xres;
536       rb->Base.Height = visual->var.yres;
537
538       /*
539       rb->Base.RedBits = visual->var.red.length;
540       rb->Base.GreenBits = visual->var.green.length;
541       rb->Base.BlueBits = visual->var.blue.length;
542       rb->Base.AlphaBits = visual->var.transp.length;
543       */
544
545       rb->Base.InternalFormat = pixelFormat;
546    }
547    return rb;
548 }
549
550 GLFBDevBufferPtr
551 glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
552                      const struct fb_var_screeninfo *varInfo,
553                      const GLFBDevVisualPtr visual,
554                      void *frontBuffer, void *backBuffer, size_t size )
555 {
556    struct GLFBDevRenderbufferRec *frontrb, *backrb;
557    GLFBDevBufferPtr buf;
558
559    ASSERT(visual);
560    ASSERT(frontBuffer);
561    ASSERT(size > 0);
562
563    /* this is to update the visual if there was a resize and the
564       buffer is created again */
565    visual->var = *varInfo;
566    visual->fix = *fixInfo;
567
568    if (visual->fix.visual != fixInfo->visual ||
569        visual->fix.type != fixInfo->type ||
570        visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
571        visual->var.grayscale != varInfo->grayscale ||
572        visual->var.red.offset != varInfo->red.offset ||
573        visual->var.green.offset != varInfo->green.offset ||
574        visual->var.blue.offset != varInfo->blue.offset ||
575        visual->var.transp.offset != varInfo->transp.offset) {
576       /* visual mismatch! */
577       return NULL;
578    }
579
580    buf = CALLOC_STRUCT(GLFBDevBufferRec);
581    if (!buf)
582       return NULL;
583
584    /* basic framebuffer setup */
585    _mesa_initialize_window_framebuffer(&buf->glframebuffer, &visual->glvisual);
586    /* add front renderbuffer */
587    frontrb = new_glfbdev_renderbuffer(frontBuffer, visual);
588    _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_FRONT_LEFT,
589                           &frontrb->Base);
590    /* add back renderbuffer */
591    if (visual->glvisual.doubleBufferMode) {
592       const int malloced = !backBuffer;
593       if (malloced) {
594          /* malloc a back buffer */
595          backBuffer = malloc(size);
596          if (!backBuffer) {
597             _mesa_free_framebuffer_data(&buf->glframebuffer);
598             free(buf);
599             return NULL;
600          }
601       }
602
603       backrb = new_glfbdev_renderbuffer(backBuffer, visual);
604       if (!backrb) {
605          /* out of mem */
606          return NULL;
607       }
608       backrb->mallocedBuffer = malloced;
609
610       _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_BACK_LEFT,
611                              &backrb->Base);
612    }
613    /* add software renderbuffers */
614    _mesa_add_soft_renderbuffers(&buf->glframebuffer,
615                                 GL_FALSE, /* color */
616                                 visual->glvisual.haveDepthBuffer,
617                                 visual->glvisual.haveStencilBuffer,
618                                 visual->glvisual.haveAccumBuffer,
619                                 GL_FALSE, /* alpha */
620                                 GL_FALSE /* aux bufs */);
621
622    buf->fix = *fixInfo;   /* struct assignment */
623    buf->var = *varInfo;   /* struct assignment */
624    buf->visual = visual;  /* ptr assignment */
625    buf->size = size;
626    buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
627
628    return buf;
629 }
630
631
632 void
633 glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
634 {
635    if (buffer) {
636       /* check if destroying the current buffer */
637       GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
638       GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
639       if (buffer == curDraw || buffer == curRead) {
640          glFBDevMakeCurrent( NULL, NULL, NULL);
641       }
642       {
643          struct gl_framebuffer *fb = &buffer->glframebuffer;
644          _mesa_reference_framebuffer(&fb, NULL);
645       }
646    }
647 }
648
649
650 int
651 glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib)
652 {
653    (void) buffer;
654    (void) attrib;
655    return -1;
656 }
657
658
659 GLFBDevBufferPtr
660 glFBDevGetCurrentDrawBuffer( void )
661 {
662    GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
663    if (fbdevctx)
664       return fbdevctx->drawBuffer;
665    else
666       return NULL;
667 }
668
669
670 GLFBDevBufferPtr
671 glFBDevGetCurrentReadBuffer( void )
672 {
673    GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
674    if (fbdevctx)
675       return fbdevctx->readBuffer;
676    else
677       return NULL;
678 }
679
680
681 void
682 glFBDevSwapBuffers( GLFBDevBufferPtr buffer )
683 {
684    GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
685    struct GLFBDevRenderbufferRec *frontrb = (struct GLFBDevRenderbufferRec *)
686       buffer->glframebuffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
687    struct GLFBDevRenderbufferRec *backrb = (struct GLFBDevRenderbufferRec *)
688       buffer->glframebuffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
689
690    if (!buffer || !buffer->visual->glvisual.doubleBufferMode)
691       return;
692
693    /* check if swapping currently bound buffer */
694    if (fbdevctx->drawBuffer == buffer) {
695       /* flush pending rendering */
696       _mesa_notifySwapBuffers(&fbdevctx->glcontext);
697    }
698
699    ASSERT(frontrb->Base.Data);
700    ASSERT(backrb->Base.Data);
701    memcpy(frontrb->Base.Data, backrb->Base.Data, buffer->size);
702 }
703
704
705 GLFBDevContextPtr
706 glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
707 {
708    GLFBDevContextPtr ctx;
709    struct gl_context *glctx;
710    struct dd_function_table functions;
711
712    ASSERT(visual);
713
714    ctx = CALLOC_STRUCT(GLFBDevContextRec);
715    if (!ctx)
716       return NULL;
717
718    /* build table of device driver functions */
719    _mesa_init_driver_functions(&functions);
720    functions.GetString = get_string;
721    functions.UpdateState = update_state;
722    functions.GetBufferSize = get_buffer_size;
723    functions.Viewport = viewport;
724
725    if (!_mesa_initialize_context(&ctx->glcontext, API_OPENGL, &visual->glvisual,
726                                  share ? &share->glcontext : NULL,
727                                  &functions, (void *) ctx)) {
728       free(ctx);
729       return NULL;
730    }
731
732    ctx->visual = visual;
733
734    /* Create module contexts */
735    glctx = (struct gl_context *) &ctx->glcontext;
736    _swrast_CreateContext( glctx );
737    _vbo_CreateContext( glctx );
738    _tnl_CreateContext( glctx );
739    _swsetup_CreateContext( glctx );
740    _swsetup_Wakeup( glctx );
741
742    /* use default TCL pipeline */
743    {
744       TNLcontext *tnl = TNL_CONTEXT(glctx);
745       tnl->Driver.RunPipeline = _tnl_run_pipeline;
746    }
747
748    _mesa_enable_sw_extensions(glctx);
749    _mesa_enable_1_3_extensions(glctx);
750    _mesa_enable_1_4_extensions(glctx);
751    _mesa_enable_1_5_extensions(glctx);
752    _mesa_enable_2_0_extensions(glctx);
753    _mesa_enable_2_1_extensions(glctx);
754
755    return ctx;
756 }
757
758
759 void
760 glFBDevDestroyContext( GLFBDevContextPtr context )
761 {
762    GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
763
764    if (context) {
765       struct gl_context *mesaCtx = &context->glcontext;
766
767       _swsetup_DestroyContext( mesaCtx );
768       _swrast_DestroyContext( mesaCtx );
769       _tnl_DestroyContext( mesaCtx );
770       _vbo_DestroyContext( mesaCtx );
771
772       if (fbdevctx == context) {
773          /* destroying current context */
774          _mesa_make_current(NULL, NULL, NULL);
775       }
776       _mesa_free_context_data(&context->glcontext);
777       free(context);
778    }
779 }
780
781
782 int
783 glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib)
784 {
785    (void) context;
786    (void) attrib;
787    return -1;
788 }
789
790
791 GLFBDevContextPtr
792 glFBDevGetCurrentContext( void )
793 {
794    GET_CURRENT_CONTEXT(ctx);
795    return (GLFBDevContextPtr) ctx;
796 }
797
798
799 int
800 glFBDevMakeCurrent( GLFBDevContextPtr context,
801                     GLFBDevBufferPtr drawBuffer,
802                     GLFBDevBufferPtr readBuffer )
803 {
804    if (context && drawBuffer && readBuffer) {
805       /* Make sure the context's visual and the buffers' visuals match.
806        * XXX we might do this by comparing specific fields like bits_per_pixel,
807        * visual, etc. in the future.
808        */
809       if (context->visual != drawBuffer->visual ||
810           context->visual != readBuffer->visual) {
811          return 0;
812       }
813       _mesa_make_current( &context->glcontext,
814                           &drawBuffer->glframebuffer,
815                           &readBuffer->glframebuffer );
816       context->drawBuffer = drawBuffer;
817       context->readBuffer = readBuffer;
818       context->curBuffer = drawBuffer;
819    }
820    else {
821       /* unbind */
822       _mesa_make_current( NULL, NULL, NULL );
823    }
824
825    return 1;
826 }
827
828 #endif /* USE_GLFBDEV_DRIVER */