2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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.
47 #include "drirenderbuffer.h"
50 #include "extensions.h"
51 #include "framebuffer.h"
52 #include "renderbuffer.h"
53 #include "array_cache/acache.h"
54 #include "swrast/swrast.h"
55 #include "swrast_setup/swrast_setup.h"
57 #include "tnl/t_context.h"
58 #include "tnl/t_pipeline.h"
59 #include "drivers/common/driverfuncs.h"
63 GLcontext
*glCtx
; /* Mesa context */
66 __DRIcontextPrivate
*context
;
67 __DRIscreenPrivate
*screen
;
68 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
71 } fbContext
, *fbContextPtr
;
74 GLframebuffer
*mesa_framebuffer
;
79 } fbDrawable
, *fbDrawablePtr
;
81 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
83 #ifdef USE_NEW_INTERFACE
84 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
85 #endif /* USE_NEW_INTERFACE */
87 static const GLubyte
*
88 get_string(GLcontext
*ctx
, GLenum pname
)
93 return (const GLubyte
*) "Mesa dumb framebuffer";
101 update_state( GLcontext
*ctx
, GLuint new_state
)
103 /* not much to do here - pass it on */
104 _swrast_InvalidateState( ctx
, new_state
);
105 _swsetup_InvalidateState( ctx
, new_state
);
106 _ac_InvalidateState( ctx
, new_state
);
107 _tnl_InvalidateState( ctx
, new_state
);
112 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
113 * current framebuffer size.
116 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
118 GET_CURRENT_CONTEXT(ctx
);
119 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
121 *width
= fbmesa
->dri
.drawable
->w
;
122 *height
= fbmesa
->dri
.drawable
->h
;
127 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
129 _mesa_ResizeBuffersMESA();
133 /* specifies the buffer for swrast span rendering/reading */
135 set_buffer( GLcontext
*ctx
, GLframebuffer
*buffer
, GLuint bufferBit
)
137 fbContextPtr fbdevctx
= FB_CONTEXT(ctx
);
138 __DRIdrawablePrivate
*dPriv
= fbdevctx
->dri
.drawable
;
139 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)dPriv
->driverPrivate
;
141 /* What a twisted mess of private structs
143 assert(buffer
== fbdrawable
->mesa_framebuffer
);
147 case BUFFER_BIT_FRONT_LEFT
:
148 fbdrawable
->currentBuffer
= fbdrawable
->frontBuffer
;
150 case BUFFER_BIT_BACK_LEFT
:
151 fbdrawable
->currentBuffer
= fbdrawable
->backBuffer
;
154 /* This happens a lot if the client renders to the frontbuffer */
155 if (0) _mesa_problem(ctx
, "bad bufferBit in set_buffer()");
161 init_core_functions( struct dd_function_table
*functions
)
163 functions
->GetString
= get_string
;
164 functions
->UpdateState
= update_state
;
165 functions
->ResizeBuffers
= _mesa_resize_framebuffer
;
166 functions
->GetBufferSize
= get_buffer_size
;
167 functions
->Viewport
= viewport
;
169 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
174 * Generate code for span functions.
178 #define NAME(PREFIX) PREFIX##_B8G8R8
179 #define FORMAT GL_RGBA8
181 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
182 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
183 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
184 #define INIT_PIXEL_PTR(P, X, Y) \
185 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 3
186 #define INC_PIXEL_PTR(P) P += 3
187 #define STORE_PIXEL(DST, X, Y, VALUE) \
188 DST[0] = VALUE[BCOMP]; \
189 DST[1] = VALUE[GCOMP]; \
190 DST[2] = VALUE[RCOMP]
191 #define FETCH_PIXEL(DST, SRC) \
192 DST[RCOMP] = SRC[2]; \
193 DST[GCOMP] = SRC[1]; \
194 DST[BCOMP] = SRC[0]; \
197 #include "swrast/s_spantemp.h"
201 #define NAME(PREFIX) PREFIX##_B8G8R8A8
202 #define FORMAT GL_RGBA8
204 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
205 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
206 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
207 #define INIT_PIXEL_PTR(P, X, Y) \
208 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 4;
209 #define INC_PIXEL_PTR(P) P += 4
210 #define STORE_PIXEL(DST, X, Y, VALUE) \
211 DST[0] = VALUE[BCOMP]; \
212 DST[1] = VALUE[GCOMP]; \
213 DST[2] = VALUE[RCOMP]; \
214 DST[3] = VALUE[ACOMP]
215 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
216 DST[0] = VALUE[BCOMP]; \
217 DST[1] = VALUE[GCOMP]; \
218 DST[2] = VALUE[RCOMP]; \
220 #define FETCH_PIXEL(DST, SRC) \
221 DST[RCOMP] = SRC[2]; \
222 DST[GCOMP] = SRC[1]; \
223 DST[BCOMP] = SRC[0]; \
226 #include "swrast/s_spantemp.h"
229 /* 16-bit BGR (XXX implement dithering someday) */
230 #define NAME(PREFIX) PREFIX##_B5G6R5
231 #define FORMAT GL_RGBA8
233 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
234 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
235 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
236 #define INIT_PIXEL_PTR(P, X, Y) \
237 GLushort *P = (GLushort *) ((char *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 2)
238 #define INC_PIXEL_PTR(P) P += 1
239 #define STORE_PIXEL(DST, X, Y, VALUE) \
240 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
241 #define FETCH_PIXEL(DST, SRC) \
242 DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \
243 DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \
244 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
247 #include "swrast/s_spantemp.h"
250 /* 15-bit BGR (XXX implement dithering someday) */
251 #define NAME(PREFIX) PREFIX##_B5G5R5
252 #define FORMAT GL_RGBA8
254 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
255 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
256 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
257 #define INIT_PIXEL_PTR(P, X, Y) \
258 GLushort *P = (GLushort *) ((char *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X) * 2)
259 #define INC_PIXEL_PTR(P) P += 1
260 #define STORE_PIXEL(DST, X, Y, VALUE) \
261 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) )
262 #define FETCH_PIXEL(DST, SRC) \
263 DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \
264 DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \
265 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
268 #include "swrast/s_spantemp.h"
271 /* 8-bit color index */
272 #define NAME(PREFIX) PREFIX##_CI8
273 #define FORMAT GL_COLOR_INDEX8_EXT
275 const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
276 __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; \
277 const fbDrawablePtr fbdrawable = (fbDrawablePtr)dPriv->driverPrivate;
278 #define INIT_PIXEL_PTR(P, X, Y) \
279 GLubyte *P = (GLubyte *)fbdrawable->currentBuffer + (Y) * fbdrawable->currentPitch + (X)
280 #define INC_PIXEL_PTR(P) P += 1
281 #define STORE_PIXEL(DST, X, Y, VALUE) \
283 #define FETCH_PIXEL(DST, SRC) \
286 #include "swrast/s_spantemp.h"
291 fbSetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
)
293 ASSERT(drb
->Base
.InternalFormat
== GL_RGBA
);
294 if (drb
->Base
.InternalFormat
== GL_RGBA
) {
295 if (vis
->redBits
== 5 && vis
->greenBits
== 6 && vis
->blueBits
== 5) {
296 drb
->Base
.GetRow
= get_row_B5G6R5
;
297 drb
->Base
.GetValues
= get_values_B5G6R5
;
298 drb
->Base
.PutRow
= put_row_B5G6R5
;
299 drb
->Base
.PutMonoRow
= put_mono_row_B5G6R5
;
300 drb
->Base
.PutRowRGB
= put_row_rgb_B5G6R5
;
301 drb
->Base
.PutValues
= put_values_B5G6R5
;
302 drb
->Base
.PutMonoValues
= put_mono_values_B5G6R5
;
304 else if (vis
->redBits
== 5 && vis
->greenBits
== 5 && vis
->blueBits
== 5) {
305 drb
->Base
.GetRow
= get_row_B5G5R5
;
306 drb
->Base
.GetValues
= get_values_B5G5R5
;
307 drb
->Base
.PutRow
= put_row_B5G5R5
;
308 drb
->Base
.PutMonoRow
= put_mono_row_B5G5R5
;
309 drb
->Base
.PutRowRGB
= put_row_rgb_B5G5R5
;
310 drb
->Base
.PutValues
= put_values_B5G5R5
;
311 drb
->Base
.PutMonoValues
= put_mono_values_B5G5R5
;
313 else if (vis
->redBits
== 8 && vis
->greenBits
== 8 && vis
->blueBits
== 8
314 && vis
->alphaBits
== 8) {
315 drb
->Base
.GetRow
= get_row_B8G8R8A8
;
316 drb
->Base
.GetValues
= get_values_B8G8R8A8
;
317 drb
->Base
.PutRow
= put_row_B8G8R8A8
;
318 drb
->Base
.PutMonoRow
= put_mono_row_B8G8R8A8
;
319 drb
->Base
.PutRowRGB
= put_row_rgb_B8G8R8A8
;
320 drb
->Base
.PutValues
= put_values_B8G8R8A8
;
321 drb
->Base
.PutMonoValues
= put_mono_values_B8G8R8A8
;
323 else if (vis
->redBits
== 8 && vis
->greenBits
== 8 && vis
->blueBits
== 8
324 && vis
->alphaBits
== 0) {
325 drb
->Base
.GetRow
= get_row_B8G8R8
;
326 drb
->Base
.GetValues
= get_values_B8G8R8
;
327 drb
->Base
.PutRow
= put_row_B8G8R8
;
328 drb
->Base
.PutMonoRow
= put_mono_row_B8G8R8
;
329 drb
->Base
.PutRowRGB
= put_row_rgb_B8G8R8
;
330 drb
->Base
.PutValues
= put_values_B8G8R8
;
331 drb
->Base
.PutMonoValues
= put_mono_values_B8G8R8
;
333 else if (vis
->indexBits
== 8) {
334 drb
->Base
.GetRow
= get_row_CI8
;
335 drb
->Base
.GetValues
= get_values_CI8
;
336 drb
->Base
.PutRow
= put_row_CI8
;
337 drb
->Base
.PutMonoRow
= put_mono_row_CI8
;
338 drb
->Base
.PutValues
= put_values_CI8
;
339 drb
->Base
.PutMonoValues
= put_mono_values_CI8
;
343 /* hardware z/stencil/etc someday */
349 /* Initialize the driver specific screen private data.
352 fbInitDriver( __DRIscreenPrivate
*sPriv
)
354 sPriv
->private = NULL
;
359 fbDestroyScreen( __DRIscreenPrivate
*sPriv
)
363 /* Create the device specific context.
366 fbCreateContext( const __GLcontextModes
*glVisual
,
367 __DRIcontextPrivate
*driContextPriv
,
368 void *sharedContextPrivate
)
371 GLcontext
*ctx
, *shareCtx
;
372 struct dd_function_table functions
;
375 assert(driContextPriv
);
377 /* Allocate the Fb context */
378 fbmesa
= (fbContextPtr
) _mesa_calloc( sizeof(*fbmesa
) );
382 /* Init default driver functions then plug in our FBdev-specific functions
384 _mesa_init_driver_functions(&functions
);
385 init_core_functions(&functions
);
387 /* Allocate the Mesa context */
388 if (sharedContextPrivate
)
389 shareCtx
= ((fbContextPtr
) sharedContextPrivate
)->glCtx
;
393 ctx
= fbmesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
394 &functions
, (void *) fbmesa
);
395 if (!fbmesa
->glCtx
) {
399 driContextPriv
->driverPrivate
= fbmesa
;
401 /* Create module contexts */
402 _swrast_CreateContext( ctx
);
403 _ac_CreateContext( ctx
);
404 _tnl_CreateContext( ctx
);
405 _swsetup_CreateContext( ctx
);
406 _swsetup_Wakeup( ctx
);
409 /* swrast init -- need to verify these tests - I just plucked the
410 * numbers out of the air. (KW)
413 struct swrast_device_driver
*swdd
;
414 swdd
= _swrast_GetDeviceDriverReference( ctx
);
415 swdd
->SetBuffer
= set_buffer
;
418 /* use default TCL pipeline */
420 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
421 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
424 _mesa_enable_sw_extensions(ctx
);
431 fbDestroyContext( __DRIcontextPrivate
*driContextPriv
)
433 GET_CURRENT_CONTEXT(ctx
);
434 fbContextPtr fbmesa
= (fbContextPtr
) driContextPriv
->driverPrivate
;
435 fbContextPtr current
= ctx
? FB_CONTEXT(ctx
) : NULL
;
437 /* check if we're deleting the currently bound context */
438 if (fbmesa
== current
) {
439 _mesa_make_current(NULL
, NULL
, NULL
);
442 /* Free fb context resources */
444 _swsetup_DestroyContext( fbmesa
->glCtx
);
445 _tnl_DestroyContext( fbmesa
->glCtx
);
446 _ac_DestroyContext( fbmesa
->glCtx
);
447 _swrast_DestroyContext( fbmesa
->glCtx
);
449 /* free the Mesa context */
450 fbmesa
->glCtx
->DriverCtx
= NULL
;
451 _mesa_destroy_context( fbmesa
->glCtx
);
453 _mesa_free( fbmesa
);
458 /* Create and initialize the Mesa and driver specific pixmap buffer
462 fbCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
463 __DRIdrawablePrivate
*driDrawPriv
,
464 const __GLcontextModes
*mesaVis
,
467 fbDrawablePtr fbdrawable
;
470 return GL_FALSE
; /* not implemented */
473 const GLboolean swDepth
= mesaVis
->depthBits
> 0;
474 const GLboolean swAlpha
= mesaVis
->alphaBits
> 0;
475 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
476 const GLboolean swStencil
= mesaVis
->stencilBits
> 0;
478 fbdrawable
= _mesa_calloc(sizeof(*fbdrawable
));
483 fbdrawable
->mesa_framebuffer
= (void *)
484 _mesa_create_framebuffer( mesaVis
,
490 if (!fbdrawable
->mesa_framebuffer
) {
491 _mesa_free(fbdrawable
);
495 fbdrawable
->mesa_framebuffer
= _mesa_create_framebuffer(mesaVis
);
496 if (!fbdrawable
->mesa_framebuffer
) {
497 _mesa_free(fbdrawable
);
501 /* XXX double-check these parameters (bpp vs cpp, etc) */
503 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, driScrnPriv
->fbBPP
,
504 driScrnPriv
->fbOrigin
,
505 driScrnPriv
->fbStride
);
506 fbSetSpanFunctions(drb
, mesaVis
);
507 _mesa_add_renderbuffer(fbdrawable
->mesa_framebuffer
,
508 BUFFER_FRONT_LEFT
, &drb
->Base
);
510 if (mesaVis
->doubleBufferMode
) {
511 /* XXX what are the correct origin/stride values? */
512 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, driScrnPriv
->fbBPP
,
513 driScrnPriv
->fbOrigin
,
514 driScrnPriv
->fbStride
);
515 fbSetSpanFunctions(drb
, mesaVis
);
516 _mesa_add_renderbuffer(fbdrawable
->mesa_framebuffer
,
517 BUFFER_BACK_LEFT
, &drb
->Base
);
520 _mesa_add_soft_renderbuffers(fbdrawable
->mesa_framebuffer
,
521 GL_FALSE
, /* color */
530 driDrawPriv
->driverPrivate
= fbdrawable
;
532 fbdrawable
->frontBuffer
= fbdrawable
->currentBuffer
= driScrnPriv
->pFB
;
533 fbdrawable
->currentPitch
= driScrnPriv
->fbStride
;
535 /* Replace the framebuffer back buffer with a malloc'ed one --
538 fbdrawable
->backBuffer
= _mesa_malloc(fbdrawable
->currentPitch
* driDrawPriv
->h
);
546 fbDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
548 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)driDrawPriv
->driverPrivate
;
550 _mesa_destroy_framebuffer(fbdrawable
->mesa_framebuffer
);
551 _mesa_free(fbdrawable
->backBuffer
);
552 _mesa_free(fbdrawable
);
553 driDrawPriv
->driverPrivate
= NULL
;
558 /* If the backbuffer is on a videocard, this is extraordinarily slow!
561 fbSwapBuffers( __DRIdrawablePrivate
*dPriv
)
563 fbDrawablePtr fbdrawable
= (fbDrawablePtr
)dPriv
->driverPrivate
;
565 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
568 fbmesa
= (fbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
570 if (ctx
->Visual
.doubleBufferMode
) {
573 char *tmp
= _mesa_malloc(fbdrawable
->currentPitch
);
575 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
577 ASSERT(fbdrawable
->frontBuffer
);
578 ASSERT(fbdrawable
->backBuffer
);
580 for (i
= 0; i
< dPriv
->h
; i
++) {
581 _mesa_memcpy(tmp
, (char *) fbdrawable
->backBuffer
+ offset
,
582 fbdrawable
->currentPitch
);
583 _mesa_memcpy((char *) fbdrawable
->frontBuffer
+ offset
, tmp
,
584 fbdrawable
->currentPitch
);
585 offset
+= fbdrawable
->currentPitch
;
592 /* XXX this shouldn't be an error but we can't handle it for now */
593 _mesa_problem(NULL
, "fbSwapBuffers: drawable has no context!\n");
598 /* Force the context `c' to be the current context and associate with it
602 fbMakeCurrent( __DRIcontextPrivate
*driContextPriv
,
603 __DRIdrawablePrivate
*driDrawPriv
,
604 __DRIdrawablePrivate
*driReadPriv
)
606 if ( driContextPriv
) {
607 fbContextPtr newFbCtx
=
608 (fbContextPtr
) driContextPriv
->driverPrivate
;
610 newFbCtx
->dri
.drawable
= driDrawPriv
;
612 _mesa_make_current( newFbCtx
->glCtx
,
613 ((fbDrawablePtr
)driDrawPriv
->driverPrivate
)->mesa_framebuffer
,
614 ((fbDrawablePtr
)driReadPriv
->driverPrivate
)->mesa_framebuffer
);
616 _mesa_make_current( NULL
, NULL
, NULL
);
623 /* Force the context `c' to be unbound from its buffer.
626 fbUnbindContext( __DRIcontextPrivate
*driContextPriv
)
631 static struct __DriverAPIRec fbAPI
= {
632 .InitDriver
= fbInitDriver
,
633 .DestroyScreen
= fbDestroyScreen
,
634 .CreateContext
= fbCreateContext
,
635 .DestroyContext
= fbDestroyContext
,
636 .CreateBuffer
= fbCreateBuffer
,
637 .DestroyBuffer
= fbDestroyBuffer
,
638 .SwapBuffers
= fbSwapBuffers
,
639 .MakeCurrent
= fbMakeCurrent
,
640 .UnbindContext
= fbUnbindContext
,
646 __driValidateMode(const DRIDriverContext
*ctx
)
652 __driInitFBDev( struct DRIDriverContextRec
*ctx
)
654 /* Note that drmOpen will try to load the kernel module, if needed. */
655 /* we need a fbdev drm driver - it will only track maps */
656 ctx
->drmFD
= drmOpen("radeon", NULL
);
657 if (ctx
->drmFD
< 0) {
658 fprintf(stderr
, "[drm] drmOpen failed\n");
662 ctx
->shared
.SAREASize
= SAREA_MAX
;
664 if (drmAddMap( ctx
->drmFD
,
666 ctx
->shared
.SAREASize
,
669 &ctx
->shared
.hSAREA
) < 0)
671 fprintf(stderr
, "[drm] drmAddMap failed\n");
674 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
675 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
677 if (drmMap( ctx
->drmFD
,
679 ctx
->shared
.SAREASize
,
680 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
682 fprintf(stderr
, "[drm] drmMap failed\n");
685 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
686 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
687 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
689 /* Need to AddMap the framebuffer and mmio regions here:
691 if (drmAddMap( ctx
->drmFD
,
692 (drm_handle_t
)ctx
->FBStart
,
700 &ctx
->shared
.hFrameBuffer
) < 0)
702 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
706 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
707 ctx
->shared
.hFrameBuffer
);
713 __driHaltFBDev( struct DRIDriverContextRec
*ctx
)
717 struct DRIDriverRec __driDriver
= {
724 #ifdef USE_NEW_INTERFACE
725 static __GLcontextModes
*
726 fbFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
727 unsigned stencil_bits
, GLboolean have_back_buffer
)
729 __GLcontextModes
* modes
;
730 __GLcontextModes
* m
;
732 unsigned depth_buffer_factor
;
733 unsigned back_buffer_factor
;
737 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
738 * enough to add support. Basically, if a context is created with an
739 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
740 * will never be used.
742 static const GLenum back_buffer_modes
[] = {
743 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
746 u_int8_t depth_bits_array
[2];
747 u_int8_t stencil_bits_array
[2];
750 depth_bits_array
[0] = depth_bits
;
751 depth_bits_array
[1] = depth_bits
;
753 /* Just like with the accumulation buffer, always provide some modes
754 * with a stencil buffer. It will be a sw fallback, but some apps won't
757 stencil_bits_array
[0] = 0;
758 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
760 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
761 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
763 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
765 if ( pixel_bits
== 16 ) {
767 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
771 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
774 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
776 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
777 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
778 back_buffer_modes
, back_buffer_factor
,
780 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
781 __func__
, __LINE__
);
785 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
786 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
787 back_buffer_modes
, back_buffer_factor
,
788 GLX_DIRECT_COLOR
) ) {
789 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
790 __func__
, __LINE__
);
794 /* Mark the visual as slow if there are "fake" stencil bits.
796 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
797 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
798 m
->visualRating
= GLX_SLOW_CONFIG
;
807 * This is the bootstrap function for the driver. libGL supplies all of the
808 * requisite information about the system, and the driver initializes itself.
809 * This routine also fills in the linked list pointed to by \c driver_modes
810 * with the \c __GLcontextModes that the driver can support for windows or
813 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
817 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
818 const __GLcontextModes
* modes
,
819 const __DRIversion
* ddx_version
,
820 const __DRIversion
* dri_version
,
821 const __DRIversion
* drm_version
,
822 const __DRIframebuffer
* frame_buffer
,
823 drmAddress pSAREA
, int fd
,
824 int internal_api_version
,
825 __GLcontextModes
** driver_modes
)
827 __DRIscreenPrivate
*psp
;
828 static const __DRIversion ddx_expected
= { 4, 0, 0 };
829 static const __DRIversion dri_expected
= { 4, 0, 0 };
830 static const __DRIversion drm_expected
= { 1, 5, 0 };
833 if ( ! driCheckDriDdxDrmVersions2( "fb",
834 dri_version
, & dri_expected
,
835 ddx_version
, & ddx_expected
,
836 drm_version
, & drm_expected
) ) {
840 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
841 ddx_version
, dri_version
, drm_version
,
842 frame_buffer
, pSAREA
, fd
,
843 internal_api_version
, &fbAPI
);
845 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
846 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
847 if ( create_context_modes
!= NULL
) {
849 *driver_modes
= fbFillInModes( psp
->fbBPP
,
850 (psp
->fbBPP
== 16) ? 16 : 24,
851 (psp
->fbBPP
== 16) ? 0 : 8,
858 #endif /* USE_NEW_INTERFACE */