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