exa.c revision 8223e2f2
105b261ecSmrg/* 205b261ecSmrg * Copyright � 2001 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Partly based on code that is Copyright � The XFree86 Project Inc. 505b261ecSmrg * 605b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 705b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 805b261ecSmrg * the above copyright notice appear in all copies and that both that 905b261ecSmrg * copyright notice and this permission notice appear in supporting 1005b261ecSmrg * documentation, and that the name of Keith Packard not be used in 1105b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1205b261ecSmrg * specific, written prior permission. Keith Packard makes no 1305b261ecSmrg * representations about the suitability of this software for any purpose. It 1405b261ecSmrg * is provided "as is" without express or implied warranty. 1505b261ecSmrg * 1605b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1705b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1805b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1905b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2005b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2105b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2205b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2305b261ecSmrg */ 2405b261ecSmrg 2505b261ecSmrg/** @file 2605b261ecSmrg * This file covers the initialization and teardown of EXA, and has various 2705b261ecSmrg * functions not responsible for performing rendering, pixmap migration, or 2805b261ecSmrg * memory management. 2905b261ecSmrg */ 3005b261ecSmrg 3105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3205b261ecSmrg#include <dix-config.h> 3305b261ecSmrg#endif 3405b261ecSmrg 3505b261ecSmrg#include <stdlib.h> 3605b261ecSmrg 3705b261ecSmrg#include "exa_priv.h" 3805b261ecSmrg#include "exa.h" 3905b261ecSmrg 406747b715SmrgDevPrivateKeyRec exaScreenPrivateKeyRec; 416747b715SmrgDevPrivateKeyRec exaPixmapPrivateKeyRec; 426747b715SmrgDevPrivateKeyRec exaGCPrivateKeyRec; 434642e01fSmrg 444642e01fSmrg#ifdef MITSHM 454642e01fSmrgstatic ShmFuncs exaShmFuncs = { NULL, NULL }; 464642e01fSmrg#endif 474642e01fSmrg 4805b261ecSmrg/** 4905b261ecSmrg * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 5005b261ecSmrg * the beginning of the given pixmap. 5105b261ecSmrg * 5205b261ecSmrg * Note that drivers are free to, and often do, munge this offset as necessary 5305b261ecSmrg * for handing to the hardware -- for example, translating it into a different 5405b261ecSmrg * aperture. This function may need to be extended in the future if we grow 5505b261ecSmrg * support for having multiple card-accessible offscreen, such as an AGP memory 5605b261ecSmrg * pool alongside the framebuffer pool. 5705b261ecSmrg */ 5805b261ecSmrgunsigned long 5905b261ecSmrgexaGetPixmapOffset(PixmapPtr pPix) 6005b261ecSmrg{ 6105b261ecSmrg ExaScreenPriv (pPix->drawable.pScreen); 626747b715Smrg ExaPixmapPriv (pPix); 6305b261ecSmrg 646747b715Smrg return (CARD8 *)pExaPixmap->fb_ptr - pExaScr->info->memoryBase; 654642e01fSmrg} 6605b261ecSmrg 674642e01fSmrgvoid * 684642e01fSmrgexaGetPixmapDriverPrivate(PixmapPtr pPix) 694642e01fSmrg{ 704642e01fSmrg ExaPixmapPriv(pPix); 714642e01fSmrg 724642e01fSmrg return pExaPixmap->driverPriv; 7305b261ecSmrg} 7405b261ecSmrg 7505b261ecSmrg/** 7605b261ecSmrg * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 7705b261ecSmrg * 7805b261ecSmrg * This is a helper to make driver code more obvious, due to the rather obscure 7905b261ecSmrg * naming of the pitch field in the pixmap. 8005b261ecSmrg */ 8105b261ecSmrgunsigned long 8205b261ecSmrgexaGetPixmapPitch(PixmapPtr pPix) 8305b261ecSmrg{ 8405b261ecSmrg return pPix->devKind; 8505b261ecSmrg} 8605b261ecSmrg 8705b261ecSmrg/** 8805b261ecSmrg * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 8905b261ecSmrg * memory. Only valid when the pixmap is currently in framebuffer. 9005b261ecSmrg */ 9105b261ecSmrgunsigned long 9205b261ecSmrgexaGetPixmapSize(PixmapPtr pPix) 9305b261ecSmrg{ 9405b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 9505b261ecSmrg 9605b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPix); 9705b261ecSmrg if (pExaPixmap != NULL) 9805b261ecSmrg return pExaPixmap->fb_size; 9905b261ecSmrg return 0; 10005b261ecSmrg} 10105b261ecSmrg 10205b261ecSmrg/** 10305b261ecSmrg * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 10405b261ecSmrg * 10505b261ecSmrg * @param pDrawable the drawable being requested. 10605b261ecSmrg * 10705b261ecSmrg * This function returns the backing pixmap for a drawable, whether it is a 10805b261ecSmrg * redirected window, unredirected window, or already a pixmap. Note that 10905b261ecSmrg * coordinate translation is needed when drawing to the backing pixmap of a 11005b261ecSmrg * redirected window, and the translation coordinates are provided by calling 11105b261ecSmrg * exaGetOffscreenPixmap() on the drawable. 11205b261ecSmrg */ 11305b261ecSmrgPixmapPtr 11405b261ecSmrgexaGetDrawablePixmap(DrawablePtr pDrawable) 11505b261ecSmrg{ 11605b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) 11705b261ecSmrg return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 11805b261ecSmrg else 11905b261ecSmrg return (PixmapPtr) pDrawable; 1206747b715Smrg} 12105b261ecSmrg 12205b261ecSmrg/** 12305b261ecSmrg * Sets the offsets to add to coordinates to make them address the same bits in 12405b261ecSmrg * the backing drawable. These coordinates are nonzero only for redirected 12505b261ecSmrg * windows. 12605b261ecSmrg */ 12705b261ecSmrgvoid 12805b261ecSmrgexaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 12905b261ecSmrg int *xp, int *yp) 13005b261ecSmrg{ 13105b261ecSmrg#ifdef COMPOSITE 13205b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 13305b261ecSmrg *xp = -pPixmap->screen_x; 13405b261ecSmrg *yp = -pPixmap->screen_y; 13505b261ecSmrg return; 13605b261ecSmrg } 13705b261ecSmrg#endif 13805b261ecSmrg 13905b261ecSmrg *xp = 0; 14005b261ecSmrg *yp = 0; 14105b261ecSmrg} 14205b261ecSmrg 14305b261ecSmrg/** 14405b261ecSmrg * exaPixmapDirty() marks a pixmap as dirty, allowing for 14505b261ecSmrg * optimizations in pixmap migration when no changes have occurred. 14605b261ecSmrg */ 14705b261ecSmrgvoid 14805b261ecSmrgexaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 14905b261ecSmrg{ 15005b261ecSmrg BoxRec box; 15105b261ecSmrg RegionRec region; 15205b261ecSmrg 15305b261ecSmrg box.x1 = max(x1, 0); 15405b261ecSmrg box.y1 = max(y1, 0); 15505b261ecSmrg box.x2 = min(x2, pPix->drawable.width); 15605b261ecSmrg box.y2 = min(y2, pPix->drawable.height); 15705b261ecSmrg 15805b261ecSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 15905b261ecSmrg return; 16005b261ecSmrg 1616747b715Smrg RegionInit(®ion, &box, 1); 1628223e2f2Smrg DamageDamageRegion(&pPix->drawable, ®ion); 1636747b715Smrg RegionUninit(®ion); 16405b261ecSmrg} 16505b261ecSmrg 16605b261ecSmrgstatic int 16705b261ecSmrgexaLog2(int val) 16805b261ecSmrg{ 16905b261ecSmrg int bits; 17005b261ecSmrg 17105b261ecSmrg if (val <= 0) 17205b261ecSmrg return 0; 17305b261ecSmrg for (bits = 0; val != 0; bits++) 17405b261ecSmrg val >>= 1; 17505b261ecSmrg return bits - 1; 17605b261ecSmrg} 17705b261ecSmrg 1786747b715Smrgvoid 1794642e01fSmrgexaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 1804642e01fSmrg int w, int h, int bpp) 1814642e01fSmrg{ 1824642e01fSmrg pExaPixmap->accel_blocked = 0; 1834642e01fSmrg 1844642e01fSmrg if (pExaScr->info->maxPitchPixels) { 1856747b715Smrg int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp); 1864642e01fSmrg 1874642e01fSmrg if (pExaPixmap->fb_pitch > max_pitch) 1884642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 1894642e01fSmrg } 1904642e01fSmrg 1914642e01fSmrg if (pExaScr->info->maxPitchBytes && 1924642e01fSmrg pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) 1934642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 1944642e01fSmrg 1954642e01fSmrg if (w > pExaScr->info->maxX) 1964642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; 1974642e01fSmrg 1984642e01fSmrg if (h > pExaScr->info->maxY) 1994642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; 2004642e01fSmrg} 2014642e01fSmrg 2026747b715Smrgvoid 2034642e01fSmrgexaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 2044642e01fSmrg int w, int h, int bpp) 2054642e01fSmrg{ 2064642e01fSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 2076747b715Smrg pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp); 2084642e01fSmrg else 2096747b715Smrg pExaPixmap->fb_pitch = bits_to_bytes(w * bpp); 2104642e01fSmrg 2114642e01fSmrg pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 2124642e01fSmrg pExaScr->info->pixmapPitchAlign); 2134642e01fSmrg} 2144642e01fSmrg 21505b261ecSmrg/** 2166747b715Smrg * Returns TRUE if the pixmap is not movable. This is the case where it's a 2176747b715Smrg * pixmap which has no private (almost always bad) or it's a scratch pixmap created by 2186747b715Smrg * some X Server internal component (the score says it's pinned). 21905b261ecSmrg */ 2206747b715SmrgBool 2216747b715SmrgexaPixmapIsPinned (PixmapPtr pPix) 22205b261ecSmrg{ 2236747b715Smrg ExaPixmapPriv (pPix); 22405b261ecSmrg 2256747b715Smrg if (pExaPixmap == NULL) 2266747b715Smrg EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE); 22705b261ecSmrg 2286747b715Smrg return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; 2294642e01fSmrg} 2304642e01fSmrg 23105b261ecSmrg/** 2326747b715Smrg * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen 23305b261ecSmrg * memory, meaning that acceleration could probably be done to it, and that it 23405b261ecSmrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 23505b261ecSmrg * with the CPU. 23605b261ecSmrg * 23705b261ecSmrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 23805b261ecSmrg * deal with moving pixmaps in and out of system memory), EXA will give drivers 2396747b715Smrg * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE. 24005b261ecSmrg * 24105b261ecSmrg * @return TRUE if the given drawable is in framebuffer memory. 24205b261ecSmrg */ 24305b261ecSmrgBool 2446747b715SmrgexaPixmapHasGpuCopy(PixmapPtr pPixmap) 24505b261ecSmrg{ 2466747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 24705b261ecSmrg ExaScreenPriv(pScreen); 24805b261ecSmrg 2496747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 2506747b715Smrg return FALSE; 2514642e01fSmrg 2526747b715Smrg return (*pExaScr->pixmap_has_gpu_copy)(pPixmap); 25305b261ecSmrg} 25405b261ecSmrg 25505b261ecSmrg/** 2566747b715Smrg * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy(). 25705b261ecSmrg */ 25805b261ecSmrgBool 25905b261ecSmrgexaDrawableIsOffscreen (DrawablePtr pDrawable) 26005b261ecSmrg{ 2616747b715Smrg return exaPixmapHasGpuCopy (exaGetDrawablePixmap (pDrawable)); 26205b261ecSmrg} 26305b261ecSmrg 26405b261ecSmrg/** 26505b261ecSmrg * Returns the pixmap which backs a drawable, and the offsets to add to 26605b261ecSmrg * coordinates to make them address the same bits in the backing drawable. 26705b261ecSmrg */ 26805b261ecSmrgPixmapPtr 26905b261ecSmrgexaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 27005b261ecSmrg{ 27105b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 27205b261ecSmrg 27305b261ecSmrg exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); 27405b261ecSmrg 2756747b715Smrg if (exaPixmapHasGpuCopy (pPixmap)) 27605b261ecSmrg return pPixmap; 27705b261ecSmrg else 27805b261ecSmrg return NULL; 27905b261ecSmrg} 28005b261ecSmrg 2816747b715Smrg/** 2826747b715Smrg * Returns TRUE if the pixmap GPU copy is being accessed. 2836747b715Smrg */ 2846747b715SmrgBool 2856747b715SmrgExaDoPrepareAccess(PixmapPtr pPixmap, int index) 28605b261ecSmrg{ 2876747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 2886747b715Smrg ExaScreenPriv (pScreen); 2896747b715Smrg ExaPixmapPriv(pPixmap); 2906747b715Smrg Bool has_gpu_copy, ret; 2916747b715Smrg int i; 29205b261ecSmrg 2936747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 2946747b715Smrg return FALSE; 2956747b715Smrg 2966747b715Smrg if (pExaPixmap == NULL) 2976747b715Smrg EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE); 2986747b715Smrg 2996747b715Smrg /* Handle repeated / nested calls. */ 3006747b715Smrg for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 3016747b715Smrg if (pExaScr->access[i].pixmap == pPixmap) { 3026747b715Smrg pExaScr->access[i].count++; 3036747b715Smrg return pExaScr->access[i].retval; 3046747b715Smrg } 3054642e01fSmrg } 30605b261ecSmrg 3076747b715Smrg /* If slot for this index is taken, find an empty slot */ 3086747b715Smrg if (pExaScr->access[index].pixmap) { 3096747b715Smrg for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--) 3106747b715Smrg if (!pExaScr->access[index].pixmap) 3116747b715Smrg break; 3126747b715Smrg } 3136747b715Smrg 3146747b715Smrg /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */ 3156747b715Smrg if (pPixmap->devPrivate.ptr != NULL) { 3166747b715Smrg EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", 3176747b715Smrg pPixmap->devPrivate.ptr)); 3186747b715Smrg } 3196747b715Smrg 3206747b715Smrg has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 3216747b715Smrg 3226747b715Smrg if (has_gpu_copy && pExaPixmap->fb_ptr) { 3236747b715Smrg pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 3246747b715Smrg ret = TRUE; 3256747b715Smrg } else { 3266747b715Smrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 3276747b715Smrg ret = FALSE; 3286747b715Smrg } 3296747b715Smrg 3306747b715Smrg /* Store so we can handle repeated / nested calls. */ 3316747b715Smrg pExaScr->access[index].pixmap = pPixmap; 3326747b715Smrg pExaScr->access[index].count = 1; 3336747b715Smrg 3346747b715Smrg if (!has_gpu_copy) 3356747b715Smrg goto out; 33605b261ecSmrg 3376747b715Smrg exaWaitSync (pScreen); 33805b261ecSmrg 33905b261ecSmrg if (pExaScr->info->PrepareAccess == NULL) 3406747b715Smrg goto out; 34105b261ecSmrg 3426747b715Smrg if (index >= EXA_PREPARE_AUX_DEST && 3434642e01fSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 3446747b715Smrg if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 3456747b715Smrg FatalError("Unsupported AUX indices used on a pinned pixmap.\n"); 3464642e01fSmrg exaMoveOutPixmap (pPixmap); 3476747b715Smrg ret = FALSE; 3486747b715Smrg goto out; 3494642e01fSmrg } 3504642e01fSmrg 35105b261ecSmrg if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 3526747b715Smrg if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED && 3536747b715Smrg !(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) 3546747b715Smrg FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); 35505b261ecSmrg exaMoveOutPixmap (pPixmap); 3566747b715Smrg ret = FALSE; 3576747b715Smrg goto out; 35805b261ecSmrg } 3594642e01fSmrg 3606747b715Smrg ret = TRUE; 3614642e01fSmrg 3626747b715Smrgout: 3636747b715Smrg pExaScr->access[index].retval = ret; 3646747b715Smrg return ret; 3654642e01fSmrg} 3664642e01fSmrg 3674642e01fSmrg/** 3684642e01fSmrg * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 3694642e01fSmrg * 3704642e01fSmrg * It deals with waiting for synchronization with the card, determining if 3714642e01fSmrg * PrepareAccess() is necessary, and working around PrepareAccess() failure. 3724642e01fSmrg */ 3734642e01fSmrgvoid 3744642e01fSmrgexaPrepareAccess(DrawablePtr pDrawable, int index) 3754642e01fSmrg{ 3766747b715Smrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 3776747b715Smrg ExaScreenPriv(pDrawable->pScreen); 3786747b715Smrg 3796747b715Smrg if (pExaScr->prepare_access_reg) 3806747b715Smrg pExaScr->prepare_access_reg(pPixmap, index, NULL); 3816747b715Smrg else 3826747b715Smrg (void)ExaDoPrepareAccess(pPixmap, index); 3834642e01fSmrg} 3844642e01fSmrg 38505b261ecSmrg/** 38605b261ecSmrg * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 38705b261ecSmrg * 38805b261ecSmrg * It deals with calling the driver's FinishAccess() only if necessary. 38905b261ecSmrg */ 39005b261ecSmrgvoid 39105b261ecSmrgexaFinishAccess(DrawablePtr pDrawable, int index) 39205b261ecSmrg{ 39305b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 39405b261ecSmrg ExaScreenPriv (pScreen); 3954642e01fSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 3964642e01fSmrg ExaPixmapPriv (pPixmap); 3976747b715Smrg int i; 3986747b715Smrg 3996747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 4006747b715Smrg return; 40105b261ecSmrg 4026747b715Smrg if (pExaPixmap == NULL) 4036747b715Smrg EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),); 4046747b715Smrg 4056747b715Smrg /* Handle repeated / nested calls. */ 4066747b715Smrg for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 4076747b715Smrg if (pExaScr->access[i].pixmap == pPixmap) { 4086747b715Smrg if (--pExaScr->access[i].count > 0) 4096747b715Smrg return; 4106747b715Smrg break; 4116747b715Smrg } 41205b261ecSmrg } 41305b261ecSmrg 4146747b715Smrg /* Catch unbalanced Prepare/FinishAccess calls. */ 4156747b715Smrg if (i == EXA_NUM_PREPARE_INDICES) 4166747b715Smrg EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", 4176747b715Smrg pPixmap),); 4186747b715Smrg 4196747b715Smrg pExaScr->access[i].pixmap = NULL; 42005b261ecSmrg 4216747b715Smrg /* We always hide the devPrivate.ptr. */ 4226747b715Smrg pPixmap->devPrivate.ptr = NULL; 4236747b715Smrg 4248223e2f2Smrg /* Only call FinishAccess if PrepareAccess was called and succeeded. */ 4258223e2f2Smrg if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval) 42605b261ecSmrg return; 42705b261ecSmrg 4286747b715Smrg if (i >= EXA_PREPARE_AUX_DEST && 4294642e01fSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 4304642e01fSmrg ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 4314642e01fSmrg "unsupported index EXA_PREPARE_AUX*\n"); 4324642e01fSmrg return; 4334642e01fSmrg } 4344642e01fSmrg 4356747b715Smrg (*pExaScr->info->FinishAccess) (pPixmap, i); 43605b261ecSmrg} 43705b261ecSmrg 4386747b715Smrg 43905b261ecSmrg/** 4406747b715Smrg * Helper for things common to all schemes when a pixmap is destroyed 44105b261ecSmrg */ 4426747b715Smrgvoid 4436747b715SmrgexaDestroyPixmap(PixmapPtr pPixmap) 44405b261ecSmrg{ 4456747b715Smrg ExaScreenPriv(pPixmap->drawable.pScreen); 4466747b715Smrg int i; 4476747b715Smrg 4486747b715Smrg /* Finish access if it was prepared (e.g. pixmap created during 4496747b715Smrg * software fallback) 45005b261ecSmrg */ 4516747b715Smrg for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 4526747b715Smrg if (pExaScr->access[i].pixmap == pPixmap) { 4536747b715Smrg exaFinishAccess(&pPixmap->drawable, i); 4546747b715Smrg pExaScr->access[i].pixmap = NULL; 4556747b715Smrg break; 45605b261ecSmrg } 45705b261ecSmrg } 4586747b715Smrg} 4596747b715Smrg 4606747b715Smrg 4616747b715Smrg/** 4626747b715Smrg * Here begins EXA's GC code. 4636747b715Smrg * Do not ever access the fb/mi layer directly. 4646747b715Smrg */ 4656747b715Smrg 4666747b715Smrgstatic void 4676747b715SmrgexaValidateGC(GCPtr pGC, 4686747b715Smrg unsigned long changes, 4696747b715Smrg DrawablePtr pDrawable); 4706747b715Smrg 4716747b715Smrgstatic void 4726747b715SmrgexaDestroyGC(GCPtr pGC); 4736747b715Smrg 4746747b715Smrgstatic void 4756747b715SmrgexaChangeGC (GCPtr pGC, 4766747b715Smrg unsigned long mask); 4776747b715Smrg 4786747b715Smrgstatic void 4796747b715SmrgexaCopyGC (GCPtr pGCSrc, 4806747b715Smrg unsigned long mask, 4816747b715Smrg GCPtr pGCDst); 4826747b715Smrg 4836747b715Smrgstatic void 4846747b715SmrgexaChangeClip (GCPtr pGC, 4856747b715Smrg int type, 4866747b715Smrg pointer pvalue, 4876747b715Smrg int nrects); 4886747b715Smrg 4896747b715Smrgstatic void 4906747b715SmrgexaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); 4916747b715Smrg 4926747b715Smrgstatic void 4936747b715SmrgexaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); 4946747b715Smrg 4956747b715Smrgstatic void 4966747b715SmrgexaDestroyClip(GCPtr pGC); 4976747b715Smrg 4986747b715Smrgconst GCFuncs exaGCFuncs = { 4996747b715Smrg exaValidateGC, 5006747b715Smrg exaChangeGC, 5016747b715Smrg exaCopyGC, 5026747b715Smrg exaDestroyGC, 5036747b715Smrg exaChangeClip, 5046747b715Smrg exaDestroyClip, 5056747b715Smrg exaCopyClip 5066747b715Smrg}; 5076747b715Smrg 5086747b715Smrgstatic void 5096747b715SmrgexaValidateGC(GCPtr pGC, 5106747b715Smrg unsigned long changes, 5116747b715Smrg DrawablePtr pDrawable) 5126747b715Smrg{ 5136747b715Smrg /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 5146747b715Smrg * Do a few smart things so fbValidateGC can do it's work. 5156747b715Smrg */ 5166747b715Smrg 5176747b715Smrg ScreenPtr pScreen = pDrawable->pScreen; 5186747b715Smrg ExaScreenPriv(pScreen); 5196747b715Smrg ExaGCPriv(pGC); 5206747b715Smrg PixmapPtr pTile = NULL; 5216747b715Smrg Bool finish_current_tile = FALSE; 5226747b715Smrg 5236747b715Smrg /* Either of these conditions is enough to trigger access to a tile pixmap. */ 5246747b715Smrg /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ 5256747b715Smrg if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) { 5266747b715Smrg pTile = pGC->tile.pixmap; 5276747b715Smrg 5286747b715Smrg /* Sometimes tile pixmaps are swapped, you need access to: 5296747b715Smrg * - The current tile if it depth matches. 5306747b715Smrg * - Or the rotated tile if that one matches depth and !(changes & GCTile). 5316747b715Smrg * - Or the current tile pixmap and a newly created one. 53205b261ecSmrg */ 5336747b715Smrg if (pTile && pTile->drawable.depth != pDrawable->depth && !(changes & GCTile)) { 5346747b715Smrg PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); 5356747b715Smrg if (pRotatedTile && pRotatedTile->drawable.depth == pDrawable->depth) 5366747b715Smrg pTile = pRotatedTile; 5376747b715Smrg else 5386747b715Smrg finish_current_tile = TRUE; /* CreatePixmap will be called. */ 5396747b715Smrg } 54005b261ecSmrg } 54105b261ecSmrg 5426747b715Smrg if (pGC->stipple) 5436747b715Smrg exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 5446747b715Smrg if (pTile) 5456747b715Smrg exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC); 5466747b715Smrg 5476747b715Smrg /* Calls to Create/DestroyPixmap have to be identified as special. */ 5486747b715Smrg pExaScr->fallback_counter++; 5496747b715Smrg swap(pExaGC, pGC, funcs); 5506747b715Smrg (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); 5516747b715Smrg swap(pExaGC, pGC, funcs); 5526747b715Smrg pExaScr->fallback_counter--; 5536747b715Smrg 5546747b715Smrg if (pTile) 5556747b715Smrg exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); 5566747b715Smrg if (finish_current_tile && pGC->tile.pixmap) 5576747b715Smrg exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_DEST); 5586747b715Smrg if (pGC->stipple) 5596747b715Smrg exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 5606747b715Smrg} 5616747b715Smrg 5626747b715Smrg/* Is exaPrepareAccessGC() needed? */ 5636747b715Smrgstatic void 5646747b715SmrgexaDestroyGC(GCPtr pGC) 5656747b715Smrg{ 5666747b715Smrg ExaGCPriv(pGC); 5676747b715Smrg swap(pExaGC, pGC, funcs); 5686747b715Smrg (*pGC->funcs->DestroyGC)(pGC); 5696747b715Smrg swap(pExaGC, pGC, funcs); 5706747b715Smrg} 57105b261ecSmrg 5726747b715Smrgstatic void 5736747b715SmrgexaChangeGC (GCPtr pGC, 5746747b715Smrg unsigned long mask) 5756747b715Smrg{ 5766747b715Smrg ExaGCPriv(pGC); 5776747b715Smrg swap(pExaGC, pGC, funcs); 5786747b715Smrg (*pGC->funcs->ChangeGC) (pGC, mask); 5796747b715Smrg swap(pExaGC, pGC, funcs); 58005b261ecSmrg} 58105b261ecSmrg 5826747b715Smrgstatic void 5836747b715SmrgexaCopyGC (GCPtr pGCSrc, 5846747b715Smrg unsigned long mask, 5856747b715Smrg GCPtr pGCDst) 5866747b715Smrg{ 5876747b715Smrg ExaGCPriv(pGCDst); 5886747b715Smrg swap(pExaGC, pGCDst, funcs); 5896747b715Smrg (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 5906747b715Smrg swap(pExaGC, pGCDst, funcs); 5916747b715Smrg} 5926747b715Smrg 5936747b715Smrgstatic void 5946747b715SmrgexaChangeClip (GCPtr pGC, 5956747b715Smrg int type, 5966747b715Smrg pointer pvalue, 5976747b715Smrg int nrects) 5986747b715Smrg{ 5996747b715Smrg ExaGCPriv(pGC); 6006747b715Smrg swap(pExaGC, pGC, funcs); 6016747b715Smrg (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 6026747b715Smrg swap(pExaGC, pGC, funcs); 6036747b715Smrg} 6046747b715Smrg 6056747b715Smrgstatic void 6066747b715SmrgexaCopyClip(GCPtr pGCDst, GCPtr pGCSrc) 6076747b715Smrg{ 6086747b715Smrg ExaGCPriv(pGCDst); 6096747b715Smrg swap(pExaGC, pGCDst, funcs); 6106747b715Smrg (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc); 6116747b715Smrg swap(pExaGC, pGCDst, funcs); 6126747b715Smrg} 6136747b715Smrg 6146747b715Smrgstatic void 6156747b715SmrgexaDestroyClip(GCPtr pGC) 6166747b715Smrg{ 6176747b715Smrg ExaGCPriv(pGC); 6186747b715Smrg swap(pExaGC, pGC, funcs); 6196747b715Smrg (*pGC->funcs->DestroyClip)(pGC); 6206747b715Smrg swap(pExaGC, pGC, funcs); 6216747b715Smrg} 62205b261ecSmrg 62305b261ecSmrg/** 62405b261ecSmrg * exaCreateGC makes a new GC and hooks up its funcs handler, so that 62505b261ecSmrg * exaValidateGC() will get called. 62605b261ecSmrg */ 62705b261ecSmrgstatic int 62805b261ecSmrgexaCreateGC (GCPtr pGC) 62905b261ecSmrg{ 6306747b715Smrg ScreenPtr pScreen = pGC->pScreen; 6316747b715Smrg ExaScreenPriv(pScreen); 6326747b715Smrg ExaGCPriv(pGC); 6336747b715Smrg Bool ret; 63405b261ecSmrg 6356747b715Smrg swap(pExaScr, pScreen, CreateGC); 6366747b715Smrg if ((ret = (*pScreen->CreateGC) (pGC))) { 6376747b715Smrg wrap(pExaGC, pGC, funcs, (GCFuncs *) &exaGCFuncs); 6386747b715Smrg wrap(pExaGC, pGC, ops, (GCOps *) &exaOps); 6396747b715Smrg } 6406747b715Smrg swap(pExaScr, pScreen, CreateGC); 64105b261ecSmrg 6426747b715Smrg return ret; 64305b261ecSmrg} 64405b261ecSmrg 6454642e01fSmrgstatic Bool 6464642e01fSmrgexaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 6474642e01fSmrg{ 6484642e01fSmrg Bool ret; 6496747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 6506747b715Smrg ExaScreenPriv(pScreen); 6514642e01fSmrg 6524642e01fSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 6536747b715Smrg exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 6544642e01fSmrg 6554642e01fSmrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 6566747b715Smrg exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 6574642e01fSmrg 6586747b715Smrg pExaScr->fallback_counter++; 6596747b715Smrg swap(pExaScr, pScreen, ChangeWindowAttributes); 6606747b715Smrg ret = pScreen->ChangeWindowAttributes(pWin, mask); 6616747b715Smrg swap(pExaScr, pScreen, ChangeWindowAttributes); 6626747b715Smrg pExaScr->fallback_counter--; 6634642e01fSmrg 6644642e01fSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 6656747b715Smrg exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 6666747b715Smrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 6676747b715Smrg exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 6684642e01fSmrg 6694642e01fSmrg return ret; 6704642e01fSmrg} 6714642e01fSmrg 6724642e01fSmrgstatic RegionPtr 6734642e01fSmrgexaBitmapToRegion(PixmapPtr pPix) 6744642e01fSmrg{ 6756747b715Smrg RegionPtr ret; 6766747b715Smrg ScreenPtr pScreen = pPix->drawable.pScreen; 6776747b715Smrg ExaScreenPriv(pScreen); 6786747b715Smrg 6796747b715Smrg exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); 6806747b715Smrg swap(pExaScr, pScreen, BitmapToRegion); 6816747b715Smrg ret = (*pScreen->BitmapToRegion)(pPix); 6826747b715Smrg swap(pExaScr, pScreen, BitmapToRegion); 6836747b715Smrg exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); 6846747b715Smrg 6856747b715Smrg return ret; 6864642e01fSmrg} 6874642e01fSmrg 6884642e01fSmrgstatic Bool 6894642e01fSmrgexaCreateScreenResources(ScreenPtr pScreen) 6904642e01fSmrg{ 6914642e01fSmrg ExaScreenPriv(pScreen); 6924642e01fSmrg PixmapPtr pScreenPixmap; 6934642e01fSmrg Bool b; 6944642e01fSmrg 6956747b715Smrg swap(pExaScr, pScreen, CreateScreenResources); 6964642e01fSmrg b = pScreen->CreateScreenResources(pScreen); 6976747b715Smrg swap(pExaScr, pScreen, CreateScreenResources); 6984642e01fSmrg 6994642e01fSmrg if (!b) 7004642e01fSmrg return FALSE; 7014642e01fSmrg 7024642e01fSmrg pScreenPixmap = pScreen->GetScreenPixmap(pScreen); 7034642e01fSmrg 7044642e01fSmrg if (pScreenPixmap) { 7054642e01fSmrg ExaPixmapPriv(pScreenPixmap); 7064642e01fSmrg 7074642e01fSmrg exaSetAccelBlock(pExaScr, pExaPixmap, 7084642e01fSmrg pScreenPixmap->drawable.width, 7094642e01fSmrg pScreenPixmap->drawable.height, 7104642e01fSmrg pScreenPixmap->drawable.bitsPerPixel); 7114642e01fSmrg } 7124642e01fSmrg 7134642e01fSmrg return TRUE; 7144642e01fSmrg} 7154642e01fSmrg 7166747b715Smrgstatic void 7176747b715SmrgExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout, 7186747b715Smrg pointer pReadmask) 7196747b715Smrg{ 7206747b715Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 7216747b715Smrg ExaScreenPriv(pScreen); 7226747b715Smrg 7236747b715Smrg /* Move any deferred results from a software fallback to the driver pixmap */ 7246747b715Smrg if (pExaScr->deferred_mixed_pixmap) 7256747b715Smrg exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); 7266747b715Smrg 7276747b715Smrg unwrap(pExaScr, pScreen, BlockHandler); 7286747b715Smrg (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); 7296747b715Smrg wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 7306747b715Smrg 7316747b715Smrg /* The rest only applies to classic EXA */ 7326747b715Smrg if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) 7336747b715Smrg return; 7346747b715Smrg 7356747b715Smrg /* Try and keep the offscreen memory area tidy every now and then (at most 7366747b715Smrg * once per second) when the server has been idle for at least 100ms. 7376747b715Smrg */ 7386747b715Smrg if (pExaScr->numOffscreenAvailable > 1) { 7396747b715Smrg CARD32 now = GetTimeInMillis(); 7406747b715Smrg 7416747b715Smrg pExaScr->nextDefragment = now + 7426747b715Smrg max(100, (INT32)(pExaScr->lastDefragment + 1000 - now)); 7436747b715Smrg AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now); 7446747b715Smrg } 7456747b715Smrg} 7466747b715Smrg 7476747b715Smrgstatic void 7486747b715SmrgExaWakeupHandler(int screenNum, pointer wakeupData, unsigned long result, 7496747b715Smrg pointer pReadmask) 7506747b715Smrg{ 7516747b715Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 7526747b715Smrg ExaScreenPriv(pScreen); 7536747b715Smrg 7546747b715Smrg unwrap(pExaScr, pScreen, WakeupHandler); 7556747b715Smrg (*pScreen->WakeupHandler) (screenNum, wakeupData, result, pReadmask); 7566747b715Smrg wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 7576747b715Smrg 7586747b715Smrg if (result == 0 && pExaScr->numOffscreenAvailable > 1) { 7596747b715Smrg CARD32 now = GetTimeInMillis(); 7606747b715Smrg 7616747b715Smrg if ((int)(now - pExaScr->nextDefragment) > 0) { 7626747b715Smrg ExaOffscreenDefragment(pScreen); 7636747b715Smrg pExaScr->lastDefragment = now; 7646747b715Smrg } 7656747b715Smrg } 7666747b715Smrg} 7676747b715Smrg 76805b261ecSmrg/** 76905b261ecSmrg * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 77005b261ecSmrg * screen private, before calling down to the next CloseSccreen. 77105b261ecSmrg */ 77205b261ecSmrgstatic Bool 77305b261ecSmrgexaCloseScreen(int i, ScreenPtr pScreen) 77405b261ecSmrg{ 77505b261ecSmrg ExaScreenPriv(pScreen); 77605b261ecSmrg PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 77705b261ecSmrg 7784642e01fSmrg if (ps->Glyphs == exaGlyphs) 7794642e01fSmrg exaGlyphsFini(pScreen); 7804642e01fSmrg 7816747b715Smrg if (pScreen->BlockHandler == ExaBlockHandler) 7826747b715Smrg unwrap(pExaScr, pScreen, BlockHandler); 7836747b715Smrg if (pScreen->WakeupHandler == ExaWakeupHandler) 7846747b715Smrg unwrap(pExaScr, pScreen, WakeupHandler); 7856747b715Smrg unwrap(pExaScr, pScreen, CreateGC); 7866747b715Smrg unwrap(pExaScr, pScreen, CloseScreen); 7876747b715Smrg unwrap(pExaScr, pScreen, GetImage); 7886747b715Smrg unwrap(pExaScr, pScreen, GetSpans); 7896747b715Smrg if (pExaScr->SavedCreatePixmap) 7906747b715Smrg unwrap(pExaScr, pScreen, CreatePixmap); 7916747b715Smrg if (pExaScr->SavedDestroyPixmap) 7926747b715Smrg unwrap(pExaScr, pScreen, DestroyPixmap); 7936747b715Smrg if (pExaScr->SavedModifyPixmapHeader) 7946747b715Smrg unwrap(pExaScr, pScreen, ModifyPixmapHeader); 7956747b715Smrg unwrap(pExaScr, pScreen, CopyWindow); 7966747b715Smrg unwrap(pExaScr, pScreen, ChangeWindowAttributes); 7976747b715Smrg unwrap(pExaScr, pScreen, BitmapToRegion); 7986747b715Smrg unwrap(pExaScr, pScreen, CreateScreenResources); 7996747b715Smrg unwrap(pExaScr, ps, Composite); 8006747b715Smrg if (pExaScr->SavedGlyphs) 8016747b715Smrg unwrap(pExaScr, ps, Glyphs); 8026747b715Smrg unwrap(pExaScr, ps, Trapezoids); 8036747b715Smrg unwrap(pExaScr, ps, Triangles); 8046747b715Smrg unwrap(pExaScr, ps, AddTraps); 8056747b715Smrg 8066747b715Smrg free(pExaScr); 80705b261ecSmrg 80805b261ecSmrg return (*pScreen->CloseScreen) (i, pScreen); 80905b261ecSmrg} 81005b261ecSmrg 81105b261ecSmrg/** 81205b261ecSmrg * This function allocates a driver structure for EXA drivers to fill in. By 81305b261ecSmrg * having EXA allocate the structure, the driver structure can be extended 81405b261ecSmrg * without breaking ABI between EXA and the drivers. The driver's 81505b261ecSmrg * responsibility is to check beforehand that the EXA module has a matching 81605b261ecSmrg * major number and sufficient minor. Drivers are responsible for freeing the 8176747b715Smrg * driver structure using free(). 81805b261ecSmrg * 81905b261ecSmrg * @return a newly allocated, zero-filled driver structure 82005b261ecSmrg */ 82105b261ecSmrgExaDriverPtr 82205b261ecSmrgexaDriverAlloc(void) 82305b261ecSmrg{ 8246747b715Smrg return calloc(1, sizeof(ExaDriverRec)); 82505b261ecSmrg} 82605b261ecSmrg 82705b261ecSmrg/** 82805b261ecSmrg * @param pScreen screen being initialized 82905b261ecSmrg * @param pScreenInfo EXA driver record 83005b261ecSmrg * 83105b261ecSmrg * exaDriverInit sets up EXA given a driver record filled in by the driver. 83205b261ecSmrg * pScreenInfo should have been allocated by exaDriverAlloc(). See the 83305b261ecSmrg * comments in _ExaDriver for what must be filled in and what is optional. 83405b261ecSmrg * 83505b261ecSmrg * @return TRUE if EXA was successfully initialized. 83605b261ecSmrg */ 83705b261ecSmrgBool 83805b261ecSmrgexaDriverInit (ScreenPtr pScreen, 83905b261ecSmrg ExaDriverPtr pScreenInfo) 84005b261ecSmrg{ 84105b261ecSmrg ExaScreenPrivPtr pExaScr; 84205b261ecSmrg PictureScreenPtr ps; 84305b261ecSmrg 84405b261ecSmrg if (!pScreenInfo) 84505b261ecSmrg return FALSE; 84605b261ecSmrg 8474642e01fSmrg if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 8484642e01fSmrg pScreenInfo->exa_minor > EXA_VERSION_MINOR) 8494642e01fSmrg { 8504642e01fSmrg LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 8514642e01fSmrg "(%d.%d) are incompatible with EXA version (%d.%d)\n", 8524642e01fSmrg pScreen->myNum, 8534642e01fSmrg pScreenInfo->exa_major, pScreenInfo->exa_minor, 8544642e01fSmrg EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 85505b261ecSmrg return FALSE; 85605b261ecSmrg } 85705b261ecSmrg 8586747b715Smrg if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) { 8594642e01fSmrg if (!pScreenInfo->memoryBase) { 8604642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " 8614642e01fSmrg "must be non-zero\n", pScreen->myNum); 8624642e01fSmrg return FALSE; 8634642e01fSmrg } 86405b261ecSmrg 8654642e01fSmrg if (!pScreenInfo->memorySize) { 8664642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 8674642e01fSmrg "non-zero\n", pScreen->myNum); 8684642e01fSmrg return FALSE; 8694642e01fSmrg } 8704642e01fSmrg 8714642e01fSmrg if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 8724642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " 8734642e01fSmrg "be <= ExaDriverRec::memorySize\n", pScreen->myNum); 8744642e01fSmrg return FALSE; 8754642e01fSmrg } 87605b261ecSmrg } 87705b261ecSmrg 87805b261ecSmrg if (!pScreenInfo->PrepareSolid) { 87905b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 88005b261ecSmrg "non-NULL\n", pScreen->myNum); 88105b261ecSmrg return FALSE; 88205b261ecSmrg } 88305b261ecSmrg 88405b261ecSmrg if (!pScreenInfo->PrepareCopy) { 88505b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 88605b261ecSmrg "non-NULL\n", pScreen->myNum); 88705b261ecSmrg return FALSE; 88805b261ecSmrg } 88905b261ecSmrg 89005b261ecSmrg if (!pScreenInfo->WaitMarker) { 89105b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 89205b261ecSmrg "non-NULL\n", pScreen->myNum); 89305b261ecSmrg return FALSE; 89405b261ecSmrg } 89505b261ecSmrg 8964642e01fSmrg /* If the driver doesn't set any max pitch values, we'll just assume 8974642e01fSmrg * that there's a limitation by pixels, and that it's the same as 8984642e01fSmrg * maxX. 8994642e01fSmrg * 9004642e01fSmrg * We want maxPitchPixels or maxPitchBytes to be set so we can check 9014642e01fSmrg * pixmaps against the max pitch in exaCreatePixmap() -- it matters 9024642e01fSmrg * whether a pixmap is rejected because of its pitch or 9034642e01fSmrg * because of its width. 9044642e01fSmrg */ 9054642e01fSmrg if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) 90605b261ecSmrg { 9074642e01fSmrg pScreenInfo->maxPitchPixels = pScreenInfo->maxX; 90805b261ecSmrg } 90905b261ecSmrg 91005b261ecSmrg ps = GetPictureScreenIfSet(pScreen); 91105b261ecSmrg 9126747b715Smrg if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) { 9136747b715Smrg LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n", 9146747b715Smrg pScreen->myNum); 9156747b715Smrg return FALSE; 9166747b715Smrg } 91705b261ecSmrg 9186747b715Smrg pExaScr = calloc (sizeof (ExaScreenPrivRec), 1); 91905b261ecSmrg if (!pExaScr) { 92005b261ecSmrg LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 92105b261ecSmrg pScreen->myNum); 92205b261ecSmrg return FALSE; 92305b261ecSmrg } 92405b261ecSmrg 92505b261ecSmrg pExaScr->info = pScreenInfo; 92605b261ecSmrg 9274642e01fSmrg dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); 92805b261ecSmrg 92905b261ecSmrg pExaScr->migration = ExaMigrationAlways; 93005b261ecSmrg 93105b261ecSmrg exaDDXDriverInit(pScreen); 93205b261ecSmrg 9336747b715Smrg if (!dixRegisterPrivateKey(&exaGCPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { 9346747b715Smrg LogMessage(X_WARNING, 9356747b715Smrg "EXA(%d): Failed to allocate GC private\n", 9366747b715Smrg pScreen->myNum); 9376747b715Smrg return FALSE; 9386747b715Smrg } 9396747b715Smrg 94005b261ecSmrg /* 94105b261ecSmrg * Replace various fb screen functions 94205b261ecSmrg */ 9436747b715Smrg if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 9446747b715Smrg (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) || 9456747b715Smrg (pExaScr->info->flags & EXA_MIXED_PIXMAPS))) 9466747b715Smrg wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 9476747b715Smrg if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 9486747b715Smrg !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) 9496747b715Smrg wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 9506747b715Smrg wrap(pExaScr, pScreen, CreateGC, exaCreateGC); 9516747b715Smrg wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen); 9526747b715Smrg wrap(pExaScr, pScreen, GetImage, exaGetImage); 9536747b715Smrg wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans); 9546747b715Smrg wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow); 9556747b715Smrg wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes); 9566747b715Smrg wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion); 9576747b715Smrg wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources); 95805b261ecSmrg 95905b261ecSmrg if (ps) { 9606747b715Smrg wrap(pExaScr, ps, Composite, exaComposite); 9614642e01fSmrg if (pScreenInfo->PrepareComposite) { 9626747b715Smrg wrap(pExaScr, ps, Glyphs, exaGlyphs); 9636747b715Smrg } else { 9646747b715Smrg wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs); 9654642e01fSmrg } 9666747b715Smrg wrap(pExaScr, ps, Trapezoids, exaTrapezoids); 9676747b715Smrg wrap(pExaScr, ps, Triangles, exaTriangles); 9686747b715Smrg wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps); 96905b261ecSmrg } 97005b261ecSmrg 97105b261ecSmrg#ifdef MITSHM 9724642e01fSmrg /* 9734642e01fSmrg * Don't allow shared pixmaps. 97405b261ecSmrg */ 9754642e01fSmrg ShmRegisterFuncs(pScreen, &exaShmFuncs); 97605b261ecSmrg#endif 97705b261ecSmrg /* 97805b261ecSmrg * Hookup offscreen pixmaps 97905b261ecSmrg */ 9804642e01fSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) 98105b261ecSmrg { 9826747b715Smrg if (!dixRegisterPrivateKey(&exaPixmapPrivateKeyRec, PRIVATE_PIXMAP, sizeof(ExaPixmapPrivRec))) { 98305b261ecSmrg LogMessage(X_WARNING, 98405b261ecSmrg "EXA(%d): Failed to allocate pixmap private\n", 98505b261ecSmrg pScreen->myNum); 98605b261ecSmrg return FALSE; 98705b261ecSmrg } 9886747b715Smrg if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) { 9896747b715Smrg if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) { 9906747b715Smrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed); 9916747b715Smrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed); 9926747b715Smrg wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_mixed); 9936747b715Smrg pExaScr->do_migration = exaDoMigration_mixed; 9946747b715Smrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed; 9956747b715Smrg pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; 9966747b715Smrg pExaScr->do_move_out_pixmap = NULL; 9976747b715Smrg pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed; 9986747b715Smrg } else { 9996747b715Smrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver); 10006747b715Smrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver); 10016747b715Smrg wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver); 10026747b715Smrg pExaScr->do_migration = NULL; 10036747b715Smrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver; 10046747b715Smrg pExaScr->do_move_in_pixmap = NULL; 10056747b715Smrg pExaScr->do_move_out_pixmap = NULL; 10066747b715Smrg pExaScr->prepare_access_reg = NULL; 10076747b715Smrg } 10086747b715Smrg } else { 10096747b715Smrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); 10106747b715Smrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic); 10116747b715Smrg wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_classic); 10126747b715Smrg pExaScr->do_migration = exaDoMigration_classic; 10136747b715Smrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic; 10146747b715Smrg pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; 10156747b715Smrg pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; 10166747b715Smrg pExaScr->prepare_access_reg = exaPrepareAccessReg_classic; 10176747b715Smrg } 10186747b715Smrg if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 10194642e01fSmrg LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 10204642e01fSmrg pScreen->myNum, 10214642e01fSmrg pExaScr->info->memorySize - pExaScr->info->offScreenBase); 10224642e01fSmrg } else { 10234642e01fSmrg LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", 10244642e01fSmrg pScreen->myNum); 10254642e01fSmrg 10264642e01fSmrg } 102705b261ecSmrg } 102805b261ecSmrg else 102905b261ecSmrg LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 103005b261ecSmrg 10316747b715Smrg if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 10324642e01fSmrg DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 10334642e01fSmrg pExaScr->info->memorySize)); 10344642e01fSmrg if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 10354642e01fSmrg if (!exaOffscreenInit (pScreen)) { 10364642e01fSmrg LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", 10374642e01fSmrg pScreen->myNum); 10384642e01fSmrg return FALSE; 10394642e01fSmrg } 10404642e01fSmrg } 104105b261ecSmrg } 104205b261ecSmrg 10434642e01fSmrg if (ps->Glyphs == exaGlyphs) 10444642e01fSmrg exaGlyphsInit(pScreen); 10454642e01fSmrg 104605b261ecSmrg LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 104705b261ecSmrg " operations:\n", pScreen->myNum); 104805b261ecSmrg assert(pScreenInfo->PrepareSolid != NULL); 104905b261ecSmrg LogMessage(X_INFO, " Solid\n"); 105005b261ecSmrg assert(pScreenInfo->PrepareCopy != NULL); 105105b261ecSmrg LogMessage(X_INFO, " Copy\n"); 105205b261ecSmrg if (pScreenInfo->PrepareComposite != NULL) { 105305b261ecSmrg LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 105405b261ecSmrg } 105505b261ecSmrg if (pScreenInfo->UploadToScreen != NULL) { 105605b261ecSmrg LogMessage(X_INFO, " UploadToScreen\n"); 105705b261ecSmrg } 105805b261ecSmrg if (pScreenInfo->DownloadFromScreen != NULL) { 105905b261ecSmrg LogMessage(X_INFO, " DownloadFromScreen\n"); 106005b261ecSmrg } 106105b261ecSmrg 106205b261ecSmrg return TRUE; 106305b261ecSmrg} 106405b261ecSmrg 106505b261ecSmrg/** 106605b261ecSmrg * exaDriverFini tears down EXA on a given screen. 106705b261ecSmrg * 106805b261ecSmrg * @param pScreen screen being torn down. 106905b261ecSmrg */ 107005b261ecSmrgvoid 107105b261ecSmrgexaDriverFini (ScreenPtr pScreen) 107205b261ecSmrg{ 107305b261ecSmrg /*right now does nothing*/ 107405b261ecSmrg} 107505b261ecSmrg 107605b261ecSmrg/** 107705b261ecSmrg * exaMarkSync() should be called after any asynchronous drawing by the hardware. 107805b261ecSmrg * 107905b261ecSmrg * @param pScreen screen which drawing occurred on 108005b261ecSmrg * 108105b261ecSmrg * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 108205b261ecSmrg * happened and a WaitSync() will be necessary before relying on the contents of 108305b261ecSmrg * offscreen memory from the CPU's perspective. It also calls an optional 108405b261ecSmrg * driver MarkSync() callback, the return value of which may be used to do partial 108505b261ecSmrg * synchronization with the hardware in the future. 108605b261ecSmrg */ 108705b261ecSmrgvoid exaMarkSync(ScreenPtr pScreen) 108805b261ecSmrg{ 108905b261ecSmrg ExaScreenPriv(pScreen); 109005b261ecSmrg 109105b261ecSmrg pExaScr->info->needsSync = TRUE; 109205b261ecSmrg if (pExaScr->info->MarkSync != NULL) { 109305b261ecSmrg pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); 109405b261ecSmrg } 109505b261ecSmrg} 109605b261ecSmrg 109705b261ecSmrg/** 109805b261ecSmrg * exaWaitSync() ensures that all drawing has been completed. 109905b261ecSmrg * 110005b261ecSmrg * @param pScreen screen being synchronized. 110105b261ecSmrg * 110205b261ecSmrg * Calls down into the driver to ensure that all previous drawing has completed. 110305b261ecSmrg * It should always be called before relying on the framebuffer contents 110405b261ecSmrg * reflecting previous drawing, from a CPU perspective. 110505b261ecSmrg */ 110605b261ecSmrgvoid exaWaitSync(ScreenPtr pScreen) 110705b261ecSmrg{ 110805b261ecSmrg ExaScreenPriv(pScreen); 110905b261ecSmrg 111005b261ecSmrg if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 111105b261ecSmrg (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 111205b261ecSmrg pExaScr->info->needsSync = FALSE; 111305b261ecSmrg } 111405b261ecSmrg} 11156747b715Smrg 11166747b715Smrg/** 11176747b715Smrg * Performs migration of the pixmaps according to the operation information 11186747b715Smrg * provided in pixmaps and can_accel and the migration scheme chosen in the 11196747b715Smrg * config file. 11206747b715Smrg */ 11216747b715Smrgvoid 11226747b715SmrgexaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) 11236747b715Smrg{ 11246747b715Smrg ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; 11256747b715Smrg ExaScreenPriv(pScreen); 11266747b715Smrg 11276747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 11286747b715Smrg return; 11296747b715Smrg 11306747b715Smrg if (pExaScr->do_migration) 11316747b715Smrg (*pExaScr->do_migration)(pixmaps, npixmaps, can_accel); 11326747b715Smrg} 11336747b715Smrg 11346747b715Smrgvoid 11356747b715SmrgexaMoveInPixmap (PixmapPtr pPixmap) 11366747b715Smrg{ 11376747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 11386747b715Smrg ExaScreenPriv(pScreen); 11396747b715Smrg 11406747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 11416747b715Smrg return; 11426747b715Smrg 11436747b715Smrg if (pExaScr->do_move_in_pixmap) 11446747b715Smrg (*pExaScr->do_move_in_pixmap)(pPixmap); 11456747b715Smrg} 11466747b715Smrg 11476747b715Smrgvoid 11486747b715SmrgexaMoveOutPixmap (PixmapPtr pPixmap) 11496747b715Smrg{ 11506747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 11516747b715Smrg ExaScreenPriv(pScreen); 11526747b715Smrg 11536747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 11546747b715Smrg return; 11556747b715Smrg 11566747b715Smrg if (pExaScr->do_move_out_pixmap) 11576747b715Smrg (*pExaScr->do_move_out_pixmap)(pPixmap); 11586747b715Smrg} 1159