obsolete in favor of regular Makefiles
[mesa.git] / src / mesa / drivers / dri / fb / fb_dri.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 4.1
5 *
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /* Minimal swrast-based dri loadable driver.
28 *
29 * Todo:
30 * -- Use malloced (rather than framebuffer) memory for backbuffer
31 * -- 32bpp is hardwared -- fix
32 *
33 * NOTES:
34 * -- No mechanism for cliprects or resize notification --
35 * assumes this is a fullscreen device.
36 * -- No locking -- assumes this is the only driver accessing this
37 * device.
38 * -- Doesn't (yet) make use of any acceleration or other interfaces
39 * provided by fb. Would be entirely happy working against any
40 * fullscreen interface.
41 * -- HOWEVER: only a small number of pixelformats are supported, and
42 * the mechanism for choosing between them makes some assumptions
43 * that may not be valid everywhere.
44 */
45
46 #include <assert.h>
47 #include <errno.h>
48 #include <signal.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <dlfcn.h>
53 #include <fcntl.h>
54 #include <unistd.h>
55 #include <sys/ioctl.h>
56 #include <sys/mman.h>
57 #include <sys/types.h>
58 #include <sys/shm.h>
59 #include <sys/stat.h>
60 #include <linux/kd.h>
61 #include <linux/vt.h>
62
63 #include "GL/miniglx.h" /* window-system-specific */
64 #include "miniglxP.h" /* window-system-specific */
65 #include "dri_util.h" /* window-system-specific-ish */
66
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 /* specifies the buffer for swrast span rendering/reading */
138 static void
139 set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
140 {
141 fbContextPtr fbdevctx = FB_CONTEXT(ctx);
142 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
143
144 /* What a twisted mess of private structs
145 */
146 assert(buffer == dPriv->driverPrivate);
147
148
149 switch (bufferBit) {
150 case DD_FRONT_LEFT_BIT:
151 dPriv->currentBuffer = dPriv->frontBuffer;
152 break;
153 case DD_BACK_LEFT_BIT:
154 dPriv->currentBuffer = dPriv->backBuffer;
155 break;
156 default:
157 /* This happens a lot if the client renders to the frontbuffer */
158 if (0) _mesa_problem(ctx, "bad bufferBit in set_buffer()");
159 }
160 }
161
162
163 static void
164 init_core_functions( struct dd_function_table *functions )
165 {
166 functions->GetString = get_string;
167 functions->UpdateState = update_state;
168 functions->ResizeBuffers = _swrast_alloc_buffers;
169 functions->GetBufferSize = get_buffer_size;
170
171 functions->Clear = _swrast_Clear; /* could accelerate with blits */
172 }
173
174
175 /*
176 * Generate code for span functions.
177 */
178
179 /* 24-bit BGR */
180 #define NAME(PREFIX) PREFIX##_B8G8R8
181 #define SPAN_VARS \
182 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
183 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
184 #define INIT_PIXEL_PTR(P, X, Y) \
185 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 3
186 #define INC_PIXEL_PTR(P) P += 3
187 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
188 P[0] = B; P[1] = G; P[2] = R
189 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
190 P[0] = B; P[1] = G; P[2] = R
191 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
192 R = P[2]; G = P[1]; B = P[0]; A = CHAN_MAX
193
194 #include "swrast/s_spantemp.h"
195
196
197 /* 32-bit BGRA */
198 #define NAME(PREFIX) PREFIX##_B8G8R8A8
199 #define SPAN_VARS \
200 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
201 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
202 #define INIT_PIXEL_PTR(P, X, Y) \
203 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 4;
204 #define INC_PIXEL_PTR(P) P += 4
205 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
206 P[0] = B; P[1] = G; P[2] = R; P[3] = 255
207 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
208 P[0] = B; P[1] = G; P[2] = R; P[3] = A
209 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
210 R = P[2]; G = P[1]; B = P[0]; A = P[3]
211
212 #include "swrast/s_spantemp.h"
213
214
215 /* 16-bit BGR (XXX implement dithering someday) */
216 #define NAME(PREFIX) PREFIX##_B5G6R5
217 #define SPAN_VARS \
218 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
219 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
220 #define INIT_PIXEL_PTR(P, X, Y) \
221 GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
222 #define INC_PIXEL_PTR(P) P += 1
223 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
224 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
225 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
226 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
227 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
228 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
229 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
230 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
231 A = CHAN_MAX
232
233 #include "swrast/s_spantemp.h"
234
235
236 /* 15-bit BGR (XXX implement dithering someday) */
237 #define NAME(PREFIX) PREFIX##_B5G5R5
238 #define SPAN_VARS \
239 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
240 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
241 #define INIT_PIXEL_PTR(P, X, Y) \
242 GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
243 #define INC_PIXEL_PTR(P) P += 1
244 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
245 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
246 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
247 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
248 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
249 R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
250 G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
251 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
252 A = CHAN_MAX
253
254 #include "swrast/s_spantemp.h"
255
256
257 /* 8-bit color index */
258 #define NAME(PREFIX) PREFIX##_CI8
259 #define SPAN_VARS \
260 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
261 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
262 #define INIT_PIXEL_PTR(P, X, Y) \
263 GLubyte *P = (GLubyte *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X)
264 #define INC_PIXEL_PTR(P) P += 1
265 #define STORE_CI_PIXEL(P, CI) \
266 P[0] = CI
267 #define FETCH_CI_PIXEL(CI, P) \
268 CI = P[0]
269
270 #include "swrast/s_spantemp.h"
271
272
273
274 /* Initialize the driver specific screen private data.
275 */
276 static GLboolean
277 fbInitDriver( __DRIscreenPrivate *sPriv )
278 {
279 sPriv->private = NULL;
280 return GL_TRUE;
281 }
282
283 static void
284 fbDestroyScreen( __DRIscreenPrivate *sPriv )
285 {
286 }
287
288 /* Create the device specific context.
289 */
290 static GLboolean
291 fbCreateContext( const __GLcontextModes *glVisual,
292 __DRIcontextPrivate *driContextPriv,
293 void *sharedContextPrivate)
294 {
295 fbContextPtr fbmesa;
296 GLcontext *ctx, *shareCtx;
297 struct dd_function_table functions;
298
299 assert(glVisual);
300 assert(driContextPriv);
301
302 /* Allocate the Fb context */
303 fbmesa = (fbContextPtr) CALLOC( sizeof(*fbmesa) );
304 if ( !fbmesa )
305 return GL_FALSE;
306
307 /* Init default driver functions then plug in our FBdev-specific functions
308 */
309 _mesa_init_driver_functions(&functions);
310 init_core_functions(&functions);
311
312 /* Allocate the Mesa context */
313 if (sharedContextPrivate)
314 shareCtx = ((fbContextPtr) sharedContextPrivate)->glCtx;
315 else
316 shareCtx = NULL;
317
318 ctx = fbmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
319 &functions, (void *) fbmesa);
320 if (!fbmesa->glCtx) {
321 FREE(fbmesa);
322 return GL_FALSE;
323 }
324 driContextPriv->driverPrivate = fbmesa;
325
326 /* Create module contexts */
327 _swrast_CreateContext( ctx );
328 _ac_CreateContext( ctx );
329 _tnl_CreateContext( ctx );
330 _swsetup_CreateContext( ctx );
331 _swsetup_Wakeup( ctx );
332
333
334 /* swrast init -- need to verify these tests - I just plucked the
335 * numbers out of the air. (KW)
336 */
337 {
338 struct swrast_device_driver *swdd;
339 swdd = _swrast_GetDeviceDriverReference( ctx );
340 swdd->SetBuffer = set_buffer;
341 if (!glVisual->rgbMode) {
342 swdd->WriteCI32Span = write_index32_span_CI8;
343 swdd->WriteCI8Span = write_index8_span_CI8;
344 swdd->WriteMonoCISpan = write_monoindex_span_CI8;
345 swdd->WriteCI32Pixels = write_index_pixels_CI8;
346 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
347 swdd->ReadCI32Span = read_index_span_CI8;
348 swdd->ReadCI32Pixels = read_index_pixels_CI8;
349 }
350 else if (glVisual->rgbBits == 24 &&
351 glVisual->alphaBits == 0) {
352 swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
353 swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
354 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
355 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
356 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
357 swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
358 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
359 }
360 else if (glVisual->rgbBits == 32 &&
361 glVisual->alphaBits == 8) {
362 swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
363 swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
364 swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
365 swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
366 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
367 swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
368 swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
369 }
370 else if (glVisual->rgbBits == 16 &&
371 glVisual->alphaBits == 0) {
372 swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
373 swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
374 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
375 swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
376 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
377 swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
378 swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
379 }
380 else if (glVisual->rgbBits == 15 &&
381 glVisual->alphaBits == 0) {
382 swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
383 swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
384 swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
385 swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
386 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
387 swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
388 swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
389 }
390 else {
391 _mesa_printf("bad pixelformat rgb %d alpha %d\n",
392 glVisual->rgbBits,
393 glVisual->alphaBits );
394 }
395 }
396
397 /* use default TCL pipeline */
398 {
399 TNLcontext *tnl = TNL_CONTEXT(ctx);
400 tnl->Driver.RunPipeline = _tnl_run_pipeline;
401 }
402
403 _mesa_enable_sw_extensions(ctx);
404
405 return GL_TRUE;
406 }
407
408
409 static void
410 fbDestroyContext( __DRIcontextPrivate *driContextPriv )
411 {
412 GET_CURRENT_CONTEXT(ctx);
413 fbContextPtr fbmesa = (fbContextPtr) driContextPriv->driverPrivate;
414 fbContextPtr current = ctx ? FB_CONTEXT(ctx) : NULL;
415
416 /* check if we're deleting the currently bound context */
417 if (fbmesa == current) {
418 _mesa_make_current2(NULL, NULL, NULL);
419 }
420
421 /* Free fb context resources */
422 if ( fbmesa ) {
423 _swsetup_DestroyContext( fbmesa->glCtx );
424 _tnl_DestroyContext( fbmesa->glCtx );
425 _ac_DestroyContext( fbmesa->glCtx );
426 _swrast_DestroyContext( fbmesa->glCtx );
427
428 /* free the Mesa context */
429 fbmesa->glCtx->DriverCtx = NULL;
430 _mesa_destroy_context( fbmesa->glCtx );
431
432 FREE( fbmesa );
433 }
434 }
435
436
437 /* Create and initialize the Mesa and driver specific pixmap buffer
438 * data.
439 */
440 static GLboolean
441 fbCreateBuffer( __DRIscreenPrivate *driScrnPriv,
442 __DRIdrawablePrivate *driDrawPriv,
443 const __GLcontextModes *mesaVis,
444 GLboolean isPixmap )
445 {
446 if (isPixmap) {
447 return GL_FALSE; /* not implemented */
448 }
449 else {
450 const GLboolean swDepth = mesaVis->depthBits > 0;
451 const GLboolean swAlpha = mesaVis->alphaBits > 0;
452 const GLboolean swAccum = mesaVis->accumRedBits > 0;
453 const GLboolean swStencil = mesaVis->stencilBits > 0;
454 driDrawPriv->driverPrivate = (void *)
455 _mesa_create_framebuffer( mesaVis,
456 swDepth,
457 swStencil,
458 swAccum,
459 swAlpha );
460
461 if (!driDrawPriv->driverPrivate)
462 return 0;
463
464 /* Replace the framebuffer back buffer with a malloc'ed one --
465 * big speedup.
466 */
467 if (driDrawPriv->backBuffer)
468 driDrawPriv->backBuffer = malloc(driDrawPriv->currentPitch * driDrawPriv->h);
469
470 return 1;
471 }
472 }
473
474
475 static void
476 fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
477 {
478 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
479 free(driDrawPriv->backBuffer);
480 }
481
482
483
484 /* If the backbuffer is on a videocard, this is extraordinarily slow!
485 */
486 static void
487 fbSwapBuffers( __DRIdrawablePrivate *dPriv )
488 {
489
490 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
491 fbContextPtr fbmesa;
492 GLcontext *ctx;
493 fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate;
494 ctx = fbmesa->glCtx;
495 if (ctx->Visual.doubleBufferMode) {
496 int i;
497 int offset = 0;
498 char *tmp = malloc( dPriv->currentPitch );
499
500 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
501
502 ASSERT(dPriv->frontBuffer);
503 ASSERT(dPriv->backBuffer);
504
505
506 for (i = 0 ; i < dPriv->h ; i++ ) {
507 memcpy( tmp, (char *)dPriv->frontBuffer + offset, dPriv->currentPitch );
508 memcpy( (char *)dPriv->backBuffer + offset, tmp, dPriv->currentPitch );
509 offset += dPriv->currentPitch;
510 }
511
512 free( tmp );
513 }
514 }
515 else {
516 /* XXX this shouldn't be an error but we can't handle it for now */
517 _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n");
518 }
519 }
520
521
522 /* Force the context `c' to be the current context and associate with it
523 * buffer `b'.
524 */
525 static GLboolean
526 fbMakeCurrent( __DRIcontextPrivate *driContextPriv,
527 __DRIdrawablePrivate *driDrawPriv,
528 __DRIdrawablePrivate *driReadPriv )
529 {
530 if ( driContextPriv ) {
531 fbContextPtr newFbCtx =
532 (fbContextPtr) driContextPriv->driverPrivate;
533
534 newFbCtx->dri.drawable = driDrawPriv;
535
536 _mesa_make_current2( newFbCtx->glCtx,
537 (GLframebuffer *) driDrawPriv->driverPrivate,
538 (GLframebuffer *) driReadPriv->driverPrivate );
539
540 if ( !newFbCtx->glCtx->Viewport.Width ) {
541 _mesa_set_viewport( newFbCtx->glCtx, 0, 0,
542 driDrawPriv->w, driDrawPriv->h );
543 }
544 } else {
545 _mesa_make_current( 0, 0 );
546 }
547
548 return GL_TRUE;
549 }
550
551
552 /* Force the context `c' to be unbound from its buffer.
553 */
554 static GLboolean
555 fbUnbindContext( __DRIcontextPrivate *driContextPriv )
556 {
557 return GL_TRUE;
558 }
559
560 static GLboolean
561 fbOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
562 {
563 return GL_TRUE;
564 }
565
566 static struct __DriverAPIRec fbAPI = {
567 fbInitDriver,
568 fbDestroyScreen,
569 fbCreateContext,
570 fbDestroyContext,
571 fbCreateBuffer,
572 fbDestroyBuffer,
573 fbSwapBuffers,
574 fbMakeCurrent,
575 fbUnbindContext,
576 fbOpenCloseFullScreen,
577 fbOpenCloseFullScreen
578 };
579
580
581 void
582 __driRegisterExtensions( void )
583 {
584 }
585
586
587 /*
588 * This is the bootstrap function for the driver.
589 * The __driCreateScreen name is the symbol that libGL.so fetches.
590 * Return: pointer to a __DRIscreenPrivate.
591 */
592 void *
593 __driCreateScreen(struct DRIDriverRec *driver,
594 struct DRIDriverContextRec *driverContext)
595 {
596 __DRIscreenPrivate *psp;
597 psp = __driUtilCreateScreenNoDRM(driver, driverContext, &fbAPI);
598 return (void *) psp;
599 }
600
601
602
603 /**
604 * \brief Establish the set of modes available for the display.
605 *
606 * \param ctx display handle.
607 * \param numModes will receive the number of supported modes.
608 * \param modes will point to the list of supported modes.
609 *
610 * \return one on success, or zero on failure.
611 *
612 * Allocates a single visual and fills it with information according to the
613 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
614 * otherwise.
615 */
616 const __GLcontextModes __glModes[] = {
617
618 /* 32 bit, RGBA Depth=24 Stencil=8 */
619 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
620 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
621 .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
622 .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
623 .rgbBits = 32, .indexBits = 0,
624 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
625 .depthBits = 24, .stencilBits = 8,
626 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
627
628 /* 16 bit, RGB Depth=16 */
629 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
630 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
631 .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
632 .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
633 .rgbBits = 16, .indexBits = 0,
634 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
635 .depthBits = 16, .stencilBits = 0,
636 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
637 };
638
639
640 static int
641 __driInitScreenModes( const DRIDriverContext *ctx,
642 int *numModes, const __GLcontextModes **modes)
643 {
644 *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
645 *modes = &__glModes[0];
646 return 1;
647 }
648
649
650
651 static int
652 __driValidateMode(const DRIDriverContext *ctx )
653 {
654 return 1;
655 }
656
657 /* HACK - for now, put this here... */
658 /* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
659 #if defined(__alpha__)
660 # define DRM_PAGE_SIZE 8192
661 #elif defined(__ia64__)
662 # define DRM_PAGE_SIZE getpagesize()
663 #else
664 # define DRM_PAGE_SIZE 4096
665 #endif
666
667
668 static int
669 __driInitFBDev( struct DRIDriverContextRec *ctx )
670 {
671 int id;
672 ctx->shared.hFrameBuffer = ctx->FBStart;
673 ctx->shared.fbSize = ctx->FBSize;
674 ctx->shared.hSAREA = 0xB37D;
675 ctx->shared.SAREASize = DRM_PAGE_SIZE;
676 id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
677 if (id == -1) {
678 /* segment will already exist if previous server segfaulted */
679 id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, 0);
680 if (id == -1) {
681 fprintf(stderr, "fb: shmget failed\n");
682 return 0;
683 }
684 }
685 ctx->pSAREA = shmat(id, NULL, 0);
686 if (ctx->pSAREA == (void *)-1) {
687 fprintf(stderr, "fb: shmat failed\n");
688 return 0;
689 }
690 memset(ctx->pSAREA, 0, DRM_PAGE_SIZE);
691 return 1;
692 }
693
694 static void
695 __driHaltFBDev( struct DRIDriverContextRec *ctx )
696 {
697 }
698
699
700
701 struct DRIDriverRec __driDriver = {
702 __driInitScreenModes,
703 __driValidateMode,
704 __driValidateMode,
705 __driInitFBDev,
706 __driHaltFBDev
707 };
708