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