2 * Test egl driver for fb_dri.so
11 #include <sys/ioctl.h>
17 #include "extensions.h"
18 #include "framebuffer.h"
19 #include "renderbuffer.h"
20 #include "array_cache/acache.h"
21 #include "swrast/swrast.h"
22 #include "swrast_setup/swrast_setup.h"
24 #include "tnl/t_context.h"
25 #include "tnl/t_pipeline.h"
26 #include "drivers/common/driverfuncs.h"
27 #include "drirenderbuffer.h"
29 #include "eglconfig.h"
30 #include "eglcontext.h"
31 #include "egldisplay.h"
32 #include "egldriver.h"
33 #include "eglglobals.h"
35 #include "eglscreen.h"
36 #include "eglsurface.h"
39 fbSetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
);
42 * fb driver-specific driver class derived from _EGLDriver
44 typedef struct fb_driver
46 _EGLDriver Base
; /* base class/object */
51 * fb display-specific driver class derived from _EGLDisplay
53 typedef struct fb_display
55 _EGLDisplay Base
; /* base class/object */
60 * fb driver-specific screen class derived from _EGLScreen
62 typedef struct fb_screen
70 * fb driver-specific surface class derived from _EGLSurface
72 typedef struct fb_surface
74 _EGLSurface Base
; /* base class/object */
75 struct gl_framebuffer
*mesa_framebuffer
;
80 * fb driver-specific context class derived from _EGLContext
82 typedef struct fb_context
84 _EGLContext Base
; /* base class/object */
87 __DRIcontextPrivate
*context
;
88 __DRIscreenPrivate
*screen
;
89 __DRIdrawablePrivate
*drawable
; /* drawable bound to this ctx */
91 } fbContext
, *fbContextPtr
;
93 #define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
97 fbFillInConfigs(_EGLDisplay
*disp
, unsigned pixel_bits
, unsigned depth_bits
,
98 unsigned stencil_bits
, GLboolean have_back_buffer
) {
101 unsigned int i
, num_configs
;
102 unsigned int depth_buffer_factor
;
103 unsigned int back_buffer_factor
;
107 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
108 * enough to add support. Basically, if a context is created with an
109 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
110 * will never be used.
112 static const GLenum back_buffer_modes
[] = {
113 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
116 u_int8_t depth_bits_array
[2];
117 u_int8_t stencil_bits_array
[2];
119 depth_bits_array
[0] = 0;
120 depth_bits_array
[1] = depth_bits
;
122 /* Just like with the accumulation buffer, always provide some modes
123 * with a stencil buffer. It will be a sw fallback, but some apps won't
126 stencil_bits_array
[0] = 0;
127 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
129 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
130 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
132 num_configs
= depth_buffer_factor
* back_buffer_factor
* 2;
134 if (pixel_bits
== 16) {
136 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
139 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
142 configs
= calloc(sizeof(*configs
), num_configs
);
144 if (!_eglFillInConfigs(c
, fb_format
, fb_type
,
145 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
146 back_buffer_modes
, back_buffer_factor
,
148 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
153 /* Mark the visual as slow if there are "fake" stencil bits.
155 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++) {
156 int stencil
= GET_CONFIG_ATTRIB(c
, EGL_STENCIL_SIZE
);
157 if ((stencil
!= 0) && (stencil
!= stencil_bits
)) {
158 SET_CONFIG_ATTRIB(c
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
162 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++)
163 _eglAddConfig(disp
, c
);
171 fbSetupFramebuffer(fbDisplay
*disp
, char *fbdev
)
175 struct fb_var_screeninfo varInfo
;
176 struct fb_fix_screeninfo fixedInfo
;
178 snprintf(dev
, sizeof(dev
), "/dev/%s", fbdev
);
180 /* open the framebuffer device */
181 fd
= open(dev
, O_RDWR
);
183 fprintf(stderr
, "Error opening %s: %s\n", fbdev
, strerror(errno
));
187 /* get the original variable screen info */
188 if (ioctl(fd
, FBIOGET_VSCREENINFO
, &varInfo
)) {
189 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
194 /* Turn off hw accels (otherwise mmap of mmio region will be
197 if (varInfo
.accel_flags
) {
198 varInfo
.accel_flags
= 0;
199 if (ioctl(fd
, FBIOPUT_VSCREENINFO
, &varInfo
)) {
200 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
206 /* Get the fixed screen info */
207 if (ioctl(fd
, FBIOGET_FSCREENINFO
, &fixedInfo
)) {
208 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
213 if (fixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
215 unsigned short red
[256], green
[256], blue
[256];
216 int rcols
= 1 << varInfo
.red
.length
;
217 int gcols
= 1 << varInfo
.green
.length
;
218 int bcols
= 1 << varInfo
.blue
.length
;
228 for (i
= 0; i
< rcols
; i
++)
229 red
[i
] = (65536/(rcols
-1)) * i
;
231 for (i
= 0; i
< gcols
; i
++)
232 green
[i
] = (65536/(gcols
-1)) * i
;
234 for (i
= 0; i
< bcols
; i
++)
235 blue
[i
] = (65536/(bcols
-1)) * i
;
237 if (ioctl(fd
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
238 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
243 /* mmap the framebuffer into our address space */
245 disp
->pFB
= (caddr_t
)mmap(0, /* start */
246 fixedInfo
.smem_len
, /* bytes */
247 PROT_READ
| PROT_WRITE
, /* prot */
248 MAP_SHARED
, /* flags */
251 if (disp
->pFB
== (caddr_t
)-1) {
252 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
260 const char *sysfs
= "/sys/class/graphics";
263 fbInitialize(_EGLDriver
*drv
, EGLDisplay dpy
, EGLint
*major
, EGLint
*minor
)
265 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
270 unsigned int x
, y
, r
;
273 struct dirent
*dirent
;
276 /* Switch display structure to one with our private fields */
277 display
= calloc(1, sizeof(*display
));
278 display
->Base
= *disp
;
279 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
285 dir
= opendir(sysfs
);
287 printf("EGL - %s framebuffer device not found.", sysfs
);
291 while ((dirent
= readdir(dir
))) { /* assignment! */
293 if (dirent
->d_name
[0] != 'f')
295 if (dirent
->d_name
[1] != 'b')
298 if (fbSetupFramebuffer(display
, dirent
->d_name
) == EGL_FALSE
)
301 /* Create a screen */
302 s
= (fbScreen
*) calloc(1, sizeof(fbScreen
));
306 strncpy(s
->fb
, dirent
->d_name
, NAME_MAX
);
308 _eglInitScreen(scrn
);
309 _eglAddScreen(&display
->Base
, scrn
);
311 snprintf(path
, sizeof(path
), "%s/%s/modes", sysfs
, s
->fb
);
312 file
= fopen(path
, "r");
313 while (fgets(path
, sizeof(path
), file
)) {
314 sscanf(path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
315 _eglAddMode(scrn
, x
, y
, r
* 1000, path
);
319 fbFillInConfigs(&display
->Base
, 32, 24, 8, 1);
324 drv
->Initialized
= EGL_TRUE
;
330 Lookup_fbDisplay(EGLDisplay dpy
)
332 _EGLDisplay
*d
= _eglLookupDisplay(dpy
);
333 return (fbDisplay
*) d
;
338 Lookup_fbScreen(EGLDisplay dpy
, EGLScreenMESA screen
)
340 _EGLScreen
*s
= _eglLookupScreen(dpy
, screen
);
341 return (fbScreen
*) s
;
346 Lookup_fbContext(EGLContext ctx
)
348 _EGLContext
*c
= _eglLookupContext(ctx
);
349 return (fbContext
*) c
;
354 Lookup_fbSurface(EGLSurface surf
)
356 _EGLSurface
*s
= _eglLookupSurface(surf
);
357 return (fbSurface
*) s
;
362 fbTerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
364 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
365 _eglCleanupDisplay(&display
->Base
);
372 static const GLubyte
*
373 get_string(GLcontext
*ctx
, GLenum pname
)
378 return (const GLubyte
*) "Mesa dumb framebuffer";
386 update_state( GLcontext
*ctx
, GLuint new_state
)
388 /* not much to do here - pass it on */
389 _swrast_InvalidateState( ctx
, new_state
);
390 _swsetup_InvalidateState( ctx
, new_state
);
391 _ac_InvalidateState( ctx
, new_state
);
392 _tnl_InvalidateState( ctx
, new_state
);
397 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
398 * current framebuffer size.
401 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
403 *width
= buffer
->Width
;
404 *height
= buffer
->Height
;
409 updateFramebufferSize(GLcontext
*ctx
)
411 fbContextPtr fbmesa
= FB_CONTEXT(ctx
);
412 struct gl_framebuffer
*fb
= ctx
->WinSysDrawBuffer
;
413 if (fbmesa
->dri
.drawable
->w
!= fb
->Width
||
414 fbmesa
->dri
.drawable
->h
!= fb
->Height
) {
415 driUpdateFramebufferSize(ctx
, fbmesa
->dri
.drawable
);
420 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
422 /* XXX this should be called after we acquire the DRI lock, not here */
423 updateFramebufferSize(ctx
);
428 init_core_functions( struct dd_function_table
*functions
)
430 functions
->GetString
= get_string
;
431 functions
->UpdateState
= update_state
;
432 functions
->ResizeBuffers
= _mesa_resize_framebuffer
;
433 functions
->GetBufferSize
= get_buffer_size
;
434 functions
->Viewport
= viewport
;
436 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
441 fbCreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, EGLContext share_list
, const EGLint
*attrib_list
)
446 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
447 struct dd_function_table functions
;
451 conf
= _eglLookupConfig(drv
, dpy
, config
);
453 _eglError(EGL_BAD_CONFIG
, "eglCreateContext");
454 return EGL_NO_CONTEXT
;
457 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
458 switch (attrib_list
[i
]) {
459 /* no attribs defined for now */
461 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateContext");
462 return EGL_NO_CONTEXT
;
466 c
= (fbContext
*) calloc(1, sizeof(fbContext
));
468 return EGL_NO_CONTEXT
;
470 _eglInitContext(&c
->Base
);
471 c
->Base
.Display
= disp
;
472 c
->Base
.Config
= conf
;
473 c
->Base
.DrawSurface
= EGL_NO_SURFACE
;
474 c
->Base
.ReadSurface
= EGL_NO_SURFACE
;
476 /* generate handle and insert into hash table */
477 _eglSaveContext(&c
->Base
);
478 assert(c
->Base
.Handle
);
480 /* Init default driver functions then plug in our FBdev-specific functions
482 _mesa_init_driver_functions(&functions
);
483 init_core_functions(&functions
);
485 _eglConfigToContextModesRec(conf
, &vis
);
487 ctx
= c
->glCtx
= _mesa_create_context(&vis
, NULL
, &functions
, (void *)c
);
493 /* Create module contexts */
494 _swrast_CreateContext( ctx
);
495 _ac_CreateContext( ctx
);
496 _tnl_CreateContext( ctx
);
497 _swsetup_CreateContext( ctx
);
498 _swsetup_Wakeup( ctx
);
501 /* use default TCL pipeline */
503 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
504 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
507 _mesa_enable_sw_extensions(ctx
);
509 return c
->Base
.Handle
;
514 fbCreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativeWindowType window
, const EGLint
*attrib_list
)
517 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
518 switch (attrib_list
[i
]) {
519 /* no attribs at this time */
521 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateWindowSurface");
522 return EGL_NO_SURFACE
;
525 printf("eglCreateWindowSurface()\n");
528 return EGL_NO_SURFACE
;
533 fbCreatePixmapSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
538 conf
= _eglLookupConfig(drv
, dpy
, config
);
540 _eglError(EGL_BAD_CONFIG
, "eglCreatePixmapSurface");
541 return EGL_NO_SURFACE
;
544 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
545 switch (attrib_list
[i
]) {
546 /* no attribs at this time */
548 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePixmapSurface");
549 return EGL_NO_SURFACE
;
553 if (conf
->Attrib
[EGL_SURFACE_TYPE
- FIRST_ATTRIB
] == 0) {
554 _eglError(EGL_BAD_MATCH
, "eglCreatePixmapSurface");
555 return EGL_NO_SURFACE
;
558 printf("eglCreatePixmapSurface()\n");
559 return EGL_NO_SURFACE
;
564 fbCreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, const EGLint
*attrib_list
)
568 surf
= (fbSurface
*) calloc(1, sizeof(fbSurface
));
570 return EGL_NO_SURFACE
;
573 if (_eglInitPbufferSurface(&surf
->Base
, drv
, dpy
, config
, attrib_list
) == EGL_NO_SURFACE
) {
575 return EGL_NO_SURFACE
;
578 /* create software-based pbuffer */
580 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
582 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
583 assert(conf
); /* bad config should be caught earlier */
584 _eglConfigToContextModesRec(conf
, &vis
);
586 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
587 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
588 GL_TRUE
, /* color bufs */
590 vis
.haveStencilBuffer
,
592 GL_FALSE
, /* alpha */
593 GL_FALSE
/* aux */ );
595 /* set pbuffer/framebuffer size */
596 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
597 surf
->Base
.Width
, surf
->Base
.Height
);
600 return surf
->Base
.Handle
;
605 fbDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
607 fbSurface
*fs
= Lookup_fbSurface(surface
);
608 _eglRemoveSurface(&fs
->Base
);
609 if (fs
->Base
.IsBound
) {
610 fs
->Base
.DeletePending
= EGL_TRUE
;
620 fbDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
622 fbContext
*fc
= Lookup_fbContext(context
);
623 _eglRemoveContext(&fc
->Base
);
624 if (fc
->Base
.IsBound
) {
625 fc
->Base
.DeletePending
= EGL_TRUE
;
635 fbMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
, EGLSurface read
, EGLContext context
)
637 fbSurface
*readSurf
= Lookup_fbSurface(read
);
638 fbSurface
*drawSurf
= Lookup_fbSurface(draw
);
639 fbContext
*ctx
= Lookup_fbContext(context
);
642 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
647 _mesa_make_current( ctx
->glCtx
,
648 drawSurf
->mesa_framebuffer
,
649 readSurf
->mesa_framebuffer
);
651 _mesa_make_current( NULL
, NULL
, NULL
);
658 * Create a drawing surface which can be directly displayed on a screen.
661 fbCreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
662 const EGLint
*attrib_list
)
664 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
665 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
669 GLcontext
*ctx
= NULL
; /* this should be OK */
670 int origin
, bytesPerPixel
;
671 int width
, height
, stride
;
673 surface
= (fbSurface
*) malloc(sizeof(*surface
));
675 return EGL_NO_SURFACE
;
678 /* init base class, error check, etc. */
679 surf
= _eglInitScreenSurface(&surface
->Base
, drv
, dpy
, cfg
, attrib_list
);
680 if (surf
== EGL_NO_SURFACE
) {
682 return EGL_NO_SURFACE
;
685 /* convert EGLConfig to GLvisual */
686 _eglConfigToContextModesRec(config
, &vis
);
688 /* create Mesa framebuffer */
689 surface
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
690 if (!surface
->mesa_framebuffer
) {
692 _eglRemoveSurface(&surface
->Base
);
693 return EGL_NO_SURFACE
;
696 width
= surface
->Base
.Width
;
697 height
= surface
->Base
.Height
;
698 bytesPerPixel
= vis
.rgbBits
/ 8;
699 stride
= width
* bytesPerPixel
;
702 /* front color renderbuffer */
704 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, display
->pFB
,
706 origin
, stride
, NULL
);
707 fbSetSpanFunctions(drb
, &vis
);
708 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
709 BUFFER_FRONT_LEFT
, &drb
->Base
);
712 /* back color renderbuffer */
713 if (vis
.doubleBufferMode
) {
714 GLubyte
*backBuf
= _mesa_malloc(stride
* height
);
715 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, backBuf
,
717 origin
, stride
, NULL
);
718 fbSetSpanFunctions(drb
, &vis
);
719 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
720 BUFFER_BACK_LEFT
, &drb
->Base
);
723 /* other renderbuffers- software based */
724 _mesa_add_soft_renderbuffers(surface
->mesa_framebuffer
,
725 GL_FALSE
, /* color */
727 vis
.haveStencilBuffer
,
729 GL_FALSE
, /* alpha */
732 _mesa_resize_framebuffer(ctx
, surface
->mesa_framebuffer
, width
, height
);
739 * Show the given surface on the named screen.
740 * If surface is EGL_NO_SURFACE, disable the screen's output.
743 fbShowSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
744 EGLSurface surface
, EGLModeMESA m
)
746 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
747 fbScreen
*scrn
= Lookup_fbScreen(dpy
, screen
);
748 fbSurface
*surf
= Lookup_fbSurface(surface
);
750 char buffer
[NAME_MAX
];
751 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
754 if (!_eglShowSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
757 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
759 file
= fopen(buffer
, "r+");
762 printf("chown all fb sysfs attrib to allow write - %s\n", buffer
);
765 snprintf(buffer
, sizeof(buffer
), "%d", (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
769 if (m
== EGL_NO_MODE_MESA
)
772 snprintf(buffer
, sizeof(buffer
), "%s/%s/mode", sysfs
, scrn
->fb
);
774 file
= fopen(buffer
, "r+");
777 fputs(mode
->Name
, file
);
780 snprintf(buffer
, sizeof(buffer
), "%s/%s/bits_per_pixel", sysfs
, scrn
->fb
);
782 file
= fopen(buffer
, "r+");
785 bits
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
786 snprintf(buffer
, sizeof(buffer
), "%d", bits
);
790 fbSetupFramebuffer(display
, scrn
->fb
);
792 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
794 file
= fopen(buffer
, "r+");
798 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
806 /* If the backbuffer is on a videocard, this is extraordinarily slow!
809 fbSwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
811 fbContext
*context
= (fbContext
*)_eglGetCurrentContext();
812 fbSurface
*fs
= Lookup_fbSurface(draw
);
813 struct gl_renderbuffer
* front_renderbuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
814 void *frontBuffer
= front_renderbuffer
->Data
;
815 int currentPitch
= ((driRenderbuffer
*)front_renderbuffer
)->pitch
;
816 void *backBuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
->Data
;
818 if (!_eglSwapBuffers(drv
, dpy
, draw
))
822 GLcontext
*ctx
= context
->glCtx
;
824 if (ctx
->Visual
.doubleBufferMode
) {
827 char *tmp
= _mesa_malloc(currentPitch
);
829 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
834 for (i
= 0; i
< fs
->Base
.Height
; i
++) {
835 _mesa_memcpy(tmp
, (char *) backBuffer
+ offset
,
837 _mesa_memcpy((char *) frontBuffer
+ offset
, tmp
,
839 offset
+= currentPitch
;
846 /* XXX this shouldn't be an error but we can't handle it for now */
847 _mesa_problem(NULL
, "fbSwapBuffers: drawable has no context!\n");
855 * The bootstrap function. Return a new fbDriver object and
856 * plug in API functions.
859 _eglMain(_EGLDisplay
*dpy
)
863 fb
= (fbDriver
*) calloc(1, sizeof(fbDriver
));
868 /* First fill in the dispatch table with defaults */
869 _eglInitDriverFallbacks(&fb
->Base
);
871 /* then plug in our fb-specific functions */
872 fb
->Base
.Initialize
= fbInitialize
;
873 fb
->Base
.Terminate
= fbTerminate
;
874 fb
->Base
.CreateContext
= fbCreateContext
;
875 fb
->Base
.MakeCurrent
= fbMakeCurrent
;
876 fb
->Base
.CreateWindowSurface
= fbCreateWindowSurface
;
877 fb
->Base
.CreatePixmapSurface
= fbCreatePixmapSurface
;
878 fb
->Base
.CreatePbufferSurface
= fbCreatePbufferSurface
;
879 fb
->Base
.DestroySurface
= fbDestroySurface
;
880 fb
->Base
.DestroyContext
= fbDestroyContext
;
881 fb
->Base
.CreateScreenSurfaceMESA
= fbCreateScreenSurfaceMESA
;
882 fb
->Base
.ShowSurfaceMESA
= fbShowSurfaceMESA
;
883 fb
->Base
.SwapBuffers
= fbSwapBuffers
;
885 /* enable supported extensions */
886 fb
->Base
.MESA_screen_surface
= EGL_TRUE
;
887 fb
->Base
.MESA_copy_context
= EGL_TRUE
;