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.
25 /* Minimal swrast-based dri loadable driver.
28 * -- Use malloced (rather than framebuffer) memory for backbuffer
29 * -- 32bpp is hardwared -- fix
32 * -- No mechanism for cliprects or resize notification --
33 * assumes this is a fullscreen device.
34 * -- No locking -- assumes this is the only driver accessing this
36 * -- Doesn't (yet) make use of any acceleration or other interfaces
37 * provided by fb. Would be entirely happy working against any
38 * fullscreen interface.
39 * -- HOWEVER: only a small number of pixelformats are supported, and
40 * the mechanism for choosing between them makes some assumptions
41 * that may not be valid everywhere.
49 #include "extensions.h"
50 #include "array_cache/acache.h"
51 #include "swrast/swrast.h"
52 #include "swrast_setup/swrast_setup.h"
54 #include "tnl/t_context.h"
55 #include "tnl/t_pipeline.h"
56 #include "drivers/common/driverfuncs.h"
60 GLcontext
*glCtx
; /* Mesa context */
63 __DRIcontextPrivate
*context
;
64 __DRIscreenPrivate
*screen
;
65 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
68 } fbContext
, *fbContextPtr
;
71 GLframebuffer
*mesa_framebuffer
;
76 } fbDrawable
, *fbDrawablePtr
;
79 unsigned long hFrameBuffer
;
90 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
92 #ifdef USE_NEW_INTERFACE
93 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
94 #endif /* USE_NEW_INTERFACE */
96 static const GLubyte
*
97 get_string(GLcontext
*ctx
, GLenum pname
)
102 return (const GLubyte
*) "Mesa dumb framebuffer";
110 update_state( GLcontext
*ctx
, GLuint new_state
)
112 /* not much to do here - pass it on */
113 _swrast_InvalidateState( ctx
, new_state
);
114 _swsetup_InvalidateState( ctx
, new_state
);
115 _ac_InvalidateState( ctx
, new_state
);
116 _tnl_InvalidateState( ctx
, new_state
);
121 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
122 * current framebuffer size.
125 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
127 GET_CURRENT_CONTEXT(ctx
);
128 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
130 *width
= fbmesa
->dri
.drawable
->w
;
131 *height
= fbmesa
->dri
.drawable
->h
;
136 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
138 _mesa_ResizeBuffersMESA();
142 /* specifies the buffer for swrast span rendering/reading */
144 set_buffer( GLcontext
*ctx
, GLframebuffer
*buffer
, GLuint bufferBit
)
146 fbContextPtr fbdevctx
= FB_CONTEXT(ctx
);
147 __DRIdrawablePrivate
*dPriv
= fbdevctx
->dri
.drawable
;
148 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)dPriv
->driverPrivate
;
150 /* What a twisted mess of private structs
152 assert(buffer
== fbdrawable
->mesa_framebuffer
);
156 case DD_FRONT_LEFT_BIT
:
157 fbdrawable
->currentBuffer
= fbdrawable
->frontBuffer
;
159 case DD_BACK_LEFT_BIT
:
160 fbdrawable
->currentBuffer
= fbdrawable
->backBuffer
;
163 /* This happens a lot if the client renders to the frontbuffer */
164 if (0) _mesa_problem(ctx
, "bad bufferBit in set_buffer()");
170 init_core_functions( struct dd_function_table
*functions
)
172 functions
->GetString
= get_string
;
173 functions
->UpdateState
= update_state
;
174 functions
->ResizeBuffers
= _swrast_alloc_buffers
;
175 functions
->GetBufferSize
= get_buffer_size
;
176 functions
->Viewport
= viewport
;
178 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
183 * Generate code for span functions.
187 #define NAME(PREFIX) PREFIX##_B8G8R8
189 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
190 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
191 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
192 #define INIT_PIXEL_PTR(P, X, Y) \
193 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->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 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
211 #define INIT_PIXEL_PTR(P, X, Y) \
212 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 4;
213 #define INC_PIXEL_PTR(P) P += 4
214 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
215 P[0] = B; P[1] = G; P[2] = R; P[3] = 255
216 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
217 P[0] = B; P[1] = G; P[2] = R; P[3] = A
218 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
219 R = P[2]; G = P[1]; B = P[0]; A = P[3]
221 #include "swrast/s_spantemp.h"
224 /* 16-bit BGR (XXX implement dithering someday) */
225 #define NAME(PREFIX) PREFIX##_B5G6R5
227 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
228 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
229 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
230 #define INIT_PIXEL_PTR(P, X, Y) \
231 GLushort *P = (GLushort *) ((char *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 2)
232 #define INC_PIXEL_PTR(P) P += 1
233 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
234 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
235 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
236 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
237 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
238 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
239 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
240 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
243 #include "swrast/s_spantemp.h"
246 /* 15-bit BGR (XXX implement dithering someday) */
247 #define NAME(PREFIX) PREFIX##_B5G5R5
249 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
250 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
251 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
252 #define INIT_PIXEL_PTR(P, X, Y) \
253 GLushort *P = (GLushort *) ((char *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 2)
254 #define INC_PIXEL_PTR(P) P += 1
255 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
256 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
257 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
258 *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
259 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
260 R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
261 G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
262 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
265 #include "swrast/s_spantemp.h"
268 /* 8-bit color index */
269 #define NAME(PREFIX) PREFIX##_CI8
271 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
272 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
273 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
274 #define INIT_PIXEL_PTR(P, X, Y) \
275 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X)
276 #define INC_PIXEL_PTR(P) P += 1
277 #define STORE_CI_PIXEL(P, CI) \
279 #define FETCH_CI_PIXEL(CI, P) \
282 #include "swrast/s_spantemp.h"
285 /* Initialize the driver specific screen private data.
288 fbInitDriver( __DRIscreenPrivate
*sPriv
)
290 fbDRIPtr dri_priv
= (fbDRIPtr
)sPriv
->pDevPriv
;
294 drmFD
= drmOpen("radeon", NULL
);
296 fprintf(stderr
, "[drm] drmOpen failed\n");
300 priv
= _mesa_malloc(sizeof(*priv
));
307 if (drmMap(drmFD
, priv
->hFrameBuffer
, priv
->fbSize
, &priv
->fbMap
) < 0) {
308 fprintf(stderr
, "[drm] drmMap framebuffer failed\n");
313 sPriv
->private = priv
;
318 fbDestroyScreen( __DRIscreenPrivate
*sPriv
)
320 fbDRIPtr priv
= (fbDRIPtr
)sPriv
->private;
322 drmUnmap(priv
->fbMap
, priv
->fbSize
);
323 drmClose(priv
->drmFD
);
327 /* Create the device specific context.
330 fbCreateContext( const __GLcontextModes
*glVisual
,
331 __DRIcontextPrivate
*driContextPriv
,
332 void *sharedContextPrivate
)
335 GLcontext
*ctx
, *shareCtx
;
336 struct dd_function_table functions
;
339 assert(driContextPriv
);
341 /* Allocate the Fb context */
342 fbmesa
= (fbContextPtr
) _mesa_calloc( sizeof(*fbmesa
) );
346 /* Init default driver functions then plug in our FBdev-specific functions
348 _mesa_init_driver_functions(&functions
);
349 init_core_functions(&functions
);
351 /* Allocate the Mesa context */
352 if (sharedContextPrivate
)
353 shareCtx
= ((fbContextPtr
) sharedContextPrivate
)->glCtx
;
357 ctx
= fbmesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
358 &functions
, (void *) fbmesa
);
359 if (!fbmesa
->glCtx
) {
363 driContextPriv
->driverPrivate
= fbmesa
;
365 /* Create module contexts */
366 _swrast_CreateContext( ctx
);
367 _ac_CreateContext( ctx
);
368 _tnl_CreateContext( ctx
);
369 _swsetup_CreateContext( ctx
);
370 _swsetup_Wakeup( ctx
);
373 /* swrast init -- need to verify these tests - I just plucked the
374 * numbers out of the air. (KW)
377 struct swrast_device_driver
*swdd
;
378 swdd
= _swrast_GetDeviceDriverReference( ctx
);
379 swdd
->SetBuffer
= set_buffer
;
380 if (!glVisual
->rgbMode
) {
381 swdd
->WriteCI32Span
= write_index32_span_CI8
;
382 swdd
->WriteCI8Span
= write_index8_span_CI8
;
383 swdd
->WriteMonoCISpan
= write_monoindex_span_CI8
;
384 swdd
->WriteCI32Pixels
= write_index_pixels_CI8
;
385 swdd
->WriteMonoCIPixels
= write_monoindex_pixels_CI8
;
386 swdd
->ReadCI32Span
= read_index_span_CI8
;
387 swdd
->ReadCI32Pixels
= read_index_pixels_CI8
;
389 else if (glVisual
->rgbBits
== 24 &&
390 glVisual
->alphaBits
== 0) {
391 swdd
->WriteRGBASpan
= write_rgba_span_B8G8R8
;
392 swdd
->WriteRGBSpan
= write_rgb_span_B8G8R8
;
393 swdd
->WriteMonoRGBASpan
= write_monorgba_span_B8G8R8
;
394 swdd
->WriteRGBAPixels
= write_rgba_pixels_B8G8R8
;
395 swdd
->WriteMonoRGBAPixels
= write_monorgba_pixels_B8G8R8
;
396 swdd
->ReadRGBASpan
= read_rgba_span_B8G8R8
;
397 swdd
->ReadRGBAPixels
= read_rgba_pixels_B8G8R8
;
399 else if (glVisual
->rgbBits
== 32 &&
400 glVisual
->alphaBits
== 8) {
401 swdd
->WriteRGBASpan
= write_rgba_span_B8G8R8A8
;
402 swdd
->WriteRGBSpan
= write_rgb_span_B8G8R8A8
;
403 swdd
->WriteMonoRGBASpan
= write_monorgba_span_B8G8R8A8
;
404 swdd
->WriteRGBAPixels
= write_rgba_pixels_B8G8R8A8
;
405 swdd
->WriteMonoRGBAPixels
= write_monorgba_pixels_B8G8R8A8
;
406 swdd
->ReadRGBASpan
= read_rgba_span_B8G8R8A8
;
407 swdd
->ReadRGBAPixels
= read_rgba_pixels_B8G8R8A8
;
409 else if (glVisual
->rgbBits
== 16 &&
410 glVisual
->alphaBits
== 0) {
411 swdd
->WriteRGBASpan
= write_rgba_span_B5G6R5
;
412 swdd
->WriteRGBSpan
= write_rgb_span_B5G6R5
;
413 swdd
->WriteMonoRGBASpan
= write_monorgba_span_B5G6R5
;
414 swdd
->WriteRGBAPixels
= write_rgba_pixels_B5G6R5
;
415 swdd
->WriteMonoRGBAPixels
= write_monorgba_pixels_B5G6R5
;
416 swdd
->ReadRGBASpan
= read_rgba_span_B5G6R5
;
417 swdd
->ReadRGBAPixels
= read_rgba_pixels_B5G6R5
;
419 else if (glVisual
->rgbBits
== 15 &&
420 glVisual
->alphaBits
== 0) {
421 swdd
->WriteRGBASpan
= write_rgba_span_B5G5R5
;
422 swdd
->WriteRGBSpan
= write_rgb_span_B5G5R5
;
423 swdd
->WriteMonoRGBASpan
= write_monorgba_span_B5G5R5
;
424 swdd
->WriteRGBAPixels
= write_rgba_pixels_B5G5R5
;
425 swdd
->WriteMonoRGBAPixels
= write_monorgba_pixels_B5G5R5
;
426 swdd
->ReadRGBASpan
= read_rgba_span_B5G5R5
;
427 swdd
->ReadRGBAPixels
= read_rgba_pixels_B5G5R5
;
430 _mesa_printf("bad pixelformat rgb %d alpha %d\n",
432 glVisual
->alphaBits
);
436 /* use default TCL pipeline */
438 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
439 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
442 _mesa_enable_sw_extensions(ctx
);
449 fbDestroyContext( __DRIcontextPrivate
*driContextPriv
)
451 GET_CURRENT_CONTEXT(ctx
);
452 fbContextPtr fbmesa
= (fbContextPtr
) driContextPriv
->driverPrivate
;
453 fbContextPtr current
= ctx
? FB_CONTEXT(ctx
) : NULL
;
455 /* check if we're deleting the currently bound context */
456 if (fbmesa
== current
) {
457 _mesa_make_current2(NULL
, NULL
, NULL
);
460 /* Free fb context resources */
462 _swsetup_DestroyContext( fbmesa
->glCtx
);
463 _tnl_DestroyContext( fbmesa
->glCtx
);
464 _ac_DestroyContext( fbmesa
->glCtx
);
465 _swrast_DestroyContext( fbmesa
->glCtx
);
467 /* free the Mesa context */
468 fbmesa
->glCtx
->DriverCtx
= NULL
;
469 _mesa_destroy_context( fbmesa
->glCtx
);
471 _mesa_free( fbmesa
);
476 /* Create and initialize the Mesa and driver specific pixmap buffer
480 fbCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
481 __DRIdrawablePrivate
*driDrawPriv
,
482 const __GLcontextModes
*mesaVis
,
485 fbDRIPtr spriv
= (fbDRIPtr
)driScrnPriv
->private;
486 fbDrawablePtr fbdrawable
;
489 return GL_FALSE
; /* not implemented */
492 const GLboolean swDepth
= mesaVis
->depthBits
> 0;
493 const GLboolean swAlpha
= mesaVis
->alphaBits
> 0;
494 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
495 const GLboolean swStencil
= mesaVis
->stencilBits
> 0;
497 fbdrawable
= _mesa_calloc(sizeof(*fbdrawable
));
501 fbdrawable
->mesa_framebuffer
= (void *)
502 _mesa_create_framebuffer( mesaVis
,
508 if (!fbdrawable
->mesa_framebuffer
) {
509 _mesa_free(fbdrawable
);
512 driDrawPriv
->driverPrivate
= fbdrawable
;
514 fbdrawable
->frontBuffer
= fbdrawable
->currentBuffer
= spriv
->fbMap
;
515 fbdrawable
->currentPitch
= spriv
->fbWidth
;
517 /* Replace the framebuffer back buffer with a malloc'ed one --
520 fbdrawable
->backBuffer
= _mesa_malloc(fbdrawable
->currentPitch
* driDrawPriv
->h
);
528 fbDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
530 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)driDrawPriv
->driverPrivate
;
532 _mesa_destroy_framebuffer(fbdrawable
->mesa_framebuffer
);
533 _mesa_free(fbdrawable
->backBuffer
);
534 _mesa_free(fbdrawable
);
535 driDrawPriv
->driverPrivate
= NULL
;
540 /* If the backbuffer is on a videocard, this is extraordinarily slow!
543 fbSwapBuffers( __DRIdrawablePrivate
*dPriv
)
545 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)dPriv
->driverPrivate
;
547 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
550 fbmesa
= (fbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
552 if (ctx
->Visual
.doubleBufferMode
) {
555 char *tmp
= _mesa_malloc(fbdrawable
->currentPitch
);
557 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
559 ASSERT(fbdrawable
->frontBuffer
);
560 ASSERT(fbdrawable
->backBuffer
);
562 for (i
= 0; i
< dPriv
->h
; i
++) {
563 _mesa_memcpy(tmp
, (char *) fbdrawable
->backBuffer
+ offset
,
564 fbdrawable
->currentPitch
);
565 _mesa_memcpy((char *) fbdrawable
->frontBuffer
+ offset
, tmp
,
566 fbdrawable
->currentPitch
);
567 offset
+= fbdrawable
->currentPitch
;
574 /* XXX this shouldn't be an error but we can't handle it for now */
575 _mesa_problem(NULL
, "fbSwapBuffers: drawable has no context!\n");
580 /* Force the context `c' to be the current context and associate with it
584 fbMakeCurrent( __DRIcontextPrivate
*driContextPriv
,
585 __DRIdrawablePrivate
*driDrawPriv
,
586 __DRIdrawablePrivate
*driReadPriv
)
588 if ( driContextPriv
) {
589 fbContextPtr newFbCtx
=
590 (fbContextPtr
) driContextPriv
->driverPrivate
;
592 newFbCtx
->dri
.drawable
= driDrawPriv
;
594 _mesa_make_current2( newFbCtx
->glCtx
,
595 ((fbDrawablePtr
)driDrawPriv
->driverPrivate
)->mesa_framebuffer
,
596 ((fbDrawablePtr
)driReadPriv
->driverPrivate
)->mesa_framebuffer
);
598 _mesa_make_current( 0, 0 );
605 /* Force the context `c' to be unbound from its buffer.
608 fbUnbindContext( __DRIcontextPrivate
*driContextPriv
)
613 static struct __DriverAPIRec fbAPI
= {
614 .InitDriver
= fbInitDriver
,
615 .DestroyScreen
= fbDestroyScreen
,
616 .CreateContext
= fbCreateContext
,
617 .DestroyContext
= fbDestroyContext
,
618 .CreateBuffer
= fbCreateBuffer
,
619 .DestroyBuffer
= fbDestroyBuffer
,
620 .SwapBuffers
= fbSwapBuffers
,
621 .MakeCurrent
= fbMakeCurrent
,
622 .UnbindContext
= fbUnbindContext
,
628 __driValidateMode(const DRIDriverContext
*ctx
)
634 __driInitFBDev( struct DRIDriverContextRec
*ctx
)
638 /* Note that drmOpen will try to load the kernel module, if needed. */
639 /* we need a fbdev drm driver - it will only track maps */
640 ctx
->drmFD
= drmOpen("radeon", NULL
);
641 if (ctx
->drmFD
< 0) {
642 fprintf(stderr
, "[drm] drmOpen failed\n");
646 ctx
->shared
.SAREASize
= SAREA_MAX
;
648 if (drmAddMap( ctx
->drmFD
,
650 ctx
->shared
.SAREASize
,
653 &ctx
->shared
.hSAREA
) < 0)
655 fprintf(stderr
, "[drm] drmAddMap failed\n");
658 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
659 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
661 if (drmMap( ctx
->drmFD
,
663 ctx
->shared
.SAREASize
,
664 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
666 fprintf(stderr
, "[drm] drmMap failed\n");
669 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
670 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
671 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
673 /* Need to AddMap the framebuffer and mmio regions here:
675 if (drmAddMap( ctx
->drmFD
,
676 (drm_handle_t
)ctx
->FBStart
,
684 &ctx
->shared
.hFrameBuffer
) < 0)
686 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
690 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
691 ctx
->shared
.hFrameBuffer
);
693 pfbDRI
= (fbDRIPtr
)malloc(sizeof(*pfbDRI
));
694 pfbDRI
->hFrameBuffer
= ctx
->shared
.hFrameBuffer
;
695 pfbDRI
->fbOrigin
= ctx
->shared
.fbOrigin
;
696 pfbDRI
->fbSize
= ctx
->shared
.fbSize
;
697 pfbDRI
->fbStride
= ctx
->shared
.fbStride
;
698 pfbDRI
->fbWidth
= ctx
->shared
.virtualWidth
;
699 pfbDRI
->fbHeight
= ctx
->shared
.virtualHeight
;
700 pfbDRI
->bpp
= ctx
->bpp
;
702 ctx
->driverClientMsg
= pfbDRI
;
703 ctx
->driverClientMsgSize
= sizeof(*pfbDRI
);
709 __driHaltFBDev( struct DRIDriverContextRec
*ctx
)
713 struct DRIDriverRec __driDriver
= {
720 #ifdef USE_NEW_INTERFACE
721 static __GLcontextModes
*
722 fbFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
723 unsigned stencil_bits
, GLboolean have_back_buffer
)
725 __GLcontextModes
* modes
;
726 __GLcontextModes
* m
;
728 unsigned depth_buffer_factor
;
729 unsigned back_buffer_factor
;
733 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
734 * enough to add support. Basically, if a context is created with an
735 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
736 * will never be used.
738 static const GLenum back_buffer_modes
[] = {
739 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
742 u_int8_t depth_bits_array
[2];
743 u_int8_t stencil_bits_array
[2];
746 depth_bits_array
[0] = depth_bits
;
747 depth_bits_array
[1] = depth_bits
;
749 /* Just like with the accumulation buffer, always provide some modes
750 * with a stencil buffer. It will be a sw fallback, but some apps won't
753 stencil_bits_array
[0] = 0;
754 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
756 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
757 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
759 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
761 if ( pixel_bits
== 16 ) {
763 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
767 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
770 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
772 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
773 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
774 back_buffer_modes
, back_buffer_factor
,
776 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
777 __func__
, __LINE__
);
781 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
782 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
783 back_buffer_modes
, back_buffer_factor
,
784 GLX_DIRECT_COLOR
) ) {
785 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
786 __func__
, __LINE__
);
790 /* Mark the visual as slow if there are "fake" stencil bits.
792 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
793 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
794 m
->visualRating
= GLX_SLOW_CONFIG
;
803 * This is the bootstrap function for the driver. libGL supplies all of the
804 * requisite information about the system, and the driver initializes itself.
805 * This routine also fills in the linked list pointed to by \c driver_modes
806 * with the \c __GLcontextModes that the driver can support for windows or
809 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
813 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
814 const __GLcontextModes
* modes
,
815 const __DRIversion
* ddx_version
,
816 const __DRIversion
* dri_version
,
817 const __DRIversion
* drm_version
,
818 const __DRIframebuffer
* frame_buffer
,
819 drmAddress pSAREA
, int fd
,
820 int internal_api_version
,
821 __GLcontextModes
** driver_modes
)
823 __DRIscreenPrivate
*psp
;
824 static const __DRIversion ddx_expected
= { 4, 0, 0 };
825 static const __DRIversion dri_expected
= { 4, 0, 0 };
826 static const __DRIversion drm_expected
= { 1, 5, 0 };
829 if ( ! driCheckDriDdxDrmVersions2( "fb",
830 dri_version
, & dri_expected
,
831 ddx_version
, & ddx_expected
,
832 drm_version
, & drm_expected
) ) {
836 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
837 ddx_version
, dri_version
, drm_version
,
838 frame_buffer
, pSAREA
, fd
,
839 internal_api_version
, &fbAPI
);
841 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
842 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
843 if ( create_context_modes
!= NULL
) {
845 fbDRIPtr dri_priv
= (fbDRIPtr
) psp
->pDevPriv
;
846 *driver_modes
= fbFillInModes( dri_priv
->bpp
,
847 (dri_priv
->bpp
== 16) ? 16 : 24,
848 (dri_priv
->bpp
== 16) ? 0 : 8,
849 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
851 *driver_modes
= fbFillInModes( 24, 24, 8, 0);
857 #endif /* USE_NEW_INTERFACE */