summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will@willthompson.co.uk>2012-04-24 18:58:58 +0100
committerWill Thompson <will@willthompson.co.uk>2012-05-04 18:01:15 +0100
commit1643585820f0c4773fcdc91b21826efc8b79d691 (patch)
treec5528fb14956b03a6d8f1929267d1bbe5e114df1
parentf1b1a687b4ce1b817cae889931e8d85d8890a848 (diff)
Implement the essential bits of the EXA API
This doesn't work yet, not least because we let PrepareAccess fail for the screen pixmap.
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am10
-rw-r--r--src/videocore-exa.c558
-rw-r--r--src/videocore-exa.h9
-rw-r--r--src/videocore.c35
-rw-r--r--src/videocore.h3
6 files changed, 610 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 6dbc141..393dac6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,7 @@ fi
# Checks for libraries.
+PKG_CHECK_MODULES([VC], [bcm-host, egl])
AC_SUBST([moduledir])
diff --git a/src/Makefile.am b/src/Makefile.am
index d29dbef..242665c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,15 +25,19 @@
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = \
-Wall \
- @XORG_CFLAGS@
+ @XORG_CFLAGS@ \
+ @VC_CFLAGS@
videocore_drv_la_LTLIBRARIES = videocore_drv.la
-videocore_drv_la_LDFLAGS = -module -avoid-version
+videocore_drv_la_LDFLAGS = -module -avoid-version @VC_LIBS@
videocore_drv_ladir = @moduledir@/drivers
videocore_drv_la_SOURCES = \
videocore.c \
videocore.h \
- videocore-debug.h
+ videocore-debug.h \
+ videocore-exa.c \
+ videocore-exa.h \
+ $(NULL)
# vim: set et :
diff --git a/src/videocore-exa.c b/src/videocore-exa.c
new file mode 100644
index 0000000..7f25426
--- /dev/null
+++ b/src/videocore-exa.c
@@ -0,0 +1,558 @@
+/* vim: set noet sw=8 sts=8 cino=:0,t0,(0 :
+ *
+ * Copyright © 2012 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is fur-
+ * nished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+ * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+ * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the XFree86 Project shall not
+ * be used in advertising or otherwise to promote the sale, use or other deal-
+ * ings in this Software without prior written authorization from the XFree86
+ * Project.
+ */
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+/* eglGetProcAddress() doesn't work for eglCreateGlobalImageBRCM and friends. */
+#define EGL_EGLEXT_PROTOTYPES 1
+#include <EGL/eglext_brcm.h>
+#undef EGL_EGLEXT_PROTOTYPES
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <bcm_host.h>
+
+#include "videocore-exa.h"
+#include "videocore-debug.h"
+
+struct _VideoCoreExa {
+ ExaDriverPtr exa;
+ EGLDisplay display;
+ EGLConfig config;
+ EGLContext ctx;
+ EGLSurface surf;
+
+ EGL_DISPMANX_WINDOW_T nativeWindow;
+
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
+};
+
+static inline ScrnInfoPtr
+pix2scrn(PixmapPtr pPixmap)
+{
+ return xf86Screens[(pPixmap)->drawable.pScreen->myNum];
+}
+
+static Bool
+CheckGLError(ScrnInfoPtr pScrn, const char *context)
+{
+ GLenum error_code = glGetError ();
+
+ switch (error_code)
+ {
+ case GL_NO_ERROR:
+ return TRUE;
+ break;
+ case GL_INVALID_ENUM:
+ WARNING_MSG("%s: GL_INVALID_ENUM\n", context);
+ break;
+ case GL_INVALID_VALUE:
+ WARNING_MSG("%s: GL_INVALID_VALUE\n", context);
+ break;
+ case GL_INVALID_OPERATION:
+ WARNING_MSG("%s: GL_INVALID_OPERATION\n", context);
+ break;
+ case GL_OUT_OF_MEMORY:
+ WARNING_MSG("%s: GL_OUT_OF_MEMORY\n", context);
+ break;
+ default:
+ WARNING_MSG("%s: unknown error %x\n", context, error_code);
+ }
+
+ return FALSE;
+}
+
+static Bool
+InitEGL(ScreenPtr pScreen, VideoCoreExaPtr vcExa)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ EGLint num_config;
+ int32_t success = 0;
+ uint32_t screen_width, screen_height;
+
+ DISPMANX_DISPLAY_HANDLE_T dispman_display;
+ DISPMANX_UPDATE_HANDLE_T dispman_update;
+
+ VC_RECT_T src_rect, dst_rect;
+
+ static const EGLint chooseConfigAttrs[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE
+ };
+
+ static const EGLint createContextAttrs[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ static const EGLint createWindowSurfaceAttrs[] =
+ {
+ EGL_NONE
+ };
+
+ DEBUG_MSG("calling bcm_host_init");
+ bcm_host_init();
+
+ vcExa->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (vcExa->display == EGL_NO_DISPLAY) {
+ CheckGLError(pScrn, "eglGetDisplay returned EGL_NO_DISPLAY");
+ return FALSE;
+ }
+
+ DEBUG_MSG("eglInitialize");
+
+ if (!eglInitialize(vcExa->display, NULL, NULL)) {
+ CheckGLError(pScrn, "eglInitialize failed");
+ return FALSE;
+ }
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ ERROR_MSG("eglBindAPI(EGL_OPENGL_ES_API) failed. We're doomed.");
+ return FALSE;
+ }
+
+ if (!eglChooseConfig(vcExa->display, chooseConfigAttrs, &vcExa->config, 1, &num_config)) {
+ CheckGLError(pScrn, "eglChooseConfig failed");
+ return FALSE;
+ }
+
+ vcExa->ctx = eglCreateContext(vcExa->display, vcExa->config, EGL_NO_CONTEXT, createContextAttrs);
+ if (vcExa->ctx == EGL_NO_CONTEXT) {
+ ERROR_MSG("eglCreateContext failed");
+ return FALSE;
+ }
+
+ vcExa->glEGLImageTargetTexture2DOES = (void *)
+ eglGetProcAddress("glEGLImageTargetTexture2DOES");
+ if (vcExa->glEGLImageTargetTexture2DOES == NULL) {
+ ERROR_MSG("couldn't find glEGLImageTargetTexture2DOES");
+ return FALSE;
+ }
+
+ /* TODO: open the correct display, make sure the resolutions match up. */
+ success = graphics_get_display_size(DISPMANX_ID_MAIN_LCD, &screen_width, &screen_height);
+ if (success < 0) {
+ ERROR_MSG("graphics_get_display_size failed (%i)", success);
+ return FALSE;
+ }
+
+ DEBUG_MSG("videocore thinks the screen is %u x %u", screen_width, screen_height);
+
+ dst_rect.x = 0;
+ dst_rect.y = 0;
+ dst_rect.width = screen_width;
+ dst_rect.height = screen_height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = screen_width << 16;
+ src_rect.height = screen_height << 16;
+
+ dispman_display = vc_dispmanx_display_open(DISPMANX_ID_MAIN_LCD);
+ dispman_update = vc_dispmanx_update_start( 0 );
+
+ vcExa->nativeWindow.element =
+ vc_dispmanx_element_add(dispman_update, dispman_display,
+ 0/*layer*/, &dst_rect, 0/*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);
+
+ vcExa->nativeWindow.width = screen_width;
+ vcExa->nativeWindow.height = screen_height;
+ vc_dispmanx_update_submit_sync( dispman_update );
+
+ vcExa->surf = eglCreateWindowSurface(vcExa->display, vcExa->config,
+ &vcExa->nativeWindow,
+ createWindowSurfaceAttrs);
+
+ if (vcExa->surf == EGL_NO_SURFACE) {
+ CheckGLError(pScrn, "eglCreateWindowSurface failed");
+ return FALSE;
+ }
+
+ if (!eglMakeCurrent(vcExa->display, vcExa->surf, vcExa->surf, vcExa->ctx)) {
+ CheckGLError(pScrn, "eglMakeCurrent failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+VideoCoreWaitMarker(ScreenPtr pScreen, int marker)
+{
+ /* TODO */
+}
+
+#define GLOBAL_IMAGE_ID0 0
+#define GLOBAL_IMAGE_ID1 1
+#define GLOBAL_IMAGE_WIDTH 2
+#define GLOBAL_IMAGE_HEIGHT 3
+#define GLOBAL_IMAGE_PIXEL_FORMAT 4
+
+typedef struct _VideoCorePixmapPriv {
+ EGLint global_image[5];
+ EGLImageKHR egl_image;
+ GLuint texture_id;
+} VideoCorePixmapPrivRec, *VideoCorePixmapPrivPtr;
+
+static void *
+VideoCoreCreatePixmap2(ScreenPtr pScreen, int width, int height,
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch)
+{
+ VideoCorePixmapPrivPtr priv = calloc(sizeof(VideoCorePixmapPrivPtr), 1);
+
+ return priv;
+}
+
+static Bool
+AllocateGlobalImage(ScrnInfoPtr pScrn, int width, int height,
+ EGLint *global_image)
+{
+ int i, *tmp;
+ EGLint pixel_format;
+
+ assert(width > 0);
+ assert(height > 0);
+ assert(global_image != NULL);
+
+ tmp = calloc(sizeof(int), width * height);
+ /* Red-fill for potential debugging joy */
+ for (i = 0; i != width * height; i++) {
+ tmp[i] = 0xff << 8;
+ }
+
+ pixel_format = EGL_PIXEL_FORMAT_ARGB_8888_BRCM
+ | EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
+ eglCreateGlobalImageBRCM(width, height, pixel_format,
+ tmp, width * sizeof (int),
+ global_image);
+ free(tmp);
+
+ if (!CheckGLError(pScrn, "eglCreateGlobalImageBRCM")) {
+ return FALSE;
+ }
+
+ global_image[GLOBAL_IMAGE_WIDTH] = width;
+ global_image[GLOBAL_IMAGE_HEIGHT] = height;
+ global_image[GLOBAL_IMAGE_PIXEL_FORMAT] = pixel_format;
+ return TRUE;
+}
+
+static Bool
+CreateEGLImage(VideoCoreExaPtr vcExa, ScrnInfoPtr pScrn,
+ EGLint *global_image,
+ EGLImageKHR *egl_image_out)
+{
+ *egl_image_out = eglCreateImageKHR(vcExa->display, EGL_NO_CONTEXT,
+ EGL_NATIVE_PIXMAP_KHR,
+ (EGLClientBuffer) global_image,
+ NULL);
+ return CheckGLError(pScrn, "eglCreateImageKHR");
+}
+
+static Bool
+BindToTexture(VideoCoreExaPtr vcExa, ScrnInfoPtr pScrn, EGLImageKHR egl_image,
+ GLuint *texture_id_out)
+{
+ glGenTextures(1, texture_id_out);
+ glBindTexture(GL_TEXTURE_2D, *texture_id_out);
+ vcExa->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return CheckGLError(pScrn, "glEGLImageTargetTexture2DOES");
+}
+
+static void
+DestroyGlobalImage(VideoCoreExaPtr vcExa, ScrnInfoPtr pScrn,
+ VideoCorePixmapPrivPtr priv)
+{
+ if (priv->texture_id != 0) {
+ glDeleteTextures(1, &priv->texture_id);
+ priv->texture_id = 0;
+ }
+
+ if (priv->egl_image != EGL_NO_IMAGE_KHR) {
+ if (!eglDestroyImageKHR(vcExa->display, priv->egl_image)) {
+ WARNING_MSG("failed to destroy EGLImage");
+ }
+ priv->egl_image = EGL_NO_IMAGE_KHR;
+ }
+
+ if (priv->global_image[GLOBAL_IMAGE_ID0] != 0 &&
+ priv->global_image[GLOBAL_IMAGE_ID1] != 0) {
+ if (!eglDestroyGlobalImageBRCM(priv->global_image)) {
+ WARNING_MSG("failed to destroy global image (%u, %u)",
+ priv->global_image[GLOBAL_IMAGE_ID0],
+ priv->global_image[GLOBAL_IMAGE_ID1]);
+ }
+ priv->global_image[GLOBAL_IMAGE_ID0] = 0;
+ priv->global_image[GLOBAL_IMAGE_ID1] = 0;
+ }
+}
+
+static Bool
+VideoCoreModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData)
+{
+ VideoCorePixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+ ScrnInfoPtr pScrn = pix2scrn(pPixmap);
+ VideoCorePtr vcPtr = VIDEOCOREPTR(pScrn);
+ VideoCoreExaPtr vcExa = VideoCoreGetExa(vcPtr);
+
+ if (!miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel,
+ devKind, pPixData)) {
+ return FALSE;
+ }
+
+ /* TODO: check if pPixData is the magic value corresponding to the
+ * framebuffer.
+ */
+
+ if (pPixData) {
+ /* Unaccelerated pixel soup */
+ pPixmap->devPrivate.ptr = pPixData;
+ pPixmap->devKind = devKind;
+
+ /* Quoth -omap: "scratch-pixmap (see GetScratchPixmapHeader())
+ * gets recycled, so could have a previous bo!"
+ */
+ DestroyGlobalImage(vcExa, pScrn, priv);
+ return FALSE;
+ }
+
+ /* passed in values could be zero, indicating that existing values
+ * should be kept.. miModifyPixmapHeader() will deal with that, but
+ * we need to resync to ensure we have the right values in the rest
+ * of this function
+ */
+ width = pPixmap->drawable.width;
+ height = pPixmap->drawable.height;
+ depth = pPixmap->drawable.depth;
+ bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+
+ if (width * height == 0) {
+ DEBUG_MSG("zero area! (%u x %u)", width, height);
+ return TRUE;
+ }
+
+ if (priv->texture_id != 0) {
+ /* FIXME: check if it's already suitable? */
+ DestroyGlobalImage(vcExa, pScrn, priv);
+ }
+
+ /* FIXME: respect depth/bpp */
+ if (AllocateGlobalImage(pScrn, width, height, priv->global_image) &&
+ CreateEGLImage(vcExa, pScrn, priv->global_image, &priv->egl_image) &&
+ BindToTexture(vcExa, pScrn, priv->egl_image, &priv->texture_id)) {
+ return TRUE;
+ } else {
+ /* Okay, never mind. Roll that back. */
+ DestroyGlobalImage(vcExa, pScrn, priv);
+ return FALSE;
+ }
+}
+
+static void
+VideoCoreDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VideoCorePtr vcPtr = VIDEOCOREPTR(pScrn);
+ VideoCoreExaPtr vcExa = VideoCoreGetExa(vcPtr);
+ VideoCorePixmapPrivPtr priv = driverPriv;
+
+ DestroyGlobalImage(vcExa, pScrn, priv);
+
+ free(priv);
+}
+
+/*
+ * PrepareAccess() sets up an offscreen pixmap for CPU access. We can't do this
+ * efficiently, so we only support it for the visible screen, and fail in all
+ * other cases, which forces X to fall back to DownloadFromScreen().
+ */
+static Bool
+VideoCorePrepareAccess(PixmapPtr pPix, int index)
+{
+ /* TODO: if pPix is the visible screen, copy from the EGL surface to
+ * devPrivate.ptr and return TRUE. */
+ return FALSE;
+}
+
+static void
+VideoCoreFinishAccess(PixmapPtr pPix, int index)
+{
+ /* TODO: assert that pPix is the visible screen, and then copy back to
+ * the EGL surface. */
+}
+
+static Bool
+VideoCorePixmapIsOffscreen(PixmapPtr pPixmap)
+{
+ VideoCorePixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ return priv && priv->egl_image != EGL_NO_IMAGE_KHR;
+}
+
+static Bool
+PrepareSolidFail(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fill_colour)
+{
+ return FALSE;
+}
+
+static Bool
+PrepareCopyFail(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir,
+ int alu, Pixel planemask)
+{
+ return FALSE;
+}
+
+static Bool
+CheckCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ return FALSE;
+}
+
+static Bool
+PrepareCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ return FALSE;
+}
+
+static Bool
+VideoCoreUploadToScreen(PixmapPtr pDst,
+ int x, int y, int w, int h,
+ char *src, int src_pitch)
+{
+ VideoCorePixmapPrivPtr priv = exaGetPixmapDriverPrivate(pDst);
+ ScrnInfoPtr pScrn = pix2scrn(pDst);
+
+ if (priv->texture_id == 0) {
+ return FALSE;
+ }
+
+ /* TODO: obey src_pitch */
+ glBindTexture(GL_TEXTURE_2D, priv->texture_id);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
+ GL_RGBA, GL_UNSIGNED_BYTE, src);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return CheckGLError(pScrn, "UploadToScreen");
+}
+
+static Bool
+VideoCoreDownloadFromScreen(PixmapPtr pSrc,
+ int x, int y, int w, int h,
+ char *dst, int dst_pitch)
+{
+ VideoCorePixmapPrivPtr priv = exaGetPixmapDriverPrivate(pSrc);
+ ScrnInfoPtr pScrn = pix2scrn(pSrc);
+ GLuint sampleFramebuffer;
+
+ if (priv->texture_id == 0) {
+ return FALSE;
+ }
+
+ glGenFramebuffers(1, &sampleFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, sampleFramebuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, priv->texture_id, 0);
+
+ /* TODO: respect dst_pitch; do we need to turn things upside-down? */
+ glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, dst);
+
+ glDeleteFramebuffers(1, &sampleFramebuffer);
+
+ return CheckGLError(pScrn, "DownloadFromScreen");
+}
+
+VideoCoreExaPtr
+VideoCoreExaInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VideoCoreExaPtr vcExa;
+ ExaDriverPtr exa;
+
+ exa = exaDriverAlloc();
+ if (!exa) {
+ return NULL;
+ }
+
+ exa->exa_major = EXA_VERSION_MAJOR;
+ exa->exa_minor = EXA_VERSION_MINOR;
+
+ /* Cargo-culted from the OMAP driver. Hooray. */
+ exa->pixmapOffsetAlign = 0;
+ exa->pixmapPitchAlign = 32 * 4;
+ exa->flags = EXA_OFFSCREEN_PIXMAPS |
+ EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX;
+ exa->maxX = 4096;
+ exa->maxY = 4096;
+
+ exa->WaitMarker = VideoCoreWaitMarker;
+ exa->CreatePixmap2 = VideoCoreCreatePixmap2;
+ exa->DestroyPixmap = VideoCoreDestroyPixmap;
+ exa->ModifyPixmapHeader = VideoCoreModifyPixmapHeader;
+
+ exa->PrepareAccess = VideoCorePrepareAccess;
+ exa->FinishAccess = VideoCoreFinishAccess;
+ exa->PixmapIsOffscreen = VideoCorePixmapIsOffscreen;
+
+ /* OMAP fails all these, but maybe we should accelerate them? */
+ exa->PrepareSolid = PrepareSolidFail;
+ exa->PrepareCopy = PrepareCopyFail;
+ exa->CheckComposite = CheckCompositeFail;
+ exa->PrepareComposite = PrepareCompositeFail;
+
+ /* We need these because PrepareAccess can fail. */
+ exa->UploadToScreen = VideoCoreUploadToScreen;
+ exa->DownloadFromScreen = VideoCoreDownloadFromScreen;
+
+ vcExa = calloc(sizeof (*vcExa), 1);
+ vcExa->exa = exa;
+
+ if (InitEGL(pScreen, vcExa)) {
+ if (!exaDriverInit(pScreen, exa)) {
+ ERROR_MSG("exaDriverInit failed");
+ }
+ }
+
+ return vcExa;
+}
+
+/* TODO: free! */
diff --git a/src/videocore-exa.h b/src/videocore-exa.h
new file mode 100644
index 0000000..919ccb7
--- /dev/null
+++ b/src/videocore-exa.h
@@ -0,0 +1,9 @@
+#ifndef VIDEOCORE_EXA_H
+#define VIDEOCORE_EXA_H
+
+#include "exa.h"
+#include "videocore.h"
+
+VideoCoreExaPtr VideoCoreExaInit(ScreenPtr pScreen);
+
+#endif /* VIDEOCORE_EXA_H */
diff --git a/src/videocore.c b/src/videocore.c
index 22a86df..f0dac8d 100644
--- a/src/videocore.c
+++ b/src/videocore.c
@@ -1,6 +1,7 @@
-/*
+/* vim: set noet sw=8 sts=8 ts=8 cino=:0,t0,(0 :
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
- * Michel Dänzer, <michel@tungstengraphics.com>
+ * Michel Dänzer, <michel@tungstengraphics.com>
+ * Will Thompson <will.thompson@collabora.co.uk>
*/
#ifdef HAVE_CONFIG_H
@@ -38,6 +39,7 @@
#endif
#include "videocore.h"
+#include "videocore-exa.h"
#include "videocore-debug.h"
Bool videoCoreDebug = 0;
@@ -174,6 +176,9 @@ struct _VideoCoreRec {
EntityInfoPtr pEnt;
OptionInfoPtr Options;
+
+ /* EXA stuff */
+ VideoCoreExaPtr vcExa;
};
static Bool
@@ -195,6 +200,12 @@ FBDevFreeRec(ScrnInfoPtr pScrn)
pScrn->driverPrivate = NULL;
}
+VideoCoreExaPtr
+VideoCoreGetExa(VideoCorePtr vc)
+{
+ return vc->vcExa;
+}
+
/* -------------------------------------------------------------------- */
static const OptionInfoRec *
@@ -529,7 +540,8 @@ FBDevPreInit(ScrnInfoPtr pScrn, int flags)
"unrecognised fbdev hardware type (%d)\n", type);
return FALSE;
}
- if (xf86LoadSubModule(pScrn, "fb") == NULL) {
+ if (xf86LoadSubModule(pScrn, "fb") == NULL ||
+ xf86LoadSubModule(pScrn, "exa") == NULL) {
FBDevFreeRec(pScrn);
return FALSE;
}
@@ -538,6 +550,15 @@ FBDevPreInit(ScrnInfoPtr pScrn, int flags)
return TRUE;
}
+static void
+VideoCoreAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VideoCorePtr fPtr = VIDEOCOREPTR(pScrn);
+
+ fPtr->vcExa = VideoCoreExaInit(pScreen);
+}
+
static Bool
FBDevScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
@@ -692,6 +713,9 @@ FBDevScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
"Render extension initialisation failed\n");
xf86SetBlackWhitePixels(pScreen);
+
+ VideoCoreAccelInit(pScreen);
+
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
@@ -770,6 +794,11 @@ FBDevCloseScreen(int scrnIndex, ScreenPtr pScreen)
fbdevHWUnmapVidmem(pScrn);
pScrn->vtSema = FALSE;
+ if (fPtr->vcExa) {
+ /* FIXME: VideoCoreExaCloseScreen() ? */
+ fPtr->vcExa = NULL;
+ }
+
pScreen->CreateScreenResources = fPtr->CreateScreenResources;
pScreen->CloseScreen = fPtr->CloseScreen;
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
diff --git a/src/videocore.h b/src/videocore.h
index c67b62d..f23a3e5 100644
--- a/src/videocore.h
+++ b/src/videocore.h
@@ -24,6 +24,9 @@
#define VIDEOCORE_H
typedef struct _VideoCoreRec VideoCoreRec, *VideoCorePtr;
+typedef struct _VideoCoreExa VideoCoreExa, *VideoCoreExaPtr;
+
+VideoCoreExaPtr VideoCoreGetExa(VideoCorePtr vc);
/* @p: a ScrnInfoPtr
*/