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