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 "main/extensions.h"
51 #include "main/framebuffer.h"
52 #include "main/renderbuffer.h"
54 #include "swrast/swrast.h"
55 #include "swrast_setup/swrast_setup.h"
57 #include "tnl/tcontext.h"
58 #include "tnl/t_pipeline.h"
59 #include "drivers/common/driverfuncs.h"
61 void fbSetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
);
64 GLcontext
*glCtx
; /* Mesa context */
67 __DRIcontextPrivate
*context
;
68 __DRIscreenPrivate
*screen
;
69 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
72 } fbContext
, *fbContextPtr
;
74 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
77 static const GLubyte
*
78 get_string(GLcontext
*ctx
, GLenum pname
)
83 return (const GLubyte
*) "Mesa dumb framebuffer";
91 update_state( GLcontext
*ctx
, GLuint new_state
)
93 /* not much to do here - pass it on */
94 _swrast_InvalidateState( ctx
, new_state
);
95 _swsetup_InvalidateState( ctx
, new_state
);
96 _vbo_InvalidateState( ctx
, new_state
);
97 _tnl_InvalidateState( ctx
, new_state
);
102 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
103 * current framebuffer size.
106 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
108 GET_CURRENT_CONTEXT(ctx
);
109 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
111 *width
= fbmesa
->dri
.drawable
->w
;
112 *height
= fbmesa
->dri
.drawable
->h
;
117 updateFramebufferSize(GLcontext
*ctx
)
119 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
120 struct gl_framebuffer
*fb
= ctx
->WinSysDrawBuffer
;
121 if (fbmesa
->dri
.drawable
->w
!= fb
->Width
||
122 fbmesa
->dri
.drawable
->h
!= fb
->Height
) {
123 driUpdateFramebufferSize(ctx
, fbmesa
->dri
.drawable
);
128 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
130 /* XXX this should be called after we acquire the DRI lock, not here */
131 updateFramebufferSize(ctx
);
136 init_core_functions( struct dd_function_table
*functions
)
138 functions
->GetString
= get_string
;
139 functions
->UpdateState
= update_state
;
140 functions
->GetBufferSize
= get_buffer_size
;
141 functions
->Viewport
= viewport
;
143 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
148 * Generate code for span functions.
152 #define NAME(PREFIX) PREFIX##_B8G8R8
153 #define FORMAT GL_RGBA8
155 driRenderbuffer *drb = (driRenderbuffer *) rb;
156 #define INIT_PIXEL_PTR(P, X, Y) \
157 GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 3;
158 #define INC_PIXEL_PTR(P) P += 3
159 #define STORE_PIXEL(DST, X, Y, VALUE) \
160 DST[0] = VALUE[BCOMP]; \
161 DST[1] = VALUE[GCOMP]; \
162 DST[2] = VALUE[RCOMP]
163 #define FETCH_PIXEL(DST, SRC) \
164 DST[RCOMP] = SRC[2]; \
165 DST[GCOMP] = SRC[1]; \
166 DST[BCOMP] = SRC[0]; \
169 #include "swrast/s_spantemp.h"
173 #define NAME(PREFIX) PREFIX##_B8G8R8A8
174 #define FORMAT GL_RGBA8
176 driRenderbuffer *drb = (driRenderbuffer *) rb;
177 #define INIT_PIXEL_PTR(P, X, Y) \
178 GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 4;
179 #define INC_PIXEL_PTR(P) P += 4
180 #define STORE_PIXEL(DST, X, Y, VALUE) \
181 DST[0] = VALUE[BCOMP]; \
182 DST[1] = VALUE[GCOMP]; \
183 DST[2] = VALUE[RCOMP]; \
184 DST[3] = VALUE[ACOMP]
185 #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
186 DST[0] = VALUE[BCOMP]; \
187 DST[1] = VALUE[GCOMP]; \
188 DST[2] = VALUE[RCOMP]; \
190 #define FETCH_PIXEL(DST, SRC) \
191 DST[RCOMP] = SRC[2]; \
192 DST[GCOMP] = SRC[1]; \
193 DST[BCOMP] = SRC[0]; \
196 #include "swrast/s_spantemp.h"
199 /* 16-bit BGR (XXX implement dithering someday) */
200 #define NAME(PREFIX) PREFIX##_B5G6R5
201 #define FORMAT GL_RGBA8
203 driRenderbuffer *drb = (driRenderbuffer *) rb;
204 #define INIT_PIXEL_PTR(P, X, Y) \
205 GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2;
206 #define INC_PIXEL_PTR(P) P += 1
207 #define STORE_PIXEL(DST, X, Y, VALUE) \
208 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
209 #define FETCH_PIXEL(DST, SRC) \
210 DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \
211 DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \
212 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
215 #include "swrast/s_spantemp.h"
218 /* 15-bit BGR (XXX implement dithering someday) */
219 #define NAME(PREFIX) PREFIX##_B5G5R5
220 #define FORMAT GL_RGBA8
222 driRenderbuffer *drb = (driRenderbuffer *) rb;
223 #define INIT_PIXEL_PTR(P, X, Y) \
224 GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2;
225 #define INC_PIXEL_PTR(P) P += 1
226 #define STORE_PIXEL(DST, X, Y, VALUE) \
227 DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) )
228 #define FETCH_PIXEL(DST, SRC) \
229 DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \
230 DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \
231 DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
234 #include "swrast/s_spantemp.h"
237 /* 8-bit color index */
238 #define NAME(PREFIX) PREFIX##_CI8
239 #define FORMAT GL_COLOR_INDEX8_EXT
241 driRenderbuffer *drb = (driRenderbuffer *) rb;
242 #define INIT_PIXEL_PTR(P, X, Y) \
243 GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X);
244 #define INC_PIXEL_PTR(P) P += 1
245 #define STORE_PIXEL(DST, X, Y, VALUE) \
247 #define FETCH_PIXEL(DST, SRC) \
250 #include "swrast/s_spantemp.h"
255 fbSetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
)
257 ASSERT(drb
->Base
.InternalFormat
== GL_RGBA
);
258 if (drb
->Base
.InternalFormat
== GL_RGBA
) {
259 if (vis
->redBits
== 5 && vis
->greenBits
== 6 && vis
->blueBits
== 5) {
260 drb
->Base
.GetRow
= get_row_B5G6R5
;
261 drb
->Base
.GetValues
= get_values_B5G6R5
;
262 drb
->Base
.PutRow
= put_row_B5G6R5
;
263 drb
->Base
.PutMonoRow
= put_mono_row_B5G6R5
;
264 drb
->Base
.PutRowRGB
= put_row_rgb_B5G6R5
;
265 drb
->Base
.PutValues
= put_values_B5G6R5
;
266 drb
->Base
.PutMonoValues
= put_mono_values_B5G6R5
;
268 else if (vis
->redBits
== 5 && vis
->greenBits
== 5 && vis
->blueBits
== 5) {
269 drb
->Base
.GetRow
= get_row_B5G5R5
;
270 drb
->Base
.GetValues
= get_values_B5G5R5
;
271 drb
->Base
.PutRow
= put_row_B5G5R5
;
272 drb
->Base
.PutMonoRow
= put_mono_row_B5G5R5
;
273 drb
->Base
.PutRowRGB
= put_row_rgb_B5G5R5
;
274 drb
->Base
.PutValues
= put_values_B5G5R5
;
275 drb
->Base
.PutMonoValues
= put_mono_values_B5G5R5
;
277 else if (vis
->redBits
== 8 && vis
->greenBits
== 8 && vis
->blueBits
== 8
278 && vis
->alphaBits
== 8) {
279 drb
->Base
.GetRow
= get_row_B8G8R8A8
;
280 drb
->Base
.GetValues
= get_values_B8G8R8A8
;
281 drb
->Base
.PutRow
= put_row_B8G8R8A8
;
282 drb
->Base
.PutMonoRow
= put_mono_row_B8G8R8A8
;
283 drb
->Base
.PutRowRGB
= put_row_rgb_B8G8R8A8
;
284 drb
->Base
.PutValues
= put_values_B8G8R8A8
;
285 drb
->Base
.PutMonoValues
= put_mono_values_B8G8R8A8
;
287 else if (vis
->redBits
== 8 && vis
->greenBits
== 8 && vis
->blueBits
== 8
288 && vis
->alphaBits
== 0) {
289 drb
->Base
.GetRow
= get_row_B8G8R8
;
290 drb
->Base
.GetValues
= get_values_B8G8R8
;
291 drb
->Base
.PutRow
= put_row_B8G8R8
;
292 drb
->Base
.PutMonoRow
= put_mono_row_B8G8R8
;
293 drb
->Base
.PutRowRGB
= put_row_rgb_B8G8R8
;
294 drb
->Base
.PutValues
= put_values_B8G8R8
;
295 drb
->Base
.PutMonoValues
= put_mono_values_B8G8R8
;
297 else if (vis
->indexBits
== 8) {
298 drb
->Base
.GetRow
= get_row_CI8
;
299 drb
->Base
.GetValues
= get_values_CI8
;
300 drb
->Base
.PutRow
= put_row_CI8
;
301 drb
->Base
.PutMonoRow
= put_mono_row_CI8
;
302 drb
->Base
.PutValues
= put_values_CI8
;
303 drb
->Base
.PutMonoValues
= put_mono_values_CI8
;
307 /* hardware z/stencil/etc someday */
313 /* Initialize the driver specific screen private data.
316 fbInitDriver( __DRIscreenPrivate
*sPriv
)
318 sPriv
->private = NULL
;
323 fbDestroyScreen( __DRIscreenPrivate
*sPriv
)
328 /* Create the device specific context.
331 fbCreateContext( const __GLcontextModes
*glVisual
,
332 __DRIcontextPrivate
*driContextPriv
,
333 void *sharedContextPrivate
)
336 GLcontext
*ctx
, *shareCtx
;
337 struct dd_function_table functions
;
340 assert(driContextPriv
);
342 /* Allocate the Fb context */
343 fbmesa
= (fbContextPtr
) _mesa_calloc( sizeof(*fbmesa
) );
347 /* Init default driver functions then plug in our FBdev-specific functions
349 _mesa_init_driver_functions(&functions
);
350 init_core_functions(&functions
);
352 /* Allocate the Mesa context */
353 if (sharedContextPrivate
)
354 shareCtx
= ((fbContextPtr
) sharedContextPrivate
)->glCtx
;
358 ctx
= fbmesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
359 &functions
, (void *) fbmesa
);
360 if (!fbmesa
->glCtx
) {
364 driContextPriv
->driverPrivate
= fbmesa
;
366 /* Create module contexts */
367 _swrast_CreateContext( ctx
);
368 _vbo_CreateContext( ctx
);
369 _tnl_CreateContext( ctx
);
370 _swsetup_CreateContext( ctx
);
371 _swsetup_Wakeup( ctx
);
374 /* use default TCL pipeline */
376 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
377 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
380 _mesa_enable_sw_extensions(ctx
);
387 fbDestroyContext( __DRIcontextPrivate
*driContextPriv
)
389 GET_CURRENT_CONTEXT(ctx
);
390 fbContextPtr fbmesa
= (fbContextPtr
) driContextPriv
->driverPrivate
;
391 fbContextPtr current
= ctx
? FB_CONTEXT(ctx
) : NULL
;
393 /* check if we're deleting the currently bound context */
394 if (fbmesa
== current
) {
395 _mesa_make_current(NULL
, NULL
, NULL
);
398 /* Free fb context resources */
400 _swsetup_DestroyContext( fbmesa
->glCtx
);
401 _tnl_DestroyContext( fbmesa
->glCtx
);
402 _vbo_DestroyContext( fbmesa
->glCtx
);
403 _swrast_DestroyContext( fbmesa
->glCtx
);
405 /* free the Mesa context */
406 fbmesa
->glCtx
->DriverCtx
= NULL
;
407 _mesa_destroy_context( fbmesa
->glCtx
);
409 _mesa_free( fbmesa
);
414 /* Create and initialize the Mesa and driver specific pixmap buffer
418 fbCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
419 __DRIdrawablePrivate
*driDrawPriv
,
420 const __GLcontextModes
*mesaVis
,
423 struct gl_framebuffer
*mesa_framebuffer
;
426 return GL_FALSE
; /* not implemented */
429 const GLboolean swDepth
= mesaVis
->depthBits
> 0;
430 const GLboolean swAlpha
= mesaVis
->alphaBits
> 0;
431 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
432 const GLboolean swStencil
= mesaVis
->stencilBits
> 0;
434 mesa_framebuffer
= _mesa_create_framebuffer(mesaVis
);
435 if (!mesa_framebuffer
)
438 /* XXX double-check these parameters (bpp vs cpp, etc) */
440 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
,
442 driScrnPriv
->fbBPP
/ 8,
443 driScrnPriv
->fbOrigin
,
444 driScrnPriv
->fbStride
,
446 fbSetSpanFunctions(drb
, mesaVis
);
447 _mesa_add_renderbuffer(mesa_framebuffer
,
448 BUFFER_FRONT_LEFT
, &drb
->Base
);
450 if (mesaVis
->doubleBufferMode
) {
451 /* XXX what are the correct origin/stride values? */
452 GLvoid
*backBuf
= _mesa_malloc(driScrnPriv
->fbStride
453 * driScrnPriv
->fbHeight
);
454 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
,
456 driScrnPriv
->fbBPP
/8,
457 driScrnPriv
->fbOrigin
,
458 driScrnPriv
->fbStride
,
460 fbSetSpanFunctions(drb
, mesaVis
);
461 _mesa_add_renderbuffer(mesa_framebuffer
,
462 BUFFER_BACK_LEFT
, &drb
->Base
);
465 _mesa_add_soft_renderbuffers(mesa_framebuffer
,
466 GL_FALSE
, /* color */
470 swAlpha
, /* or always zero? */
473 driDrawPriv
->driverPrivate
= mesa_framebuffer
;
481 fbDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
483 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
488 /* If the backbuffer is on a videocard, this is extraordinarily slow!
491 fbSwapBuffers( __DRIdrawablePrivate
*dPriv
)
493 struct gl_framebuffer
*mesa_framebuffer
= (struct gl_framebuffer
*)dPriv
->driverPrivate
;
494 struct gl_renderbuffer
* front_renderbuffer
= mesa_framebuffer
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
495 void *frontBuffer
= front_renderbuffer
->Data
;
496 int currentPitch
= ((driRenderbuffer
*)front_renderbuffer
)->pitch
;
497 void *backBuffer
= mesa_framebuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
->Data
;
499 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
500 fbContextPtr fbmesa
= (fbContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
501 GLcontext
*ctx
= fbmesa
->glCtx
;
503 if (ctx
->Visual
.doubleBufferMode
) {
506 char *tmp
= _mesa_malloc(currentPitch
);
508 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
513 for (i
= 0; i
< dPriv
->h
; i
++) {
514 _mesa_memcpy(tmp
, (char *) backBuffer
+ offset
,
516 _mesa_memcpy((char *) frontBuffer
+ offset
, tmp
,
518 offset
+= 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_current( newFbCtx
->glCtx
,
546 driDrawPriv
->driverPrivate
,
547 driReadPriv
->driverPrivate
);
549 _mesa_make_current( NULL
, NULL
, NULL
);
556 /* Force the context `c' to be unbound from its buffer.
559 fbUnbindContext( __DRIcontextPrivate
*driContextPriv
)
564 static struct __DriverAPIRec fbAPI
= {
565 .InitDriver
= fbInitDriver
,
566 .DestroyScreen
= fbDestroyScreen
,
567 .CreateContext
= fbCreateContext
,
568 .DestroyContext
= fbDestroyContext
,
569 .CreateBuffer
= fbCreateBuffer
,
570 .DestroyBuffer
= fbDestroyBuffer
,
571 .SwapBuffers
= fbSwapBuffers
,
572 .MakeCurrent
= fbMakeCurrent
,
573 .UnbindContext
= fbUnbindContext
,
579 __driValidateMode(const DRIDriverContext
*ctx
)
585 __driInitFBDev( struct DRIDriverContextRec
*ctx
)
587 /* Note that drmOpen will try to load the kernel module, if needed. */
588 /* we need a fbdev drm driver - it will only track maps */
589 ctx
->drmFD
= drmOpen("radeon", NULL
);
590 if (ctx
->drmFD
< 0) {
591 fprintf(stderr
, "[drm] drmOpen failed\n");
595 ctx
->shared
.SAREASize
= SAREA_MAX
;
597 if (drmAddMap( ctx
->drmFD
,
599 ctx
->shared
.SAREASize
,
602 &ctx
->shared
.hSAREA
) < 0)
604 fprintf(stderr
, "[drm] drmAddMap failed\n");
607 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
608 ctx
->shared
.SAREASize
,
609 (unsigned long) ctx
->shared
.hSAREA
);
611 if (drmMap( ctx
->drmFD
,
613 ctx
->shared
.SAREASize
,
614 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
616 fprintf(stderr
, "[drm] drmMap failed\n");
619 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
620 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
621 (unsigned long) ctx
->shared
.hSAREA
, ctx
->pSAREA
,
622 ctx
->shared
.SAREASize
);
624 /* Need to AddMap the framebuffer and mmio regions here:
626 if (drmAddMap( ctx
->drmFD
,
627 (drm_handle_t
)ctx
->FBStart
,
635 &ctx
->shared
.hFrameBuffer
) < 0)
637 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
641 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
642 (unsigned long) ctx
->shared
.hFrameBuffer
);
648 __driHaltFBDev( struct DRIDriverContextRec
*ctx
)
652 struct DRIDriverRec __driDriver
= {
659 static __GLcontextModes
*
660 fbFillInModes( __DRIscreenPrivate
*psp
,
661 unsigned pixel_bits
, unsigned depth_bits
,
662 unsigned stencil_bits
, GLboolean have_back_buffer
)
664 __GLcontextModes
* modes
;
665 __GLcontextModes
* m
;
667 unsigned depth_buffer_factor
;
668 unsigned back_buffer_factor
;
672 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
673 * enough to add support. Basically, if a context is created with an
674 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
675 * will never be used.
677 static const GLenum back_buffer_modes
[] = {
678 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
681 uint8_t depth_bits_array
[2];
682 uint8_t stencil_bits_array
[2];
685 depth_bits_array
[0] = depth_bits
;
686 depth_bits_array
[1] = depth_bits
;
688 /* Just like with the accumulation buffer, always provide some modes
689 * with a stencil buffer. It will be a sw fallback, but some apps won't
692 stencil_bits_array
[0] = 0;
693 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
695 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
696 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
698 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
700 if ( pixel_bits
== 16 ) {
702 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
706 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
709 modes
= (*psp
->contextModes
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
711 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
712 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
713 back_buffer_modes
, back_buffer_factor
,
715 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
716 __func__
, __LINE__
);
720 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
721 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
722 back_buffer_modes
, back_buffer_factor
,
723 GLX_DIRECT_COLOR
) ) {
724 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
725 __func__
, __LINE__
);
729 /* Mark the visual as slow if there are "fake" stencil bits.
731 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
732 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
733 m
->visualRating
= GLX_SLOW_CONFIG
;
742 * This is the bootstrap function for the driver. libGL supplies all of the
743 * requisite information about the system, and the driver initializes itself.
744 * This routine also fills in the linked list pointed to by \c driver_modes
745 * with the \c __GLcontextModes that the driver can support for windows or
748 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
752 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
753 const __GLcontextModes
* modes
,
754 const __DRIversion
* ddx_version
,
755 const __DRIversion
* dri_version
,
756 const __DRIversion
* drm_version
,
757 const __DRIframebuffer
* frame_buffer
,
758 drmAddress pSAREA
, int fd
,
759 int internal_api_version
,
760 __GLcontextModes
** driver_modes
)
762 __DRIscreenPrivate
*psp
;
763 static const __DRIversion ddx_expected
= { 4, 0, 0 };
764 static const __DRIversion dri_expected
= { 4, 0, 0 };
765 static const __DRIversion drm_expected
= { 1, 5, 0 };
768 if ( ! driCheckDriDdxDrmVersions2( "fb",
769 dri_version
, & dri_expected
,
770 ddx_version
, & ddx_expected
,
771 drm_version
, & drm_expected
) ) {
775 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
776 ddx_version
, dri_version
, drm_version
,
777 frame_buffer
, pSAREA
, fd
,
778 internal_api_version
, &fbAPI
);
780 *driver_modes
= fbFillInModes( psp
, psp
->fbBPP
,
781 (psp
->fbBPP
== 16) ? 16 : 24,
782 (psp
->fbBPP
== 16) ? 0 : 8,