/* * Copyright © 2008, 2009 Kristian Høgsberg * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include #include #include #include #include "libdri2.h" #include "eagle-internal.h" typedef struct EGLDisplayX11 *EGLDisplayX11; struct EGLDisplayX11 { struct EGLDisplay base; int eventBase; int errorBase; Window root; Display *display; }; typedef struct EGLSurfaceX11 *EGLSurfaceX11; struct EGLSurfaceX11 { struct EGLSurface base; Drawable drawable; }; static void x11GetBuffers(EGLSurface surface, uint32_t *attachments, int count) { EGLDisplayX11 x11Display = (EGLDisplayX11) surface->display; EGLSurfaceX11 x11Surface = (EGLSurfaceX11) surface; DRI2Buffer *buffers; uint32_t x11Attachments[10]; int i, j, outCount; /* Make sure we ask for a back buffer regardless of the config * in use and remap the buffers so the dri driver renders to * the back buffer in all cases. We should only do this for * Windows */ for (i = 0, j = 0; i < count; i++, j++) { if (i == 1 && attachments[i] != __DRI_BUFFER_BACK_LEFT) x11Attachments[j++] = __DRI_BUFFER_BACK_LEFT; x11Attachments[j] = attachments[i]; } buffers = DRI2GetBuffers(x11Display->display, x11Surface->drawable, &surface->width, &surface->height, x11Attachments, j, &outCount); for (j = j - i, i = 0; i < count; i++, j++) { surface->buffers[i].attachment = buffers[j].attachment; surface->buffers[i].name = buffers[j].name; surface->buffers[i].pitch = buffers[j].pitch; surface->buffers[i].cpp = buffers[j].cpp; } surface->buffers[0].attachment = __DRI_BUFFER_FRONT_LEFT; surface->count = count; XFree(buffers); } static EGLBoolean x11SwapBuffers(EGLDisplay display, EGLSurface surface) { EGLDisplayX11 x11Display = (EGLDisplayX11) display; EGLSurfaceX11 x11Surface = (EGLSurfaceX11) surface; XserverRegion region; XRectangle rect; rect.x = 0; rect.y = 0; rect.width = surface->width; rect.height = surface->height; region = XFixesCreateRegion(x11Display->display, &rect, 1); DRI2CopyRegion(x11Display->display, x11Surface->drawable, region, DRI2BufferFrontLeft, DRI2BufferBackLeft); XFixesDestroyRegion(x11Display->display, region); return EGL_TRUE; } static EGLBoolean x11DestroySurface(EGLDisplay display, EGLSurface surface) { EGLDisplayX11 x11Display = (EGLDisplayX11) display; EGLSurfaceX11 x11Surface = (EGLSurfaceX11) surface; DRI2DestroyDrawable(x11Display->display, x11Surface->drawable); return EGL_TRUE; } static const struct EagleBackend x11Backend = { x11GetBuffers, x11DestroySurface }; EAGLE_EXPORT EGLDisplay eglCreateDisplayX11(Display *display, Window root) { EGLDisplayX11 x11Display; int eventBase, errorBase; int major, minor; drm_magic_t magic; char *driverName, *deviceName; if (!DRI2QueryExtension(display, &eventBase, &errorBase)) return NULL; if (!DRI2QueryVersion(display, &major, &minor) || major < 1) return NULL; if (!DRI2Connect(display, root, &driverName, &deviceName)) return NULL; x11Display = malloc(sizeof *x11Display); if (x11Display == NULL) return NULL; x11Display->eventBase = eventBase; x11Display->errorBase = errorBase; x11Display->display = display; if (eglInitDisplay(&x11Display->base, deviceName, driverName) < 0) { free(x11Display); return NULL; } if (drmGetMagic(x11Display->base.fd, &magic)) { free(x11Display); return NULL; } DRI2Authenticate(display, root, magic); x11Display->base.backend = &x11Backend; return &x11Display->base; } EAGLE_EXPORT EGLSurface eglCreateSurfaceX11(EGLDisplay display, EGLConfig config, Window window, int width, int height) { EGLSurfaceX11 x11Surface; EGLDisplayX11 x11Display = (EGLDisplayX11) display; x11Surface = malloc(sizeof *x11Surface); if (x11Surface == NULL) return NULL; x11Surface->drawable = window; eglInitSurface(&x11Surface->base, display, config, width, height); DRI2CreateDrawable(x11Display->display, x11Surface->drawable); return &x11Surface->base; }