exa.c revision 05b261ec
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#ifdef MITSHM 3605b261ecSmrg#include "shmint.h" 3705b261ecSmrg#endif 3805b261ecSmrg 3905b261ecSmrg#include <stdlib.h> 4005b261ecSmrg 4105b261ecSmrg#include "exa_priv.h" 4205b261ecSmrg#include <X11/fonts/fontstruct.h> 4305b261ecSmrg#include "dixfontstr.h" 4405b261ecSmrg#include "exa.h" 4505b261ecSmrg#include "cw.h" 4605b261ecSmrg 4705b261ecSmrgstatic int exaGeneration; 4805b261ecSmrgint exaScreenPrivateIndex; 4905b261ecSmrgint exaPixmapPrivateIndex; 5005b261ecSmrg 5105b261ecSmrg/** 5205b261ecSmrg * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 5305b261ecSmrg * the beginning of the given pixmap. 5405b261ecSmrg * 5505b261ecSmrg * Note that drivers are free to, and often do, munge this offset as necessary 5605b261ecSmrg * for handing to the hardware -- for example, translating it into a different 5705b261ecSmrg * aperture. This function may need to be extended in the future if we grow 5805b261ecSmrg * support for having multiple card-accessible offscreen, such as an AGP memory 5905b261ecSmrg * pool alongside the framebuffer pool. 6005b261ecSmrg */ 6105b261ecSmrgunsigned long 6205b261ecSmrgexaGetPixmapOffset(PixmapPtr pPix) 6305b261ecSmrg{ 6405b261ecSmrg ExaScreenPriv (pPix->drawable.pScreen); 6505b261ecSmrg ExaPixmapPriv (pPix); 6605b261ecSmrg void *ptr; 6705b261ecSmrg 6805b261ecSmrg /* Return the offscreen pointer if we've hidden the data. */ 6905b261ecSmrg if (pPix->devPrivate.ptr == NULL) 7005b261ecSmrg ptr = pExaPixmap->fb_ptr; 7105b261ecSmrg else 7205b261ecSmrg ptr = pPix->devPrivate.ptr; 7305b261ecSmrg 7405b261ecSmrg return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase); 7505b261ecSmrg} 7605b261ecSmrg 7705b261ecSmrg/** 7805b261ecSmrg * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 7905b261ecSmrg * 8005b261ecSmrg * This is a helper to make driver code more obvious, due to the rather obscure 8105b261ecSmrg * naming of the pitch field in the pixmap. 8205b261ecSmrg */ 8305b261ecSmrgunsigned long 8405b261ecSmrgexaGetPixmapPitch(PixmapPtr pPix) 8505b261ecSmrg{ 8605b261ecSmrg return pPix->devKind; 8705b261ecSmrg} 8805b261ecSmrg 8905b261ecSmrg/** 9005b261ecSmrg * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 9105b261ecSmrg * memory. Only valid when the pixmap is currently in framebuffer. 9205b261ecSmrg */ 9305b261ecSmrgunsigned long 9405b261ecSmrgexaGetPixmapSize(PixmapPtr pPix) 9505b261ecSmrg{ 9605b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 9705b261ecSmrg 9805b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPix); 9905b261ecSmrg if (pExaPixmap != NULL) 10005b261ecSmrg return pExaPixmap->fb_size; 10105b261ecSmrg return 0; 10205b261ecSmrg} 10305b261ecSmrg 10405b261ecSmrg/** 10505b261ecSmrg * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 10605b261ecSmrg * 10705b261ecSmrg * @param pDrawable the drawable being requested. 10805b261ecSmrg * 10905b261ecSmrg * This function returns the backing pixmap for a drawable, whether it is a 11005b261ecSmrg * redirected window, unredirected window, or already a pixmap. Note that 11105b261ecSmrg * coordinate translation is needed when drawing to the backing pixmap of a 11205b261ecSmrg * redirected window, and the translation coordinates are provided by calling 11305b261ecSmrg * exaGetOffscreenPixmap() on the drawable. 11405b261ecSmrg */ 11505b261ecSmrgPixmapPtr 11605b261ecSmrgexaGetDrawablePixmap(DrawablePtr pDrawable) 11705b261ecSmrg{ 11805b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) 11905b261ecSmrg return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 12005b261ecSmrg else 12105b261ecSmrg return (PixmapPtr) pDrawable; 12205b261ecSmrg} 12305b261ecSmrg 12405b261ecSmrg/** 12505b261ecSmrg * Sets the offsets to add to coordinates to make them address the same bits in 12605b261ecSmrg * the backing drawable. These coordinates are nonzero only for redirected 12705b261ecSmrg * windows. 12805b261ecSmrg */ 12905b261ecSmrgvoid 13005b261ecSmrgexaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 13105b261ecSmrg int *xp, int *yp) 13205b261ecSmrg{ 13305b261ecSmrg#ifdef COMPOSITE 13405b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 13505b261ecSmrg *xp = -pPixmap->screen_x; 13605b261ecSmrg *yp = -pPixmap->screen_y; 13705b261ecSmrg return; 13805b261ecSmrg } 13905b261ecSmrg#endif 14005b261ecSmrg 14105b261ecSmrg *xp = 0; 14205b261ecSmrg *yp = 0; 14305b261ecSmrg} 14405b261ecSmrg 14505b261ecSmrg/** 14605b261ecSmrg * exaPixmapDirty() marks a pixmap as dirty, allowing for 14705b261ecSmrg * optimizations in pixmap migration when no changes have occurred. 14805b261ecSmrg */ 14905b261ecSmrgvoid 15005b261ecSmrgexaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 15105b261ecSmrg{ 15205b261ecSmrg ExaPixmapPriv(pPix); 15305b261ecSmrg BoxRec box; 15405b261ecSmrg RegionPtr pDamageReg; 15505b261ecSmrg RegionRec region; 15605b261ecSmrg 15705b261ecSmrg if (!pExaPixmap) 15805b261ecSmrg return; 15905b261ecSmrg 16005b261ecSmrg box.x1 = max(x1, 0); 16105b261ecSmrg box.y1 = max(y1, 0); 16205b261ecSmrg box.x2 = min(x2, pPix->drawable.width); 16305b261ecSmrg box.y2 = min(y2, pPix->drawable.height); 16405b261ecSmrg 16505b261ecSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 16605b261ecSmrg return; 16705b261ecSmrg 16805b261ecSmrg pDamageReg = DamageRegion(pExaPixmap->pDamage); 16905b261ecSmrg 17005b261ecSmrg REGION_INIT(pScreen, ®ion, &box, 1); 17105b261ecSmrg REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); 17205b261ecSmrg REGION_UNINIT(pScreen, ®ion); 17305b261ecSmrg} 17405b261ecSmrg 17505b261ecSmrgstatic Bool 17605b261ecSmrgexaDestroyPixmap (PixmapPtr pPixmap) 17705b261ecSmrg{ 17805b261ecSmrg if (pPixmap->refcnt == 1) 17905b261ecSmrg { 18005b261ecSmrg ExaPixmapPriv (pPixmap); 18105b261ecSmrg if (pExaPixmap->area) 18205b261ecSmrg { 18305b261ecSmrg DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 18405b261ecSmrg (void*)pPixmap->drawable.id, 18505b261ecSmrg ExaGetPixmapPriv(pPixmap)->area->offset, 18605b261ecSmrg pPixmap->drawable.width, 18705b261ecSmrg pPixmap->drawable.height)); 18805b261ecSmrg /* Free the offscreen area */ 18905b261ecSmrg exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 19005b261ecSmrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 19105b261ecSmrg pPixmap->devKind = pExaPixmap->sys_pitch; 19205b261ecSmrg } 19305b261ecSmrg REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg); 19405b261ecSmrg } 19505b261ecSmrg return fbDestroyPixmap (pPixmap); 19605b261ecSmrg} 19705b261ecSmrg 19805b261ecSmrgstatic int 19905b261ecSmrgexaLog2(int val) 20005b261ecSmrg{ 20105b261ecSmrg int bits; 20205b261ecSmrg 20305b261ecSmrg if (val <= 0) 20405b261ecSmrg return 0; 20505b261ecSmrg for (bits = 0; val != 0; bits++) 20605b261ecSmrg val >>= 1; 20705b261ecSmrg return bits - 1; 20805b261ecSmrg} 20905b261ecSmrg 21005b261ecSmrg/** 21105b261ecSmrg * exaCreatePixmap() creates a new pixmap. 21205b261ecSmrg * 21305b261ecSmrg * If width and height are 0, this won't be a full-fledged pixmap and it will 21405b261ecSmrg * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because 21505b261ecSmrg * ModifyPixmapHeader() would break migration. These types of pixmaps are used 21605b261ecSmrg * for scratch pixmaps, or to represent the visible screen. 21705b261ecSmrg */ 21805b261ecSmrgstatic PixmapPtr 21905b261ecSmrgexaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) 22005b261ecSmrg{ 22105b261ecSmrg PixmapPtr pPixmap; 22205b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 22305b261ecSmrg int bpp; 22405b261ecSmrg ExaScreenPriv(pScreen); 22505b261ecSmrg 22605b261ecSmrg if (w > 32767 || h > 32767) 22705b261ecSmrg return NullPixmap; 22805b261ecSmrg 22905b261ecSmrg pPixmap = fbCreatePixmap (pScreen, w, h, depth); 23005b261ecSmrg if (!pPixmap) 23105b261ecSmrg return NULL; 23205b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 23305b261ecSmrg 23405b261ecSmrg bpp = pPixmap->drawable.bitsPerPixel; 23505b261ecSmrg 23605b261ecSmrg /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */ 23705b261ecSmrg if (!w || !h) 23805b261ecSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 23905b261ecSmrg else 24005b261ecSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 24105b261ecSmrg 24205b261ecSmrg pExaPixmap->area = NULL; 24305b261ecSmrg 24405b261ecSmrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 24505b261ecSmrg pExaPixmap->sys_pitch = pPixmap->devKind; 24605b261ecSmrg 24705b261ecSmrg pExaPixmap->fb_ptr = NULL; 24805b261ecSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 24905b261ecSmrg pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; 25005b261ecSmrg else 25105b261ecSmrg pExaPixmap->fb_pitch = w * bpp / 8; 25205b261ecSmrg pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 25305b261ecSmrg pExaScr->info->pixmapPitchAlign); 25405b261ecSmrg pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 25505b261ecSmrg 25605b261ecSmrg if (pExaPixmap->fb_pitch > 131071) { 25705b261ecSmrg fbDestroyPixmap(pPixmap); 25805b261ecSmrg return NULL; 25905b261ecSmrg } 26005b261ecSmrg 26105b261ecSmrg /* Set up damage tracking */ 26205b261ecSmrg pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, 26305b261ecSmrg pScreen, pPixmap); 26405b261ecSmrg 26505b261ecSmrg if (pExaPixmap->pDamage == NULL) { 26605b261ecSmrg fbDestroyPixmap (pPixmap); 26705b261ecSmrg return NULL; 26805b261ecSmrg } 26905b261ecSmrg 27005b261ecSmrg DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); 27105b261ecSmrg DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); 27205b261ecSmrg 27305b261ecSmrg /* None of the pixmap bits are valid initially */ 27405b261ecSmrg REGION_NULL(pScreen, &pExaPixmap->validReg); 27505b261ecSmrg 27605b261ecSmrg return pPixmap; 27705b261ecSmrg} 27805b261ecSmrg 27905b261ecSmrg/** 28005b261ecSmrg * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen 28105b261ecSmrg * memory, meaning that acceleration could probably be done to it, and that it 28205b261ecSmrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 28305b261ecSmrg * with the CPU. 28405b261ecSmrg * 28505b261ecSmrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 28605b261ecSmrg * deal with moving pixmaps in and out of system memory), EXA will give drivers 28705b261ecSmrg * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE. 28805b261ecSmrg * 28905b261ecSmrg * @return TRUE if the given drawable is in framebuffer memory. 29005b261ecSmrg */ 29105b261ecSmrgBool 29205b261ecSmrgexaPixmapIsOffscreen(PixmapPtr p) 29305b261ecSmrg{ 29405b261ecSmrg ScreenPtr pScreen = p->drawable.pScreen; 29505b261ecSmrg ExaScreenPriv(pScreen); 29605b261ecSmrg 29705b261ecSmrg /* If the devPrivate.ptr is NULL, it's offscreen but we've hidden the data. 29805b261ecSmrg */ 29905b261ecSmrg if (p->devPrivate.ptr == NULL) 30005b261ecSmrg return TRUE; 30105b261ecSmrg 30205b261ecSmrg if (pExaScr->info->PixmapIsOffscreen) 30305b261ecSmrg return pExaScr->info->PixmapIsOffscreen(p); 30405b261ecSmrg 30505b261ecSmrg return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - 30605b261ecSmrg (CARD8 *) pExaScr->info->memoryBase) < 30705b261ecSmrg pExaScr->info->memorySize); 30805b261ecSmrg} 30905b261ecSmrg 31005b261ecSmrg/** 31105b261ecSmrg * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen(). 31205b261ecSmrg */ 31305b261ecSmrgBool 31405b261ecSmrgexaDrawableIsOffscreen (DrawablePtr pDrawable) 31505b261ecSmrg{ 31605b261ecSmrg return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable)); 31705b261ecSmrg} 31805b261ecSmrg 31905b261ecSmrg/** 32005b261ecSmrg * Returns the pixmap which backs a drawable, and the offsets to add to 32105b261ecSmrg * coordinates to make them address the same bits in the backing drawable. 32205b261ecSmrg */ 32305b261ecSmrgPixmapPtr 32405b261ecSmrgexaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 32505b261ecSmrg{ 32605b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 32705b261ecSmrg 32805b261ecSmrg exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); 32905b261ecSmrg 33005b261ecSmrg if (exaPixmapIsOffscreen (pPixmap)) 33105b261ecSmrg return pPixmap; 33205b261ecSmrg else 33305b261ecSmrg return NULL; 33405b261ecSmrg} 33505b261ecSmrg 33605b261ecSmrg/** 33705b261ecSmrg * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 33805b261ecSmrg * 33905b261ecSmrg * It deals with waiting for synchronization with the card, determining if 34005b261ecSmrg * PrepareAccess() is necessary, and working around PrepareAccess() failure. 34105b261ecSmrg */ 34205b261ecSmrgvoid 34305b261ecSmrgexaPrepareAccess(DrawablePtr pDrawable, int index) 34405b261ecSmrg{ 34505b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 34605b261ecSmrg ExaScreenPriv (pScreen); 34705b261ecSmrg PixmapPtr pPixmap; 34805b261ecSmrg 34905b261ecSmrg pPixmap = exaGetDrawablePixmap (pDrawable); 35005b261ecSmrg 35105b261ecSmrg if (exaPixmapIsOffscreen (pPixmap)) 35205b261ecSmrg exaWaitSync (pDrawable->pScreen); 35305b261ecSmrg else 35405b261ecSmrg return; 35505b261ecSmrg 35605b261ecSmrg /* Unhide pixmap pointer */ 35705b261ecSmrg if (pPixmap->devPrivate.ptr == NULL) { 35805b261ecSmrg ExaPixmapPriv (pPixmap); 35905b261ecSmrg 36005b261ecSmrg pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 36105b261ecSmrg } 36205b261ecSmrg 36305b261ecSmrg if (pExaScr->info->PrepareAccess == NULL) 36405b261ecSmrg return; 36505b261ecSmrg 36605b261ecSmrg if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 36705b261ecSmrg ExaPixmapPriv (pPixmap); 36805b261ecSmrg if (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED) 36905b261ecSmrg FatalError("Driver failed PrepareAccess on a pinned pixmap\n"); 37005b261ecSmrg exaMoveOutPixmap (pPixmap); 37105b261ecSmrg } 37205b261ecSmrg} 37305b261ecSmrg 37405b261ecSmrg/** 37505b261ecSmrg * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 37605b261ecSmrg * 37705b261ecSmrg * It deals with calling the driver's FinishAccess() only if necessary. 37805b261ecSmrg */ 37905b261ecSmrgvoid 38005b261ecSmrgexaFinishAccess(DrawablePtr pDrawable, int index) 38105b261ecSmrg{ 38205b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 38305b261ecSmrg ExaScreenPriv (pScreen); 38405b261ecSmrg PixmapPtr pPixmap; 38505b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 38605b261ecSmrg 38705b261ecSmrg pPixmap = exaGetDrawablePixmap (pDrawable); 38805b261ecSmrg 38905b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 39005b261ecSmrg 39105b261ecSmrg /* Rehide pixmap pointer if we're doing that. */ 39205b261ecSmrg if (pExaPixmap != NULL && pExaScr->hideOffscreenPixmapData && 39305b261ecSmrg pExaPixmap->fb_ptr == pPixmap->devPrivate.ptr) 39405b261ecSmrg { 39505b261ecSmrg pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 39605b261ecSmrg } 39705b261ecSmrg 39805b261ecSmrg if (pExaScr->info->FinishAccess == NULL) 39905b261ecSmrg return; 40005b261ecSmrg 40105b261ecSmrg if (!exaPixmapIsOffscreen (pPixmap)) 40205b261ecSmrg return; 40305b261ecSmrg 40405b261ecSmrg (*pExaScr->info->FinishAccess) (pPixmap, index); 40505b261ecSmrg} 40605b261ecSmrg 40705b261ecSmrg/** 40805b261ecSmrg * exaValidateGC() sets the ops to EXA's implementations, which may be 40905b261ecSmrg * accelerated or may sync the card and fall back to fb. 41005b261ecSmrg */ 41105b261ecSmrgstatic void 41205b261ecSmrgexaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 41305b261ecSmrg{ 41405b261ecSmrg /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 41505b261ecSmrg * Preempt fbValidateGC by doing its work and masking the change out, so 41605b261ecSmrg * that we can do the Prepare/FinishAccess. 41705b261ecSmrg */ 41805b261ecSmrg#ifdef FB_24_32BIT 41905b261ecSmrg if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 42005b261ecSmrg (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 42105b261ecSmrg fbGetRotatedPixmap(pGC) = 0; 42205b261ecSmrg } 42305b261ecSmrg 42405b261ecSmrg if (pGC->fillStyle == FillTiled) { 42505b261ecSmrg PixmapPtr pOldTile, pNewTile; 42605b261ecSmrg 42705b261ecSmrg pOldTile = pGC->tile.pixmap; 42805b261ecSmrg if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 42905b261ecSmrg { 43005b261ecSmrg pNewTile = fbGetRotatedPixmap(pGC); 43105b261ecSmrg if (!pNewTile || 43205b261ecSmrg pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 43305b261ecSmrg { 43405b261ecSmrg if (pNewTile) 43505b261ecSmrg (*pGC->pScreen->DestroyPixmap) (pNewTile); 43605b261ecSmrg /* fb24_32ReformatTile will do direct access of a newly- 43705b261ecSmrg * allocated pixmap. This isn't a problem yet, since we don't 43805b261ecSmrg * put pixmaps in FB until at least one accelerated EXA op. 43905b261ecSmrg */ 44005b261ecSmrg exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 44105b261ecSmrg pNewTile = fb24_32ReformatTile (pOldTile, 44205b261ecSmrg pDrawable->bitsPerPixel); 44305b261ecSmrg exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); 44405b261ecSmrg exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 44505b261ecSmrg } 44605b261ecSmrg if (pNewTile) 44705b261ecSmrg { 44805b261ecSmrg fbGetRotatedPixmap(pGC) = pOldTile; 44905b261ecSmrg pGC->tile.pixmap = pNewTile; 45005b261ecSmrg changes |= GCTile; 45105b261ecSmrg } 45205b261ecSmrg } 45305b261ecSmrg } 45405b261ecSmrg#endif 45505b261ecSmrg if (changes & GCTile) { 45605b261ecSmrg if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 45705b261ecSmrg pDrawable->bitsPerPixel)) 45805b261ecSmrg { 45905b261ecSmrg /* XXX This fixes corruption with tiled pixmaps, but may just be a 46005b261ecSmrg * workaround for broken drivers 46105b261ecSmrg */ 46205b261ecSmrg exaMoveOutPixmap(pGC->tile.pixmap); 46305b261ecSmrg fbPadPixmap (pGC->tile.pixmap); 46405b261ecSmrg exaPixmapDirty(pGC->tile.pixmap, 0, 0, 46505b261ecSmrg pGC->tile.pixmap->drawable.width, 46605b261ecSmrg pGC->tile.pixmap->drawable.height); 46705b261ecSmrg } 46805b261ecSmrg /* Mask out the GCTile change notification, now that we've done FB's 46905b261ecSmrg * job for it. 47005b261ecSmrg */ 47105b261ecSmrg changes &= ~GCTile; 47205b261ecSmrg } 47305b261ecSmrg 47405b261ecSmrg fbValidateGC (pGC, changes, pDrawable); 47505b261ecSmrg 47605b261ecSmrg pGC->ops = (GCOps *) &exaOps; 47705b261ecSmrg} 47805b261ecSmrg 47905b261ecSmrgstatic GCFuncs exaGCFuncs = { 48005b261ecSmrg exaValidateGC, 48105b261ecSmrg miChangeGC, 48205b261ecSmrg miCopyGC, 48305b261ecSmrg miDestroyGC, 48405b261ecSmrg miChangeClip, 48505b261ecSmrg miDestroyClip, 48605b261ecSmrg miCopyClip 48705b261ecSmrg}; 48805b261ecSmrg 48905b261ecSmrg/** 49005b261ecSmrg * exaCreateGC makes a new GC and hooks up its funcs handler, so that 49105b261ecSmrg * exaValidateGC() will get called. 49205b261ecSmrg */ 49305b261ecSmrgstatic int 49405b261ecSmrgexaCreateGC (GCPtr pGC) 49505b261ecSmrg{ 49605b261ecSmrg if (!fbCreateGC (pGC)) 49705b261ecSmrg return FALSE; 49805b261ecSmrg 49905b261ecSmrg pGC->funcs = &exaGCFuncs; 50005b261ecSmrg 50105b261ecSmrg return TRUE; 50205b261ecSmrg} 50305b261ecSmrg 50405b261ecSmrg/** 50505b261ecSmrg * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 50605b261ecSmrg * screen private, before calling down to the next CloseSccreen. 50705b261ecSmrg */ 50805b261ecSmrgstatic Bool 50905b261ecSmrgexaCloseScreen(int i, ScreenPtr pScreen) 51005b261ecSmrg{ 51105b261ecSmrg ExaScreenPriv(pScreen); 51205b261ecSmrg#ifdef RENDER 51305b261ecSmrg PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 51405b261ecSmrg#endif 51505b261ecSmrg 51605b261ecSmrg pScreen->CreateGC = pExaScr->SavedCreateGC; 51705b261ecSmrg pScreen->CloseScreen = pExaScr->SavedCloseScreen; 51805b261ecSmrg pScreen->GetImage = pExaScr->SavedGetImage; 51905b261ecSmrg pScreen->GetSpans = pExaScr->SavedGetSpans; 52005b261ecSmrg pScreen->PaintWindowBackground = pExaScr->SavedPaintWindowBackground; 52105b261ecSmrg pScreen->PaintWindowBorder = pExaScr->SavedPaintWindowBorder; 52205b261ecSmrg pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; 52305b261ecSmrg pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap; 52405b261ecSmrg pScreen->CopyWindow = pExaScr->SavedCopyWindow; 52505b261ecSmrg#ifdef RENDER 52605b261ecSmrg if (ps) { 52705b261ecSmrg ps->Composite = pExaScr->SavedComposite; 52805b261ecSmrg ps->Glyphs = pExaScr->SavedGlyphs; 52905b261ecSmrg ps->Trapezoids = pExaScr->SavedTrapezoids; 53005b261ecSmrg } 53105b261ecSmrg#endif 53205b261ecSmrg 53305b261ecSmrg xfree (pExaScr); 53405b261ecSmrg 53505b261ecSmrg return (*pScreen->CloseScreen) (i, pScreen); 53605b261ecSmrg} 53705b261ecSmrg 53805b261ecSmrg/** 53905b261ecSmrg * This function allocates a driver structure for EXA drivers to fill in. By 54005b261ecSmrg * having EXA allocate the structure, the driver structure can be extended 54105b261ecSmrg * without breaking ABI between EXA and the drivers. The driver's 54205b261ecSmrg * responsibility is to check beforehand that the EXA module has a matching 54305b261ecSmrg * major number and sufficient minor. Drivers are responsible for freeing the 54405b261ecSmrg * driver structure using xfree(). 54505b261ecSmrg * 54605b261ecSmrg * @return a newly allocated, zero-filled driver structure 54705b261ecSmrg */ 54805b261ecSmrgExaDriverPtr 54905b261ecSmrgexaDriverAlloc(void) 55005b261ecSmrg{ 55105b261ecSmrg return xcalloc(1, sizeof(ExaDriverRec)); 55205b261ecSmrg} 55305b261ecSmrg 55405b261ecSmrg/** 55505b261ecSmrg * @param pScreen screen being initialized 55605b261ecSmrg * @param pScreenInfo EXA driver record 55705b261ecSmrg * 55805b261ecSmrg * exaDriverInit sets up EXA given a driver record filled in by the driver. 55905b261ecSmrg * pScreenInfo should have been allocated by exaDriverAlloc(). See the 56005b261ecSmrg * comments in _ExaDriver for what must be filled in and what is optional. 56105b261ecSmrg * 56205b261ecSmrg * @return TRUE if EXA was successfully initialized. 56305b261ecSmrg */ 56405b261ecSmrgBool 56505b261ecSmrgexaDriverInit (ScreenPtr pScreen, 56605b261ecSmrg ExaDriverPtr pScreenInfo) 56705b261ecSmrg{ 56805b261ecSmrg ExaScreenPrivPtr pExaScr; 56905b261ecSmrg#ifdef RENDER 57005b261ecSmrg PictureScreenPtr ps; 57105b261ecSmrg#endif 57205b261ecSmrg 57305b261ecSmrg if (!pScreenInfo) 57405b261ecSmrg return FALSE; 57505b261ecSmrg 57605b261ecSmrg if (!pScreenInfo->memoryBase) { 57705b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase must be " 57805b261ecSmrg "non-zero\n", pScreen->myNum); 57905b261ecSmrg return FALSE; 58005b261ecSmrg } 58105b261ecSmrg 58205b261ecSmrg if (!pScreenInfo->memorySize) { 58305b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 58405b261ecSmrg "non-zero\n", pScreen->myNum); 58505b261ecSmrg return FALSE; 58605b261ecSmrg } 58705b261ecSmrg 58805b261ecSmrg if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 58905b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must be <= " 59005b261ecSmrg "ExaDriverRec::memorySize\n", pScreen->myNum); 59105b261ecSmrg return FALSE; 59205b261ecSmrg } 59305b261ecSmrg 59405b261ecSmrg if (!pScreenInfo->PrepareSolid) { 59505b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 59605b261ecSmrg "non-NULL\n", pScreen->myNum); 59705b261ecSmrg return FALSE; 59805b261ecSmrg } 59905b261ecSmrg 60005b261ecSmrg if (!pScreenInfo->PrepareCopy) { 60105b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 60205b261ecSmrg "non-NULL\n", pScreen->myNum); 60305b261ecSmrg return FALSE; 60405b261ecSmrg } 60505b261ecSmrg 60605b261ecSmrg if (!pScreenInfo->WaitMarker) { 60705b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 60805b261ecSmrg "non-NULL\n", pScreen->myNum); 60905b261ecSmrg return FALSE; 61005b261ecSmrg } 61105b261ecSmrg 61205b261ecSmrg if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 61305b261ecSmrg pScreenInfo->exa_minor > EXA_VERSION_MINOR) 61405b261ecSmrg { 61505b261ecSmrg LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 61605b261ecSmrg "(%d.%d) are incompatible with EXA version (%d.%d)\n", 61705b261ecSmrg pScreen->myNum, 61805b261ecSmrg pScreenInfo->exa_major, pScreenInfo->exa_minor, 61905b261ecSmrg EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 62005b261ecSmrg return FALSE; 62105b261ecSmrg } 62205b261ecSmrg 62305b261ecSmrg#ifdef RENDER 62405b261ecSmrg ps = GetPictureScreenIfSet(pScreen); 62505b261ecSmrg#endif 62605b261ecSmrg if (exaGeneration != serverGeneration) 62705b261ecSmrg { 62805b261ecSmrg exaScreenPrivateIndex = AllocateScreenPrivateIndex(); 62905b261ecSmrg exaPixmapPrivateIndex = AllocatePixmapPrivateIndex(); 63005b261ecSmrg exaGeneration = serverGeneration; 63105b261ecSmrg } 63205b261ecSmrg 63305b261ecSmrg pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1); 63405b261ecSmrg 63505b261ecSmrg if (!pExaScr) { 63605b261ecSmrg LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 63705b261ecSmrg pScreen->myNum); 63805b261ecSmrg return FALSE; 63905b261ecSmrg } 64005b261ecSmrg 64105b261ecSmrg pExaScr->info = pScreenInfo; 64205b261ecSmrg 64305b261ecSmrg pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr; 64405b261ecSmrg 64505b261ecSmrg pExaScr->migration = ExaMigrationAlways; 64605b261ecSmrg 64705b261ecSmrg exaDDXDriverInit(pScreen); 64805b261ecSmrg 64905b261ecSmrg /* 65005b261ecSmrg * Replace various fb screen functions 65105b261ecSmrg */ 65205b261ecSmrg pExaScr->SavedCloseScreen = pScreen->CloseScreen; 65305b261ecSmrg pScreen->CloseScreen = exaCloseScreen; 65405b261ecSmrg 65505b261ecSmrg pExaScr->SavedCreateGC = pScreen->CreateGC; 65605b261ecSmrg pScreen->CreateGC = exaCreateGC; 65705b261ecSmrg 65805b261ecSmrg pExaScr->SavedGetImage = pScreen->GetImage; 65905b261ecSmrg pScreen->GetImage = exaGetImage; 66005b261ecSmrg 66105b261ecSmrg pExaScr->SavedGetSpans = pScreen->GetSpans; 66205b261ecSmrg pScreen->GetSpans = exaGetSpans; 66305b261ecSmrg 66405b261ecSmrg pExaScr->SavedCopyWindow = pScreen->CopyWindow; 66505b261ecSmrg pScreen->CopyWindow = exaCopyWindow; 66605b261ecSmrg 66705b261ecSmrg pExaScr->SavedPaintWindowBackground = pScreen->PaintWindowBackground; 66805b261ecSmrg pScreen->PaintWindowBackground = exaPaintWindow; 66905b261ecSmrg 67005b261ecSmrg pExaScr->SavedPaintWindowBorder = pScreen->PaintWindowBorder; 67105b261ecSmrg pScreen->PaintWindowBorder = exaPaintWindow; 67205b261ecSmrg 67305b261ecSmrg pScreen->BackingStoreFuncs.SaveAreas = ExaCheckSaveAreas; 67405b261ecSmrg pScreen->BackingStoreFuncs.RestoreAreas = ExaCheckRestoreAreas; 67505b261ecSmrg#ifdef RENDER 67605b261ecSmrg if (ps) { 67705b261ecSmrg pExaScr->SavedComposite = ps->Composite; 67805b261ecSmrg ps->Composite = exaComposite; 67905b261ecSmrg 68005b261ecSmrg pExaScr->SavedRasterizeTrapezoid = ps->RasterizeTrapezoid; 68105b261ecSmrg ps->RasterizeTrapezoid = exaRasterizeTrapezoid; 68205b261ecSmrg 68305b261ecSmrg pExaScr->SavedAddTriangles = ps->AddTriangles; 68405b261ecSmrg ps->AddTriangles = exaAddTriangles; 68505b261ecSmrg 68605b261ecSmrg pExaScr->SavedGlyphs = ps->Glyphs; 68705b261ecSmrg ps->Glyphs = exaGlyphs; 68805b261ecSmrg 68905b261ecSmrg pExaScr->SavedTrapezoids = ps->Trapezoids; 69005b261ecSmrg ps->Trapezoids = exaTrapezoids; 69105b261ecSmrg } 69205b261ecSmrg#endif 69305b261ecSmrg 69405b261ecSmrg#ifdef MITSHM 69505b261ecSmrg /* Re-register with the MI funcs, which don't allow shared pixmaps. 69605b261ecSmrg * Shared pixmaps are almost always a performance loss for us, but this 69705b261ecSmrg * still allows for SHM PutImage. 69805b261ecSmrg */ 69905b261ecSmrg ShmRegisterFuncs(pScreen, NULL); 70005b261ecSmrg#endif 70105b261ecSmrg /* 70205b261ecSmrg * Hookup offscreen pixmaps 70305b261ecSmrg */ 70405b261ecSmrg if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 70505b261ecSmrg pExaScr->info->offScreenBase < pExaScr->info->memorySize) 70605b261ecSmrg { 70705b261ecSmrg if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 70805b261ecSmrg sizeof (ExaPixmapPrivRec))) { 70905b261ecSmrg LogMessage(X_WARNING, 71005b261ecSmrg "EXA(%d): Failed to allocate pixmap private\n", 71105b261ecSmrg pScreen->myNum); 71205b261ecSmrg return FALSE; 71305b261ecSmrg } 71405b261ecSmrg pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; 71505b261ecSmrg pScreen->CreatePixmap = exaCreatePixmap; 71605b261ecSmrg 71705b261ecSmrg pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap; 71805b261ecSmrg pScreen->DestroyPixmap = exaDestroyPixmap; 71905b261ecSmrg 72005b261ecSmrg LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n", 72105b261ecSmrg pScreen->myNum, 72205b261ecSmrg pExaScr->info->memorySize - pExaScr->info->offScreenBase); 72305b261ecSmrg } 72405b261ecSmrg else 72505b261ecSmrg { 72605b261ecSmrg LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 72705b261ecSmrg if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 0)) 72805b261ecSmrg return FALSE; 72905b261ecSmrg } 73005b261ecSmrg 73105b261ecSmrg DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 73205b261ecSmrg pExaScr->info->memorySize)); 73305b261ecSmrg if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 73405b261ecSmrg if (!exaOffscreenInit (pScreen)) { 73505b261ecSmrg LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", 73605b261ecSmrg pScreen->myNum); 73705b261ecSmrg return FALSE; 73805b261ecSmrg } 73905b261ecSmrg } 74005b261ecSmrg 74105b261ecSmrg LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 74205b261ecSmrg " operations:\n", pScreen->myNum); 74305b261ecSmrg assert(pScreenInfo->PrepareSolid != NULL); 74405b261ecSmrg LogMessage(X_INFO, " Solid\n"); 74505b261ecSmrg assert(pScreenInfo->PrepareCopy != NULL); 74605b261ecSmrg LogMessage(X_INFO, " Copy\n"); 74705b261ecSmrg if (pScreenInfo->PrepareComposite != NULL) { 74805b261ecSmrg LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 74905b261ecSmrg } 75005b261ecSmrg if (pScreenInfo->UploadToScreen != NULL) { 75105b261ecSmrg LogMessage(X_INFO, " UploadToScreen\n"); 75205b261ecSmrg } 75305b261ecSmrg if (pScreenInfo->DownloadFromScreen != NULL) { 75405b261ecSmrg LogMessage(X_INFO, " DownloadFromScreen\n"); 75505b261ecSmrg } 75605b261ecSmrg 75705b261ecSmrg return TRUE; 75805b261ecSmrg} 75905b261ecSmrg 76005b261ecSmrg/** 76105b261ecSmrg * exaDriverFini tears down EXA on a given screen. 76205b261ecSmrg * 76305b261ecSmrg * @param pScreen screen being torn down. 76405b261ecSmrg */ 76505b261ecSmrgvoid 76605b261ecSmrgexaDriverFini (ScreenPtr pScreen) 76705b261ecSmrg{ 76805b261ecSmrg /*right now does nothing*/ 76905b261ecSmrg} 77005b261ecSmrg 77105b261ecSmrg/** 77205b261ecSmrg * exaMarkSync() should be called after any asynchronous drawing by the hardware. 77305b261ecSmrg * 77405b261ecSmrg * @param pScreen screen which drawing occurred on 77505b261ecSmrg * 77605b261ecSmrg * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 77705b261ecSmrg * happened and a WaitSync() will be necessary before relying on the contents of 77805b261ecSmrg * offscreen memory from the CPU's perspective. It also calls an optional 77905b261ecSmrg * driver MarkSync() callback, the return value of which may be used to do partial 78005b261ecSmrg * synchronization with the hardware in the future. 78105b261ecSmrg */ 78205b261ecSmrgvoid exaMarkSync(ScreenPtr pScreen) 78305b261ecSmrg{ 78405b261ecSmrg ExaScreenPriv(pScreen); 78505b261ecSmrg 78605b261ecSmrg pExaScr->info->needsSync = TRUE; 78705b261ecSmrg if (pExaScr->info->MarkSync != NULL) { 78805b261ecSmrg pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); 78905b261ecSmrg } 79005b261ecSmrg} 79105b261ecSmrg 79205b261ecSmrg/** 79305b261ecSmrg * exaWaitSync() ensures that all drawing has been completed. 79405b261ecSmrg * 79505b261ecSmrg * @param pScreen screen being synchronized. 79605b261ecSmrg * 79705b261ecSmrg * Calls down into the driver to ensure that all previous drawing has completed. 79805b261ecSmrg * It should always be called before relying on the framebuffer contents 79905b261ecSmrg * reflecting previous drawing, from a CPU perspective. 80005b261ecSmrg */ 80105b261ecSmrgvoid exaWaitSync(ScreenPtr pScreen) 80205b261ecSmrg{ 80305b261ecSmrg ExaScreenPriv(pScreen); 80405b261ecSmrg 80505b261ecSmrg if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 80605b261ecSmrg (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 80705b261ecSmrg pExaScr->info->needsSync = FALSE; 80805b261ecSmrg } 80905b261ecSmrg} 810