diff options
author | Will Thompson <will@willthompson.co.uk> | 2012-04-24 18:58:58 +0100 |
---|---|---|
committer | Will Thompson <will@willthompson.co.uk> | 2012-05-04 18:01:15 +0100 |
commit | 1643585820f0c4773fcdc91b21826efc8b79d691 (patch) | |
tree | c5528fb14956b03a6d8f1929267d1bbe5e114df1 | |
parent | f1b1a687b4ce1b817cae889931e8d85d8890a848 (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.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/videocore-exa.c | 558 | ||||
-rw-r--r-- | src/videocore-exa.h | 9 | ||||
-rw-r--r-- | src/videocore.c | 35 | ||||
-rw-r--r-- | src/videocore.h | 3 |
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 */ |