105b261ecSmrg/* 235c4bbdfSmrg * Copyright © 2001 Keith Packard 305b261ecSmrg * 435c4bbdfSmrg * 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; 414642e01fSmrg 424642e01fSmrg#ifdef MITSHM 434642e01fSmrgstatic ShmFuncs exaShmFuncs = { NULL, NULL }; 444642e01fSmrg#endif 454642e01fSmrg 4605b261ecSmrg/** 4705b261ecSmrg * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 4805b261ecSmrg * the beginning of the given pixmap. 4905b261ecSmrg * 5005b261ecSmrg * Note that drivers are free to, and often do, munge this offset as necessary 5105b261ecSmrg * for handing to the hardware -- for example, translating it into a different 5205b261ecSmrg * aperture. This function may need to be extended in the future if we grow 5305b261ecSmrg * support for having multiple card-accessible offscreen, such as an AGP memory 5405b261ecSmrg * pool alongside the framebuffer pool. 5505b261ecSmrg */ 5605b261ecSmrgunsigned long 5705b261ecSmrgexaGetPixmapOffset(PixmapPtr pPix) 5805b261ecSmrg{ 5935c4bbdfSmrg ExaScreenPriv(pPix->drawable.pScreen); 6035c4bbdfSmrg ExaPixmapPriv(pPix); 6105b261ecSmrg 6235c4bbdfSmrg return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase; 634642e01fSmrg} 6405b261ecSmrg 654642e01fSmrgvoid * 664642e01fSmrgexaGetPixmapDriverPrivate(PixmapPtr pPix) 674642e01fSmrg{ 684642e01fSmrg ExaPixmapPriv(pPix); 694642e01fSmrg 704642e01fSmrg return pExaPixmap->driverPriv; 7105b261ecSmrg} 7205b261ecSmrg 7305b261ecSmrg/** 7405b261ecSmrg * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 7505b261ecSmrg * 7605b261ecSmrg * This is a helper to make driver code more obvious, due to the rather obscure 7705b261ecSmrg * naming of the pitch field in the pixmap. 7805b261ecSmrg */ 7905b261ecSmrgunsigned long 8005b261ecSmrgexaGetPixmapPitch(PixmapPtr pPix) 8105b261ecSmrg{ 8205b261ecSmrg return pPix->devKind; 8305b261ecSmrg} 8405b261ecSmrg 8505b261ecSmrg/** 8605b261ecSmrg * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 8705b261ecSmrg * memory. Only valid when the pixmap is currently in framebuffer. 8805b261ecSmrg */ 8905b261ecSmrgunsigned long 9005b261ecSmrgexaGetPixmapSize(PixmapPtr pPix) 9105b261ecSmrg{ 9205b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 9305b261ecSmrg 9405b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPix); 9505b261ecSmrg if (pExaPixmap != NULL) 9635c4bbdfSmrg return pExaPixmap->fb_size; 9705b261ecSmrg return 0; 9805b261ecSmrg} 9905b261ecSmrg 10005b261ecSmrg/** 10105b261ecSmrg * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 10205b261ecSmrg * 10305b261ecSmrg * @param pDrawable the drawable being requested. 10405b261ecSmrg * 10505b261ecSmrg * This function returns the backing pixmap for a drawable, whether it is a 10605b261ecSmrg * redirected window, unredirected window, or already a pixmap. Note that 10705b261ecSmrg * coordinate translation is needed when drawing to the backing pixmap of a 10805b261ecSmrg * redirected window, and the translation coordinates are provided by calling 10905b261ecSmrg * exaGetOffscreenPixmap() on the drawable. 11005b261ecSmrg */ 11105b261ecSmrgPixmapPtr 11205b261ecSmrgexaGetDrawablePixmap(DrawablePtr pDrawable) 11305b261ecSmrg{ 11435c4bbdfSmrg if (pDrawable->type == DRAWABLE_WINDOW) 11535c4bbdfSmrg return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); 11635c4bbdfSmrg else 11735c4bbdfSmrg return (PixmapPtr) pDrawable; 1186747b715Smrg} 11905b261ecSmrg 12005b261ecSmrg/** 12105b261ecSmrg * Sets the offsets to add to coordinates to make them address the same bits in 12205b261ecSmrg * the backing drawable. These coordinates are nonzero only for redirected 12305b261ecSmrg * windows. 12405b261ecSmrg */ 12505b261ecSmrgvoid 12635c4bbdfSmrgexaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp) 12705b261ecSmrg{ 12805b261ecSmrg#ifdef COMPOSITE 12905b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 13035c4bbdfSmrg *xp = -pPixmap->screen_x; 13135c4bbdfSmrg *yp = -pPixmap->screen_y; 13235c4bbdfSmrg return; 13305b261ecSmrg } 13405b261ecSmrg#endif 13505b261ecSmrg 13605b261ecSmrg *xp = 0; 13705b261ecSmrg *yp = 0; 13805b261ecSmrg} 13905b261ecSmrg 14005b261ecSmrg/** 14105b261ecSmrg * exaPixmapDirty() marks a pixmap as dirty, allowing for 14205b261ecSmrg * optimizations in pixmap migration when no changes have occurred. 14305b261ecSmrg */ 14405b261ecSmrgvoid 14535c4bbdfSmrgexaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2) 14605b261ecSmrg{ 14705b261ecSmrg BoxRec box; 14805b261ecSmrg RegionRec region; 14905b261ecSmrg 15005b261ecSmrg box.x1 = max(x1, 0); 15105b261ecSmrg box.y1 = max(y1, 0); 15205b261ecSmrg box.x2 = min(x2, pPix->drawable.width); 15305b261ecSmrg box.y2 = min(y2, pPix->drawable.height); 15405b261ecSmrg 15505b261ecSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 15635c4bbdfSmrg return; 15705b261ecSmrg 1586747b715Smrg RegionInit(®ion, &box, 1); 1598223e2f2Smrg DamageDamageRegion(&pPix->drawable, ®ion); 1606747b715Smrg RegionUninit(®ion); 16105b261ecSmrg} 16205b261ecSmrg 16305b261ecSmrgstatic int 16405b261ecSmrgexaLog2(int val) 16505b261ecSmrg{ 16605b261ecSmrg int bits; 16705b261ecSmrg 16805b261ecSmrg if (val <= 0) 16935c4bbdfSmrg return 0; 17005b261ecSmrg for (bits = 0; val != 0; bits++) 17135c4bbdfSmrg val >>= 1; 17205b261ecSmrg return bits - 1; 17305b261ecSmrg} 17405b261ecSmrg 1756747b715Smrgvoid 1764642e01fSmrgexaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 1774642e01fSmrg int w, int h, int bpp) 1784642e01fSmrg{ 1794642e01fSmrg pExaPixmap->accel_blocked = 0; 1804642e01fSmrg 1814642e01fSmrg if (pExaScr->info->maxPitchPixels) { 1826747b715Smrg int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp); 1834642e01fSmrg 1844642e01fSmrg if (pExaPixmap->fb_pitch > max_pitch) 1854642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 1864642e01fSmrg } 1874642e01fSmrg 1884642e01fSmrg if (pExaScr->info->maxPitchBytes && 1894642e01fSmrg pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) 1904642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 1914642e01fSmrg 1924642e01fSmrg if (w > pExaScr->info->maxX) 1934642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; 1944642e01fSmrg 1954642e01fSmrg if (h > pExaScr->info->maxY) 1964642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; 1974642e01fSmrg} 1984642e01fSmrg 1996747b715Smrgvoid 2004642e01fSmrgexaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 2014642e01fSmrg int w, int h, int bpp) 2024642e01fSmrg{ 2034642e01fSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 2046747b715Smrg pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp); 2054642e01fSmrg else 2066747b715Smrg pExaPixmap->fb_pitch = bits_to_bytes(w * bpp); 2074642e01fSmrg 2084642e01fSmrg pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 2094642e01fSmrg pExaScr->info->pixmapPitchAlign); 2104642e01fSmrg} 2114642e01fSmrg 21205b261ecSmrg/** 2136747b715Smrg * Returns TRUE if the pixmap is not movable. This is the case where it's a 2146747b715Smrg * pixmap which has no private (almost always bad) or it's a scratch pixmap created by 2156747b715Smrg * some X Server internal component (the score says it's pinned). 21605b261ecSmrg */ 2176747b715SmrgBool 21835c4bbdfSmrgexaPixmapIsPinned(PixmapPtr pPix) 21905b261ecSmrg{ 22035c4bbdfSmrg ExaPixmapPriv(pPix); 22105b261ecSmrg 2226747b715Smrg if (pExaPixmap == NULL) 22335c4bbdfSmrg EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE); 22405b261ecSmrg 2256747b715Smrg return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; 2264642e01fSmrg} 2274642e01fSmrg 22805b261ecSmrg/** 2296747b715Smrg * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen 23005b261ecSmrg * memory, meaning that acceleration could probably be done to it, and that it 23105b261ecSmrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 23205b261ecSmrg * with the CPU. 23305b261ecSmrg * 23405b261ecSmrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 23505b261ecSmrg * deal with moving pixmaps in and out of system memory), EXA will give drivers 2366747b715Smrg * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE. 23705b261ecSmrg * 23805b261ecSmrg * @return TRUE if the given drawable is in framebuffer memory. 23905b261ecSmrg */ 24005b261ecSmrgBool 2416747b715SmrgexaPixmapHasGpuCopy(PixmapPtr pPixmap) 24205b261ecSmrg{ 24335c4bbdfSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 24435c4bbdfSmrg 24505b261ecSmrg ExaScreenPriv(pScreen); 24605b261ecSmrg 2476747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 24835c4bbdfSmrg return FALSE; 2494642e01fSmrg 25035c4bbdfSmrg return (*pExaScr->pixmap_has_gpu_copy) (pPixmap); 25105b261ecSmrg} 25205b261ecSmrg 25305b261ecSmrg/** 2546747b715Smrg * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy(). 25505b261ecSmrg */ 25605b261ecSmrgBool 25735c4bbdfSmrgexaDrawableIsOffscreen(DrawablePtr pDrawable) 25805b261ecSmrg{ 25935c4bbdfSmrg return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable)); 26005b261ecSmrg} 26105b261ecSmrg 26205b261ecSmrg/** 26305b261ecSmrg * Returns the pixmap which backs a drawable, and the offsets to add to 26405b261ecSmrg * coordinates to make them address the same bits in the backing drawable. 26505b261ecSmrg */ 26605b261ecSmrgPixmapPtr 26735c4bbdfSmrgexaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp) 26805b261ecSmrg{ 26935c4bbdfSmrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 27005b261ecSmrg 27135c4bbdfSmrg exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp); 27205b261ecSmrg 27335c4bbdfSmrg if (exaPixmapHasGpuCopy(pPixmap)) 27435c4bbdfSmrg return pPixmap; 27505b261ecSmrg else 27635c4bbdfSmrg return NULL; 27705b261ecSmrg} 27805b261ecSmrg 2796747b715Smrg/** 2806747b715Smrg * Returns TRUE if the pixmap GPU copy is being accessed. 2816747b715Smrg */ 2826747b715SmrgBool 2836747b715SmrgExaDoPrepareAccess(PixmapPtr pPixmap, int index) 28405b261ecSmrg{ 2856747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 28635c4bbdfSmrg 28735c4bbdfSmrg ExaScreenPriv(pScreen); 2886747b715Smrg ExaPixmapPriv(pPixmap); 2896747b715Smrg Bool has_gpu_copy, ret; 2906747b715Smrg int i; 29105b261ecSmrg 2926747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 29335c4bbdfSmrg return FALSE; 2946747b715Smrg 2956747b715Smrg if (pExaPixmap == NULL) 29635c4bbdfSmrg EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE); 2976747b715Smrg 2986747b715Smrg /* Handle repeated / nested calls. */ 2996747b715Smrg for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 30035c4bbdfSmrg if (pExaScr->access[i].pixmap == pPixmap) { 30135c4bbdfSmrg pExaScr->access[i].count++; 30235c4bbdfSmrg return pExaScr->access[i].retval; 30335c4bbdfSmrg } 3044642e01fSmrg } 30505b261ecSmrg 3066747b715Smrg /* If slot for this index is taken, find an empty slot */ 3076747b715Smrg if (pExaScr->access[index].pixmap) { 30835c4bbdfSmrg for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--) 30935c4bbdfSmrg if (!pExaScr->access[index].pixmap) 31035c4bbdfSmrg break; 3116747b715Smrg } 3126747b715Smrg 3136747b715Smrg /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */ 3146747b715Smrg if (pPixmap->devPrivate.ptr != NULL) { 31535c4bbdfSmrg EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap->devPrivate.ptr)); 3166747b715Smrg } 3176747b715Smrg 3186747b715Smrg has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 3196747b715Smrg 3206747b715Smrg if (has_gpu_copy && pExaPixmap->fb_ptr) { 32135c4bbdfSmrg pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 32235c4bbdfSmrg ret = TRUE; 32335c4bbdfSmrg } 32435c4bbdfSmrg else { 32535c4bbdfSmrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 32635c4bbdfSmrg ret = FALSE; 3276747b715Smrg } 3286747b715Smrg 3296747b715Smrg /* Store so we can handle repeated / nested calls. */ 3306747b715Smrg pExaScr->access[index].pixmap = pPixmap; 3316747b715Smrg pExaScr->access[index].count = 1; 3326747b715Smrg 3336747b715Smrg if (!has_gpu_copy) 33435c4bbdfSmrg goto out; 33505b261ecSmrg 33635c4bbdfSmrg exaWaitSync(pScreen); 33705b261ecSmrg 33805b261ecSmrg if (pExaScr->info->PrepareAccess == NULL) 33935c4bbdfSmrg goto out; 34005b261ecSmrg 3416747b715Smrg if (index >= EXA_PREPARE_AUX_DEST && 34235c4bbdfSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 34335c4bbdfSmrg if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 34435c4bbdfSmrg FatalError("Unsupported AUX indices used on a pinned pixmap.\n"); 34535c4bbdfSmrg exaMoveOutPixmap(pPixmap); 34635c4bbdfSmrg ret = FALSE; 34735c4bbdfSmrg goto out; 3484642e01fSmrg } 3494642e01fSmrg 35005b261ecSmrg if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 35135c4bbdfSmrg if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED && 35235c4bbdfSmrg !(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) 35335c4bbdfSmrg FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); 35435c4bbdfSmrg exaMoveOutPixmap(pPixmap); 35535c4bbdfSmrg ret = FALSE; 35635c4bbdfSmrg goto out; 35705b261ecSmrg } 3584642e01fSmrg 3596747b715Smrg ret = TRUE; 3604642e01fSmrg 36135c4bbdfSmrg out: 3626747b715Smrg pExaScr->access[index].retval = ret; 3636747b715Smrg return ret; 3644642e01fSmrg} 3654642e01fSmrg 3664642e01fSmrg/** 3674642e01fSmrg * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 3684642e01fSmrg * 3694642e01fSmrg * It deals with waiting for synchronization with the card, determining if 3704642e01fSmrg * PrepareAccess() is necessary, and working around PrepareAccess() failure. 3714642e01fSmrg */ 3724642e01fSmrgvoid 3734642e01fSmrgexaPrepareAccess(DrawablePtr pDrawable, int index) 3744642e01fSmrg{ 3756747b715Smrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 37635c4bbdfSmrg 3776747b715Smrg ExaScreenPriv(pDrawable->pScreen); 3786747b715Smrg 3796747b715Smrg if (pExaScr->prepare_access_reg) 38035c4bbdfSmrg pExaScr->prepare_access_reg(pPixmap, index, NULL); 3816747b715Smrg else 38235c4bbdfSmrg (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{ 39335c4bbdfSmrg ScreenPtr pScreen = pDrawable->pScreen; 39435c4bbdfSmrg 39535c4bbdfSmrg ExaScreenPriv(pScreen); 39635c4bbdfSmrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 39735c4bbdfSmrg 39835c4bbdfSmrg ExaPixmapPriv(pPixmap); 3996747b715Smrg int i; 4006747b715Smrg 4016747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 40235c4bbdfSmrg return; 40305b261ecSmrg 4046747b715Smrg if (pExaPixmap == NULL) 40535c4bbdfSmrg EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),); 4066747b715Smrg 4076747b715Smrg /* Handle repeated / nested calls. */ 4086747b715Smrg for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 40935c4bbdfSmrg if (pExaScr->access[i].pixmap == pPixmap) { 41035c4bbdfSmrg if (--pExaScr->access[i].count > 0) 41135c4bbdfSmrg return; 41235c4bbdfSmrg break; 41335c4bbdfSmrg } 41405b261ecSmrg } 41505b261ecSmrg 4166747b715Smrg /* Catch unbalanced Prepare/FinishAccess calls. */ 4176747b715Smrg if (i == EXA_NUM_PREPARE_INDICES) 41835c4bbdfSmrg EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap),); 4196747b715Smrg 4206747b715Smrg pExaScr->access[i].pixmap = NULL; 42105b261ecSmrg 4226747b715Smrg /* We always hide the devPrivate.ptr. */ 4236747b715Smrg pPixmap->devPrivate.ptr = NULL; 4246747b715Smrg 4258223e2f2Smrg /* Only call FinishAccess if PrepareAccess was called and succeeded. */ 4268223e2f2Smrg if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval) 42735c4bbdfSmrg return; 42805b261ecSmrg 4296747b715Smrg if (i >= EXA_PREPARE_AUX_DEST && 43035c4bbdfSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 43135c4bbdfSmrg ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 43235c4bbdfSmrg "unsupported index EXA_PREPARE_AUX*\n"); 43335c4bbdfSmrg return; 4344642e01fSmrg } 4354642e01fSmrg 4366747b715Smrg (*pExaScr->info->FinishAccess) (pPixmap, i); 43705b261ecSmrg} 43805b261ecSmrg 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++) { 45235c4bbdfSmrg if (pExaScr->access[i].pixmap == pPixmap) { 45335c4bbdfSmrg exaFinishAccess(&pPixmap->drawable, i); 45435c4bbdfSmrg pExaScr->access[i].pixmap = NULL; 45535c4bbdfSmrg break; 45635c4bbdfSmrg } 45705b261ecSmrg } 4586747b715Smrg} 4596747b715Smrg 4606747b715Smrg/** 4616747b715Smrg * Here begins EXA's GC code. 4626747b715Smrg * Do not ever access the fb/mi layer directly. 4636747b715Smrg */ 4646747b715Smrg 4656747b715Smrgstatic void 46635c4bbdfSmrg exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); 4676747b715Smrg 4686747b715Smrgstatic void 46935c4bbdfSmrg exaDestroyGC(GCPtr pGC); 4706747b715Smrg 4716747b715Smrgstatic void 47235c4bbdfSmrg exaChangeGC(GCPtr pGC, unsigned long mask); 4736747b715Smrg 4746747b715Smrgstatic void 47535c4bbdfSmrg exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); 4766747b715Smrg 4776747b715Smrgstatic void 47835c4bbdfSmrg exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects); 4796747b715Smrg 4806747b715Smrgstatic void 48135c4bbdfSmrg exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); 4826747b715Smrg 4836747b715Smrgstatic void 48435c4bbdfSmrg exaDestroyClip(GCPtr pGC); 4856747b715Smrg 4866747b715Smrgconst GCFuncs exaGCFuncs = { 4876747b715Smrg exaValidateGC, 4886747b715Smrg exaChangeGC, 4896747b715Smrg exaCopyGC, 4906747b715Smrg exaDestroyGC, 4916747b715Smrg exaChangeClip, 4926747b715Smrg exaDestroyClip, 4936747b715Smrg exaCopyClip 4946747b715Smrg}; 4956747b715Smrg 4966747b715Smrgstatic void 49735c4bbdfSmrgexaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 4986747b715Smrg{ 4996747b715Smrg /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 500ed6184dfSmrg * Do a few smart things so fbValidateGC can do its work. 5016747b715Smrg */ 5026747b715Smrg 5036747b715Smrg ScreenPtr pScreen = pDrawable->pScreen; 50435c4bbdfSmrg 5056747b715Smrg ExaScreenPriv(pScreen); 5066747b715Smrg ExaGCPriv(pGC); 5076747b715Smrg PixmapPtr pTile = NULL; 5086747b715Smrg 5091b5d61b8Smrg /* Either of these conditions is enough to trigger access to a tile pixmap. 5101b5d61b8Smrg * With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid 5111b5d61b8Smrg * tile pixmap pointer. 5121b5d61b8Smrg */ 51335c4bbdfSmrg if (pGC->fillStyle == FillTiled || 51435c4bbdfSmrg ((changes & GCTile) && !pGC->tileIsPixel)) { 51535c4bbdfSmrg pTile = pGC->tile.pixmap; 51605b261ecSmrg } 51705b261ecSmrg 5186747b715Smrg if (pGC->stipple) 5196747b715Smrg exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 5206747b715Smrg if (pTile) 52135c4bbdfSmrg exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC); 5226747b715Smrg 5236747b715Smrg /* Calls to Create/DestroyPixmap have to be identified as special. */ 5246747b715Smrg pExaScr->fallback_counter++; 5256747b715Smrg swap(pExaGC, pGC, funcs); 52635c4bbdfSmrg (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); 5276747b715Smrg swap(pExaGC, pGC, funcs); 5286747b715Smrg pExaScr->fallback_counter--; 5296747b715Smrg 5306747b715Smrg if (pTile) 53135c4bbdfSmrg exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); 5326747b715Smrg if (pGC->stipple) 53335c4bbdfSmrg exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 5346747b715Smrg} 5356747b715Smrg 5366747b715Smrg/* Is exaPrepareAccessGC() needed? */ 5376747b715Smrgstatic void 5386747b715SmrgexaDestroyGC(GCPtr pGC) 5396747b715Smrg{ 5406747b715Smrg ExaGCPriv(pGC); 5416747b715Smrg swap(pExaGC, pGC, funcs); 54235c4bbdfSmrg (*pGC->funcs->DestroyGC) (pGC); 5436747b715Smrg swap(pExaGC, pGC, funcs); 5446747b715Smrg} 54505b261ecSmrg 5466747b715Smrgstatic void 54735c4bbdfSmrgexaChangeGC(GCPtr pGC, unsigned long mask) 5486747b715Smrg{ 5496747b715Smrg ExaGCPriv(pGC); 5506747b715Smrg swap(pExaGC, pGC, funcs); 5516747b715Smrg (*pGC->funcs->ChangeGC) (pGC, mask); 5526747b715Smrg swap(pExaGC, pGC, funcs); 55305b261ecSmrg} 55405b261ecSmrg 5556747b715Smrgstatic void 55635c4bbdfSmrgexaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 5576747b715Smrg{ 5586747b715Smrg ExaGCPriv(pGCDst); 5596747b715Smrg swap(pExaGC, pGCDst, funcs); 5606747b715Smrg (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 5616747b715Smrg swap(pExaGC, pGCDst, funcs); 5626747b715Smrg} 5636747b715Smrg 5646747b715Smrgstatic void 56535c4bbdfSmrgexaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects) 5666747b715Smrg{ 5676747b715Smrg ExaGCPriv(pGC); 5686747b715Smrg swap(pExaGC, pGC, funcs); 5696747b715Smrg (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 5706747b715Smrg swap(pExaGC, pGC, funcs); 5716747b715Smrg} 5726747b715Smrg 5736747b715Smrgstatic void 5746747b715SmrgexaCopyClip(GCPtr pGCDst, GCPtr pGCSrc) 5756747b715Smrg{ 5766747b715Smrg ExaGCPriv(pGCDst); 5776747b715Smrg swap(pExaGC, pGCDst, funcs); 57835c4bbdfSmrg (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); 5796747b715Smrg swap(pExaGC, pGCDst, funcs); 5806747b715Smrg} 5816747b715Smrg 5826747b715Smrgstatic void 5836747b715SmrgexaDestroyClip(GCPtr pGC) 5846747b715Smrg{ 5856747b715Smrg ExaGCPriv(pGC); 5866747b715Smrg swap(pExaGC, pGC, funcs); 58735c4bbdfSmrg (*pGC->funcs->DestroyClip) (pGC); 5886747b715Smrg swap(pExaGC, pGC, funcs); 5896747b715Smrg} 59005b261ecSmrg 59105b261ecSmrg/** 59205b261ecSmrg * exaCreateGC makes a new GC and hooks up its funcs handler, so that 59305b261ecSmrg * exaValidateGC() will get called. 59405b261ecSmrg */ 59505b261ecSmrgstatic int 59635c4bbdfSmrgexaCreateGC(GCPtr pGC) 59705b261ecSmrg{ 5986747b715Smrg ScreenPtr pScreen = pGC->pScreen; 59935c4bbdfSmrg 6006747b715Smrg ExaScreenPriv(pScreen); 6016747b715Smrg ExaGCPriv(pGC); 6026747b715Smrg Bool ret; 60305b261ecSmrg 6046747b715Smrg swap(pExaScr, pScreen, CreateGC); 6056747b715Smrg if ((ret = (*pScreen->CreateGC) (pGC))) { 60635c4bbdfSmrg wrap(pExaGC, pGC, funcs, &exaGCFuncs); 60735c4bbdfSmrg wrap(pExaGC, pGC, ops, &exaOps); 6086747b715Smrg } 6096747b715Smrg swap(pExaScr, pScreen, CreateGC); 61005b261ecSmrg 6116747b715Smrg return ret; 61205b261ecSmrg} 61305b261ecSmrg 6144642e01fSmrgstatic Bool 6154642e01fSmrgexaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 6164642e01fSmrg{ 6174642e01fSmrg Bool ret; 6186747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 61935c4bbdfSmrg 6206747b715Smrg ExaScreenPriv(pScreen); 6214642e01fSmrg 62235c4bbdfSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 62335c4bbdfSmrg exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 6244642e01fSmrg 6254642e01fSmrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 62635c4bbdfSmrg exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 6274642e01fSmrg 6286747b715Smrg pExaScr->fallback_counter++; 6296747b715Smrg swap(pExaScr, pScreen, ChangeWindowAttributes); 6306747b715Smrg ret = pScreen->ChangeWindowAttributes(pWin, mask); 6316747b715Smrg swap(pExaScr, pScreen, ChangeWindowAttributes); 6326747b715Smrg pExaScr->fallback_counter--; 6334642e01fSmrg 63435c4bbdfSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 63535c4bbdfSmrg exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 6366747b715Smrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 63735c4bbdfSmrg exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 6384642e01fSmrg 6394642e01fSmrg return ret; 6404642e01fSmrg} 6414642e01fSmrg 6424642e01fSmrgstatic RegionPtr 6434642e01fSmrgexaBitmapToRegion(PixmapPtr pPix) 6444642e01fSmrg{ 6456747b715Smrg RegionPtr ret; 6466747b715Smrg ScreenPtr pScreen = pPix->drawable.pScreen; 64735c4bbdfSmrg 6486747b715Smrg ExaScreenPriv(pScreen); 6496747b715Smrg 6506747b715Smrg exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); 6516747b715Smrg swap(pExaScr, pScreen, BitmapToRegion); 65235c4bbdfSmrg ret = (*pScreen->BitmapToRegion) (pPix); 6536747b715Smrg swap(pExaScr, pScreen, BitmapToRegion); 6546747b715Smrg exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); 6556747b715Smrg 6566747b715Smrg return ret; 6574642e01fSmrg} 6584642e01fSmrg 6594642e01fSmrgstatic Bool 6604642e01fSmrgexaCreateScreenResources(ScreenPtr pScreen) 6614642e01fSmrg{ 6624642e01fSmrg ExaScreenPriv(pScreen); 6634642e01fSmrg PixmapPtr pScreenPixmap; 6644642e01fSmrg Bool b; 6654642e01fSmrg 6666747b715Smrg swap(pExaScr, pScreen, CreateScreenResources); 6674642e01fSmrg b = pScreen->CreateScreenResources(pScreen); 6686747b715Smrg swap(pExaScr, pScreen, CreateScreenResources); 6694642e01fSmrg 6704642e01fSmrg if (!b) 6714642e01fSmrg return FALSE; 6724642e01fSmrg 6734642e01fSmrg pScreenPixmap = pScreen->GetScreenPixmap(pScreen); 6744642e01fSmrg 6754642e01fSmrg if (pScreenPixmap) { 6764642e01fSmrg ExaPixmapPriv(pScreenPixmap); 6774642e01fSmrg 6784642e01fSmrg exaSetAccelBlock(pExaScr, pExaPixmap, 6794642e01fSmrg pScreenPixmap->drawable.width, 6804642e01fSmrg pScreenPixmap->drawable.height, 6814642e01fSmrg pScreenPixmap->drawable.bitsPerPixel); 6824642e01fSmrg } 6834642e01fSmrg 6844642e01fSmrg return TRUE; 6854642e01fSmrg} 6864642e01fSmrg 6876747b715Smrgstatic void 6881b5d61b8SmrgExaBlockHandler(ScreenPtr pScreen, void *pTimeout) 6896747b715Smrg{ 6906747b715Smrg ExaScreenPriv(pScreen); 6916747b715Smrg 6926747b715Smrg /* Move any deferred results from a software fallback to the driver pixmap */ 6936747b715Smrg if (pExaScr->deferred_mixed_pixmap) 69435c4bbdfSmrg exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); 6956747b715Smrg 6966747b715Smrg unwrap(pExaScr, pScreen, BlockHandler); 6971b5d61b8Smrg (*pScreen->BlockHandler) (pScreen, pTimeout); 6986747b715Smrg wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 6996747b715Smrg 7006747b715Smrg /* The rest only applies to classic EXA */ 7016747b715Smrg if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) 70235c4bbdfSmrg return; 7036747b715Smrg 70435c4bbdfSmrg /* Try and keep the offscreen memory area tidy every now and then (at most 7056747b715Smrg * once per second) when the server has been idle for at least 100ms. 7066747b715Smrg */ 7076747b715Smrg if (pExaScr->numOffscreenAvailable > 1) { 70835c4bbdfSmrg CARD32 now = GetTimeInMillis(); 7096747b715Smrg 71035c4bbdfSmrg pExaScr->nextDefragment = now + 71135c4bbdfSmrg max(100, (INT32) (pExaScr->lastDefragment + 1000 - now)); 71235c4bbdfSmrg AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now); 7136747b715Smrg } 7146747b715Smrg} 7156747b715Smrg 7166747b715Smrgstatic void 7171b5d61b8SmrgExaWakeupHandler(ScreenPtr pScreen, int result) 7186747b715Smrg{ 7196747b715Smrg ExaScreenPriv(pScreen); 7206747b715Smrg 7216747b715Smrg unwrap(pExaScr, pScreen, WakeupHandler); 7221b5d61b8Smrg (*pScreen->WakeupHandler) (pScreen, result); 7236747b715Smrg wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 7246747b715Smrg 7256747b715Smrg if (result == 0 && pExaScr->numOffscreenAvailable > 1) { 72635c4bbdfSmrg CARD32 now = GetTimeInMillis(); 7276747b715Smrg 72835c4bbdfSmrg if ((int) (now - pExaScr->nextDefragment) > 0) { 72935c4bbdfSmrg ExaOffscreenDefragment(pScreen); 73035c4bbdfSmrg pExaScr->lastDefragment = now; 73135c4bbdfSmrg } 7326747b715Smrg } 7336747b715Smrg} 7346747b715Smrg 73505b261ecSmrg/** 73605b261ecSmrg * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 73705b261ecSmrg * screen private, before calling down to the next CloseSccreen. 73805b261ecSmrg */ 73905b261ecSmrgstatic Bool 74035c4bbdfSmrgexaCloseScreen(ScreenPtr pScreen) 74105b261ecSmrg{ 74205b261ecSmrg ExaScreenPriv(pScreen); 74335c4bbdfSmrg PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 74405b261ecSmrg 7454642e01fSmrg if (ps->Glyphs == exaGlyphs) 74635c4bbdfSmrg exaGlyphsFini(pScreen); 7474642e01fSmrg 7486747b715Smrg if (pScreen->BlockHandler == ExaBlockHandler) 74935c4bbdfSmrg unwrap(pExaScr, pScreen, BlockHandler); 7506747b715Smrg if (pScreen->WakeupHandler == ExaWakeupHandler) 75135c4bbdfSmrg unwrap(pExaScr, pScreen, WakeupHandler); 7526747b715Smrg unwrap(pExaScr, pScreen, CreateGC); 7536747b715Smrg unwrap(pExaScr, pScreen, CloseScreen); 7546747b715Smrg unwrap(pExaScr, pScreen, GetImage); 7556747b715Smrg unwrap(pExaScr, pScreen, GetSpans); 7566747b715Smrg if (pExaScr->SavedCreatePixmap) 75735c4bbdfSmrg unwrap(pExaScr, pScreen, CreatePixmap); 7586747b715Smrg if (pExaScr->SavedDestroyPixmap) 75935c4bbdfSmrg unwrap(pExaScr, pScreen, DestroyPixmap); 7606747b715Smrg if (pExaScr->SavedModifyPixmapHeader) 76135c4bbdfSmrg unwrap(pExaScr, pScreen, ModifyPixmapHeader); 7626747b715Smrg unwrap(pExaScr, pScreen, CopyWindow); 7636747b715Smrg unwrap(pExaScr, pScreen, ChangeWindowAttributes); 7646747b715Smrg unwrap(pExaScr, pScreen, BitmapToRegion); 7656747b715Smrg unwrap(pExaScr, pScreen, CreateScreenResources); 76635c4bbdfSmrg if (pExaScr->SavedSharePixmapBacking) 76735c4bbdfSmrg unwrap(pExaScr, pScreen, SharePixmapBacking); 76835c4bbdfSmrg if (pExaScr->SavedSetSharedPixmapBacking) 76935c4bbdfSmrg unwrap(pExaScr, pScreen, SetSharedPixmapBacking); 7706747b715Smrg unwrap(pExaScr, ps, Composite); 7716747b715Smrg if (pExaScr->SavedGlyphs) 77235c4bbdfSmrg unwrap(pExaScr, ps, Glyphs); 7736747b715Smrg unwrap(pExaScr, ps, Trapezoids); 7746747b715Smrg unwrap(pExaScr, ps, Triangles); 7756747b715Smrg unwrap(pExaScr, ps, AddTraps); 7766747b715Smrg 7776747b715Smrg free(pExaScr); 77805b261ecSmrg 77935c4bbdfSmrg return (*pScreen->CloseScreen) (pScreen); 78005b261ecSmrg} 78105b261ecSmrg 78205b261ecSmrg/** 78305b261ecSmrg * This function allocates a driver structure for EXA drivers to fill in. By 78405b261ecSmrg * having EXA allocate the structure, the driver structure can be extended 78505b261ecSmrg * without breaking ABI between EXA and the drivers. The driver's 78605b261ecSmrg * responsibility is to check beforehand that the EXA module has a matching 78705b261ecSmrg * major number and sufficient minor. Drivers are responsible for freeing the 7886747b715Smrg * driver structure using free(). 78905b261ecSmrg * 79005b261ecSmrg * @return a newly allocated, zero-filled driver structure 79105b261ecSmrg */ 79205b261ecSmrgExaDriverPtr 79305b261ecSmrgexaDriverAlloc(void) 79405b261ecSmrg{ 7956747b715Smrg return calloc(1, sizeof(ExaDriverRec)); 79605b261ecSmrg} 79705b261ecSmrg 79805b261ecSmrg/** 79905b261ecSmrg * @param pScreen screen being initialized 80005b261ecSmrg * @param pScreenInfo EXA driver record 80105b261ecSmrg * 80205b261ecSmrg * exaDriverInit sets up EXA given a driver record filled in by the driver. 80305b261ecSmrg * pScreenInfo should have been allocated by exaDriverAlloc(). See the 80405b261ecSmrg * comments in _ExaDriver for what must be filled in and what is optional. 80505b261ecSmrg * 80605b261ecSmrg * @return TRUE if EXA was successfully initialized. 80705b261ecSmrg */ 80805b261ecSmrgBool 80935c4bbdfSmrgexaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo) 81005b261ecSmrg{ 81105b261ecSmrg ExaScreenPrivPtr pExaScr; 81205b261ecSmrg PictureScreenPtr ps; 81305b261ecSmrg 81405b261ecSmrg if (!pScreenInfo) 81535c4bbdfSmrg return FALSE; 81605b261ecSmrg 8174642e01fSmrg if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 81835c4bbdfSmrg pScreenInfo->exa_minor > EXA_VERSION_MINOR) { 81935c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 82035c4bbdfSmrg "(%d.%d) are incompatible with EXA version (%d.%d)\n", 82135c4bbdfSmrg pScreen->myNum, 82235c4bbdfSmrg pScreenInfo->exa_major, pScreenInfo->exa_minor, 82335c4bbdfSmrg EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 82435c4bbdfSmrg return FALSE; 82505b261ecSmrg } 82605b261ecSmrg 8276747b715Smrg if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) { 82835c4bbdfSmrg if (!pScreenInfo->memoryBase) { 82935c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " 83035c4bbdfSmrg "must be non-zero\n", pScreen->myNum); 83135c4bbdfSmrg return FALSE; 83235c4bbdfSmrg } 83335c4bbdfSmrg 83435c4bbdfSmrg if (!pScreenInfo->memorySize) { 83535c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 83635c4bbdfSmrg "non-zero\n", pScreen->myNum); 83735c4bbdfSmrg return FALSE; 83835c4bbdfSmrg } 83935c4bbdfSmrg 84035c4bbdfSmrg if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 84135c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " 84235c4bbdfSmrg "be <= ExaDriverRec::memorySize\n", pScreen->myNum); 84335c4bbdfSmrg return FALSE; 84435c4bbdfSmrg } 84505b261ecSmrg } 84605b261ecSmrg 84705b261ecSmrg if (!pScreenInfo->PrepareSolid) { 84835c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 84935c4bbdfSmrg "non-NULL\n", pScreen->myNum); 85035c4bbdfSmrg return FALSE; 85105b261ecSmrg } 85205b261ecSmrg 85305b261ecSmrg if (!pScreenInfo->PrepareCopy) { 85435c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 85535c4bbdfSmrg "non-NULL\n", pScreen->myNum); 85635c4bbdfSmrg return FALSE; 85705b261ecSmrg } 85805b261ecSmrg 85905b261ecSmrg if (!pScreenInfo->WaitMarker) { 86035c4bbdfSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 86135c4bbdfSmrg "non-NULL\n", pScreen->myNum); 86235c4bbdfSmrg return FALSE; 86305b261ecSmrg } 86405b261ecSmrg 8654642e01fSmrg /* If the driver doesn't set any max pitch values, we'll just assume 8664642e01fSmrg * that there's a limitation by pixels, and that it's the same as 8674642e01fSmrg * maxX. 8684642e01fSmrg * 8694642e01fSmrg * We want maxPitchPixels or maxPitchBytes to be set so we can check 8704642e01fSmrg * pixmaps against the max pitch in exaCreatePixmap() -- it matters 8714642e01fSmrg * whether a pixmap is rejected because of its pitch or 8724642e01fSmrg * because of its width. 8734642e01fSmrg */ 87435c4bbdfSmrg if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) { 8754642e01fSmrg pScreenInfo->maxPitchPixels = pScreenInfo->maxX; 87605b261ecSmrg } 87705b261ecSmrg 87805b261ecSmrg ps = GetPictureScreenIfSet(pScreen); 87905b261ecSmrg 8806747b715Smrg if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) { 8816747b715Smrg LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n", 88235c4bbdfSmrg pScreen->myNum); 88335c4bbdfSmrg return FALSE; 8846747b715Smrg } 88505b261ecSmrg 88635c4bbdfSmrg pExaScr = calloc(sizeof(ExaScreenPrivRec), 1); 88705b261ecSmrg if (!pExaScr) { 88805b261ecSmrg LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 88935c4bbdfSmrg pScreen->myNum); 89035c4bbdfSmrg return FALSE; 89105b261ecSmrg } 89205b261ecSmrg 89305b261ecSmrg pExaScr->info = pScreenInfo; 89405b261ecSmrg 8954642e01fSmrg dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); 89605b261ecSmrg 89705b261ecSmrg pExaScr->migration = ExaMigrationAlways; 89805b261ecSmrg 89905b261ecSmrg exaDDXDriverInit(pScreen); 90005b261ecSmrg 90135c4bbdfSmrg if (!dixRegisterScreenSpecificPrivateKey 90235c4bbdfSmrg (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { 90335c4bbdfSmrg LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n", 90435c4bbdfSmrg pScreen->myNum); 90535c4bbdfSmrg return FALSE; 9066747b715Smrg } 9076747b715Smrg 90805b261ecSmrg /* 90905b261ecSmrg * Replace various fb screen functions 91005b261ecSmrg */ 9116747b715Smrg if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 91235c4bbdfSmrg (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) || 91335c4bbdfSmrg (pExaScr->info->flags & EXA_MIXED_PIXMAPS))) 91435c4bbdfSmrg wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 9156747b715Smrg if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 91635c4bbdfSmrg !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) 91735c4bbdfSmrg wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 9186747b715Smrg wrap(pExaScr, pScreen, CreateGC, exaCreateGC); 9196747b715Smrg wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen); 9206747b715Smrg wrap(pExaScr, pScreen, GetImage, exaGetImage); 9216747b715Smrg wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans); 9226747b715Smrg wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow); 9236747b715Smrg wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes); 9246747b715Smrg wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion); 9256747b715Smrg wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources); 92605b261ecSmrg 92705b261ecSmrg if (ps) { 92835c4bbdfSmrg wrap(pExaScr, ps, Composite, exaComposite); 92935c4bbdfSmrg if (pScreenInfo->PrepareComposite) { 93035c4bbdfSmrg wrap(pExaScr, ps, Glyphs, exaGlyphs); 93135c4bbdfSmrg } 93235c4bbdfSmrg else { 93335c4bbdfSmrg wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs); 93435c4bbdfSmrg } 93535c4bbdfSmrg wrap(pExaScr, ps, Trapezoids, exaTrapezoids); 93635c4bbdfSmrg wrap(pExaScr, ps, Triangles, exaTriangles); 93735c4bbdfSmrg wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps); 93805b261ecSmrg } 93905b261ecSmrg 94005b261ecSmrg#ifdef MITSHM 9414642e01fSmrg /* 9424642e01fSmrg * Don't allow shared pixmaps. 94305b261ecSmrg */ 9444642e01fSmrg ShmRegisterFuncs(pScreen, &exaShmFuncs); 94505b261ecSmrg#endif 94605b261ecSmrg /* 94705b261ecSmrg * Hookup offscreen pixmaps 94805b261ecSmrg */ 94935c4bbdfSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { 95035c4bbdfSmrg if (!dixRegisterScreenSpecificPrivateKey 95135c4bbdfSmrg (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP, 95235c4bbdfSmrg sizeof(ExaPixmapPrivRec))) { 95305b261ecSmrg LogMessage(X_WARNING, 95435c4bbdfSmrg "EXA(%d): Failed to allocate pixmap private\n", 95535c4bbdfSmrg pScreen->myNum); 95635c4bbdfSmrg return FALSE; 95735c4bbdfSmrg } 95835c4bbdfSmrg if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) { 95935c4bbdfSmrg if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) { 96035c4bbdfSmrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed); 96135c4bbdfSmrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed); 96235c4bbdfSmrg wrap(pExaScr, pScreen, ModifyPixmapHeader, 96335c4bbdfSmrg exaModifyPixmapHeader_mixed); 96435c4bbdfSmrg wrap(pExaScr, pScreen, SharePixmapBacking, exaSharePixmapBacking_mixed); 96535c4bbdfSmrg wrap(pExaScr, pScreen, SetSharedPixmapBacking, exaSetSharedPixmapBacking_mixed); 96635c4bbdfSmrg 96735c4bbdfSmrg pExaScr->do_migration = exaDoMigration_mixed; 96835c4bbdfSmrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed; 96935c4bbdfSmrg pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; 97035c4bbdfSmrg pExaScr->do_move_out_pixmap = NULL; 97135c4bbdfSmrg pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed; 97235c4bbdfSmrg } 97335c4bbdfSmrg else { 97435c4bbdfSmrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver); 97535c4bbdfSmrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver); 97635c4bbdfSmrg wrap(pExaScr, pScreen, ModifyPixmapHeader, 97735c4bbdfSmrg exaModifyPixmapHeader_driver); 97835c4bbdfSmrg pExaScr->do_migration = NULL; 97935c4bbdfSmrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver; 98035c4bbdfSmrg pExaScr->do_move_in_pixmap = NULL; 98135c4bbdfSmrg pExaScr->do_move_out_pixmap = NULL; 98235c4bbdfSmrg pExaScr->prepare_access_reg = NULL; 98335c4bbdfSmrg } 98435c4bbdfSmrg } 98535c4bbdfSmrg else { 98635c4bbdfSmrg wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); 98735c4bbdfSmrg wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic); 98835c4bbdfSmrg wrap(pExaScr, pScreen, ModifyPixmapHeader, 98935c4bbdfSmrg exaModifyPixmapHeader_classic); 99035c4bbdfSmrg pExaScr->do_migration = exaDoMigration_classic; 99135c4bbdfSmrg pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic; 99235c4bbdfSmrg pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; 99335c4bbdfSmrg pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; 99435c4bbdfSmrg pExaScr->prepare_access_reg = exaPrepareAccessReg_classic; 99535c4bbdfSmrg } 99635c4bbdfSmrg if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 99735c4bbdfSmrg LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 99835c4bbdfSmrg pScreen->myNum, 99935c4bbdfSmrg pExaScr->info->memorySize - 100035c4bbdfSmrg pExaScr->info->offScreenBase); 100135c4bbdfSmrg } 100235c4bbdfSmrg else { 100335c4bbdfSmrg LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", 100435c4bbdfSmrg pScreen->myNum); 100535c4bbdfSmrg 100605b261ecSmrg } 100705b261ecSmrg } 100805b261ecSmrg else 100905b261ecSmrg LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 101005b261ecSmrg 10116747b715Smrg if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 101235c4bbdfSmrg DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 101335c4bbdfSmrg pExaScr->info->memorySize)); 101435c4bbdfSmrg if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 101535c4bbdfSmrg if (!exaOffscreenInit(pScreen)) { 101635c4bbdfSmrg LogMessage(X_WARNING, 101735c4bbdfSmrg "EXA(%d): Offscreen pixmap setup failed\n", 101835c4bbdfSmrg pScreen->myNum); 101935c4bbdfSmrg return FALSE; 102035c4bbdfSmrg } 102135c4bbdfSmrg } 102205b261ecSmrg } 102305b261ecSmrg 10244642e01fSmrg if (ps->Glyphs == exaGlyphs) 102535c4bbdfSmrg exaGlyphsInit(pScreen); 10264642e01fSmrg 102705b261ecSmrg LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 102835c4bbdfSmrg " operations:\n", pScreen->myNum); 102905b261ecSmrg assert(pScreenInfo->PrepareSolid != NULL); 103005b261ecSmrg LogMessage(X_INFO, " Solid\n"); 103105b261ecSmrg assert(pScreenInfo->PrepareCopy != NULL); 103205b261ecSmrg LogMessage(X_INFO, " Copy\n"); 103305b261ecSmrg if (pScreenInfo->PrepareComposite != NULL) { 103435c4bbdfSmrg LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 103505b261ecSmrg } 103605b261ecSmrg if (pScreenInfo->UploadToScreen != NULL) { 103735c4bbdfSmrg LogMessage(X_INFO, " UploadToScreen\n"); 103805b261ecSmrg } 103905b261ecSmrg if (pScreenInfo->DownloadFromScreen != NULL) { 104035c4bbdfSmrg LogMessage(X_INFO, " DownloadFromScreen\n"); 104105b261ecSmrg } 104205b261ecSmrg 104305b261ecSmrg return TRUE; 104405b261ecSmrg} 104505b261ecSmrg 104605b261ecSmrg/** 104705b261ecSmrg * exaDriverFini tears down EXA on a given screen. 104805b261ecSmrg * 104905b261ecSmrg * @param pScreen screen being torn down. 105005b261ecSmrg */ 105105b261ecSmrgvoid 105235c4bbdfSmrgexaDriverFini(ScreenPtr pScreen) 105305b261ecSmrg{ 105435c4bbdfSmrg /*right now does nothing */ 105505b261ecSmrg} 105605b261ecSmrg 105705b261ecSmrg/** 105805b261ecSmrg * exaMarkSync() should be called after any asynchronous drawing by the hardware. 105905b261ecSmrg * 106005b261ecSmrg * @param pScreen screen which drawing occurred on 106105b261ecSmrg * 106205b261ecSmrg * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 106305b261ecSmrg * happened and a WaitSync() will be necessary before relying on the contents of 106405b261ecSmrg * offscreen memory from the CPU's perspective. It also calls an optional 106505b261ecSmrg * driver MarkSync() callback, the return value of which may be used to do partial 106605b261ecSmrg * synchronization with the hardware in the future. 106705b261ecSmrg */ 106835c4bbdfSmrgvoid 106935c4bbdfSmrgexaMarkSync(ScreenPtr pScreen) 107005b261ecSmrg{ 107105b261ecSmrg ExaScreenPriv(pScreen); 107205b261ecSmrg 107305b261ecSmrg pExaScr->info->needsSync = TRUE; 107405b261ecSmrg if (pExaScr->info->MarkSync != NULL) { 107535c4bbdfSmrg pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen); 107605b261ecSmrg } 107705b261ecSmrg} 107805b261ecSmrg 107905b261ecSmrg/** 108005b261ecSmrg * exaWaitSync() ensures that all drawing has been completed. 108105b261ecSmrg * 108205b261ecSmrg * @param pScreen screen being synchronized. 108305b261ecSmrg * 108405b261ecSmrg * Calls down into the driver to ensure that all previous drawing has completed. 108505b261ecSmrg * It should always be called before relying on the framebuffer contents 108605b261ecSmrg * reflecting previous drawing, from a CPU perspective. 108705b261ecSmrg */ 108835c4bbdfSmrgvoid 108935c4bbdfSmrgexaWaitSync(ScreenPtr pScreen) 109005b261ecSmrg{ 109105b261ecSmrg ExaScreenPriv(pScreen); 109205b261ecSmrg 109305b261ecSmrg if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 109435c4bbdfSmrg (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker); 109505b261ecSmrg pExaScr->info->needsSync = FALSE; 109605b261ecSmrg } 109705b261ecSmrg} 10986747b715Smrg 10996747b715Smrg/** 11006747b715Smrg * Performs migration of the pixmaps according to the operation information 11016747b715Smrg * provided in pixmaps and can_accel and the migration scheme chosen in the 11026747b715Smrg * config file. 11036747b715Smrg */ 11046747b715Smrgvoid 110535c4bbdfSmrgexaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) 11066747b715Smrg{ 11076747b715Smrg ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; 110835c4bbdfSmrg 11096747b715Smrg ExaScreenPriv(pScreen); 11106747b715Smrg 11116747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 111235c4bbdfSmrg return; 11136747b715Smrg 11146747b715Smrg if (pExaScr->do_migration) 111535c4bbdfSmrg (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel); 11166747b715Smrg} 11176747b715Smrg 11186747b715Smrgvoid 111935c4bbdfSmrgexaMoveInPixmap(PixmapPtr pPixmap) 11206747b715Smrg{ 11216747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 112235c4bbdfSmrg 11236747b715Smrg ExaScreenPriv(pScreen); 11246747b715Smrg 11256747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 112635c4bbdfSmrg return; 11276747b715Smrg 11286747b715Smrg if (pExaScr->do_move_in_pixmap) 112935c4bbdfSmrg (*pExaScr->do_move_in_pixmap) (pPixmap); 11306747b715Smrg} 11316747b715Smrg 11326747b715Smrgvoid 113335c4bbdfSmrgexaMoveOutPixmap(PixmapPtr pPixmap) 11346747b715Smrg{ 11356747b715Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 113635c4bbdfSmrg 11376747b715Smrg ExaScreenPriv(pScreen); 11386747b715Smrg 11396747b715Smrg if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 114035c4bbdfSmrg return; 11416747b715Smrg 11426747b715Smrg if (pExaScr->do_move_out_pixmap) 114335c4bbdfSmrg (*pExaScr->do_move_out_pixmap) (pPixmap); 11446747b715Smrg} 1145