2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 /* Minimal swrast-based dri loadable driver.
29 * -- Use malloced (rather than framebuffer) memory for backbuffer
30 * -- 32bpp is hardwared -- fix
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
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.
54 #include <sys/ioctl.h>
56 #include <sys/types.h>
62 #include "GL/miniglx.h" /* window-system-specific */
63 #include "miniglxP.h" /* window-system-specific */
64 #include "dri_util.h" /* window-system-specific-ish */
68 #include "extensions.h"
71 #include "texformat.h"
74 #include "array_cache/acache.h"
75 #include "swrast/swrast.h"
76 #include "swrast_setup/swrast_setup.h"
78 #include "tnl/t_context.h"
79 #include "tnl/t_pipeline.h"
80 #include "drivers/common/driverfuncs.h"
85 GLcontext
*glCtx
; /* Mesa context */
88 __DRIcontextPrivate
*context
;
89 __DRIscreenPrivate
*screen
;
90 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
92 } fbContext
, *fbContextPtr
;
95 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
98 static const GLubyte
*
99 get_string(GLcontext
*ctx
, GLenum pname
)
104 return (const GLubyte
*) "Mesa dumb framebuffer";
112 update_state( GLcontext
*ctx
, GLuint new_state
)
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
);
123 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
124 * current framebuffer size.
127 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
129 GET_CURRENT_CONTEXT(ctx
);
130 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
132 *width
= fbmesa
->dri
.drawable
->w
;
133 *height
= fbmesa
->dri
.drawable
->h
;
138 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
140 _mesa_ResizeBuffersMESA();
144 /* specifies the buffer for swrast span rendering/reading */
146 set_buffer( GLcontext
*ctx
, GLframebuffer
*buffer
, GLuint bufferBit
)
148 fbContextPtr fbdevctx
= FB_CONTEXT(ctx
);
149 __DRIdrawablePrivate
*dPriv
= fbdevctx
->dri
.drawable
;
151 /* What a twisted mess of private structs
153 assert(buffer
== dPriv
->driverPrivate
);
157 case DD_FRONT_LEFT_BIT
:
158 dPriv
->currentBuffer
= dPriv
->frontBuffer
;
160 case DD_BACK_LEFT_BIT
:
161 dPriv
->currentBuffer
= dPriv
->backBuffer
;
164 /* This happens a lot if the client renders to the frontbuffer */
165 if (0) _mesa_problem(ctx
, "bad bufferBit in set_buffer()");
171 init_core_functions( struct dd_function_table
*functions
)
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
;
179 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
184 * Generate code for span functions.
188 #define NAME(PREFIX) PREFIX##_B8G8R8
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
202 #include "swrast/s_spantemp.h"
206 #define NAME(PREFIX) PREFIX##_B8G8R8A8
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]
220 #include "swrast/s_spantemp.h"
223 /* 16-bit BGR (XXX implement dithering someday) */
224 #define NAME(PREFIX) PREFIX##_B5G6R5
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) ); \
241 #include "swrast/s_spantemp.h"
244 /* 15-bit BGR (XXX implement dithering someday) */
245 #define NAME(PREFIX) PREFIX##_B5G5R5
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) ); \
262 #include "swrast/s_spantemp.h"
265 /* 8-bit color index */
266 #define NAME(PREFIX) PREFIX##_CI8
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) \
275 #define FETCH_CI_PIXEL(CI, P) \
278 #include "swrast/s_spantemp.h"
282 /* Initialize the driver specific screen private data.
285 fbInitDriver( __DRIscreenPrivate
*sPriv
)
287 sPriv
->private = NULL
;
292 fbDestroyScreen( __DRIscreenPrivate
*sPriv
)
296 /* Create the device specific context.
299 fbCreateContext( const __GLcontextModes
*glVisual
,
300 __DRIcontextPrivate
*driContextPriv
,
301 void *sharedContextPrivate
)
304 GLcontext
*ctx
, *shareCtx
;
305 struct dd_function_table functions
;
308 assert(driContextPriv
);
310 /* Allocate the Fb context */
311 fbmesa
= (fbContextPtr
) _mesa_calloc( sizeof(*fbmesa
) );
315 /* Init default driver functions then plug in our FBdev-specific functions
317 _mesa_init_driver_functions(&functions
);
318 init_core_functions(&functions
);
320 /* Allocate the Mesa context */
321 if (sharedContextPrivate
)
322 shareCtx
= ((fbContextPtr
) sharedContextPrivate
)->glCtx
;
326 ctx
= fbmesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
327 &functions
, (void *) fbmesa
);
328 if (!fbmesa
->glCtx
) {
332 driContextPriv
->driverPrivate
= fbmesa
;
334 /* Create module contexts */
335 _swrast_CreateContext( ctx
);
336 _ac_CreateContext( ctx
);
337 _tnl_CreateContext( ctx
);
338 _swsetup_CreateContext( ctx
);
339 _swsetup_Wakeup( ctx
);
342 /* swrast init -- need to verify these tests - I just plucked the
343 * numbers out of the air. (KW)
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
;
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
;
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
;
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
;
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
;
399 _mesa_printf("bad pixelformat rgb %d alpha %d\n",
401 glVisual
->alphaBits
);
405 /* use default TCL pipeline */
407 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
408 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
411 _mesa_enable_sw_extensions(ctx
);
418 fbDestroyContext( __DRIcontextPrivate
*driContextPriv
)
420 GET_CURRENT_CONTEXT(ctx
);
421 fbContextPtr fbmesa
= (fbContextPtr
) driContextPriv
->driverPrivate
;
422 fbContextPtr current
= ctx
? FB_CONTEXT(ctx
) : NULL
;
424 /* check if we're deleting the currently bound context */
425 if (fbmesa
== current
) {
426 _mesa_make_current2(NULL
, NULL
, NULL
);
429 /* Free fb context resources */
431 _swsetup_DestroyContext( fbmesa
->glCtx
);
432 _tnl_DestroyContext( fbmesa
->glCtx
);
433 _ac_DestroyContext( fbmesa
->glCtx
);
434 _swrast_DestroyContext( fbmesa
->glCtx
);
436 /* free the Mesa context */
437 fbmesa
->glCtx
->DriverCtx
= NULL
;
438 _mesa_destroy_context( fbmesa
->glCtx
);
440 _mesa_free( fbmesa
);
445 /* Create and initialize the Mesa and driver specific pixmap buffer
449 fbCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
450 __DRIdrawablePrivate
*driDrawPriv
,
451 const __GLcontextModes
*mesaVis
,
455 return GL_FALSE
; /* not implemented */
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
,
469 if (!driDrawPriv
->driverPrivate
)
472 /* Replace the framebuffer back buffer with a malloc'ed one --
475 if (driDrawPriv
->backBuffer
)
476 driDrawPriv
->backBuffer
= _mesa_malloc(driDrawPriv
->currentPitch
* driDrawPriv
->h
);
484 fbDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
486 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
487 _mesa_free(driDrawPriv
->backBuffer
);
492 /* If the backbuffer is on a videocard, this is extraordinarily slow!
495 fbSwapBuffers( __DRIdrawablePrivate
*dPriv
)
498 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
501 fbmesa
= (fbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
503 if (ctx
->Visual
.doubleBufferMode
) {
506 char *tmp
= _mesa_malloc(dPriv
->currentPitch
);
508 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
510 ASSERT(dPriv
->frontBuffer
);
511 ASSERT(dPriv
->backBuffer
);
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
;
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");
531 /* Force the context `c' to be the current context and associate with it
535 fbMakeCurrent( __DRIcontextPrivate
*driContextPriv
,
536 __DRIdrawablePrivate
*driDrawPriv
,
537 __DRIdrawablePrivate
*driReadPriv
)
539 if ( driContextPriv
) {
540 fbContextPtr newFbCtx
=
541 (fbContextPtr
) driContextPriv
->driverPrivate
;
543 newFbCtx
->dri
.drawable
= driDrawPriv
;
545 _mesa_make_current2( newFbCtx
->glCtx
,
546 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
547 (GLframebuffer
*) driReadPriv
->driverPrivate
);
549 _mesa_make_current( 0, 0 );
556 /* Force the context `c' to be unbound from its buffer.
559 fbUnbindContext( __DRIcontextPrivate
*driContextPriv
)
564 static struct __DriverAPIRec fbAPI
= {
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.
583 __driCreateScreen(struct DRIDriverRec
*driver
,
584 struct DRIDriverContextRec
*driverContext
)
586 __DRIscreenPrivate
*psp
;
587 psp
= __driUtilCreateScreenNoDRM(driver
, driverContext
, &fbAPI
);
593 * \brief Establish the set of modes available for the display.
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.
599 * \return one on success, or zero on failure.
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
605 const __GLcontextModes __glModes
[] = {
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
, },
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
, },
630 __driInitScreenModes( const DRIDriverContext
*ctx
,
631 int *numModes
, const __GLcontextModes
**modes
)
633 *numModes
= sizeof(__glModes
)/sizeof(__GLcontextModes
*);
634 *modes
= &__glModes
[0];
641 __driValidateMode(const DRIDriverContext
*ctx
)
647 __driInitFBDev( struct DRIDriverContextRec
*ctx
)
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
);
656 /* segment will already exist if previous server segfaulted */
657 id
= shmget(ctx
->shared
.hSAREA
, ctx
->shared
.SAREASize
, 0);
659 fprintf(stderr
, "fb: shmget failed\n");
663 ctx
->pSAREA
= shmat(id
, NULL
, 0);
664 if (ctx
->pSAREA
== (void *)-1) {
665 fprintf(stderr
, "fb: shmat failed\n");
668 memset(ctx
->pSAREA
, 0, SAREA_MAX
);
673 __driHaltFBDev( struct DRIDriverContextRec
*ctx
)
679 struct DRIDriverRec __driDriver
= {
680 __driInitScreenModes
,