Implemented support for software-based AUX color buffers.
[mesa.git] / src / mesa / drivers / fbdev / glfbdev.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 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
43 #ifdef USE_GLFBDEV_DRIVER
44
45 #include "glheader.h"
46 #include <linux/fb.h>
47 #include "GL/glfbdev.h"
48 #include "context.h"
49 #include "extensions.h"
50 #include "imports.h"
51 #include "texformat.h"
52 #include "teximage.h"
53 #include "texstore.h"
54 #include "array_cache/acache.h"
55 #include "swrast/swrast.h"
56 #include "swrast_setup/swrast_setup.h"
57 #include "tnl/tnl.h"
58 #include "tnl/t_context.h"
59 #include "tnl/t_pipeline.h"
60 #include "drivers/common/driverfuncs.h"
61
62
63 #define PF_B8G8R8 1
64 #define PF_B8G8R8A8 2
65 #define PF_B5G6R5 3
66 #define PF_B5G5R5 4
67 #define PF_CI8 5
68
69
70 /*
71 * Derived from Mesa's GLvisual class.
72 */
73 struct GLFBDevVisualRec {
74 GLvisual glvisual; /* base class */
75 struct fb_fix_screeninfo fix;
76 struct fb_var_screeninfo var;
77 int pixelFormat;
78 };
79
80 /*
81 * Derived from Mesa's GLframebuffer class.
82 */
83 struct GLFBDevBufferRec {
84 GLframebuffer glframebuffer; /* base class */
85 GLFBDevVisualPtr visual;
86 struct fb_fix_screeninfo fix;
87 struct fb_var_screeninfo var;
88 void *frontStart;
89 void *backStart;
90 size_t size;
91 GLuint bytesPerPixel;
92 GLuint rowStride; /* in bytes */
93 GLubyte *frontBottom; /* pointer to last row */
94 GLubyte *backBottom; /* pointer to last row */
95 GLubyte *curBottom; /* = frontBottom or backBottom */
96 GLboolean mallocBackBuffer;
97 };
98
99 /*
100 * Derived from Mesa's GLcontext class.
101 */
102 struct GLFBDevContextRec {
103 GLcontext glcontext; /* base class */
104 GLFBDevVisualPtr visual;
105 GLFBDevBufferPtr drawBuffer;
106 GLFBDevBufferPtr readBuffer;
107 GLFBDevBufferPtr curBuffer;
108 };
109
110
111
112 #define GLFBDEV_CONTEXT(CTX) ((GLFBDevContextPtr) (CTX))
113 #define GLFBDEV_BUFFER(BUF) ((GLFBDevBufferPtr) (BUF))
114
115
116 /**********************************************************************/
117 /* Internal device driver functions */
118 /**********************************************************************/
119
120
121 static const GLubyte *
122 get_string(GLcontext *ctx, GLenum pname)
123 {
124 (void) ctx;
125 switch (pname) {
126 case GL_RENDERER:
127 return (const GLubyte *) "Mesa glfbdev";
128 default:
129 return NULL;
130 }
131 }
132
133
134 static void
135 update_state( GLcontext *ctx, GLuint new_state )
136 {
137 /* not much to do here - pass it on */
138 _swrast_InvalidateState( ctx, new_state );
139 _swsetup_InvalidateState( ctx, new_state );
140 _ac_InvalidateState( ctx, new_state );
141 _tnl_InvalidateState( ctx, new_state );
142 }
143
144
145 static void
146 get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
147 {
148 const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer;
149 *width = fbdevbuffer->var.xres_virtual;
150 *height = fbdevbuffer->var.yres_virtual;
151 }
152
153
154 /* specifies the buffer for swrast span rendering/reading */
155 static void
156 set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
157 {
158 GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx);
159 GLFBDevBufferPtr fbdevbuf = GLFBDEV_BUFFER(buffer);
160 fbdevctx->curBuffer = fbdevbuf;
161 switch (bufferBit) {
162 case DD_FRONT_LEFT_BIT:
163 fbdevbuf->curBottom = fbdevbuf->frontBottom;
164 break;
165 case DD_BACK_LEFT_BIT:
166 fbdevbuf->curBottom = fbdevbuf->backBottom;
167 break;
168 default:
169 _mesa_problem(ctx, "bad bufferBit in set_buffer()");
170 }
171 }
172
173
174 /*
175 * Generate code for span functions.
176 */
177
178 /* 24-bit BGR */
179 #define NAME(PREFIX) PREFIX##_B8G8R8
180 #define SPAN_VARS \
181 const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
182 const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
183 #define INIT_PIXEL_PTR(P, X, Y) \
184 GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 3
185 #define INC_PIXEL_PTR(P) P += 3
186 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
187 P[0] = B; P[1] = G; P[2] = R
188 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
189 P[0] = B; P[1] = G; P[2] = R
190 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
191 R = P[2]; G = P[1]; B = P[0]; A = CHAN_MAX
192
193 #include "swrast/s_spantemp.h"
194
195
196 /* 32-bit BGRA */
197 #define NAME(PREFIX) PREFIX##_B8G8R8A8
198 #define SPAN_VARS \
199 const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
200 const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
201 #define INIT_PIXEL_PTR(P, X, Y) \
202 GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 4
203 #define INC_PIXEL_PTR(P) P += 4
204 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
205 P[0] = B; P[1] = G; P[2] = R; P[3] = 255
206 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
207 P[0] = B; P[1] = G; P[2] = R; P[3] = A
208 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
209 R = P[2]; G = P[1]; B = P[0]; A = P[3]
210
211 #include "swrast/s_spantemp.h"
212
213
214 /* 16-bit BGR (XXX implement dithering someday) */
215 #define NAME(PREFIX) PREFIX##_B5G6R5
216 #define SPAN_VARS \
217 const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
218 const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
219 #define INIT_PIXEL_PTR(P, X, Y) \
220 GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
221 #define INC_PIXEL_PTR(P) P += 1
222 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
223 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
224 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
225 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
226 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
227 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
228 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
229 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
230 A = CHAN_MAX
231
232 #include "swrast/s_spantemp.h"
233
234
235 /* 15-bit BGR (XXX implement dithering someday) */
236 #define NAME(PREFIX) PREFIX##_B5G5R5
237 #define SPAN_VARS \
238 const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
239 const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
240 #define INIT_PIXEL_PTR(P, X, Y) \
241 GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
242 #define INC_PIXEL_PTR(P) P += 1
243 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
244 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
245 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
246 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
247 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
248 R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
249 G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
250 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
251 A = CHAN_MAX
252
253 #include "swrast/s_spantemp.h"
254
255
256 /* 8-bit color index */
257 #define NAME(PREFIX) PREFIX##_CI8
258 #define SPAN_VARS \
259 const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
260 const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
261 #define INIT_PIXEL_PTR(P, X, Y) \
262 GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X)
263 #define INC_PIXEL_PTR(P) P += 1
264 #define STORE_CI_PIXEL(P, CI) \
265 P[0] = CI
266 #define FETCH_CI_PIXEL(CI, P) \
267 CI = P[0]
268
269 #include "swrast/s_spantemp.h"
270
271 /**********************************************************************/
272 /* Public API functions */
273 /**********************************************************************/
274
275
276 const char *
277 glFBDevGetString( int str )
278 {
279 switch (str) {
280 case GLFBDEV_VENDOR:
281 return "Mesa Project";
282 case GLFBDEV_VERSION:
283 return "1.0.0";
284 default:
285 return NULL;
286 }
287 }
288
289
290 const void *
291 glFBDevGetProcAddress( const char *procName )
292 {
293 struct name_address {
294 const char *name;
295 const void *func;
296 };
297 static const struct name_address functions[] = {
298 { "glFBDevGetString", (void *) glFBDevGetString },
299 { "glFBDevGetProcAddress", (void *) glFBDevGetProcAddress },
300 { "glFBDevCreateVisual", (void *) glFBDevCreateVisual },
301 { "glFBDevDestroyVisual", (void *) glFBDevDestroyVisual },
302 { "glFBDevGetVisualAttrib", (void *) glFBDevGetVisualAttrib },
303 { "glFBDevCreateBuffer", (void *) glFBDevCreateBuffer },
304 { "glFBDevDestroyBuffer", (void *) glFBDevDestroyBuffer },
305 { "glFBDevGetBufferAttrib", (void *) glFBDevGetBufferAttrib },
306 { "glFBDevGetCurrentDrawBuffer", (void *) glFBDevGetCurrentDrawBuffer },
307 { "glFBDevGetCurrentReadBuffer", (void *) glFBDevGetCurrentReadBuffer },
308 { "glFBDevSwapBuffers", (void *) glFBDevSwapBuffers },
309 { "glFBDevCreateContext", (void *) glFBDevCreateContext },
310 { "glFBDevDestroyContext", (void *) glFBDevDestroyContext },
311 { "glFBDevGetContextAttrib", (void *) glFBDevGetContextAttrib },
312 { "glFBDevGetCurrentContext", (void *) glFBDevGetCurrentContext },
313 { "glFBDevMakeCurrent", (void *) glFBDevMakeCurrent },
314 { NULL, NULL }
315 };
316 const struct name_address *entry;
317 for (entry = functions; entry->name; entry++) {
318 if (_mesa_strcmp(entry->name, procName) == 0) {
319 return entry->func;
320 }
321 }
322 return _glapi_get_proc_address(procName);
323 }
324
325
326 GLFBDevVisualPtr
327 glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
328 const struct fb_var_screeninfo *varInfo,
329 const int *attribs )
330 {
331 GLFBDevVisualPtr vis;
332 const int *attrib;
333 GLboolean rgbFlag = GL_TRUE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
334 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
335 GLint indexBits = 0, depthBits = 0, stencilBits = 0;
336 GLint accumRedBits = 0, accumGreenBits = 0;
337 GLint accumBlueBits = 0, accumAlphaBits = 0;
338 GLint numSamples = 0;
339
340 ASSERT(fixInfo);
341 ASSERT(varInfo);
342
343 vis = CALLOC_STRUCT(GLFBDevVisualRec);
344 if (!vis)
345 return NULL;
346
347 vis->fix = *fixInfo; /* struct assignment */
348 vis->var = *varInfo; /* struct assignment */
349
350 for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) {
351 switch (*attrib) {
352 case GLFBDEV_DOUBLE_BUFFER:
353 dbFlag = GL_TRUE;
354 break;
355 case GLFBDEV_COLOR_INDEX:
356 rgbFlag = GL_FALSE;
357 break;
358 case GLFBDEV_DEPTH_SIZE:
359 depthBits = attrib[1];
360 attrib++;
361 break;
362 case GLFBDEV_STENCIL_SIZE:
363 stencilBits = attrib[1];
364 attrib++;
365 break;
366 case GLFBDEV_ACCUM_SIZE:
367 accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits
368 = attrib[1];
369 attrib++;
370 break;
371 case GLFBDEV_LEVEL:
372 /* ignored for now */
373 break;
374 default:
375 /* unexpected token */
376 _mesa_free(vis);
377 return NULL;
378 }
379 }
380
381 if (rgbFlag) {
382 redBits = varInfo->red.length;
383 greenBits = varInfo->green.length;
384 blueBits = varInfo->blue.length;
385 alphaBits = varInfo->transp.length;
386
387 if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
388 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
389 && varInfo->bits_per_pixel == 24
390 && varInfo->red.offset == 16
391 && varInfo->green.offset == 8
392 && varInfo->blue.offset == 0) {
393 vis->pixelFormat = PF_B8G8R8;
394 }
395 else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
396 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
397 && varInfo->bits_per_pixel == 32
398 && varInfo->red.offset == 16
399 && varInfo->green.offset == 8
400 && varInfo->blue.offset == 0
401 && varInfo->transp.offset == 24) {
402 vis->pixelFormat = PF_B8G8R8A8;
403 }
404 else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
405 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
406 && varInfo->bits_per_pixel == 16
407 && varInfo->red.offset == 11
408 && varInfo->green.offset == 5
409 && varInfo->blue.offset == 0) {
410 vis->pixelFormat = PF_B5G6R5;
411 }
412 else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
413 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
414 && varInfo->bits_per_pixel == 16
415 && varInfo->red.offset == 10
416 && varInfo->green.offset == 5
417 && varInfo->blue.offset == 0) {
418 vis->pixelFormat = PF_B5G5R5;
419 }
420 else {
421 _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
422 /*
423 printf("fixInfo->visual = 0x%x\n", fixInfo->visual);
424 printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel);
425 printf("varInfo->red.offset = %d\n", varInfo->red.offset);
426 printf("varInfo->green.offset = %d\n", varInfo->green.offset);
427 printf("varInfo->blue.offset = %d\n", varInfo->blue.offset);
428 */
429 _mesa_free(vis);
430 return NULL;
431 }
432 }
433 else {
434 indexBits = varInfo->bits_per_pixel;
435 if ((fixInfo->visual == FB_VISUAL_PSEUDOCOLOR ||
436 fixInfo->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
437 && varInfo->bits_per_pixel == 8) {
438 vis->pixelFormat = PF_CI8;
439 }
440 else {
441 _mesa_problem(NULL, "Unsupported fbdev CI visual/bitdepth!\n");
442 _mesa_free(vis);
443 return NULL;
444 }
445 }
446
447 if (!_mesa_initialize_visual(&vis->glvisual, rgbFlag, dbFlag, stereoFlag,
448 redBits, greenBits, blueBits, alphaBits,
449 indexBits, depthBits, stencilBits,
450 accumRedBits, accumGreenBits,
451 accumBlueBits, accumAlphaBits,
452 numSamples)) {
453 /* something was invalid */
454 _mesa_free(vis);
455 return NULL;
456 }
457
458 return vis;
459 }
460
461
462 void
463 glFBDevDestroyVisual( GLFBDevVisualPtr visual )
464 {
465 if (visual)
466 _mesa_free(visual);
467 }
468
469
470 int
471 glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib)
472 {
473 (void) visual;
474 (void) attrib;
475 return -1;
476 }
477
478
479
480 GLFBDevBufferPtr
481 glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
482 const struct fb_var_screeninfo *varInfo,
483 const GLFBDevVisualPtr visual,
484 void *frontBuffer, void *backBuffer, size_t size )
485 {
486 GLFBDevBufferPtr buf;
487
488 ASSERT(visual);
489 ASSERT(frontBuffer);
490 ASSERT(size > 0);
491
492 if (visual->fix.visual != fixInfo->visual ||
493 visual->fix.type != fixInfo->type ||
494 visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
495 visual->var.grayscale != varInfo->grayscale ||
496 visual->var.red.offset != varInfo->red.offset ||
497 visual->var.green.offset != varInfo->green.offset ||
498 visual->var.blue.offset != varInfo->blue.offset ||
499 visual->var.transp.offset != varInfo->transp.offset) {
500 /* visual mismatch! */
501 return NULL;
502 }
503
504 buf = CALLOC_STRUCT(GLFBDevBufferRec);
505 if (!buf)
506 return NULL;
507
508 _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual,
509 visual->glvisual.haveDepthBuffer,
510 visual->glvisual.haveStencilBuffer,
511 visual->glvisual.haveAccumBuffer,
512 GL_FALSE);
513
514 buf->fix = *fixInfo; /* struct assignment */
515 buf->var = *varInfo; /* struct assignment */
516 buf->visual = visual; /* ptr assignment */
517 buf->frontStart = frontBuffer;
518 buf->size = size;
519 buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
520 buf->rowStride = visual->var.xres_virtual * buf->bytesPerPixel;
521 buf->frontBottom = (GLubyte *) buf->frontStart
522 + (visual->var.yres_virtual - 1) * buf->rowStride;
523
524 if (visual->glvisual.doubleBufferMode) {
525 if (backBuffer) {
526 buf->backStart = backBuffer;
527 buf->mallocBackBuffer = GL_FALSE;
528 }
529 else {
530 buf->backStart = _mesa_malloc(size);
531 if (!buf->backStart) {
532 _mesa_free_framebuffer_data(&buf->glframebuffer);
533 _mesa_free(buf);
534 return NULL;
535 }
536 buf->mallocBackBuffer = GL_TRUE;
537 }
538 buf->backBottom = (GLubyte *) buf->backStart
539 + (visual->var.yres_virtual - 1) * buf->rowStride;
540 buf->curBottom = buf->backBottom;
541 }
542 else {
543 buf->backStart = NULL;
544 buf->mallocBackBuffer = GL_FALSE;
545 buf->backBottom = NULL;
546 buf->curBottom = buf->frontBottom;
547 }
548
549 return buf;
550 }
551
552
553 void
554 glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
555 {
556 if (buffer) {
557 /* check if destroying the current buffer */
558 GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
559 GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
560 if (buffer == curDraw || buffer == curRead) {
561 glFBDevMakeCurrent( NULL, NULL, NULL);
562 }
563 if (buffer->mallocBackBuffer) {
564 _mesa_free(buffer->backStart);
565 }
566 /* free the software depth, stencil, accum buffers */
567 _mesa_free_framebuffer_data(&buffer->glframebuffer);
568 _mesa_free(buffer);
569 }
570 }
571
572
573 int
574 glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib)
575 {
576 (void) buffer;
577 (void) attrib;
578 return -1;
579 }
580
581
582 GLFBDevBufferPtr
583 glFBDevGetCurrentDrawBuffer( void )
584 {
585 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
586 if (fbdevctx)
587 return fbdevctx->drawBuffer;
588 else
589 return NULL;
590 }
591
592
593 GLFBDevBufferPtr
594 glFBDevGetCurrentReadBuffer( void )
595 {
596 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
597 if (fbdevctx)
598 return fbdevctx->readBuffer;
599 else
600 return NULL;
601 }
602
603
604 void
605 glFBDevSwapBuffers( GLFBDevBufferPtr buffer )
606 {
607 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
608
609 if (!buffer || !buffer->visual->glvisual.doubleBufferMode)
610 return;
611
612 /* check if swapping currently bound buffer */
613 if (fbdevctx->drawBuffer == buffer) {
614 /* flush pending rendering */
615 _mesa_notifySwapBuffers(&fbdevctx->glcontext);
616 }
617
618 ASSERT(buffer->frontStart);
619 ASSERT(buffer->backStart);
620 _mesa_memcpy(buffer->frontStart, buffer->backStart, buffer->size);
621 }
622
623
624 GLFBDevContextPtr
625 glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
626 {
627 GLFBDevContextPtr ctx;
628 GLcontext *glctx;
629 struct dd_function_table functions;
630
631 ASSERT(visual);
632
633 ctx = CALLOC_STRUCT(GLFBDevContextRec);
634 if (!ctx)
635 return NULL;
636
637 /* build table of device driver functions */
638 _mesa_init_driver_functions(&functions);
639 functions.GetString = get_string;
640 functions.UpdateState = update_state;
641 functions.GetBufferSize = get_buffer_size;
642
643 if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual,
644 share ? &share->glcontext : NULL,
645 &functions, (void *) ctx)) {
646 _mesa_free(ctx);
647 return NULL;
648 }
649
650 ctx->visual = visual;
651
652 /* Create module contexts */
653 glctx = (GLcontext *) &ctx->glcontext;
654 _swrast_CreateContext( glctx );
655 _ac_CreateContext( glctx );
656 _tnl_CreateContext( glctx );
657 _swsetup_CreateContext( glctx );
658 _swsetup_Wakeup( glctx );
659
660 /* swrast init */
661 {
662 struct swrast_device_driver *swdd;
663 swdd = _swrast_GetDeviceDriverReference( glctx );
664 swdd->SetBuffer = set_buffer;
665 if (visual->pixelFormat == PF_B8G8R8) {
666 swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
667 swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
668 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
669 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
670 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
671 swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
672 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
673 }
674 else if (visual->pixelFormat == PF_B8G8R8A8) {
675 swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
676 swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
677 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
678 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
679 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
680 swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
681 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
682 }
683 else if (visual->pixelFormat == PF_B5G6R5) {
684 swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
685 swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
686 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
687 swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
688 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
689 swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
690 swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
691 }
692 else if (visual->pixelFormat == PF_B5G5R5) {
693 swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
694 swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
695 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
696 swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
697 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
698 swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
699 swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
700 }
701 else if (visual->pixelFormat == PF_CI8) {
702 swdd->WriteCI32Span = write_index32_span_CI8;
703 swdd->WriteCI8Span = write_index8_span_CI8;
704 swdd->WriteMonoCISpan = write_monoindex_span_CI8;
705 swdd->WriteCI32Pixels = write_index_pixels_CI8;
706 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
707 swdd->ReadCI32Span = read_index_span_CI8;
708 swdd->ReadCI32Pixels = read_index_pixels_CI8;
709 }
710 else {
711 _mesa_printf("bad pixelformat: %d\n", visual->pixelFormat);
712 }
713 }
714
715 /* use default TCL pipeline */
716 {
717 TNLcontext *tnl = TNL_CONTEXT(glctx);
718 tnl->Driver.RunPipeline = _tnl_run_pipeline;
719 }
720
721 _mesa_enable_sw_extensions(glctx);
722
723 return ctx;
724 }
725
726
727 void
728 glFBDevDestroyContext( GLFBDevContextPtr context )
729 {
730 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
731
732 if (context) {
733 if (fbdevctx == context) {
734 /* destroying current context */
735 _mesa_make_current2(NULL, NULL, NULL);
736 _mesa_notifyDestroy(&context->glcontext);
737 }
738 _mesa_free_context_data(&context->glcontext);
739 _mesa_free(context);
740 }
741 }
742
743
744 int
745 glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib)
746 {
747 (void) context;
748 (void) attrib;
749 return -1;
750 }
751
752
753 GLFBDevContextPtr
754 glFBDevGetCurrentContext( void )
755 {
756 GET_CURRENT_CONTEXT(ctx);
757 return (GLFBDevContextPtr) ctx;
758 }
759
760
761 int
762 glFBDevMakeCurrent( GLFBDevContextPtr context,
763 GLFBDevBufferPtr drawBuffer,
764 GLFBDevBufferPtr readBuffer )
765 {
766 if (context && drawBuffer && readBuffer) {
767 /* Make sure the context's visual and the buffers' visuals match.
768 * XXX we might do this by comparing specific fields like bits_per_pixel,
769 * visual, etc. in the future.
770 */
771 if (context->visual != drawBuffer->visual ||
772 context->visual != readBuffer->visual) {
773 return 0;
774 }
775 _mesa_make_current2( &context->glcontext,
776 &drawBuffer->glframebuffer,
777 &readBuffer->glframebuffer );
778 context->drawBuffer = drawBuffer;
779 context->readBuffer = readBuffer;
780 context->curBuffer = drawBuffer;
781 }
782 else {
783 /* unbind */
784 _mesa_make_current2( NULL, NULL, NULL );
785 }
786
787 return 1;
788 }
789
790 #endif /* USE_GLFBDEV_DRIVER */
791