*/
+#include <dlfcn.h>
#include <X11/Xutil.h>
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
-#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
+#include "util/u_memory.h"
#include "softpipe/sp_winsys.h"
#include "eglconfig.h"
}
+static unsigned int
+bitcount(unsigned int n)
+{
+ unsigned int bits;
+ for (bits = 0; n > 0; n = n >> 1) {
+ bits += (n & 1);
+ }
+ return bits;
+}
+
+
/**
- * XXX temporary
- * Need to query X server's GLX visuals.
+ * Create the EGLConfigs. (one per X visual)
*/
static void
-init_configs(_EGLDriver *drv, EGLDisplay dpy)
+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);
- int i;
+ 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 < 2; i++) {
- _EGLConfig config;
+ for (i = 0; i < num_visuals; i++) {
+ _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
int id = i + 1;
- _eglInitConfig(&config, id);
- SET_CONFIG_ATTRIB(&config, EGL_RED_SIZE, 8);
- SET_CONFIG_ATTRIB(&config, EGL_GREEN_SIZE, 8);
- SET_CONFIG_ATTRIB(&config, EGL_BLUE_SIZE, 8);
- SET_CONFIG_ATTRIB(&config, EGL_ALPHA_SIZE, 8);
- if (i > 0) {
- SET_CONFIG_ATTRIB(&config, EGL_DEPTH_SIZE, 24);
- SET_CONFIG_ATTRIB(&config, EGL_STENCIL_SIZE, 8);
- }
- _eglAddConfig(disp, &config);
+ 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);
}
}
-
/**
* Called via eglInitialize(), drv->API.Initialize().
*/
xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
EGLint *minor, EGLint *major)
{
- /* visual configs */
-
- init_configs(drv, dpy);
-
+ create_configs(drv, dpy);
drv->Initialized = EGL_TRUE;
static EGLBoolean
xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
{
-
return EGL_TRUE;
}
+static _EGLProc
+xlib_eglGetProcAddress(const char *procname)
+{
+ return (_EGLProc) st_get_proc_address(procname);
+}
+
+
+static void
+get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo)
+{
+ XWindowAttributes attr;
+ XVisualInfo visTemp, *vis;
+ int num_visuals;
+
+ XGetWindowAttributes(dpy, d, &attr);
+
+ visTemp.screen = DefaultScreen(dpy);
+ visTemp.visualid = attr.visual->visualid;
+ vis = XGetVisualInfo(dpy,
+ (VisualScreenMask | VisualIDMask),
+ &visTemp, &num_visuals);
+ if (vis)
+ *visInfo = *vis;
+
+ XFree(vis);
+}
+
+
+
/** Get size of given window */
static Status
get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
}
+static void
+check_and_update_buffer_size(struct xlib_egl_surface *surface)
+{
+ uint width, height;
+ get_drawable_size(surface->Dpy, surface->Win, &width, &height);
+ st_resize_framebuffer(surface->Framebuffer, width, height);
+ surface->Base.Width = width;
+ surface->Base.Height = height;
+}
+
+
+
static void
display_surface(struct pipe_winsys *pws,
struct pipe_surface *psurf,
ximage->data = data;
ximage->width = psurf->width;
ximage->height = psurf->height;
- ximage->bytes_per_line = psurf->pitch * psurf->cpp;
+ ximage->bytes_per_line = psurf->stride;
XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc,
ximage, 0, 0, 0, 0, psurf->width, psurf->height);
+ XSync(xsurf->Dpy, 0);
+
ximage->data = NULL;
XDestroyImage(ximage);
return EGL_NO_CONTEXT;
}
- /* create a softpipe context */
- ctx->pipe = softpipe_create(xdrv->screen, xdrv->winsys, NULL);
-
- /* Now do xlib / state tracker inits here */
- _eglConfigToContextModesRec(conf, &visual);
- ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
+ /* API-dependent context creation */
+ switch (ctx->Base.ClientAPI) {
+ case EGL_OPENVG_API:
+ case EGL_OPENGL_ES_API:
+ _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n",
+ ctx->Base.ClientVersion);
+ /* fall-through */
+ case EGL_OPENGL_API:
+ /* create a softpipe context */
+ ctx->pipe = softpipe_create(xdrv->screen, xdrv->winsys, NULL);
+ /* Now do xlib / state tracker inits here */
+ _eglConfigToContextModesRec(conf, &visual);
+ ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
+ break;
+ default:
+ _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)");
+ free(ctx);
+ return EGL_NO_CONTEXT;
+ }
+ _eglSaveContext(&ctx->Base);
return _eglGetContextHandle(&ctx->Base);
}
context->Base.DeletePending = EGL_TRUE;
}
else {
- st_destroy_context(context->Context);
+ /* API-dependent clean-up */
+ switch (context->Base.ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ /* fall-through */
+ case EGL_OPENGL_API:
+ st_destroy_context(context->Context);
+ break;
+ default:
+ assert(0);
+ }
free(context);
}
return EGL_TRUE;
* Called via eglMakeCurrent(), drv->API.MakeCurrent().
*/
static EGLBoolean
-xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
- EGLSurface r, EGLContext context)
+xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy,
+ EGLSurface draw, EGLSurface read, EGLContext ctx)
{
- if (!_eglMakeCurrent(drv, dpy, d, r, context))
+ struct xlib_egl_context *context = lookup_context(ctx);
+ struct xlib_egl_surface *draw_surf = lookup_surface(draw);
+ struct xlib_egl_surface *read_surf = lookup_surface(read);
+
+ if (!_eglMakeCurrent(drv, dpy, draw, read, context))
return EGL_FALSE;
- /* XXX anything todo? */
+ st_make_current((context ? context->Context : NULL),
+ (draw_surf ? draw_surf->Framebuffer : NULL),
+ (read_surf ? read_surf->Framebuffer : NULL));
+
+ if (draw_surf)
+ check_and_update_buffer_size(draw_surf);
+ if (read_surf && read_surf != draw_surf)
+ check_and_update_buffer_size(draw_surf);
return EGL_TRUE;
}
choose_depth_format(const __GLcontextModes *visual)
{
if (visual->depthBits > 0)
- return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_S8Z24_UNORM;
else
return PIPE_FORMAT_NONE;
}
choose_stencil_format(const __GLcontextModes *visual)
{
if (visual->stencilBits > 0)
- return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_S8Z24_UNORM;
else
return PIPE_FORMAT_NONE;
}
return EGL_NO_SURFACE;
}
+ _eglSaveSurface(&surf->Base);
+
/*
* Now init the Xlib and gallium stuff
*/
_eglConfigToContextModesRec(conf, &visual);
get_drawable_size(surf->Dpy, surf->Win, &width, &height);
+ get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo);
+
+ surf->Base.Width = width;
+ surf->Base.Height = height;
/* Create GL statetracker framebuffer */
surf->Framebuffer = st_create_framebuffer(&visual,
choose_stencil_format(&visual),
width, height,
(void *) surf);
- return surf;
+
+ st_resize_framebuffer(surf->Framebuffer, width, height);
+
+ return _eglGetSurfaceHandle(&surf->Base);
+}
+
+
+static EGLBoolean
+xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+ struct xlib_egl_surface *surf = lookup_surface(surface);
+ if (surf) {
+ _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
+ if (surf->Base.IsBound) {
+ surf->Base.DeletePending = EGL_TRUE;
+ }
+ else {
+ XFreeGC(surf->Dpy, surf->Gc);
+ st_unreference_framebuffer(surf->Framebuffer);
+ free(surf);
+ }
+ return EGL_TRUE;
+ }
+ else {
+ _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
+ return EGL_FALSE;
+ }
}
struct pipe_surface *psurf =
st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT);
+ st_notify_swapbuffers(xsurf->Framebuffer);
+
display_surface(pws, psurf, xsurf);
+
+ check_and_update_buffer_size(xsurf);
}
return EGL_TRUE;
}
+/**
+ * Determine which API(s) is(are) present by looking for some specific
+ * global symbols.
+ */
+static EGLint
+find_supported_apis(void)
+{
+ EGLint mask = 0;
+ void *handle;
+
+ handle = dlopen(NULL, 0);
+
+ if (dlsym(handle, "st_api_OpenGL_ES1"))
+ mask |= EGL_OPENGL_ES_BIT;
+
+ if (dlsym(handle, "st_api_OpenGL_ES2"))
+ mask |= EGL_OPENGL_ES2_BIT;
+
+ if (dlsym(handle, "st_api_OpenGL"))
+ mask |= EGL_OPENGL_BIT;
+
+ if (dlsym(handle, "st_api_OpenVG"))
+ mask |= EGL_OPENVG_BIT;
+
+ dlclose(handle);
+
+ return mask;
+}
+
+
/**
* This is the main entrypoint into the driver.
* Called by libEGL to instantiate an _EGLDriver object.
if (!xdrv)
return NULL;
+ if (!dpy->Xdpy) {
+ dpy->Xdpy = XOpenDisplay(NULL);
+ }
+
_eglInitDriverFallbacks(&xdrv->Base);
xdrv->Base.API.Initialize = xlib_eglInitialize;
xdrv->Base.API.Terminate = xlib_eglTerminate;
+ xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress;
xdrv->Base.API.CreateContext = xlib_eglCreateContext;
xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
+ xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
+ xdrv->Base.ClientAPIsMask = find_supported_apis();
+ if (xdrv->Base.ClientAPIsMask == 0x0) {
+ /* the app isn't directly linked with any EGL-supprted APIs
+ * (such as libGLESv2.so) so use an EGL utility to see what
+ * APIs might be loaded dynamically on this system.
+ */
+ xdrv->Base.ClientAPIsMask = _eglFindAPIs();
+ }
- xdrv->Base.ClientAPIs = "OpenGL"; /* "OpenGL_ES" */
xdrv->Base.Name = "Xlib/softpipe";
/* create one winsys and use it for all contexts/surfaces */
xdrv->screen = softpipe_create_screen(xdrv->winsys);
-
return &xdrv->Base;
}