From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c | 881 +++++++++++++++++++++ 1 file changed, 881 insertions(+) create mode 100644 nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c') diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c new file mode 100644 index 000000000..2cea48808 --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c @@ -0,0 +1,881 @@ +/* + * Test egl driver for fb_dri.so + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "buffers.h" +#include "extensions.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#include "drivers/common/driverfuncs.h" +#include "drirenderbuffer.h" + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "eglmode.h" +#include "eglscreen.h" +#include "eglsurface.h" + +extern void +fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis); +extern void +fbSetBuffer( GLcontext *ctx, GLframebuffer *colorBuffer, GLuint bufferBit); + +/** + * fb driver-specific driver class derived from _EGLDriver + */ +typedef struct fb_driver +{ + _EGLDriver Base; /* base class/object */ + GLuint fbStuff; +} fbDriver; + +/** + * fb display-specific driver class derived from _EGLDisplay + */ +typedef struct fb_display +{ + _EGLDisplay Base; /* base class/object */ + void *pFB; +} fbDisplay; + +/** + * fb driver-specific screen class derived from _EGLScreen + */ +typedef struct fb_screen +{ + _EGLScreen Base; + char fb[NAME_MAX]; +} fbScreen; + + +/** + * fb driver-specific surface class derived from _EGLSurface + */ +typedef struct fb_surface +{ + _EGLSurface Base; /* base class/object */ + struct gl_framebuffer *mesa_framebuffer; +} fbSurface; + + +/** + * fb driver-specific context class derived from _EGLContext + */ +typedef struct fb_context +{ + _EGLContext Base; /* base class/object */ + GLcontext *glCtx; +} fbContext; + + +static EGLBoolean +fbFillInConfigs(_EGLDisplay *disp, unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer) { + _EGLConfig *configs; + _EGLConfig *c; + unsigned int i, num_configs; + unsigned int depth_buffer_factor; + unsigned int back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy + * enough to add support. Basically, if a context is created with an + * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping + * will never be used. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */ + }; + + u_int8_t depth_bits_array[2]; + u_int8_t stencil_bits_array[2]; + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1; + back_buffer_factor = (have_back_buffer) ? 2 : 1; + + num_configs = depth_buffer_factor * back_buffer_factor * 2; + + if (pixel_bits == 16) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } else { + fb_format = GL_RGBA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + configs = calloc(sizeof(*configs), num_configs); + c = configs; + if (!_eglFillInConfigs(c, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR)) { + fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__); + return EGL_FALSE; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for (i = 0, c = configs; i < num_configs; i++, c++) { + int stencil = GET_CONFIG_ATTRIB(c, EGL_STENCIL_SIZE); + if ((stencil != 0) && (stencil != stencil_bits)) { + SET_CONFIG_ATTRIB(c, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG); + } + } + + for (i = 0, c = configs; i < num_configs; i++, c++) + _eglAddConfig(disp, c); + + free(configs); + + return EGL_TRUE; +} + +static EGLBoolean +fbSetupFramebuffer(fbDisplay *disp, char *fbdev) +{ + int fd; + char dev[20]; + struct fb_var_screeninfo varInfo; + struct fb_fix_screeninfo fixedInfo; + + snprintf(dev, sizeof(dev), "/dev/%s", fbdev); + + /* open the framebuffer device */ + fd = open(dev, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Error opening %s: %s\n", fbdev, strerror(errno)); + return EGL_FALSE; + } + + /* get the original variable screen info */ + if (ioctl(fd, FBIOGET_VSCREENINFO, &varInfo)) { + fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", + strerror(errno)); + return EGL_FALSE; + } + + /* Turn off hw accels (otherwise mmap of mmio region will be + * refused) + */ + if (varInfo.accel_flags) { + varInfo.accel_flags = 0; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &varInfo)) { + fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n", + strerror(errno)); + return EGL_FALSE; + } + } + + /* Get the fixed screen info */ + if (ioctl(fd, FBIOGET_FSCREENINFO, &fixedInfo)) { + fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", + strerror(errno)); + return EGL_FALSE; + } + + if (fixedInfo.visual == FB_VISUAL_DIRECTCOLOR) { + struct fb_cmap cmap; + unsigned short red[256], green[256], blue[256]; + int rcols = 1 << varInfo.red.length; + int gcols = 1 << varInfo.green.length; + int bcols = 1 << varInfo.blue.length; + int i; + + cmap.start = 0; + cmap.len = gcols; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = NULL; + + for (i = 0; i < rcols ; i++) + red[i] = (65536/(rcols-1)) * i; + + for (i = 0; i < gcols ; i++) + green[i] = (65536/(gcols-1)) * i; + + for (i = 0; i < bcols ; i++) + blue[i] = (65536/(bcols-1)) * i; + + if (ioctl(fd, FBIOPUTCMAP, (void *) &cmap) < 0) { + fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i); + exit(1); + } + } + + /* mmap the framebuffer into our address space */ + if (!disp->pFB) + disp->pFB = (caddr_t)mmap(0, /* start */ + fixedInfo.smem_len, /* bytes */ + PROT_READ | PROT_WRITE, /* prot */ + MAP_SHARED, /* flags */ + fd, /* fd */ + 0); /* offset */ + if (disp->pFB == (caddr_t)-1) { + fprintf(stderr, "error: unable to mmap framebuffer: %s\n", + strerror(errno)); + return EGL_FALSE; + } + + return EGL_TRUE; +} + +const char *sysfs = "/sys/class/graphics"; + +static EGLBoolean +fbInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + fbDisplay *display; + fbScreen *s; + _EGLScreen *scrn; + char c; + unsigned int x, y, r; + DIR *dir; + FILE *file; + struct dirent *dirent; + char path[NAME_MAX]; + + /* Switch display structure to one with our private fields */ + display = calloc(1, sizeof(*display)); + display->Base = *disp; + _eglHashInsert(_eglGlobal.Displays, disp->Handle, display); + free(disp); + + *major = 1; + *minor = 0; + + dir = opendir(sysfs); + if (!dir) { + printf("EGL - %s framebuffer device not found.", sysfs); + return EGL_FALSE; + } + + while ((dirent = readdir(dir))) { /* assignment! */ + + if (dirent->d_name[0] != 'f') + continue; + if (dirent->d_name[1] != 'b') + continue; + + if (fbSetupFramebuffer(display, dirent->d_name) == EGL_FALSE) + continue; + + /* Create a screen */ + s = (fbScreen *) calloc(1, sizeof(fbScreen)); + if (!s) + return EGL_FALSE; + + strncpy(s->fb, dirent->d_name, NAME_MAX); + scrn = &s->Base; + _eglInitScreen(scrn); + _eglAddScreen(&display->Base, scrn); + + snprintf(path, sizeof(path), "%s/%s/modes", sysfs, s->fb); + file = fopen(path, "r"); + while (fgets(path, sizeof(path), file)) { + sscanf(path, "%c:%ux%u-%u", &c, &x, &y, &r); + _eglAddMode(scrn, x, y, r * 1000, path); + } + fclose(file); + + fbFillInConfigs(&display->Base, 32, 24, 8, 1); + + } + closedir(dir); + + drv->Initialized = EGL_TRUE; + return EGL_TRUE; +} + + +static fbDisplay * +Lookup_fbDisplay(EGLDisplay dpy) +{ + _EGLDisplay *d = _eglLookupDisplay(dpy); + return (fbDisplay *) d; +} + + +static fbScreen * +Lookup_fbScreen(EGLDisplay dpy, EGLScreenMESA screen) +{ + _EGLScreen *s = _eglLookupScreen(dpy, screen); + return (fbScreen *) s; +} + + +static fbContext * +Lookup_fbContext(EGLContext ctx) +{ + _EGLContext *c = _eglLookupContext(ctx); + return (fbContext *) c; +} + + +static fbSurface * +Lookup_fbSurface(EGLSurface surf) +{ + _EGLSurface *s = _eglLookupSurface(surf); + return (fbSurface *) s; +} + + +static EGLBoolean +fbTerminate(_EGLDriver *drv, EGLDisplay dpy) +{ + fbDisplay *display = Lookup_fbDisplay(dpy); + _eglCleanupDisplay(&display->Base); + free(display); + free(drv); + return EGL_TRUE; +} + + +static const GLubyte * +get_string(GLcontext *ctx, GLenum pname) +{ + (void) ctx; + switch (pname) { + case GL_RENDERER: + return (const GLubyte *) "Mesa dumb framebuffer"; + default: + return NULL; + } +} + + +static void +update_state( GLcontext *ctx, GLuint new_state ) +{ + /* not much to do here - pass it on */ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); +} + + +/** + * Called by ctx->Driver.GetBufferSize from in core Mesa to query the + * current framebuffer size. + */ +static void +get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +{ + *width = buffer->Width; + *height = buffer->Height; +} + + +static void +viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + _mesa_ResizeBuffersMESA(); +} + + +static void +init_core_functions( struct dd_function_table *functions ) +{ + functions->GetString = get_string; + functions->UpdateState = update_state; + functions->ResizeBuffers = _mesa_resize_framebuffer; + functions->GetBufferSize = get_buffer_size; + functions->Viewport = viewport; + + functions->Clear = _swrast_Clear; /* could accelerate with blits */ +} + + +static EGLContext +fbCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +{ + GLcontext *ctx; + _EGLConfig *conf; + fbContext *c; + _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct dd_function_table functions; + GLvisual vis; + int i; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateContext"); + return EGL_NO_CONTEXT; + } + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + /* no attribs defined for now */ + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); + return EGL_NO_CONTEXT; + } + } + + c = (fbContext *) calloc(1, sizeof(fbContext)); + if (!c) + return EGL_NO_CONTEXT; + + _eglInitContext(&c->Base); + c->Base.Display = disp; + c->Base.Config = conf; + c->Base.DrawSurface = EGL_NO_SURFACE; + c->Base.ReadSurface = EGL_NO_SURFACE; + + /* generate handle and insert into hash table */ + _eglSaveContext(&c->Base); + assert(c->Base.Handle); + + /* Init default driver functions then plug in our FBdev-specific functions + */ + _mesa_init_driver_functions(&functions); + init_core_functions(&functions); + + _eglConfigToContextModesRec(conf, &vis); + + ctx = c->glCtx = _mesa_create_context(&vis, NULL, &functions, (void *)c); + if (!c->glCtx) { + _mesa_free(c); + return GL_FALSE; + } + + /* Create module contexts */ + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + _swsetup_Wakeup( ctx ); + + + /* swrast init -- need to verify these tests - I just plucked the + * numbers out of the air. (KW) + */ + { + struct swrast_device_driver *swdd; + swdd = _swrast_GetDeviceDriverReference( ctx ); + swdd->SetBuffer = fbSetBuffer; + } + + /* use default TCL pipeline */ + { + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.RunPipeline = _tnl_run_pipeline; + } + + _mesa_enable_sw_extensions(ctx); + + return c->Base.Handle; +} + + +static EGLSurface +fbCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +{ + int i; + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + /* no attribs at this time */ + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface"); + return EGL_NO_SURFACE; + } + } + printf("eglCreateWindowSurface()\n"); + /* XXX unfinished */ + + return EGL_NO_SURFACE; +} + + +static EGLSurface +fbCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +{ + _EGLConfig *conf; + EGLint i; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface"); + return EGL_NO_SURFACE; + } + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + /* no attribs at this time */ + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface"); + return EGL_NO_SURFACE; + } + } + + if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) { + _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface"); + return EGL_NO_SURFACE; + } + + printf("eglCreatePixmapSurface()\n"); + return EGL_NO_SURFACE; +} + + +static EGLSurface +fbCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + fbSurface *surf; + + surf = (fbSurface *) calloc(1, sizeof(fbSurface)); + if (!surf) { + return EGL_NO_SURFACE; + } + + if (_eglInitPbufferSurface(&surf->Base, drv, dpy, config, attrib_list) == EGL_NO_SURFACE) { + free(surf); + return EGL_NO_SURFACE; + } + + /* create software-based pbuffer */ + { + GLcontext *ctx = NULL; /* this _should_ be OK */ + GLvisual vis; + _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + assert(conf); /* bad config should be caught earlier */ + _eglConfigToContextModesRec(conf, &vis); + + surf->mesa_framebuffer = _mesa_create_framebuffer(&vis); + _mesa_add_soft_renderbuffers(surf->mesa_framebuffer, + GL_TRUE, /* color bufs */ + vis.haveDepthBuffer, + vis.haveStencilBuffer, + vis.haveAccumBuffer, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */ ); + + /* set pbuffer/framebuffer size */ + _mesa_resize_framebuffer(ctx, surf->mesa_framebuffer, + surf->Base.Width, surf->Base.Height); + } + + return surf->Base.Handle; +} + + +static EGLBoolean +fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + fbSurface *fs = Lookup_fbSurface(surface); + _eglRemoveSurface(&fs->Base); + if (fs->Base.IsBound) { + fs->Base.DeletePending = EGL_TRUE; + } + else { + free(fs); + } + return EGL_TRUE; +} + + +static EGLBoolean +fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) +{ + fbContext *fc = Lookup_fbContext(context); + _eglRemoveContext(&fc->Base); + if (fc->Base.IsBound) { + fc->Base.DeletePending = EGL_TRUE; + } + else { + free(fc); + } + return EGL_TRUE; +} + + +static EGLBoolean +fbMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context) +{ + fbSurface *readSurf = Lookup_fbSurface(read); + fbSurface *drawSurf = Lookup_fbSurface(draw); + fbContext *ctx = Lookup_fbContext(context); + EGLBoolean b; + + b = _eglMakeCurrent(drv, dpy, draw, read, context); + if (!b) + return EGL_FALSE; + + if (ctx) { + _mesa_make_current( ctx->glCtx, + drawSurf->mesa_framebuffer, + readSurf->mesa_framebuffer); + } else + _mesa_make_current( NULL, NULL, NULL ); + + return EGL_TRUE; +} + + +/** + * Create a drawing surface which can be directly displayed on a screen. + */ +static EGLSurface +fbCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, + const EGLint *attrib_list) +{ + _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg); + fbDisplay *display = Lookup_fbDisplay(dpy); + fbSurface *surface; + EGLSurface surf; + GLvisual vis; + GLcontext *ctx = NULL; /* this should be OK */ + int origin, bytesPerPixel; + int width, height, stride; + + surface = (fbSurface *) malloc(sizeof(*surface)); + if (!surface) { + return EGL_NO_SURFACE; + } + + /* init base class, error check, etc. */ + surf = _eglInitScreenSurface(&surface->Base, drv, dpy, cfg, attrib_list); + if (surf == EGL_NO_SURFACE) { + free(surface); + return EGL_NO_SURFACE; + } + + /* convert EGLConfig to GLvisual */ + _eglConfigToContextModesRec(config, &vis); + + /* create Mesa framebuffer */ + surface->mesa_framebuffer = _mesa_create_framebuffer(&vis); + if (!surface->mesa_framebuffer) { + free(surface); + _eglRemoveSurface(&surface->Base); + return EGL_NO_SURFACE; + } + + width = surface->Base.Width; + height = surface->Base.Height; + bytesPerPixel = vis.rgbBits / 8; + stride = width * bytesPerPixel; + origin = 0; + + /* front color renderbuffer */ + { + driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, bytesPerPixel, + origin, stride); + fbSetSpanFunctions(drb, &vis); + drb->Base.Data = display->pFB; + _mesa_add_renderbuffer(surface->mesa_framebuffer, + BUFFER_FRONT_LEFT, &drb->Base); + } + + /* back color renderbuffer */ + if (vis.doubleBufferMode) { + driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, bytesPerPixel, + origin, stride); + fbSetSpanFunctions(drb, &vis); + drb->Base.Data = _mesa_malloc(stride * height); + _mesa_add_renderbuffer(surface->mesa_framebuffer, + BUFFER_BACK_LEFT, &drb->Base); + } + + /* other renderbuffers- software based */ + _mesa_add_soft_renderbuffers(surface->mesa_framebuffer, + GL_FALSE, /* color */ + vis.haveDepthBuffer, + vis.haveStencilBuffer, + vis.haveAccumBuffer, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + + _mesa_resize_framebuffer(ctx, surface->mesa_framebuffer, width, height); + + return surf; +} + + +/** + * Show the given surface on the named screen. + * If surface is EGL_NO_SURFACE, disable the screen's output. + */ +static EGLBoolean +fbShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, + EGLSurface surface, EGLModeMESA m) +{ + fbDisplay *display = Lookup_fbDisplay(dpy); + fbScreen *scrn = Lookup_fbScreen(dpy, screen); + fbSurface *surf = Lookup_fbSurface(surface); + FILE *file; + char buffer[NAME_MAX]; + _EGLMode *mode = _eglLookupMode(dpy, m); + int bits; + + if (!_eglShowSurfaceMESA(drv, dpy, screen, surface, m)) + return EGL_FALSE; + + snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb); + + file = fopen(buffer, "r+"); + if (!file) { +err: + printf("chown all fb sysfs attrib to allow write - %s\n", buffer); + return EGL_FALSE; + } + snprintf(buffer, sizeof(buffer), "%d", (m == EGL_NO_MODE_MESA ? VESA_POWERDOWN : VESA_VSYNC_SUSPEND)); + fputs(buffer, file); + fclose(file); + + if (m == EGL_NO_MODE_MESA) + return EGL_TRUE; + + snprintf(buffer, sizeof(buffer), "%s/%s/mode", sysfs, scrn->fb); + + file = fopen(buffer, "r+"); + if (!file) + goto err; + fputs(mode->Name, file); + fclose(file); + + snprintf(buffer, sizeof(buffer), "%s/%s/bits_per_pixel", sysfs, scrn->fb); + + file = fopen(buffer, "r+"); + if (!file) + goto err; + bits = GET_CONFIG_ATTRIB(surf->Base.Config, EGL_BUFFER_SIZE); + snprintf(buffer, sizeof(buffer), "%d", bits); + fputs(buffer, file); + fclose(file); + + fbSetupFramebuffer(display, scrn->fb); + + snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb); + + file = fopen(buffer, "r+"); + if (!file) + goto err; + + snprintf(buffer, sizeof(buffer), "%d", VESA_NO_BLANKING); + fputs(buffer, file); + fclose(file); + + return EGL_TRUE; +} + + +/* If the backbuffer is on a videocard, this is extraordinarily slow! + */ +static EGLBoolean +fbSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + fbContext *context = (fbContext *)_eglGetCurrentContext(); + fbSurface *fs = Lookup_fbSurface(draw); + struct gl_renderbuffer * front_renderbuffer = fs->mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + void *frontBuffer = front_renderbuffer->Data; + int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch; + void *backBuffer = fs->mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data; + + if (!_eglSwapBuffers(drv, dpy, draw)) + return EGL_FALSE; + + if (context) { + GLcontext *ctx = context->glCtx; + + if (ctx->Visual.doubleBufferMode) { + int i; + int offset = 0; + char *tmp = _mesa_malloc(currentPitch); + + _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ + + ASSERT(frontBuffer); + ASSERT(backBuffer); + + for (i = 0; i < fs->Base.Height; i++) { + _mesa_memcpy(tmp, (char *) backBuffer + offset, + currentPitch); + _mesa_memcpy((char *) frontBuffer + offset, tmp, + currentPitch); + offset += currentPitch; + } + + _mesa_free(tmp); + } + } + else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n"); + return EGL_FALSE; + } + return EGL_TRUE; +} + + +/** + * The bootstrap function. Return a new fbDriver object and + * plug in API functions. + */ +_EGLDriver * +_eglMain(_EGLDisplay *dpy) +{ + fbDriver *fb; + + fb = (fbDriver *) calloc(1, sizeof(fbDriver)); + if (!fb) { + return NULL; + } + + /* First fill in the dispatch table with defaults */ + _eglInitDriverFallbacks(&fb->Base); + + /* then plug in our fb-specific functions */ + fb->Base.Initialize = fbInitialize; + fb->Base.Terminate = fbTerminate; + fb->Base.CreateContext = fbCreateContext; + fb->Base.MakeCurrent = fbMakeCurrent; + fb->Base.CreateWindowSurface = fbCreateWindowSurface; + fb->Base.CreatePixmapSurface = fbCreatePixmapSurface; + fb->Base.CreatePbufferSurface = fbCreatePbufferSurface; + fb->Base.DestroySurface = fbDestroySurface; + fb->Base.DestroyContext = fbDestroyContext; + fb->Base.CreateScreenSurfaceMESA = fbCreateScreenSurfaceMESA; + fb->Base.ShowSurfaceMESA = fbShowSurfaceMESA; + fb->Base.SwapBuffers = fbSwapBuffers; + + /* enable supported extensions */ + fb->Base.MESA_screen_surface = EGL_TRUE; + fb->Base.MESA_copy_context = EGL_TRUE; + + return &fb->Base; +} -- cgit v1.2.3