(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[mesa.git] / src / mesa / drivers / dri / fb / fb_dri.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 /* Minimal swrast-based dri loadable driver.
27 *
28 * Todo:
29 * -- Use malloced (rather than framebuffer) memory for backbuffer
30 * -- 32bpp is hardwared -- fix
31 *
32 * NOTES:
33 * -- No mechanism for cliprects or resize notification --
34 * assumes this is a fullscreen device.
35 * -- No locking -- assumes this is the only driver accessing this
36 * device.
37 * -- Doesn't (yet) make use of any acceleration or other interfaces
38 * provided by fb. Would be entirely happy working against any
39 * fullscreen interface.
40 * -- HOWEVER: only a small number of pixelformats are supported, and
41 * the mechanism for choosing between them makes some assumptions
42 * that may not be valid everywhere.
43 */
44
45 #include <assert.h>
46 #include <errno.h>
47 #include <signal.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <dlfcn.h>
52 #include <fcntl.h>
53 #include <unistd.h>
54 #include <sys/ioctl.h>
55 #include <sys/mman.h>
56 #include <sys/types.h>
57 #include <sys/shm.h>
58 #include <sys/stat.h>
59 #include <linux/kd.h>
60 #include <linux/vt.h>
61
62 #include "GL/miniglx.h" /* window-system-specific */
63 #include "miniglxP.h" /* window-system-specific */
64 #include "dri_util.h" /* window-system-specific-ish */
65
66 #include "buffers.h"
67 #include "context.h"
68 #include "extensions.h"
69 #include "imports.h"
70 #include "matrix.h"
71 #include "texformat.h"
72 #include "texstore.h"
73 #include "teximage.h"
74 #include "array_cache/acache.h"
75 #include "swrast/swrast.h"
76 #include "swrast_setup/swrast_setup.h"
77 #include "tnl/tnl.h"
78 #include "tnl/t_context.h"
79 #include "tnl/t_pipeline.h"
80 #include "drivers/common/driverfuncs.h"
81
82
83
84 typedef struct {
85 GLcontext *glCtx; /* Mesa context */
86
87 struct {
88 __DRIcontextPrivate *context;
89 __DRIscreenPrivate *screen;
90 __DRIdrawablePrivate *drawable; /* drawable bound to this ctx */
91 } dri;
92 } fbContext, *fbContextPtr;
93
94
95 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
96
97
98 static const GLubyte *
99 get_string(GLcontext *ctx, GLenum pname)
100 {
101 (void) ctx;
102 switch (pname) {
103 case GL_RENDERER:
104 return (const GLubyte *) "Mesa dumb framebuffer";
105 default:
106 return NULL;
107 }
108 }
109
110
111 static void
112 update_state( GLcontext *ctx, GLuint new_state )
113 {
114 /* not much to do here - pass it on */
115 _swrast_InvalidateState( ctx, new_state );
116 _swsetup_InvalidateState( ctx, new_state );
117 _ac_InvalidateState( ctx, new_state );
118 _tnl_InvalidateState( ctx, new_state );
119 }
120
121
122 /**
123 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
124 * current framebuffer size.
125 */
126 static void
127 get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
128 {
129 GET_CURRENT_CONTEXT(ctx);
130 fbContextPtr fbmesa = FB_CONTEXT(ctx);
131
132 *width = fbmesa->dri.drawable->w;
133 *height = fbmesa->dri.drawable->h;
134 }
135
136
137 static void
138 viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
139 {
140 _mesa_ResizeBuffersMESA();
141 }
142
143
144 /* specifies the buffer for swrast span rendering/reading */
145 static void
146 set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
147 {
148 fbContextPtr fbdevctx = FB_CONTEXT(ctx);
149 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
150
151 /* What a twisted mess of private structs
152 */
153 assert(buffer == dPriv->driverPrivate);
154
155
156 switch (bufferBit) {
157 case DD_FRONT_LEFT_BIT:
158 dPriv->currentBuffer = dPriv->frontBuffer;
159 break;
160 case DD_BACK_LEFT_BIT:
161 dPriv->currentBuffer = dPriv->backBuffer;
162 break;
163 default:
164 /* This happens a lot if the client renders to the frontbuffer */
165 if (0) _mesa_problem(ctx, "bad bufferBit in set_buffer()");
166 }
167 }
168
169
170 static void
171 init_core_functions( struct dd_function_table *functions )
172 {
173 functions->GetString = get_string;
174 functions->UpdateState = update_state;
175 functions->ResizeBuffers = _swrast_alloc_buffers;
176 functions->GetBufferSize = get_buffer_size;
177 functions->Viewport = viewport;
178
179 functions->Clear = _swrast_Clear; /* could accelerate with blits */
180 }
181
182
183 /*
184 * Generate code for span functions.
185 */
186
187 /* 24-bit BGR */
188 #define NAME(PREFIX) PREFIX##_B8G8R8
189 #define SPAN_VARS \
190 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
191 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
192 #define INIT_PIXEL_PTR(P, X, Y) \
193 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 3
194 #define INC_PIXEL_PTR(P) P += 3
195 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
196 P[0] = B; P[1] = G; P[2] = R
197 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
198 P[0] = B; P[1] = G; P[2] = R
199 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
200 R = P[2]; G = P[1]; B = P[0]; A = CHAN_MAX
201
202 #include "swrast/s_spantemp.h"
203
204
205 /* 32-bit BGRA */
206 #define NAME(PREFIX) PREFIX##_B8G8R8A8
207 #define SPAN_VARS \
208 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
209 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
210 #define INIT_PIXEL_PTR(P, X, Y) \
211 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 4;
212 #define INC_PIXEL_PTR(P) P += 4
213 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
214 P[0] = B; P[1] = G; P[2] = R; P[3] = 255
215 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
216 P[0] = B; P[1] = G; P[2] = R; P[3] = A
217 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
218 R = P[2]; G = P[1]; B = P[0]; A = P[3]
219
220 #include "swrast/s_spantemp.h"
221
222
223 /* 16-bit BGR (XXX implement dithering someday) */
224 #define NAME(PREFIX) PREFIX##_B5G6R5
225 #define SPAN_VARS \
226 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
227 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
228 #define INIT_PIXEL_PTR(P, X, Y) \
229 GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
230 #define INC_PIXEL_PTR(P) P += 1
231 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
232 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
233 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
234 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
235 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
236 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
237 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
238 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
239 A = CHAN_MAX
240
241 #include "swrast/s_spantemp.h"
242
243
244 /* 15-bit BGR (XXX implement dithering someday) */
245 #define NAME(PREFIX) PREFIX##_B5G5R5
246 #define SPAN_VARS \
247 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
248 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
249 #define INIT_PIXEL_PTR(P, X, Y) \
250 GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
251 #define INC_PIXEL_PTR(P) P += 1
252 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
253 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
254 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
255 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
256 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
257 R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
258 G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
259 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
260 A = CHAN_MAX
261
262 #include "swrast/s_spantemp.h"
263
264
265 /* 8-bit color index */
266 #define NAME(PREFIX) PREFIX##_CI8
267 #define SPAN_VARS \
268 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
269 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
270 #define INIT_PIXEL_PTR(P, X, Y) \
271 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X)
272 #define INC_PIXEL_PTR(P) P += 1
273 #define STORE_CI_PIXEL(P, CI) \
274 P[0] = CI
275 #define FETCH_CI_PIXEL(CI, P) \
276 CI = P[0]
277
278 #include "swrast/s_spantemp.h"
279
280
281
282 /* Initialize the driver specific screen private data.
283 */
284 static GLboolean
285 fbInitDriver( __DRIscreenPrivate *sPriv )
286 {
287 sPriv->private = NULL;
288 return GL_TRUE;
289 }
290
291 static void
292 fbDestroyScreen( __DRIscreenPrivate *sPriv )
293 {
294 }
295
296 /* Create the device specific context.
297 */
298 static GLboolean
299 fbCreateContext( const __GLcontextModes *glVisual,
300 __DRIcontextPrivate *driContextPriv,
301 void *sharedContextPrivate)
302 {
303 fbContextPtr fbmesa;
304 GLcontext *ctx, *shareCtx;
305 struct dd_function_table functions;
306
307 assert(glVisual);
308 assert(driContextPriv);
309
310 /* Allocate the Fb context */
311 fbmesa = (fbContextPtr) _mesa_calloc( sizeof(*fbmesa) );
312 if ( !fbmesa )
313 return GL_FALSE;
314
315 /* Init default driver functions then plug in our FBdev-specific functions
316 */
317 _mesa_init_driver_functions(&functions);
318 init_core_functions(&functions);
319
320 /* Allocate the Mesa context */
321 if (sharedContextPrivate)
322 shareCtx = ((fbContextPtr) sharedContextPrivate)->glCtx;
323 else
324 shareCtx = NULL;
325
326 ctx = fbmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
327 &functions, (void *) fbmesa);
328 if (!fbmesa->glCtx) {
329 _mesa_free(fbmesa);
330 return GL_FALSE;
331 }
332 driContextPriv->driverPrivate = fbmesa;
333
334 /* Create module contexts */
335 _swrast_CreateContext( ctx );
336 _ac_CreateContext( ctx );
337 _tnl_CreateContext( ctx );
338 _swsetup_CreateContext( ctx );
339 _swsetup_Wakeup( ctx );
340
341
342 /* swrast init -- need to verify these tests - I just plucked the
343 * numbers out of the air. (KW)
344 */
345 {
346 struct swrast_device_driver *swdd;
347 swdd = _swrast_GetDeviceDriverReference( ctx );
348 swdd->SetBuffer = set_buffer;
349 if (!glVisual->rgbMode) {
350 swdd->WriteCI32Span = write_index32_span_CI8;
351 swdd->WriteCI8Span = write_index8_span_CI8;
352 swdd->WriteMonoCISpan = write_monoindex_span_CI8;
353 swdd->WriteCI32Pixels = write_index_pixels_CI8;
354 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
355 swdd->ReadCI32Span = read_index_span_CI8;
356 swdd->ReadCI32Pixels = read_index_pixels_CI8;
357 }
358 else if (glVisual->rgbBits == 24 &&
359 glVisual->alphaBits == 0) {
360 swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
361 swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
362 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
363 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
364 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
365 swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
366 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
367 }
368 else if (glVisual->rgbBits == 32 &&
369 glVisual->alphaBits == 8) {
370 swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
371 swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
372 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
373 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
374 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
375 swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
376 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
377 }
378 else if (glVisual->rgbBits == 16 &&
379 glVisual->alphaBits == 0) {
380 swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
381 swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
382 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
383 swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
384 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
385 swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
386 swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
387 }
388 else if (glVisual->rgbBits == 15 &&
389 glVisual->alphaBits == 0) {
390 swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
391 swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
392 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
393 swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
394 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
395 swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
396 swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
397 }
398 else {
399 _mesa_printf("bad pixelformat rgb %d alpha %d\n",
400 glVisual->rgbBits,
401 glVisual->alphaBits );
402 }
403 }
404
405 /* use default TCL pipeline */
406 {
407 TNLcontext *tnl = TNL_CONTEXT(ctx);
408 tnl->Driver.RunPipeline = _tnl_run_pipeline;
409 }
410
411 _mesa_enable_sw_extensions(ctx);
412
413 return GL_TRUE;
414 }
415
416
417 static void
418 fbDestroyContext( __DRIcontextPrivate *driContextPriv )
419 {
420 GET_CURRENT_CONTEXT(ctx);
421 fbContextPtr fbmesa = (fbContextPtr) driContextPriv->driverPrivate;
422 fbContextPtr current = ctx ? FB_CONTEXT(ctx) : NULL;
423
424 /* check if we're deleting the currently bound context */
425 if (fbmesa == current) {
426 _mesa_make_current2(NULL, NULL, NULL);
427 }
428
429 /* Free fb context resources */
430 if ( fbmesa ) {
431 _swsetup_DestroyContext( fbmesa->glCtx );
432 _tnl_DestroyContext( fbmesa->glCtx );
433 _ac_DestroyContext( fbmesa->glCtx );
434 _swrast_DestroyContext( fbmesa->glCtx );
435
436 /* free the Mesa context */
437 fbmesa->glCtx->DriverCtx = NULL;
438 _mesa_destroy_context( fbmesa->glCtx );
439
440 _mesa_free( fbmesa );
441 }
442 }
443
444
445 /* Create and initialize the Mesa and driver specific pixmap buffer
446 * data.
447 */
448 static GLboolean
449 fbCreateBuffer( __DRIscreenPrivate *driScrnPriv,
450 __DRIdrawablePrivate *driDrawPriv,
451 const __GLcontextModes *mesaVis,
452 GLboolean isPixmap )
453 {
454 if (isPixmap) {
455 return GL_FALSE; /* not implemented */
456 }
457 else {
458 const GLboolean swDepth = mesaVis->depthBits > 0;
459 const GLboolean swAlpha = mesaVis->alphaBits > 0;
460 const GLboolean swAccum = mesaVis->accumRedBits > 0;
461 const GLboolean swStencil = mesaVis->stencilBits > 0;
462 driDrawPriv->driverPrivate = (void *)
463 _mesa_create_framebuffer( mesaVis,
464 swDepth,
465 swStencil,
466 swAccum,
467 swAlpha );
468
469 if (!driDrawPriv->driverPrivate)
470 return 0;
471
472 /* Replace the framebuffer back buffer with a malloc'ed one --
473 * big speedup.
474 */
475 if (driDrawPriv->backBuffer)
476 driDrawPriv->backBuffer = _mesa_malloc(driDrawPriv->currentPitch * driDrawPriv->h);
477
478 return 1;
479 }
480 }
481
482
483 static void
484 fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
485 {
486 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
487 _mesa_free(driDrawPriv->backBuffer);
488 }
489
490
491
492 /* If the backbuffer is on a videocard, this is extraordinarily slow!
493 */
494 static void
495 fbSwapBuffers( __DRIdrawablePrivate *dPriv )
496 {
497
498 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
499 fbContextPtr fbmesa;
500 GLcontext *ctx;
501 fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate;
502 ctx = fbmesa->glCtx;
503 if (ctx->Visual.doubleBufferMode) {
504 int i;
505 int offset = 0;
506 char *tmp = _mesa_malloc(dPriv->currentPitch);
507
508 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
509
510 ASSERT(dPriv->frontBuffer);
511 ASSERT(dPriv->backBuffer);
512
513 for (i = 0; i < dPriv->h; i++) {
514 _mesa_memcpy(tmp, (char *) dPriv->backBuffer + offset,
515 dPriv->currentPitch);
516 _mesa_memcpy((char *) dPriv->frontBuffer + offset, tmp,
517 dPriv->currentPitch);
518 offset += dPriv->currentPitch;
519 }
520
521 _mesa_free(tmp);
522 }
523 }
524 else {
525 /* XXX this shouldn't be an error but we can't handle it for now */
526 _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n");
527 }
528 }
529
530
531 /* Force the context `c' to be the current context and associate with it
532 * buffer `b'.
533 */
534 static GLboolean
535 fbMakeCurrent( __DRIcontextPrivate *driContextPriv,
536 __DRIdrawablePrivate *driDrawPriv,
537 __DRIdrawablePrivate *driReadPriv )
538 {
539 if ( driContextPriv ) {
540 fbContextPtr newFbCtx =
541 (fbContextPtr) driContextPriv->driverPrivate;
542
543 newFbCtx->dri.drawable = driDrawPriv;
544
545 _mesa_make_current2( newFbCtx->glCtx,
546 (GLframebuffer *) driDrawPriv->driverPrivate,
547 (GLframebuffer *) driReadPriv->driverPrivate );
548 } else {
549 _mesa_make_current( 0, 0 );
550 }
551
552 return GL_TRUE;
553 }
554
555
556 /* Force the context `c' to be unbound from its buffer.
557 */
558 static GLboolean
559 fbUnbindContext( __DRIcontextPrivate *driContextPriv )
560 {
561 return GL_TRUE;
562 }
563
564 static struct __DriverAPIRec fbAPI = {
565 fbInitDriver,
566 fbDestroyScreen,
567 fbCreateContext,
568 fbDestroyContext,
569 fbCreateBuffer,
570 fbDestroyBuffer,
571 fbSwapBuffers,
572 fbMakeCurrent,
573 fbUnbindContext
574 };
575
576
577 /*
578 * This is the bootstrap function for the driver.
579 * The __driCreateScreen name is the symbol that libGL.so fetches.
580 * Return: pointer to a __DRIscreenPrivate.
581 */
582 void *
583 __driCreateScreen(struct DRIDriverRec *driver,
584 struct DRIDriverContextRec *driverContext)
585 {
586 __DRIscreenPrivate *psp;
587 psp = __driUtilCreateScreenNoDRM(driver, driverContext, &fbAPI);
588 return (void *) psp;
589 }
590
591
592 /**
593 * \brief Establish the set of modes available for the display.
594 *
595 * \param ctx display handle.
596 * \param numModes will receive the number of supported modes.
597 * \param modes will point to the list of supported modes.
598 *
599 * \return one on success, or zero on failure.
600 *
601 * Allocates a single visual and fills it with information according to the
602 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
603 * otherwise.
604 */
605 const __GLcontextModes __glModes[] = {
606
607 /* 32 bit, RGBA Depth=24 Stencil=8 */
608 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
609 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
610 .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
611 .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
612 .rgbBits = 32, .indexBits = 0,
613 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
614 .depthBits = 24, .stencilBits = 8,
615 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
616
617 /* 16 bit, RGB Depth=16 */
618 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
619 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
620 .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
621 .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
622 .rgbBits = 16, .indexBits = 0,
623 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
624 .depthBits = 16, .stencilBits = 0,
625 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
626 };
627
628
629 static int
630 __driInitScreenModes( const DRIDriverContext *ctx,
631 int *numModes, const __GLcontextModes **modes)
632 {
633 *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
634 *modes = &__glModes[0];
635 return 1;
636 }
637
638
639
640 static int
641 __driValidateMode(const DRIDriverContext *ctx )
642 {
643 return 1;
644 }
645
646 static int
647 __driInitFBDev( struct DRIDriverContextRec *ctx )
648 {
649 int id;
650 ctx->shared.hFrameBuffer = ctx->FBStart;
651 ctx->shared.fbSize = ctx->FBSize;
652 ctx->shared.hSAREA = 0xB37D;
653 ctx->shared.SAREASize = SAREA_MAX;
654 id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
655 if (id == -1) {
656 /* segment will already exist if previous server segfaulted */
657 id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, 0);
658 if (id == -1) {
659 fprintf(stderr, "fb: shmget failed\n");
660 return 0;
661 }
662 }
663 ctx->pSAREA = shmat(id, NULL, 0);
664 if (ctx->pSAREA == (void *)-1) {
665 fprintf(stderr, "fb: shmat failed\n");
666 return 0;
667 }
668 memset(ctx->pSAREA, 0, SAREA_MAX);
669 return 1;
670 }
671
672 static void
673 __driHaltFBDev( struct DRIDriverContextRec *ctx )
674 {
675 }
676
677
678
679 struct DRIDriverRec __driDriver = {
680 __driInitScreenModes,
681 __driValidateMode,
682 __driValidateMode,
683 __driInitFBDev,
684 __driHaltFBDev
685 };
686