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