/** * Produce a set of EGL configs. */ static EGLint create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) { int id = first_id; for (; m; m = m->next) { struct xdri_egl_config *xdri_conf; _EGLConfig conf; EGLint rb; if (!convert_config(&conf, id, m)) continue; rb = (m->doubleBufferMode) ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER; xdri_conf = CALLOC_STRUCT(xdri_egl_config); if (xdri_conf) { memcpy(&xdri_conf->Base, &conf, sizeof(conf)); xdri_conf->mode = m; xdri_conf->window_render_buffer = rb; _eglAddConfig(disp, &xdri_conf->Base); id++; } } return id; }
/** * Create the EGLConfigs. (one per X visual) */ static void create_configs(_EGLDriver *drv, EGLDisplay dpy) { static const EGLint all_apis = (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT | EGL_OPENGL_BIT); _EGLDisplay *disp = _eglLookupDisplay(dpy); XVisualInfo *visInfo, visTemplate; int num_visuals, i; /* get list of all X visuals, create an EGL config for each */ visTemplate.screen = DefaultScreen(disp->Xdpy); visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask, &visTemplate, &num_visuals); if (!visInfo) { printf("egl_xlib.c: couldn't get any X visuals\n"); abort(); } for (i = 0; i < num_visuals; i++) { _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); int id = i + 1; int rbits = bitcount(visInfo[i].red_mask); int gbits = bitcount(visInfo[i].green_mask); int bbits = bitcount(visInfo[i].blue_mask); int abits = bbits == 8 ? 8 : 0; int zbits = 24; int sbits = 8; int visid = visInfo[i].visualid; #if defined(__cplusplus) || defined(c_plusplus) int vistype = visInfo[i].c_class; #else int vistype = visInfo[i].class; #endif _eglInitConfig(config, id); SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits); SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits); SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits); SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits); SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits); SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits); SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits); SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid); SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype); SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE); SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis); SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis); SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); _eglAddConfig(disp, config); } }
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; }
EGLBoolean drm_initialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) { struct drm_device *dev; struct drm_screen *screen = NULL; drmModeConnectorPtr connector = NULL; drmModeResPtr res = NULL; unsigned count_connectors = 0; int num_screens = 0; EGLint i; int fd; _EGLConfig *config; dev = (struct drm_device *) calloc(1, sizeof(struct drm_device)); if (!dev) return EGL_FALSE; dev->api = drm_api_create(); /* try the first node */ fd = drm_open_minor(0); if (fd < 0) goto err_fd; dev->drmFD = fd; drm_get_device_id(dev); dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL); if (!dev->screen) goto err_screen; dev->winsys = dev->screen->winsys; driInitExtensions(NULL, NULL, GL_FALSE); drm_update_res(dev); res = dev->res; if (res) count_connectors = res->count_connectors; else _eglLog(_EGL_WARNING, "Could not retrive kms information\n"); for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) { connector = drmModeGetConnector(fd, res->connectors[i]); if (!connector) continue; if (connector->connection != DRM_MODE_CONNECTED) { drmModeFreeConnector(connector); continue; } screen = malloc(sizeof(struct drm_screen)); memset(screen, 0, sizeof(*screen)); screen->connector = connector; screen->connectorID = connector->connector_id; _eglInitScreen(&screen->base); _eglAddScreen(disp, &screen->base); drm_add_modes_from_connector(&screen->base, connector); drm_find_dpms(dev, screen); dev->screens[num_screens++] = screen; } dev->count_screens = num_screens; disp->DriverData = dev; /* for now we only have one config */ config = calloc(1, sizeof(*config)); memset(config, 1, sizeof(*config)); _eglInitConfig(config, 1); _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24); _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); _eglAddConfig(disp, config); disp->ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; /* enable supported extensions */ disp->Extensions.MESA_screen_surface = EGL_TRUE; disp->Extensions.MESA_copy_context = EGL_TRUE; *major = 1; *minor = 4; return EGL_TRUE; err_screen: drmClose(fd); err_fd: free(dev); return EGL_FALSE; }
static void dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, int depth, xcb_visualtype_t *visual) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy; _EGLConfig base; unsigned int attrib, value, double_buffer; EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; int i; dri2_dpy = disp->DriverData; _eglInitConfig(&base, disp, id); i = 0; while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { switch (attrib) { case __DRI_ATTRIB_RENDER_TYPE: if (value & __DRI_ATTRIB_RGBA_BIT) value = EGL_RGB_BUFFER; else if (value & __DRI_ATTRIB_LUMINANCE_BIT) value = EGL_LUMINANCE_BUFFER; else /* not valid */; _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); break; case __DRI_ATTRIB_CONFIG_CAVEAT: if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) value = EGL_NON_CONFORMANT_CONFIG; else if (value & __DRI_ATTRIB_SLOW_BIT) value = EGL_SLOW_CONFIG; else value = EGL_NONE; _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); break; case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: bind_to_texture_rgb = value; break; case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: bind_to_texture_rgba = value; break; case __DRI_ATTRIB_DOUBLE_BUFFER: double_buffer = value; break; default: key = dri2_to_egl_attribute_map[attrib]; if (key != 0) _eglSetConfigKey(&base, key, value); break; } } /* In EGL, double buffer or not isn't a config attribute. Pixmaps * surfaces are always single buffered, pbuffer surfaces are always * back buffers and windows can be either, selected by passing an * attribute at window surface construction time. To support this * we ignore all double buffer configs and manipulate the buffer we * return in the getBuffer callback to get the behaviour we want. */ if (double_buffer) return; if (visual != NULL) { if (depth != _eglGetConfigKey(&base, EGL_BUFFER_SIZE)) return; _eglSetConfigKey(&base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT); _eglSetConfigKey(&base, EGL_NATIVE_VISUAL_ID, visual->visual_id); _eglSetConfigKey(&base, EGL_NATIVE_VISUAL_TYPE, visual->_class); } else { _eglSetConfigKey(&base, EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_PBUFFER_BIT); } _eglSetConfigKey(&base, EGL_NATIVE_RENDERABLE, EGL_TRUE); _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb); if (_eglGetConfigKey(&base, EGL_ALPHA_SIZE) > 0) _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba); /* EGL_OPENGL_ES_BIT, EGL_OPENVG_BIT, EGL_OPENGL_ES2_BIT */ _eglSetConfigKey(&base, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT); _eglSetConfigKey(&base, EGL_CONFORMANT, EGL_OPENGL_BIT); if (!_eglValidateConfig(&base, EGL_FALSE)) { _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); return; } conf = malloc(sizeof *conf); if (conf != NULL) { memcpy(&conf->base, &base, sizeof base); conf->dri_config = dri_config; _eglAddConfig(disp, &conf->base); } }