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