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
);
41 fbSetBuffer( GLcontext
*ctx
, GLframebuffer
*colorBuffer
, GLuint bufferBit
);
44 * fb driver-specific driver class derived from _EGLDriver
46 typedef struct fb_driver
48 _EGLDriver Base
; /* base class/object */
53 * fb display-specific driver class derived from _EGLDisplay
55 typedef struct fb_display
57 _EGLDisplay Base
; /* base class/object */
62 * fb driver-specific screen class derived from _EGLScreen
64 typedef struct fb_screen
72 * fb driver-specific surface class derived from _EGLSurface
74 typedef struct fb_surface
76 _EGLSurface Base
; /* base class/object */
77 struct gl_framebuffer
*mesa_framebuffer
;
82 * fb driver-specific context class derived from _EGLContext
84 typedef struct fb_context
86 _EGLContext Base
; /* base class/object */
92 fbFillInConfigs(_EGLDisplay
*disp
, unsigned pixel_bits
, unsigned depth_bits
,
93 unsigned stencil_bits
, GLboolean have_back_buffer
) {
96 unsigned int i
, num_configs
;
97 unsigned int depth_buffer_factor
;
98 unsigned int back_buffer_factor
;
102 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
103 * enough to add support. Basically, if a context is created with an
104 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
105 * will never be used.
107 static const GLenum back_buffer_modes
[] = {
108 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
111 u_int8_t depth_bits_array
[2];
112 u_int8_t stencil_bits_array
[2];
114 depth_bits_array
[0] = 0;
115 depth_bits_array
[1] = depth_bits
;
117 /* Just like with the accumulation buffer, always provide some modes
118 * with a stencil buffer. It will be a sw fallback, but some apps won't
121 stencil_bits_array
[0] = 0;
122 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
124 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
125 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
127 num_configs
= depth_buffer_factor
* back_buffer_factor
* 2;
129 if (pixel_bits
== 16) {
131 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
134 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
137 configs
= calloc(sizeof(*configs
), num_configs
);
139 if (!_eglFillInConfigs(c
, fb_format
, fb_type
,
140 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
141 back_buffer_modes
, back_buffer_factor
,
143 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
148 /* Mark the visual as slow if there are "fake" stencil bits.
150 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++) {
151 int stencil
= GET_CONFIG_ATTRIB(c
, EGL_STENCIL_SIZE
);
152 if ((stencil
!= 0) && (stencil
!= stencil_bits
)) {
153 SET_CONFIG_ATTRIB(c
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
157 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++)
158 _eglAddConfig(disp
, c
);
166 fbSetupFramebuffer(fbDisplay
*disp
, char *fbdev
)
170 struct fb_var_screeninfo varInfo
;
171 struct fb_fix_screeninfo fixedInfo
;
173 snprintf(dev
, sizeof(dev
), "/dev/%s", fbdev
);
175 /* open the framebuffer device */
176 fd
= open(dev
, O_RDWR
);
178 fprintf(stderr
, "Error opening %s: %s\n", fbdev
, strerror(errno
));
182 /* get the original variable screen info */
183 if (ioctl(fd
, FBIOGET_VSCREENINFO
, &varInfo
)) {
184 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
189 /* Turn off hw accels (otherwise mmap of mmio region will be
192 if (varInfo
.accel_flags
) {
193 varInfo
.accel_flags
= 0;
194 if (ioctl(fd
, FBIOPUT_VSCREENINFO
, &varInfo
)) {
195 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
201 /* Get the fixed screen info */
202 if (ioctl(fd
, FBIOGET_FSCREENINFO
, &fixedInfo
)) {
203 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
208 if (fixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
210 unsigned short red
[256], green
[256], blue
[256];
211 int rcols
= 1 << varInfo
.red
.length
;
212 int gcols
= 1 << varInfo
.green
.length
;
213 int bcols
= 1 << varInfo
.blue
.length
;
223 for (i
= 0; i
< rcols
; i
++)
224 red
[i
] = (65536/(rcols
-1)) * i
;
226 for (i
= 0; i
< gcols
; i
++)
227 green
[i
] = (65536/(gcols
-1)) * i
;
229 for (i
= 0; i
< bcols
; i
++)
230 blue
[i
] = (65536/(bcols
-1)) * i
;
232 if (ioctl(fd
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
233 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
238 /* mmap the framebuffer into our address space */
240 disp
->pFB
= (caddr_t
)mmap(0, /* start */
241 fixedInfo
.smem_len
, /* bytes */
242 PROT_READ
| PROT_WRITE
, /* prot */
243 MAP_SHARED
, /* flags */
246 if (disp
->pFB
== (caddr_t
)-1) {
247 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
255 const char *sysfs
= "/sys/class/graphics";
258 fbInitialize(_EGLDriver
*drv
, EGLDisplay dpy
, EGLint
*major
, EGLint
*minor
)
260 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
265 unsigned int x
, y
, r
;
268 struct dirent
*dirent
;
271 /* Switch display structure to one with our private fields */
272 display
= calloc(1, sizeof(*display
));
273 display
->Base
= *disp
;
274 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
280 dir
= opendir(sysfs
);
282 printf("EGL - %s framebuffer device not found.", sysfs
);
286 while ((dirent
= readdir(dir
))) { /* assignment! */
288 if (dirent
->d_name
[0] != 'f')
290 if (dirent
->d_name
[1] != 'b')
293 if (fbSetupFramebuffer(display
, dirent
->d_name
) == EGL_FALSE
)
296 /* Create a screen */
297 s
= (fbScreen
*) calloc(1, sizeof(fbScreen
));
301 strncpy(s
->fb
, dirent
->d_name
, NAME_MAX
);
303 _eglInitScreen(scrn
);
304 _eglAddScreen(&display
->Base
, scrn
);
306 snprintf(path
, sizeof(path
), "%s/%s/modes", sysfs
, s
->fb
);
307 file
= fopen(path
, "r");
308 while (fgets(path
, sizeof(path
), file
)) {
309 sscanf(path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
310 _eglAddMode(scrn
, x
, y
, r
* 1000, path
);
314 fbFillInConfigs(&display
->Base
, 32, 24, 8, 1);
319 drv
->Initialized
= EGL_TRUE
;
325 Lookup_fbDisplay(EGLDisplay dpy
)
327 _EGLDisplay
*d
= _eglLookupDisplay(dpy
);
328 return (fbDisplay
*) d
;
333 Lookup_fbScreen(EGLDisplay dpy
, EGLScreenMESA screen
)
335 _EGLScreen
*s
= _eglLookupScreen(dpy
, screen
);
336 return (fbScreen
*) s
;
341 Lookup_fbContext(EGLContext ctx
)
343 _EGLContext
*c
= _eglLookupContext(ctx
);
344 return (fbContext
*) c
;
349 Lookup_fbSurface(EGLSurface surf
)
351 _EGLSurface
*s
= _eglLookupSurface(surf
);
352 return (fbSurface
*) s
;
357 fbTerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
359 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
360 _eglCleanupDisplay(&display
->Base
);
367 static const GLubyte
*
368 get_string(GLcontext
*ctx
, GLenum pname
)
373 return (const GLubyte
*) "Mesa dumb framebuffer";
381 update_state( GLcontext
*ctx
, GLuint new_state
)
383 /* not much to do here - pass it on */
384 _swrast_InvalidateState( ctx
, new_state
);
385 _swsetup_InvalidateState( ctx
, new_state
);
386 _ac_InvalidateState( ctx
, new_state
);
387 _tnl_InvalidateState( ctx
, new_state
);
392 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
393 * current framebuffer size.
396 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
398 *width
= buffer
->Width
;
399 *height
= buffer
->Height
;
404 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
406 _mesa_ResizeBuffersMESA();
411 init_core_functions( struct dd_function_table
*functions
)
413 functions
->GetString
= get_string
;
414 functions
->UpdateState
= update_state
;
415 functions
->ResizeBuffers
= _mesa_resize_framebuffer
;
416 functions
->GetBufferSize
= get_buffer_size
;
417 functions
->Viewport
= viewport
;
419 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
424 fbCreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, EGLContext share_list
, const EGLint
*attrib_list
)
429 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
430 struct dd_function_table functions
;
434 conf
= _eglLookupConfig(drv
, dpy
, config
);
436 _eglError(EGL_BAD_CONFIG
, "eglCreateContext");
437 return EGL_NO_CONTEXT
;
440 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
441 switch (attrib_list
[i
]) {
442 /* no attribs defined for now */
444 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateContext");
445 return EGL_NO_CONTEXT
;
449 c
= (fbContext
*) calloc(1, sizeof(fbContext
));
451 return EGL_NO_CONTEXT
;
453 _eglInitContext(&c
->Base
);
454 c
->Base
.Display
= disp
;
455 c
->Base
.Config
= conf
;
456 c
->Base
.DrawSurface
= EGL_NO_SURFACE
;
457 c
->Base
.ReadSurface
= EGL_NO_SURFACE
;
459 /* generate handle and insert into hash table */
460 _eglSaveContext(&c
->Base
);
461 assert(c
->Base
.Handle
);
463 /* Init default driver functions then plug in our FBdev-specific functions
465 _mesa_init_driver_functions(&functions
);
466 init_core_functions(&functions
);
468 _eglConfigToContextModesRec(conf
, &vis
);
470 ctx
= c
->glCtx
= _mesa_create_context(&vis
, NULL
, &functions
, (void *)c
);
476 /* Create module contexts */
477 _swrast_CreateContext( ctx
);
478 _ac_CreateContext( ctx
);
479 _tnl_CreateContext( ctx
);
480 _swsetup_CreateContext( ctx
);
481 _swsetup_Wakeup( ctx
);
484 /* swrast init -- need to verify these tests - I just plucked the
485 * numbers out of the air. (KW)
488 struct swrast_device_driver
*swdd
;
489 swdd
= _swrast_GetDeviceDriverReference( ctx
);
490 swdd
->SetBuffer
= fbSetBuffer
;
493 /* use default TCL pipeline */
495 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
496 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
499 _mesa_enable_sw_extensions(ctx
);
501 return c
->Base
.Handle
;
506 fbCreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativeWindowType window
, const EGLint
*attrib_list
)
509 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
510 switch (attrib_list
[i
]) {
511 /* no attribs at this time */
513 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateWindowSurface");
514 return EGL_NO_SURFACE
;
517 printf("eglCreateWindowSurface()\n");
520 return EGL_NO_SURFACE
;
525 fbCreatePixmapSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
530 conf
= _eglLookupConfig(drv
, dpy
, config
);
532 _eglError(EGL_BAD_CONFIG
, "eglCreatePixmapSurface");
533 return EGL_NO_SURFACE
;
536 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
537 switch (attrib_list
[i
]) {
538 /* no attribs at this time */
540 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePixmapSurface");
541 return EGL_NO_SURFACE
;
545 if (conf
->Attrib
[EGL_SURFACE_TYPE
- FIRST_ATTRIB
] == 0) {
546 _eglError(EGL_BAD_MATCH
, "eglCreatePixmapSurface");
547 return EGL_NO_SURFACE
;
550 printf("eglCreatePixmapSurface()\n");
551 return EGL_NO_SURFACE
;
556 fbCreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, const EGLint
*attrib_list
)
560 surf
= (fbSurface
*) calloc(1, sizeof(fbSurface
));
562 return EGL_NO_SURFACE
;
565 if (_eglInitPbufferSurface(&surf
->Base
, drv
, dpy
, config
, attrib_list
) == EGL_NO_SURFACE
) {
567 return EGL_NO_SURFACE
;
570 /* create software-based pbuffer */
572 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
574 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
575 assert(conf
); /* bad config should be caught earlier */
576 _eglConfigToContextModesRec(conf
, &vis
);
578 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
579 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
580 GL_TRUE
, /* color bufs */
582 vis
.haveStencilBuffer
,
584 GL_FALSE
, /* alpha */
585 GL_FALSE
/* aux */ );
587 /* set pbuffer/framebuffer size */
588 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
589 surf
->Base
.Width
, surf
->Base
.Height
);
592 return surf
->Base
.Handle
;
597 fbDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
599 fbSurface
*fs
= Lookup_fbSurface(surface
);
600 _eglRemoveSurface(&fs
->Base
);
601 if (fs
->Base
.IsBound
) {
602 fs
->Base
.DeletePending
= EGL_TRUE
;
612 fbDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
614 fbContext
*fc
= Lookup_fbContext(context
);
615 _eglRemoveContext(&fc
->Base
);
616 if (fc
->Base
.IsBound
) {
617 fc
->Base
.DeletePending
= EGL_TRUE
;
627 fbMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
, EGLSurface read
, EGLContext context
)
629 fbSurface
*readSurf
= Lookup_fbSurface(read
);
630 fbSurface
*drawSurf
= Lookup_fbSurface(draw
);
631 fbContext
*ctx
= Lookup_fbContext(context
);
634 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
639 _mesa_make_current( ctx
->glCtx
,
640 drawSurf
->mesa_framebuffer
,
641 readSurf
->mesa_framebuffer
);
643 _mesa_make_current( NULL
, NULL
, NULL
);
650 * Create a drawing surface which can be directly displayed on a screen.
653 fbCreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
654 const EGLint
*attrib_list
)
656 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
657 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
661 GLcontext
*ctx
= NULL
; /* this should be OK */
662 int origin
, bytesPerPixel
;
663 int width
, height
, stride
;
665 surface
= (fbSurface
*) malloc(sizeof(*surface
));
667 return EGL_NO_SURFACE
;
670 /* init base class, error check, etc. */
671 surf
= _eglInitScreenSurface(&surface
->Base
, drv
, dpy
, cfg
, attrib_list
);
672 if (surf
== EGL_NO_SURFACE
) {
674 return EGL_NO_SURFACE
;
677 /* convert EGLConfig to GLvisual */
678 _eglConfigToContextModesRec(config
, &vis
);
680 /* create Mesa framebuffer */
681 surface
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
682 if (!surface
->mesa_framebuffer
) {
684 _eglRemoveSurface(&surface
->Base
);
685 return EGL_NO_SURFACE
;
688 width
= surface
->Base
.Width
;
689 height
= surface
->Base
.Height
;
690 bytesPerPixel
= vis
.rgbBits
/ 8;
691 stride
= width
* bytesPerPixel
;
694 /* front color renderbuffer */
696 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, bytesPerPixel
,
698 fbSetSpanFunctions(drb
, &vis
);
699 drb
->Base
.Data
= display
->pFB
;
700 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
701 BUFFER_FRONT_LEFT
, &drb
->Base
);
704 /* back color renderbuffer */
705 if (vis
.doubleBufferMode
) {
706 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, bytesPerPixel
,
708 fbSetSpanFunctions(drb
, &vis
);
709 drb
->Base
.Data
= _mesa_malloc(stride
* height
);
710 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
711 BUFFER_BACK_LEFT
, &drb
->Base
);
714 /* other renderbuffers- software based */
715 _mesa_add_soft_renderbuffers(surface
->mesa_framebuffer
,
716 GL_FALSE
, /* color */
718 vis
.haveStencilBuffer
,
720 GL_FALSE
, /* alpha */
723 _mesa_resize_framebuffer(ctx
, surface
->mesa_framebuffer
, width
, height
);
730 * Show the given surface on the named screen.
731 * If surface is EGL_NO_SURFACE, disable the screen's output.
734 fbShowSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
735 EGLSurface surface
, EGLModeMESA m
)
737 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
738 fbScreen
*scrn
= Lookup_fbScreen(dpy
, screen
);
739 fbSurface
*surf
= Lookup_fbSurface(surface
);
741 char buffer
[NAME_MAX
];
742 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
745 if (!_eglShowSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
748 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
750 file
= fopen(buffer
, "r+");
753 printf("chown all fb sysfs attrib to allow write - %s\n", buffer
);
756 snprintf(buffer
, sizeof(buffer
), "%d", (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
760 if (m
== EGL_NO_MODE_MESA
)
763 snprintf(buffer
, sizeof(buffer
), "%s/%s/mode", sysfs
, scrn
->fb
);
765 file
= fopen(buffer
, "r+");
768 fputs(mode
->Name
, file
);
771 snprintf(buffer
, sizeof(buffer
), "%s/%s/bits_per_pixel", sysfs
, scrn
->fb
);
773 file
= fopen(buffer
, "r+");
776 bits
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
777 snprintf(buffer
, sizeof(buffer
), "%d", bits
);
781 fbSetupFramebuffer(display
, scrn
->fb
);
783 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
785 file
= fopen(buffer
, "r+");
789 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
797 /* If the backbuffer is on a videocard, this is extraordinarily slow!
800 fbSwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
802 fbContext
*context
= (fbContext
*)_eglGetCurrentContext();
803 fbSurface
*fs
= Lookup_fbSurface(draw
);
804 struct gl_renderbuffer
* front_renderbuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
805 void *frontBuffer
= front_renderbuffer
->Data
;
806 int currentPitch
= ((driRenderbuffer
*)front_renderbuffer
)->pitch
;
807 void *backBuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
->Data
;
809 if (!_eglSwapBuffers(drv
, dpy
, draw
))
813 GLcontext
*ctx
= context
->glCtx
;
815 if (ctx
->Visual
.doubleBufferMode
) {
818 char *tmp
= _mesa_malloc(currentPitch
);
820 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
825 for (i
= 0; i
< fs
->Base
.Height
; i
++) {
826 _mesa_memcpy(tmp
, (char *) backBuffer
+ offset
,
828 _mesa_memcpy((char *) frontBuffer
+ offset
, tmp
,
830 offset
+= currentPitch
;
837 /* XXX this shouldn't be an error but we can't handle it for now */
838 _mesa_problem(NULL
, "fbSwapBuffers: drawable has no context!\n");
846 * Just to silence warning
849 _eglMain(NativeDisplayType dpy
);
853 * The bootstrap function. Return a new fbDriver object and
854 * plug in API functions.
857 _eglMain(NativeDisplayType dpy
)
861 fb
= (fbDriver
*) calloc(1, sizeof(fbDriver
));
866 /* First fill in the dispatch table with defaults */
867 _eglInitDriverFallbacks(&fb
->Base
);
869 /* then plug in our fb-specific functions */
870 fb
->Base
.Initialize
= fbInitialize
;
871 fb
->Base
.Terminate
= fbTerminate
;
872 fb
->Base
.CreateContext
= fbCreateContext
;
873 fb
->Base
.MakeCurrent
= fbMakeCurrent
;
874 fb
->Base
.CreateWindowSurface
= fbCreateWindowSurface
;
875 fb
->Base
.CreatePixmapSurface
= fbCreatePixmapSurface
;
876 fb
->Base
.CreatePbufferSurface
= fbCreatePbufferSurface
;
877 fb
->Base
.DestroySurface
= fbDestroySurface
;
878 fb
->Base
.DestroyContext
= fbDestroyContext
;
879 fb
->Base
.CreateScreenSurfaceMESA
= fbCreateScreenSurfaceMESA
;
880 fb
->Base
.ShowSurfaceMESA
= fbShowSurfaceMESA
;
881 fb
->Base
.SwapBuffers
= fbSwapBuffers
;
883 /* enable supported extensions */
884 fb
->Base
.MESA_screen_surface
= EGL_TRUE
;
885 fb
->Base
.MESA_copy_context
= EGL_TRUE
;