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