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 */
90 fbFillInConfigs(_EGLDisplay
*disp
, unsigned pixel_bits
, unsigned depth_bits
,
91 unsigned stencil_bits
, GLboolean have_back_buffer
) {
94 unsigned int i
, num_configs
;
95 unsigned int depth_buffer_factor
;
96 unsigned int back_buffer_factor
;
100 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
101 * enough to add support. Basically, if a context is created with an
102 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
103 * will never be used.
105 static const GLenum back_buffer_modes
[] = {
106 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
109 u_int8_t depth_bits_array
[2];
110 u_int8_t stencil_bits_array
[2];
112 depth_bits_array
[0] = 0;
113 depth_bits_array
[1] = depth_bits
;
115 /* Just like with the accumulation buffer, always provide some modes
116 * with a stencil buffer. It will be a sw fallback, but some apps won't
119 stencil_bits_array
[0] = 0;
120 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
122 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
123 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
125 num_configs
= depth_buffer_factor
* back_buffer_factor
* 2;
127 if (pixel_bits
== 16) {
129 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
132 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
135 configs
= calloc(sizeof(*configs
), num_configs
);
137 if (!_eglFillInConfigs(c
, fb_format
, fb_type
,
138 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
139 back_buffer_modes
, back_buffer_factor
,
141 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
146 /* Mark the visual as slow if there are "fake" stencil bits.
148 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++) {
149 int stencil
= GET_CONFIG_ATTRIB(c
, EGL_STENCIL_SIZE
);
150 if ((stencil
!= 0) && (stencil
!= stencil_bits
)) {
151 SET_CONFIG_ATTRIB(c
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
155 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++)
156 _eglAddConfig(disp
, c
);
164 fbSetupFramebuffer(fbDisplay
*disp
, char *fbdev
)
168 struct fb_var_screeninfo varInfo
;
169 struct fb_fix_screeninfo fixedInfo
;
171 snprintf(dev
, sizeof(dev
), "/dev/%s", fbdev
);
173 /* open the framebuffer device */
174 fd
= open(dev
, O_RDWR
);
176 fprintf(stderr
, "Error opening %s: %s\n", fbdev
, strerror(errno
));
180 /* get the original variable screen info */
181 if (ioctl(fd
, FBIOGET_VSCREENINFO
, &varInfo
)) {
182 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
187 /* Turn off hw accels (otherwise mmap of mmio region will be
190 if (varInfo
.accel_flags
) {
191 varInfo
.accel_flags
= 0;
192 if (ioctl(fd
, FBIOPUT_VSCREENINFO
, &varInfo
)) {
193 fprintf(stderr
, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
199 /* Get the fixed screen info */
200 if (ioctl(fd
, FBIOGET_FSCREENINFO
, &fixedInfo
)) {
201 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
206 /* mmap the framebuffer into our address space */
207 disp
->pFB
= (caddr_t
)mmap(0, /* start */
208 fixedInfo
.smem_len
, /* bytes */
209 PROT_READ
| PROT_WRITE
, /* prot */
210 MAP_SHARED
, /* flags */
213 if (disp
->pFB
== (caddr_t
)-1) {
214 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
222 const char *sysfs
= "/sys/class/graphics";
225 fbInitialize(_EGLDriver
*drv
, EGLDisplay dpy
, EGLint
*major
, EGLint
*minor
)
227 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
232 unsigned int x
, y
, r
;
235 struct dirent
*dirent
;
238 /* Switch display structure to one with our private fields */
239 display
= calloc(1, sizeof(*display
));
240 display
->Base
= *disp
;
241 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
247 dir
= opendir(sysfs
);
249 printf("EGL - %s framebuffer device not found.", sysfs
);
253 while ((dirent
= readdir(dir
))) { /* assignment! */
255 if (dirent
->d_name
[0] != 'f')
257 if (dirent
->d_name
[1] != 'b')
260 if (fbSetupFramebuffer(display
, dirent
->d_name
) == EGL_FALSE
)
263 /* Create a screen */
264 s
= (fbScreen
*) calloc(1, sizeof(fbScreen
));
268 strncpy(s
->fb
, dirent
->d_name
, NAME_MAX
);
270 _eglInitScreen(scrn
);
271 _eglAddScreen(&display
->Base
, scrn
);
273 snprintf(path
, sizeof(path
), "%s/%s/modes", sysfs
, s
->fb
);
274 file
= fopen(path
, "r");
275 while (fgets(path
, sizeof(path
), file
)) {
276 sscanf(path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
277 _eglAddMode(scrn
, x
, y
, r
* 1000, path
);
281 fbFillInConfigs(&display
->Base
, 32, 24, 8, 1);
286 drv
->Initialized
= EGL_TRUE
;
292 Lookup_fbDisplay(EGLDisplay dpy
)
294 _EGLDisplay
*d
= _eglLookupDisplay(dpy
);
295 return (fbDisplay
*) d
;
300 Lookup_fbScreen(EGLDisplay dpy
, EGLScreenMESA screen
)
302 _EGLScreen
*s
= _eglLookupScreen(dpy
, screen
);
303 return (fbScreen
*) s
;
308 Lookup_fbContext(EGLContext ctx
)
310 _EGLContext
*c
= _eglLookupContext(ctx
);
311 return (fbContext
*) c
;
316 Lookup_fbSurface(EGLSurface surf
)
318 _EGLSurface
*s
= _eglLookupSurface(surf
);
319 return (fbSurface
*) s
;
324 fbTerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
326 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
327 _eglCleanupDisplay(&display
->Base
);
334 static const GLubyte
*
335 get_string(GLcontext
*ctx
, GLenum pname
)
340 return (const GLubyte
*) "Mesa dumb framebuffer";
348 update_state( GLcontext
*ctx
, GLuint new_state
)
350 /* not much to do here - pass it on */
351 _swrast_InvalidateState( ctx
, new_state
);
352 _swsetup_InvalidateState( ctx
, new_state
);
353 _ac_InvalidateState( ctx
, new_state
);
354 _tnl_InvalidateState( ctx
, new_state
);
359 * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
360 * current framebuffer size.
363 get_buffer_size( GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
365 *width
= buffer
->Width
;
366 *height
= buffer
->Height
;
371 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
373 _mesa_ResizeBuffersMESA();
378 init_core_functions( struct dd_function_table
*functions
)
380 functions
->GetString
= get_string
;
381 functions
->UpdateState
= update_state
;
382 functions
->ResizeBuffers
= _mesa_resize_framebuffer
;
383 functions
->GetBufferSize
= get_buffer_size
;
384 functions
->Viewport
= viewport
;
386 functions
->Clear
= _swrast_Clear
; /* could accelerate with blits */
391 fbCreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, EGLContext share_list
, const EGLint
*attrib_list
)
396 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
397 struct dd_function_table functions
;
401 conf
= _eglLookupConfig(drv
, dpy
, config
);
403 _eglError(EGL_BAD_CONFIG
, "eglCreateContext");
404 return EGL_NO_CONTEXT
;
407 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
408 switch (attrib_list
[i
]) {
409 /* no attribs defined for now */
411 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateContext");
412 return EGL_NO_CONTEXT
;
416 c
= (fbContext
*) calloc(1, sizeof(fbContext
));
418 return EGL_NO_CONTEXT
;
420 _eglInitContext(&c
->Base
);
421 c
->Base
.Display
= disp
;
422 c
->Base
.Config
= conf
;
423 c
->Base
.DrawSurface
= EGL_NO_SURFACE
;
424 c
->Base
.ReadSurface
= EGL_NO_SURFACE
;
425 printf("fbCreateContext\n");
427 /* generate handle and insert into hash table */
428 _eglSaveContext(&c
->Base
);
429 assert(c
->Base
.Handle
);
431 /* Init default driver functions then plug in our FBdev-specific functions
433 _mesa_init_driver_functions(&functions
);
434 init_core_functions(&functions
);
436 _eglConfigToContextModesRec(conf
, &vis
);
438 ctx
= c
->glCtx
= _mesa_create_context(&vis
, NULL
, &functions
, (void *)c
);
444 /* Create module contexts */
445 _swrast_CreateContext( ctx
);
446 _ac_CreateContext( ctx
);
447 _tnl_CreateContext( ctx
);
448 _swsetup_CreateContext( ctx
);
449 _swsetup_Wakeup( ctx
);
452 /* swrast init -- need to verify these tests - I just plucked the
453 * numbers out of the air. (KW)
456 struct swrast_device_driver
*swdd
;
457 swdd
= _swrast_GetDeviceDriverReference( ctx
);
460 /* use default TCL pipeline */
462 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
463 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
466 _mesa_enable_sw_extensions(ctx
);
468 return c
->Base
.Handle
;
473 fbCreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativeWindowType window
, const EGLint
*attrib_list
)
476 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
477 switch (attrib_list
[i
]) {
478 /* no attribs at this time */
480 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateWindowSurface");
481 return EGL_NO_SURFACE
;
484 printf("eglCreateWindowSurface()\n");
487 return EGL_NO_SURFACE
;
492 fbCreatePixmapSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
497 conf
= _eglLookupConfig(drv
, dpy
, config
);
499 _eglError(EGL_BAD_CONFIG
, "eglCreatePixmapSurface");
500 return EGL_NO_SURFACE
;
503 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
504 switch (attrib_list
[i
]) {
505 /* no attribs at this time */
507 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePixmapSurface");
508 return EGL_NO_SURFACE
;
512 if (conf
->Attrib
[EGL_SURFACE_TYPE
- FIRST_ATTRIB
] == 0) {
513 _eglError(EGL_BAD_MATCH
, "eglCreatePixmapSurface");
514 return EGL_NO_SURFACE
;
517 printf("eglCreatePixmapSurface()\n");
518 return EGL_NO_SURFACE
;
523 fbCreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, const EGLint
*attrib_list
)
527 surf
= (fbSurface
*) calloc(1, sizeof(fbSurface
));
529 return EGL_NO_SURFACE
;
532 if (_eglInitPbufferSurface(&surf
->Base
, drv
, dpy
, config
, attrib_list
) == EGL_NO_SURFACE
) {
534 return EGL_NO_SURFACE
;
537 /* create software-based pbuffer */
539 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
541 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
542 assert(conf
); /* bad config should be caught earlier */
543 _eglConfigToContextModesRec(conf
, &vis
);
545 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
546 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
547 GL_TRUE
, /* color bufs */
549 vis
.haveStencilBuffer
,
551 GL_FALSE
, /* alpha */
552 GL_FALSE
/* aux */ );
554 /* set pbuffer/framebuffer size */
555 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
556 surf
->Base
.Width
, surf
->Base
.Height
);
559 return surf
->Base
.Handle
;
564 fbDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
566 fbSurface
*fs
= Lookup_fbSurface(surface
);
567 _eglRemoveSurface(&fs
->Base
);
568 if (fs
->Base
.IsBound
) {
569 fs
->Base
.DeletePending
= EGL_TRUE
;
579 fbDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
581 fbContext
*fc
= Lookup_fbContext(context
);
582 _eglRemoveContext(&fc
->Base
);
583 if (fc
->Base
.IsBound
) {
584 fc
->Base
.DeletePending
= EGL_TRUE
;
594 fbMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
, EGLSurface read
, EGLContext context
)
596 fbSurface
*readSurf
= Lookup_fbSurface(read
);
597 fbSurface
*drawSurf
= Lookup_fbSurface(draw
);
598 fbContext
*ctx
= Lookup_fbContext(context
);
601 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
606 _mesa_make_current( ctx
->glCtx
,
607 drawSurf
->mesa_framebuffer
,
608 readSurf
->mesa_framebuffer
);
610 _mesa_make_current( NULL
, NULL
, NULL
);
612 printf("eglMakeCurrent()\n");
618 * Create a drawing surface which can be directly displayed on a screen.
621 fbCreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
622 const EGLint
*attrib_list
)
624 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
625 fbDisplay
*display
= Lookup_fbDisplay(dpy
);
629 GLcontext
*ctx
= NULL
; /* this should be OK */
630 int origin
, bytesPerPixel
;
631 int width
, height
, stride
;
633 surface
= (fbSurface
*) malloc(sizeof(*surface
));
635 return EGL_NO_SURFACE
;
638 /* init base class, error check, etc. */
639 surf
= _eglInitScreenSurface(&surface
->Base
, drv
, dpy
, cfg
, attrib_list
);
640 if (surf
== EGL_NO_SURFACE
) {
642 return EGL_NO_SURFACE
;
645 /* convert EGLConfig to GLvisual */
646 _eglConfigToContextModesRec(config
, &vis
);
648 /* create Mesa framebuffer */
649 surface
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
650 if (!surface
->mesa_framebuffer
) {
652 _eglRemoveSurface(&surface
->Base
);
653 return EGL_NO_SURFACE
;
656 width
= surface
->Base
.Width
;
657 height
= surface
->Base
.Height
;
658 bytesPerPixel
= vis
.rgbBits
/ 8;
659 stride
= width
* bytesPerPixel
;
662 /* front color renderbuffer */
664 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, bytesPerPixel
,
666 fbSetSpanFunctions(drb
, &vis
);
667 drb
->Base
.Data
= display
->pFB
;
668 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
669 BUFFER_FRONT_LEFT
, &drb
->Base
);
672 /* back color renderbuffer */
673 if (vis
.doubleBufferMode
) {
674 driRenderbuffer
*drb
= driNewRenderbuffer(GL_RGBA
, bytesPerPixel
,
676 fbSetSpanFunctions(drb
, &vis
);
677 drb
->Base
.Data
= _mesa_malloc(stride
* height
);
678 _mesa_add_renderbuffer(surface
->mesa_framebuffer
,
679 BUFFER_BACK_LEFT
, &drb
->Base
);
682 /* other renderbuffers- software based */
683 _mesa_add_soft_renderbuffers(surface
->mesa_framebuffer
,
684 GL_FALSE
, /* color */
686 vis
.haveStencilBuffer
,
688 GL_FALSE
, /* alpha */
691 _mesa_resize_framebuffer(ctx
, surface
->mesa_framebuffer
, width
, height
);
698 * Show the given surface on the named screen.
699 * If surface is EGL_NO_SURFACE, disable the screen's output.
702 fbShowSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
703 EGLSurface surface
, EGLModeMESA m
)
706 char buffer
[NAME_MAX
];
707 fbScreen
*scrn
= Lookup_fbScreen(dpy
, screen
);
708 fbSurface
*surf
= Lookup_fbSurface(surface
);
709 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
712 if (!_eglShowSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
715 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
717 file
= fopen(buffer
, "r+");
720 printf("chown all fb sysfs attrib to allow write - %s\n", buffer
);
723 snprintf(buffer
, sizeof(buffer
), "%d", (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
727 if (m
== EGL_NO_MODE_MESA
)
730 snprintf(buffer
, sizeof(buffer
), "%s/%s/mode", sysfs
, scrn
->fb
);
732 file
= fopen(buffer
, "r+");
735 fputs(mode
->Name
, file
);
738 snprintf(buffer
, sizeof(buffer
), "%s/%s/bits_per_pixel", sysfs
, scrn
->fb
);
740 file
= fopen(buffer
, "r+");
743 bits
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
744 snprintf(buffer
, sizeof(buffer
), "%d", bits
);
748 snprintf(buffer
, sizeof(buffer
), "%s/%s/blank", sysfs
, scrn
->fb
);
750 file
= fopen(buffer
, "r+");
754 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
762 /* If the backbuffer is on a videocard, this is extraordinarily slow!
765 fbSwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
767 fbContext
*context
= (fbContext
*)_eglGetCurrentContext();
768 fbSurface
*fs
= Lookup_fbSurface(draw
);
769 struct gl_renderbuffer
* front_renderbuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
770 void *frontBuffer
= front_renderbuffer
->Data
;
771 int currentPitch
= ((driRenderbuffer
*)front_renderbuffer
)->pitch
;
772 void *backBuffer
= fs
->mesa_framebuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
->Data
;
774 if (!_eglSwapBuffers(drv
, dpy
, draw
))
778 GLcontext
*ctx
= context
->glCtx
;
780 if (ctx
->Visual
.doubleBufferMode
) {
783 char *tmp
= _mesa_malloc(currentPitch
);
785 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
790 for (i
= 0; i
< fs
->Base
.Height
; i
++) {
791 _mesa_memcpy(tmp
, (char *) backBuffer
+ offset
,
793 _mesa_memcpy((char *) frontBuffer
+ offset
, tmp
,
795 offset
+= currentPitch
;
802 /* XXX this shouldn't be an error but we can't handle it for now */
803 _mesa_problem(NULL
, "fbSwapBuffers: drawable has no context!\n");
809 * Just to silence warning
812 _eglMain(NativeDisplayType dpy
);
816 * The bootstrap function. Return a new fbDriver object and
817 * plug in API functions.
820 _eglMain(NativeDisplayType dpy
)
824 fb
= (fbDriver
*) calloc(1, sizeof(fbDriver
));
829 /* First fill in the dispatch table with defaults */
830 _eglInitDriverFallbacks(&fb
->Base
);
832 /* then plug in our fb-specific functions */
833 fb
->Base
.Initialize
= fbInitialize
;
834 fb
->Base
.Terminate
= fbTerminate
;
835 fb
->Base
.CreateContext
= fbCreateContext
;
836 fb
->Base
.MakeCurrent
= fbMakeCurrent
;
837 fb
->Base
.CreateWindowSurface
= fbCreateWindowSurface
;
838 fb
->Base
.CreatePixmapSurface
= fbCreatePixmapSurface
;
839 fb
->Base
.CreatePbufferSurface
= fbCreatePbufferSurface
;
840 fb
->Base
.DestroySurface
= fbDestroySurface
;
841 fb
->Base
.DestroyContext
= fbDestroyContext
;
842 fb
->Base
.CreateScreenSurfaceMESA
= fbCreateScreenSurfaceMESA
;
843 fb
->Base
.ShowSurfaceMESA
= fbShowSurfaceMESA
;
844 fb
->Base
.SwapBuffers
= fbSwapBuffers
;
846 /* enable supported extensions */
847 fb
->Base
.MESA_screen_surface
= EGL_TRUE
;
848 fb
->Base
.MESA_copy_context
= EGL_TRUE
;