renderbuffer fixes (Sean D'Epagnier)
[mesa.git] / src / mesa / drivers / fbdev / glfbdev.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.1
4 *
5 * Copyright (C) 1999-2006 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 "glheader.h"
45 #include <linux/fb.h>
46 #include "GL/glfbdev.h"
47 #include "buffers.h"
48 #include "context.h"
49 #include "extensions.h"
50 #include "fbobject.h"
51 #include "framebuffer.h"
52 #include "imports.h"
53 #include "renderbuffer.h"
54 #include "texformat.h"
55 #include "teximage.h"
56 #include "texstore.h"
57 #include "array_cache/acache.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 #define PF_B8G8R8 1
67 #define PF_B8G8R8A8 2
68 #define PF_B5G6R5 3
69 #define PF_B5G5R5 4
70 #define PF_CI8 5
71
72
73 /*
74 * Derived from Mesa's GLvisual class.
75 */
76 struct GLFBDevVisualRec {
77 GLvisual glvisual; /* base class */
78 struct fb_fix_screeninfo fix;
79 struct fb_var_screeninfo var;
80 int pixelFormat;
81 };
82
83 /*
84 * Derived from Mesa's GLframebuffer class.
85 */
86 struct GLFBDevBufferRec {
87 GLframebuffer glframebuffer; /* base class */
88 GLFBDevVisualPtr visual;
89 struct fb_fix_screeninfo fix;
90 struct fb_var_screeninfo var;
91 size_t size; /* color buffer size in bytes */
92 GLuint bytesPerPixel;
93 };
94
95 /*
96 * Derived from Mesa's GLcontext class.
97 */
98 struct GLFBDevContextRec {
99 GLcontext glcontext; /* base class */
100 GLFBDevVisualPtr visual;
101 GLFBDevBufferPtr drawBuffer;
102 GLFBDevBufferPtr readBuffer;
103 GLFBDevBufferPtr curBuffer;
104 };
105
106 /*
107 * Derived from Mesa's gl_renderbuffer class.
108 */
109 struct GLFBDevRenderbufferRec {
110 struct gl_renderbuffer Base;
111 GLubyte *bottom; /* pointer to last row */
112 GLuint rowStride; /* in bytes */
113 GLboolean mallocedBuffer;
114 };
115
116
117
118 #define GLFBDEV_CONTEXT(CTX) ((GLFBDevContextPtr) (CTX))
119 #define GLFBDEV_BUFFER(BUF) ((GLFBDevBufferPtr) (BUF))
120
121
122 /**********************************************************************/
123 /* Internal device driver functions */
124 /**********************************************************************/
125
126
127 static const GLubyte *
128 get_string(GLcontext *ctx, GLenum pname)
129 {
130 (void) ctx;
131 switch (pname) {
132 case GL_RENDERER:
133 return (const GLubyte *) "Mesa glfbdev";
134 default:
135 return NULL;
136 }
137 }
138
139
140 static void
141 update_state( GLcontext *ctx, GLuint new_state )
142 {
143 /* not much to do here - pass it on */
144 _swrast_InvalidateState( ctx, new_state );
145 _swsetup_InvalidateState( ctx, new_state );
146 _ac_InvalidateState( ctx, new_state );
147 _tnl_InvalidateState( ctx, new_state );
148 }
149
150
151 static void
152 get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
153 {
154 const GLFBDevBufferPtr fbdevbuffer = GLFBDEV_BUFFER(buffer);
155 *width = fbdevbuffer->var.xres_virtual;
156 *height = fbdevbuffer->var.yres_virtual;
157 }
158
159
160 static void
161 viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
162 {
163 /* poll for window size change and realloc software Z/stencil/etc if needed */
164 _mesa_ResizeBuffersMESA();
165 }
166
167
168 /*
169 * Generate code for span functions.
170 */
171
172 /* 24-bit BGR */
173 #define NAME(PREFIX) PREFIX##_B8G8R8
174 #define RB_TYPE GLubyte
175 #define SPAN_VARS \
176 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
177 #define INIT_PIXEL_PTR(P, X, Y) \
178 GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 3
179 #define INC_PIXEL_PTR(P) P += 3
180 #define STORE_PIXEL(DST, X, Y, VALUE) \
181 DST[0] = VALUE[BCOMP]; \
182 DST[1] = VALUE[GCOMP]; \
183 DST[2] = VALUE[RCOMP]
184 #define FETCH_PIXEL(DST, SRC) \
185 DST[RCOMP] = SRC[2]; \
186 DST[GCOMP] = SRC[1]; \
187 DST[BCOMP] = SRC[0]; \
188 DST[ACOMP] = CHAN_MAX
189
190 #include "swrast/s_spantemp.h"
191
192
193 /* 32-bit BGRA */
194 #define NAME(PREFIX) PREFIX##_B8G8R8A8
195 #define RB_TYPE GLubyte
196 #define SPAN_VARS \
197 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
198 #define INIT_PIXEL_PTR(P, X, Y) \
199 GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X) * 4
200 #define INC_PIXEL_PTR(P) P += 4
201 #define STORE_PIXEL(DST, X, Y, VALUE) \
202 DST[0] = VALUE[BCOMP]; \
203 DST[1] = VALUE[GCOMP]; \
204 DST[2] = VALUE[RCOMP]; \
205 DST[3] = VALUE[ACOMP]
206 #define FETCH_PIXEL(DST, SRC) \
207 DST[RCOMP] = SRC[2]; \
208 DST[GCOMP] = SRC[1]; \
209 DST[BCOMP] = SRC[0]; \
210 DST[ACOMP] = SRC[3]
211
212 #include "swrast/s_spantemp.h"
213
214
215 /* 16-bit BGR (XXX implement dithering someday) */
216 #define NAME(PREFIX) PREFIX##_B5G6R5
217 #define RB_TYPE GLubyte
218 #define SPAN_VARS \
219 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
220 #define INIT_PIXEL_PTR(P, X, Y) \
221 GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2)
222 #define INC_PIXEL_PTR(P) P += 1
223 #define STORE_PIXEL(DST, X, Y, VALUE) \
224 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
225 #define FETCH_PIXEL(DST, SRC) \
226 DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \
227 DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \
228 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
229 DST[ACOMP] = CHAN_MAX
230
231 #include "swrast/s_spantemp.h"
232
233
234 /* 15-bit BGR (XXX implement dithering someday) */
235 #define NAME(PREFIX) PREFIX##_B5G5R5
236 #define RB_TYPE GLubyte
237 #define SPAN_VARS \
238 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
239 #define INIT_PIXEL_PTR(P, X, Y) \
240 GLushort *P = (GLushort *) (frb->bottom - (Y) * frb->rowStride + (X) * 2)
241 #define INC_PIXEL_PTR(P) P += 1
242 #define STORE_PIXEL(DST, X, Y, VALUE) \
243 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) )
244 #define FETCH_PIXEL(DST, SRC) \
245 DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \
246 DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \
247 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
248 DST[ACOMP] = CHAN_MAX
249
250 #include "swrast/s_spantemp.h"
251
252
253 /* 8-bit color index */
254 #define NAME(PREFIX) PREFIX##_CI8
255 #define CI_MODE
256 #define RB_TYPE GLubyte
257 #define SPAN_VARS \
258 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
259 #define INIT_PIXEL_PTR(P, X, Y) \
260 GLubyte *P = frb->bottom - (Y) * frb->rowStride + (X)
261 #define INC_PIXEL_PTR(P) P += 1
262 #define STORE_PIXEL(DST, X, Y, VALUE) \
263 *DST = VALUE[0]
264 #define FETCH_PIXEL(DST, SRC) \
265 DST = SRC[0]
266
267 #include "swrast/s_spantemp.h"
268
269
270
271
272 /**********************************************************************/
273 /* Public API functions */
274 /**********************************************************************/
275
276
277 const char *
278 glFBDevGetString( int str )
279 {
280 switch (str) {
281 case GLFBDEV_VENDOR:
282 return "Mesa Project";
283 case GLFBDEV_VERSION:
284 return "1.0.0";
285 default:
286 return NULL;
287 }
288 }
289
290
291 GLFBDevProc
292 glFBDevGetProcAddress( const char *procName )
293 {
294 struct name_address {
295 const char *name;
296 const GLFBDevProc func;
297 };
298 static const struct name_address functions[] = {
299 { "glFBDevGetString", (GLFBDevProc) glFBDevGetString },
300 { "glFBDevGetProcAddress", (GLFBDevProc) glFBDevGetProcAddress },
301 { "glFBDevCreateVisual", (GLFBDevProc) glFBDevCreateVisual },
302 { "glFBDevDestroyVisual", (GLFBDevProc) glFBDevDestroyVisual },
303 { "glFBDevGetVisualAttrib", (GLFBDevProc) glFBDevGetVisualAttrib },
304 { "glFBDevCreateBuffer", (GLFBDevProc) glFBDevCreateBuffer },
305 { "glFBDevDestroyBuffer", (GLFBDevProc) glFBDevDestroyBuffer },
306 { "glFBDevGetBufferAttrib", (GLFBDevProc) glFBDevGetBufferAttrib },
307 { "glFBDevGetCurrentDrawBuffer", (GLFBDevProc) glFBDevGetCurrentDrawBuffer },
308 { "glFBDevGetCurrentReadBuffer", (GLFBDevProc) glFBDevGetCurrentReadBuffer },
309 { "glFBDevSwapBuffers", (GLFBDevProc) glFBDevSwapBuffers },
310 { "glFBDevCreateContext", (GLFBDevProc) glFBDevCreateContext },
311 { "glFBDevDestroyContext", (GLFBDevProc) glFBDevDestroyContext },
312 { "glFBDevGetContextAttrib", (GLFBDevProc) glFBDevGetContextAttrib },
313 { "glFBDevGetCurrentContext", (GLFBDevProc) glFBDevGetCurrentContext },
314 { "glFBDevMakeCurrent", (GLFBDevProc) glFBDevMakeCurrent },
315 { NULL, NULL }
316 };
317 const struct name_address *entry;
318 for (entry = functions; entry->name; entry++) {
319 if (_mesa_strcmp(entry->name, procName) == 0) {
320 return entry->func;
321 }
322 }
323 return _glapi_get_proc_address(procName);
324 }
325
326
327 GLFBDevVisualPtr
328 glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
329 const struct fb_var_screeninfo *varInfo,
330 const int *attribs )
331 {
332 GLFBDevVisualPtr vis;
333 const int *attrib;
334 GLboolean rgbFlag = GL_TRUE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
335 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
336 GLint indexBits = 0, depthBits = 0, stencilBits = 0;
337 GLint accumRedBits = 0, accumGreenBits = 0;
338 GLint accumBlueBits = 0, accumAlphaBits = 0;
339 GLint numSamples = 0;
340
341 ASSERT(fixInfo);
342 ASSERT(varInfo);
343
344 vis = CALLOC_STRUCT(GLFBDevVisualRec);
345 if (!vis)
346 return NULL;
347
348 vis->fix = *fixInfo; /* struct assignment */
349 vis->var = *varInfo; /* struct assignment */
350
351 for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) {
352 switch (*attrib) {
353 case GLFBDEV_DOUBLE_BUFFER:
354 dbFlag = GL_TRUE;
355 break;
356 case GLFBDEV_COLOR_INDEX:
357 rgbFlag = GL_FALSE;
358 break;
359 case GLFBDEV_DEPTH_SIZE:
360 depthBits = attrib[1];
361 attrib++;
362 break;
363 case GLFBDEV_STENCIL_SIZE:
364 stencilBits = attrib[1];
365 attrib++;
366 break;
367 case GLFBDEV_ACCUM_SIZE:
368 accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits
369 = attrib[1];
370 attrib++;
371 break;
372 case GLFBDEV_LEVEL:
373 /* ignored for now */
374 break;
375 default:
376 /* unexpected token */
377 _mesa_free(vis);
378 return NULL;
379 }
380 }
381
382 if (rgbFlag) {
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 && 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 ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
397 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
398 && varInfo->bits_per_pixel == 32
399 && varInfo->red.offset == 16
400 && varInfo->green.offset == 8
401 && varInfo->blue.offset == 0
402 && varInfo->transp.offset == 24) {
403 vis->pixelFormat = PF_B8G8R8A8;
404 }
405 else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
406 fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
407 && varInfo->bits_per_pixel == 16
408 && varInfo->red.offset == 11
409 && varInfo->green.offset == 5
410 && varInfo->blue.offset == 0) {
411 vis->pixelFormat = PF_B5G6R5;
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 == 10
417 && varInfo->green.offset == 5
418 && varInfo->blue.offset == 0) {
419 vis->pixelFormat = PF_B5G5R5;
420 }
421 else {
422 _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
423 /*
424 printf("fixInfo->visual = 0x%x\n", fixInfo->visual);
425 printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel);
426 printf("varInfo->red.offset = %d\n", varInfo->red.offset);
427 printf("varInfo->green.offset = %d\n", varInfo->green.offset);
428 printf("varInfo->blue.offset = %d\n", varInfo->blue.offset);
429 */
430 _mesa_free(vis);
431 return NULL;
432 }
433 }
434 else {
435 indexBits = varInfo->bits_per_pixel;
436 if ((fixInfo->visual == FB_VISUAL_PSEUDOCOLOR ||
437 fixInfo->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
438 && varInfo->bits_per_pixel == 8) {
439 vis->pixelFormat = PF_CI8;
440 }
441 else {
442 _mesa_problem(NULL, "Unsupported fbdev CI visual/bitdepth!\n");
443 _mesa_free(vis);
444 return NULL;
445 }
446 }
447
448 if (!_mesa_initialize_visual(&vis->glvisual, rgbFlag, dbFlag, stereoFlag,
449 redBits, greenBits, blueBits, alphaBits,
450 indexBits, depthBits, stencilBits,
451 accumRedBits, accumGreenBits,
452 accumBlueBits, accumAlphaBits,
453 numSamples)) {
454 /* something was invalid */
455 _mesa_free(vis);
456 return NULL;
457 }
458
459 return vis;
460 }
461
462
463 void
464 glFBDevDestroyVisual( GLFBDevVisualPtr visual )
465 {
466 if (visual)
467 _mesa_free(visual);
468 }
469
470
471 int
472 glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib)
473 {
474 /* XXX unfinished */
475 (void) visual;
476 (void) attrib;
477 return -1;
478 }
479
480
481 static void
482 delete_renderbuffer(struct gl_renderbuffer *rb)
483 {
484 struct GLFBDevRenderbufferRec *frb = (struct GLFBDevRenderbufferRec *) rb;
485 if (frb->mallocedBuffer) {
486 _mesa_free(frb->Base.Data);
487 }
488 _mesa_free(frb);
489 }
490
491
492 static GLboolean
493 renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
494 GLenum internalFormat, GLuint width, GLuint height)
495 {
496 /* no-op: the renderbuffer storage is allocated just once when it's
497 * created. Never resized or reallocated.
498 */
499 return GL_TRUE;
500 }
501
502
503 static struct GLFBDevRenderbufferRec *
504 new_glfbdev_renderbuffer(void *bufferStart, const GLFBDevVisualPtr visual)
505 {
506 struct GLFBDevRenderbufferRec *rb = CALLOC_STRUCT(GLFBDevRenderbufferRec);
507 if (rb) {
508 GLuint name = 0;
509 int pixelFormat = visual->pixelFormat;
510
511 _mesa_init_renderbuffer(&rb->Base, name);
512
513 rb->Base.Delete = delete_renderbuffer;
514 rb->Base.AllocStorage = renderbuffer_storage;
515
516 if (pixelFormat == PF_B8G8R8) {
517 rb->Base.GetRow = get_row_B8G8R8;
518 rb->Base.GetValues = get_values_B8G8R8;
519 rb->Base.PutRow = put_row_B8G8R8;
520 rb->Base.PutRowRGB = put_row_rgb_B8G8R8;
521 rb->Base.PutMonoRow = put_mono_row_B8G8R8;
522 rb->Base.PutValues = put_values_B8G8R8;
523 rb->Base.PutMonoValues = put_mono_values_B8G8R8;
524 }
525 else if (pixelFormat == PF_B8G8R8A8) {
526 rb->Base.GetRow = get_row_B8G8R8A8;
527 rb->Base.GetValues = get_values_B8G8R8A8;
528 rb->Base.PutRow = put_row_B8G8R8A8;
529 rb->Base.PutRowRGB = put_row_rgb_B8G8R8A8;
530 rb->Base.PutMonoRow = put_mono_row_B8G8R8A8;
531 rb->Base.PutValues = put_values_B8G8R8A8;
532 rb->Base.PutMonoValues = put_mono_values_B8G8R8A8;
533 }
534 else if (pixelFormat == PF_B5G6R5) {
535 rb->Base.GetRow = get_row_B5G6R5;
536 rb->Base.GetValues = get_values_B5G6R5;
537 rb->Base.PutRow = put_row_B5G6R5;
538 rb->Base.PutRowRGB = put_row_rgb_B5G6R5;
539 rb->Base.PutMonoRow = put_mono_row_B5G6R5;
540 rb->Base.PutValues = put_values_B5G6R5;
541 rb->Base.PutMonoValues = put_mono_values_B5G6R5;
542 }
543 else if (pixelFormat == PF_B5G5R5) {
544 rb->Base.GetRow = get_row_B5G5R5;
545 rb->Base.GetValues = get_values_B5G5R5;
546 rb->Base.PutRow = put_row_B5G5R5;
547 rb->Base.PutRowRGB = put_row_rgb_B5G5R5;
548 rb->Base.PutMonoRow = put_mono_row_B5G5R5;
549 rb->Base.PutValues = put_values_B5G5R5;
550 rb->Base.PutMonoValues = put_mono_values_B5G5R5;
551 }
552 else if (pixelFormat == PF_CI8) {
553 rb->Base.GetRow = get_row_CI8;
554 rb->Base.GetValues = get_values_CI8;
555 rb->Base.PutRow = put_row_CI8;
556 rb->Base.PutMonoRow = put_mono_row_CI8;
557 rb->Base.PutValues = put_values_CI8;
558 rb->Base.PutMonoValues = put_mono_values_CI8;
559 }
560
561 if (pixelFormat == PF_CI8) {
562 rb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
563 rb->Base._BaseFormat = GL_COLOR_INDEX;
564 }
565 else {
566 rb->Base.InternalFormat = GL_RGBA;
567 rb->Base._BaseFormat = GL_RGBA;
568 }
569 rb->Base.DataType = GL_UNSIGNED_BYTE;
570 rb->Base.Data = bufferStart;
571
572 rb->rowStride = visual->var.xres_virtual * visual->var.bits_per_pixel / 8;
573 rb->bottom = (GLubyte *) bufferStart
574 + (visual->var.yres_virtual - 1) * rb->rowStride;
575
576 rb->Base.Width = visual->var.xres;
577 rb->Base.Height = visual->var.yres;
578
579 rb->Base.RedBits = visual->var.red.length;
580 rb->Base.GreenBits = visual->var.green.length;
581 rb->Base.BlueBits = visual->var.blue.length;
582 rb->Base.AlphaBits = visual->var.transp.length;
583
584 rb->Base.InternalFormat = pixelFormat;
585 }
586 return rb;
587 }
588
589
590 GLFBDevBufferPtr
591 glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
592 const struct fb_var_screeninfo *varInfo,
593 const GLFBDevVisualPtr visual,
594 void *frontBuffer, void *backBuffer, size_t size )
595 {
596 struct GLFBDevRenderbufferRec *frontrb, *backrb;
597 GLFBDevBufferPtr buf;
598
599 ASSERT(visual);
600 ASSERT(frontBuffer);
601 ASSERT(size > 0);
602
603 if (visual->fix.visual != fixInfo->visual ||
604 visual->fix.type != fixInfo->type ||
605 visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
606 visual->var.grayscale != varInfo->grayscale ||
607 visual->var.red.offset != varInfo->red.offset ||
608 visual->var.green.offset != varInfo->green.offset ||
609 visual->var.blue.offset != varInfo->blue.offset ||
610 visual->var.transp.offset != varInfo->transp.offset) {
611 /* visual mismatch! */
612 return NULL;
613 }
614
615 buf = CALLOC_STRUCT(GLFBDevBufferRec);
616 if (!buf)
617 return NULL;
618
619 /* basic framebuffer setup */
620 _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual);
621 /* add front renderbuffer */
622 frontrb = new_glfbdev_renderbuffer(frontBuffer, visual);
623 _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_FRONT_LEFT,
624 &frontrb->Base);
625 /* add back renderbuffer */
626 if (visual->glvisual.doubleBufferMode) {
627 backrb = new_glfbdev_renderbuffer(backBuffer, visual);
628 _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_BACK_LEFT,
629 &backrb->Base);
630 }
631 /* add software renderbuffers */
632 _mesa_add_soft_renderbuffers(&buf->glframebuffer,
633 GL_FALSE, /* color */
634 visual->glvisual.haveDepthBuffer,
635 visual->glvisual.haveStencilBuffer,
636 visual->glvisual.haveAccumBuffer,
637 GL_FALSE, /* alpha */
638 GL_FALSE /* aux bufs */);
639
640
641
642 buf->fix = *fixInfo; /* struct assignment */
643 buf->var = *varInfo; /* struct assignment */
644 buf->visual = visual; /* ptr assignment */
645 buf->size = size;
646 buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
647
648 if (visual->glvisual.doubleBufferMode) {
649 if (!backBuffer) {
650 /* malloc a back buffer */
651 backrb->Base.Data = _mesa_malloc(size);
652 if (!backrb->Base.Data) {
653 _mesa_free_framebuffer_data(&buf->glframebuffer);
654 _mesa_free(buf);
655 return NULL;
656 }
657 backrb->mallocedBuffer = GL_TRUE;
658 }
659 }
660 /* this causes segfault:
661 else {
662 backrb->bottom = NULL;
663 backrb->rowStride = 0;
664 }*/
665
666 return buf;
667 }
668
669
670 void
671 glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
672 {
673 if (buffer) {
674 /* check if destroying the current buffer */
675 GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
676 GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
677 if (buffer == curDraw || buffer == curRead) {
678 glFBDevMakeCurrent( NULL, NULL, NULL);
679 }
680 /* free the software depth, stencil, accum buffers */
681 _mesa_free_framebuffer_data(&buffer->glframebuffer);
682 _mesa_free(buffer);
683 }
684 }
685
686
687 int
688 glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib)
689 {
690 (void) buffer;
691 (void) attrib;
692 return -1;
693 }
694
695
696 GLFBDevBufferPtr
697 glFBDevGetCurrentDrawBuffer( void )
698 {
699 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
700 if (fbdevctx)
701 return fbdevctx->drawBuffer;
702 else
703 return NULL;
704 }
705
706
707 GLFBDevBufferPtr
708 glFBDevGetCurrentReadBuffer( void )
709 {
710 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
711 if (fbdevctx)
712 return fbdevctx->readBuffer;
713 else
714 return NULL;
715 }
716
717
718 void
719 glFBDevSwapBuffers( GLFBDevBufferPtr buffer )
720 {
721 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
722 struct GLFBDevRenderbufferRec *frontrb = (struct GLFBDevRenderbufferRec *)
723 buffer->glframebuffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
724 struct GLFBDevRenderbufferRec *backrb = (struct GLFBDevRenderbufferRec *)
725 buffer->glframebuffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
726
727 if (!buffer || !buffer->visual->glvisual.doubleBufferMode)
728 return;
729
730 /* check if swapping currently bound buffer */
731 if (fbdevctx->drawBuffer == buffer) {
732 /* flush pending rendering */
733 _mesa_notifySwapBuffers(&fbdevctx->glcontext);
734 }
735
736 ASSERT(frontrb->Base.Data);
737 ASSERT(backrb->Base.Data);
738 _mesa_memcpy(frontrb->Base.Data, backrb->Base.Data, buffer->size);
739 }
740
741
742 GLFBDevContextPtr
743 glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
744 {
745 GLFBDevContextPtr ctx;
746 GLcontext *glctx;
747 struct dd_function_table functions;
748
749 ASSERT(visual);
750
751 ctx = CALLOC_STRUCT(GLFBDevContextRec);
752 if (!ctx)
753 return NULL;
754
755 /* build table of device driver functions */
756 _mesa_init_driver_functions(&functions);
757 functions.GetString = get_string;
758 functions.UpdateState = update_state;
759 functions.GetBufferSize = get_buffer_size;
760 functions.Viewport = viewport;
761
762 if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual,
763 share ? &share->glcontext : NULL,
764 &functions, (void *) ctx)) {
765 _mesa_free(ctx);
766 return NULL;
767 }
768
769 ctx->visual = visual;
770
771 /* Create module contexts */
772 glctx = (GLcontext *) &ctx->glcontext;
773 _swrast_CreateContext( glctx );
774 _ac_CreateContext( glctx );
775 _tnl_CreateContext( glctx );
776 _swsetup_CreateContext( glctx );
777 _swsetup_Wakeup( glctx );
778
779 /* use default TCL pipeline */
780 {
781 TNLcontext *tnl = TNL_CONTEXT(glctx);
782 tnl->Driver.RunPipeline = _tnl_run_pipeline;
783 }
784
785 _mesa_enable_sw_extensions(glctx);
786
787 return ctx;
788 }
789
790
791 void
792 glFBDevDestroyContext( GLFBDevContextPtr context )
793 {
794 GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
795
796 if (context) {
797 if (fbdevctx == context) {
798 /* destroying current context */
799 _mesa_make_current(NULL, NULL, NULL);
800 _mesa_notifyDestroy(&context->glcontext);
801 }
802 _mesa_free_context_data(&context->glcontext);
803 _mesa_free(context);
804 }
805 }
806
807
808 int
809 glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib)
810 {
811 (void) context;
812 (void) attrib;
813 return -1;
814 }
815
816
817 GLFBDevContextPtr
818 glFBDevGetCurrentContext( void )
819 {
820 GET_CURRENT_CONTEXT(ctx);
821 return (GLFBDevContextPtr) ctx;
822 }
823
824
825 int
826 glFBDevMakeCurrent( GLFBDevContextPtr context,
827 GLFBDevBufferPtr drawBuffer,
828 GLFBDevBufferPtr readBuffer )
829 {
830 if (context && drawBuffer && readBuffer) {
831 /* Make sure the context's visual and the buffers' visuals match.
832 * XXX we might do this by comparing specific fields like bits_per_pixel,
833 * visual, etc. in the future.
834 */
835 if (context->visual != drawBuffer->visual ||
836 context->visual != readBuffer->visual) {
837 return 0;
838 }
839 _mesa_make_current( &context->glcontext,
840 &drawBuffer->glframebuffer,
841 &readBuffer->glframebuffer );
842 context->drawBuffer = drawBuffer;
843 context->readBuffer = readBuffer;
844 context->curBuffer = drawBuffer;
845 }
846 else {
847 /* unbind */
848 _mesa_make_current( NULL, NULL, NULL );
849 }
850
851 return 1;
852 }
853
854 #endif /* USE_GLFBDEV_DRIVER */