📄 fb_egl.c
字号:
/* * Test egl driver for fb_dri.so */#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <dirent.h> #include <errno.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <linux/fb.h>#include "utils.h"#include "buffers.h"#include "extensions.h"#include "framebuffer.h"#include "renderbuffer.h"#include "vbo/vbo.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 voidfbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis);/** * 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; struct { __DRIcontextPrivate *context; __DRIscreenPrivate *screen; __DRIdrawablePrivate *drawable; /* drawable bound to this ctx */ } dri;} fbContext, *fbContextPtr;#define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))static EGLBooleanfbFillInConfigs(_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 EGLBooleanfbSetupFramebuffer(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 EGLBooleanfbInitialize(_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 EGLBooleanfbTerminate(_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 voidupdate_state( GLcontext *ctx, GLuint new_state ){ /* not much to do here - pass it on */ _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _vbo_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 voidget_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ){ *width = buffer->Width; *height = buffer->Height;}static voidupdateFramebufferSize(GLcontext *ctx){ fbContextPtr fbmesa = FB_CONTEXT(ctx); struct gl_framebuffer *fb = ctx->WinSysDrawBuffer; if (fbmesa->dri.drawable->w != fb->Width || fbmesa->dri.drawable->h != fb->Height) { driUpdateFramebufferSize(ctx, fbmesa->dri.drawable); }}static voidviewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h){ /* XXX this should be called after we acquire the DRI lock, not here */ updateFramebufferSize(ctx);}static voidinit_core_functions( struct dd_function_table *functions ){ functions->GetString = get_string; functions->UpdateState = update_state; functions->GetBufferSize = get_buffer_size; functions->Viewport = viewport; functions->Clear = _swrast_Clear; /* could accelerate with blits */}static EGLContextfbCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list){ GLcontext *ctx; _EGLConfig *conf; fbContext *c; _EGLDisplay *disp = _eglLookupDisplay(dpy);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -