exa.c revision 4642e01f
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 404642e01fSmrgstatic int exaScreenPrivateKeyIndex; 414642e01fSmrgDevPrivateKey exaScreenPrivateKey = &exaScreenPrivateKeyIndex; 424642e01fSmrgstatic int exaPixmapPrivateKeyIndex; 434642e01fSmrgDevPrivateKey exaPixmapPrivateKey = &exaPixmapPrivateKeyIndex; 444642e01fSmrg 454642e01fSmrg#ifdef MITSHM 464642e01fSmrgstatic ShmFuncs exaShmFuncs = { NULL, NULL }; 474642e01fSmrg#endif 484642e01fSmrg 494642e01fSmrgstatic _X_INLINE void* 504642e01fSmrgExaGetPixmapAddress(PixmapPtr p) 514642e01fSmrg{ 524642e01fSmrg ExaPixmapPriv(p); 534642e01fSmrg 544642e01fSmrg if (pExaPixmap->offscreen && pExaPixmap->fb_ptr) 554642e01fSmrg return pExaPixmap->fb_ptr; 564642e01fSmrg else 574642e01fSmrg return pExaPixmap->sys_ptr; 584642e01fSmrg} 5905b261ecSmrg 6005b261ecSmrg/** 6105b261ecSmrg * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 6205b261ecSmrg * the beginning of the given pixmap. 6305b261ecSmrg * 6405b261ecSmrg * Note that drivers are free to, and often do, munge this offset as necessary 6505b261ecSmrg * for handing to the hardware -- for example, translating it into a different 6605b261ecSmrg * aperture. This function may need to be extended in the future if we grow 6705b261ecSmrg * support for having multiple card-accessible offscreen, such as an AGP memory 6805b261ecSmrg * pool alongside the framebuffer pool. 6905b261ecSmrg */ 7005b261ecSmrgunsigned long 7105b261ecSmrgexaGetPixmapOffset(PixmapPtr pPix) 7205b261ecSmrg{ 7305b261ecSmrg ExaScreenPriv (pPix->drawable.pScreen); 7405b261ecSmrg 754642e01fSmrg return ((unsigned long)ExaGetPixmapAddress(pPix) - 764642e01fSmrg (unsigned long)pExaScr->info->memoryBase); 774642e01fSmrg} 7805b261ecSmrg 794642e01fSmrgvoid * 804642e01fSmrgexaGetPixmapDriverPrivate(PixmapPtr pPix) 814642e01fSmrg{ 824642e01fSmrg ExaPixmapPriv(pPix); 834642e01fSmrg 844642e01fSmrg return pExaPixmap->driverPriv; 8505b261ecSmrg} 8605b261ecSmrg 8705b261ecSmrg/** 8805b261ecSmrg * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 8905b261ecSmrg * 9005b261ecSmrg * This is a helper to make driver code more obvious, due to the rather obscure 9105b261ecSmrg * naming of the pitch field in the pixmap. 9205b261ecSmrg */ 9305b261ecSmrgunsigned long 9405b261ecSmrgexaGetPixmapPitch(PixmapPtr pPix) 9505b261ecSmrg{ 9605b261ecSmrg return pPix->devKind; 9705b261ecSmrg} 9805b261ecSmrg 9905b261ecSmrg/** 10005b261ecSmrg * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 10105b261ecSmrg * memory. Only valid when the pixmap is currently in framebuffer. 10205b261ecSmrg */ 10305b261ecSmrgunsigned long 10405b261ecSmrgexaGetPixmapSize(PixmapPtr pPix) 10505b261ecSmrg{ 10605b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 10705b261ecSmrg 10805b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPix); 10905b261ecSmrg if (pExaPixmap != NULL) 11005b261ecSmrg return pExaPixmap->fb_size; 11105b261ecSmrg return 0; 11205b261ecSmrg} 11305b261ecSmrg 11405b261ecSmrg/** 11505b261ecSmrg * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 11605b261ecSmrg * 11705b261ecSmrg * @param pDrawable the drawable being requested. 11805b261ecSmrg * 11905b261ecSmrg * This function returns the backing pixmap for a drawable, whether it is a 12005b261ecSmrg * redirected window, unredirected window, or already a pixmap. Note that 12105b261ecSmrg * coordinate translation is needed when drawing to the backing pixmap of a 12205b261ecSmrg * redirected window, and the translation coordinates are provided by calling 12305b261ecSmrg * exaGetOffscreenPixmap() on the drawable. 12405b261ecSmrg */ 12505b261ecSmrgPixmapPtr 12605b261ecSmrgexaGetDrawablePixmap(DrawablePtr pDrawable) 12705b261ecSmrg{ 12805b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) 12905b261ecSmrg return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 13005b261ecSmrg else 13105b261ecSmrg return (PixmapPtr) pDrawable; 13205b261ecSmrg} 13305b261ecSmrg 13405b261ecSmrg/** 13505b261ecSmrg * Sets the offsets to add to coordinates to make them address the same bits in 13605b261ecSmrg * the backing drawable. These coordinates are nonzero only for redirected 13705b261ecSmrg * windows. 13805b261ecSmrg */ 13905b261ecSmrgvoid 14005b261ecSmrgexaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 14105b261ecSmrg int *xp, int *yp) 14205b261ecSmrg{ 14305b261ecSmrg#ifdef COMPOSITE 14405b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 14505b261ecSmrg *xp = -pPixmap->screen_x; 14605b261ecSmrg *yp = -pPixmap->screen_y; 14705b261ecSmrg return; 14805b261ecSmrg } 14905b261ecSmrg#endif 15005b261ecSmrg 15105b261ecSmrg *xp = 0; 15205b261ecSmrg *yp = 0; 15305b261ecSmrg} 15405b261ecSmrg 15505b261ecSmrg/** 15605b261ecSmrg * exaPixmapDirty() marks a pixmap as dirty, allowing for 15705b261ecSmrg * optimizations in pixmap migration when no changes have occurred. 15805b261ecSmrg */ 15905b261ecSmrgvoid 16005b261ecSmrgexaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 16105b261ecSmrg{ 16205b261ecSmrg ExaPixmapPriv(pPix); 16305b261ecSmrg BoxRec box; 16405b261ecSmrg RegionPtr pDamageReg; 16505b261ecSmrg RegionRec region; 16605b261ecSmrg 1674642e01fSmrg if (!pExaPixmap || !pExaPixmap->pDamage) 16805b261ecSmrg return; 16905b261ecSmrg 17005b261ecSmrg box.x1 = max(x1, 0); 17105b261ecSmrg box.y1 = max(y1, 0); 17205b261ecSmrg box.x2 = min(x2, pPix->drawable.width); 17305b261ecSmrg box.y2 = min(y2, pPix->drawable.height); 17405b261ecSmrg 17505b261ecSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 17605b261ecSmrg return; 17705b261ecSmrg 17805b261ecSmrg pDamageReg = DamageRegion(pExaPixmap->pDamage); 17905b261ecSmrg 18005b261ecSmrg REGION_INIT(pScreen, ®ion, &box, 1); 18105b261ecSmrg REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); 18205b261ecSmrg REGION_UNINIT(pScreen, ®ion); 18305b261ecSmrg} 18405b261ecSmrg 18505b261ecSmrgstatic Bool 18605b261ecSmrgexaDestroyPixmap (PixmapPtr pPixmap) 18705b261ecSmrg{ 1884642e01fSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 1894642e01fSmrg ExaScreenPriv(pScreen); 1904642e01fSmrg 19105b261ecSmrg if (pPixmap->refcnt == 1) 19205b261ecSmrg { 19305b261ecSmrg ExaPixmapPriv (pPixmap); 1944642e01fSmrg 1954642e01fSmrg if (pExaPixmap->driverPriv) { 1964642e01fSmrg pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 1974642e01fSmrg pExaPixmap->driverPriv = NULL; 1984642e01fSmrg } 1994642e01fSmrg 20005b261ecSmrg if (pExaPixmap->area) 20105b261ecSmrg { 20205b261ecSmrg DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 20305b261ecSmrg (void*)pPixmap->drawable.id, 20405b261ecSmrg ExaGetPixmapPriv(pPixmap)->area->offset, 20505b261ecSmrg pPixmap->drawable.width, 20605b261ecSmrg pPixmap->drawable.height)); 20705b261ecSmrg /* Free the offscreen area */ 20805b261ecSmrg exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 20905b261ecSmrg pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 21005b261ecSmrg pPixmap->devKind = pExaPixmap->sys_pitch; 21105b261ecSmrg } 2124642e01fSmrg REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys); 2134642e01fSmrg REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB); 21405b261ecSmrg } 21505b261ecSmrg return fbDestroyPixmap (pPixmap); 21605b261ecSmrg} 21705b261ecSmrg 21805b261ecSmrgstatic int 21905b261ecSmrgexaLog2(int val) 22005b261ecSmrg{ 22105b261ecSmrg int bits; 22205b261ecSmrg 22305b261ecSmrg if (val <= 0) 22405b261ecSmrg return 0; 22505b261ecSmrg for (bits = 0; val != 0; bits++) 22605b261ecSmrg val >>= 1; 22705b261ecSmrg return bits - 1; 22805b261ecSmrg} 22905b261ecSmrg 2304642e01fSmrgstatic void 2314642e01fSmrgexaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 2324642e01fSmrg int w, int h, int bpp) 2334642e01fSmrg{ 2344642e01fSmrg pExaPixmap->accel_blocked = 0; 2354642e01fSmrg 2364642e01fSmrg if (pExaScr->info->maxPitchPixels) { 2374642e01fSmrg int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8; 2384642e01fSmrg 2394642e01fSmrg if (pExaPixmap->fb_pitch > max_pitch) 2404642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 2414642e01fSmrg } 2424642e01fSmrg 2434642e01fSmrg if (pExaScr->info->maxPitchBytes && 2444642e01fSmrg pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) 2454642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 2464642e01fSmrg 2474642e01fSmrg if (w > pExaScr->info->maxX) 2484642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; 2494642e01fSmrg 2504642e01fSmrg if (h > pExaScr->info->maxY) 2514642e01fSmrg pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; 2524642e01fSmrg} 2534642e01fSmrg 2544642e01fSmrgstatic void 2554642e01fSmrgexaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 2564642e01fSmrg int w, int h, int bpp) 2574642e01fSmrg{ 2584642e01fSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 2594642e01fSmrg pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; 2604642e01fSmrg else 2614642e01fSmrg pExaPixmap->fb_pitch = w * bpp / 8; 2624642e01fSmrg 2634642e01fSmrg pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 2644642e01fSmrg pExaScr->info->pixmapPitchAlign); 2654642e01fSmrg} 2664642e01fSmrg 26705b261ecSmrg/** 26805b261ecSmrg * exaCreatePixmap() creates a new pixmap. 26905b261ecSmrg * 27005b261ecSmrg * If width and height are 0, this won't be a full-fledged pixmap and it will 27105b261ecSmrg * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because 27205b261ecSmrg * ModifyPixmapHeader() would break migration. These types of pixmaps are used 27305b261ecSmrg * for scratch pixmaps, or to represent the visible screen. 27405b261ecSmrg */ 27505b261ecSmrgstatic PixmapPtr 2764642e01fSmrgexaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, 2774642e01fSmrg unsigned usage_hint) 27805b261ecSmrg{ 27905b261ecSmrg PixmapPtr pPixmap; 28005b261ecSmrg ExaPixmapPrivPtr pExaPixmap; 2814642e01fSmrg int driver_alloc = 0; 28205b261ecSmrg int bpp; 28305b261ecSmrg ExaScreenPriv(pScreen); 28405b261ecSmrg 28505b261ecSmrg if (w > 32767 || h > 32767) 28605b261ecSmrg return NullPixmap; 28705b261ecSmrg 2884642e01fSmrg if (!pExaScr->info->CreatePixmap) { 2894642e01fSmrg pPixmap = fbCreatePixmap (pScreen, w, h, depth, usage_hint); 2904642e01fSmrg } else { 2914642e01fSmrg driver_alloc = 1; 2924642e01fSmrg pPixmap = fbCreatePixmap(pScreen, 0, 0, depth, usage_hint); 2934642e01fSmrg } 2944642e01fSmrg 29505b261ecSmrg if (!pPixmap) 2964642e01fSmrg return NULL; 2974642e01fSmrg 29805b261ecSmrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 2994642e01fSmrg pExaPixmap->driverPriv = NULL; 30005b261ecSmrg 30105b261ecSmrg bpp = pPixmap->drawable.bitsPerPixel; 30205b261ecSmrg 3034642e01fSmrg if (driver_alloc) { 3044642e01fSmrg size_t paddedWidth, datasize; 30505b261ecSmrg 3064642e01fSmrg paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 3074642e01fSmrg if (paddedWidth / 4 > 32767 || h > 32767) 3084642e01fSmrg return NullPixmap; 30905b261ecSmrg 3104642e01fSmrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 31105b261ecSmrg 3124642e01fSmrg if (paddedWidth < pExaPixmap->fb_pitch) 3134642e01fSmrg paddedWidth = pExaPixmap->fb_pitch; 31405b261ecSmrg 3154642e01fSmrg datasize = h * paddedWidth; 31605b261ecSmrg 3174642e01fSmrg /* Set this before driver hooks, to allow for !offscreen pixmaps. 3184642e01fSmrg * !offscreen pixmaps have a valid pointer at all times. 3194642e01fSmrg */ 3204642e01fSmrg pPixmap->devPrivate.ptr = NULL; 32105b261ecSmrg 3224642e01fSmrg pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0); 3234642e01fSmrg if (!pExaPixmap->driverPriv) { 3244642e01fSmrg fbDestroyPixmap(pPixmap); 3254642e01fSmrg return NULL; 3264642e01fSmrg } 3274642e01fSmrg 3284642e01fSmrg (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 3294642e01fSmrg paddedWidth, NULL); 3304642e01fSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 3314642e01fSmrg pExaPixmap->fb_ptr = NULL; 3324642e01fSmrg pExaPixmap->pDamage = NULL; 3334642e01fSmrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 3344642e01fSmrg 3354642e01fSmrg } else { 3364642e01fSmrg pExaPixmap->driverPriv = NULL; 3374642e01fSmrg /* Scratch pixmaps may have w/h equal to zero, and may not be 3384642e01fSmrg * migrated. 3394642e01fSmrg */ 3404642e01fSmrg if (!w || !h) 3414642e01fSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 3424642e01fSmrg else 3434642e01fSmrg pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 3444642e01fSmrg 3454642e01fSmrg pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 3464642e01fSmrg pExaPixmap->sys_pitch = pPixmap->devKind; 34705b261ecSmrg 3484642e01fSmrg pPixmap->devPrivate.ptr = NULL; 3494642e01fSmrg pExaPixmap->offscreen = FALSE; 3504642e01fSmrg 3514642e01fSmrg pExaPixmap->fb_ptr = NULL; 3524642e01fSmrg exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 3534642e01fSmrg pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 3544642e01fSmrg 3554642e01fSmrg if (pExaPixmap->fb_pitch > 131071) { 3564642e01fSmrg fbDestroyPixmap(pPixmap); 3574642e01fSmrg return NULL; 3584642e01fSmrg } 3594642e01fSmrg 3604642e01fSmrg /* Set up damage tracking */ 3614642e01fSmrg pExaPixmap->pDamage = DamageCreate (NULL, NULL, 3624642e01fSmrg DamageReportNone, TRUE, 3634642e01fSmrg pScreen, pPixmap); 3644642e01fSmrg 3654642e01fSmrg if (pExaPixmap->pDamage == NULL) { 3664642e01fSmrg fbDestroyPixmap (pPixmap); 3674642e01fSmrg return NULL; 3684642e01fSmrg } 3694642e01fSmrg 3704642e01fSmrg DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); 3714642e01fSmrg /* This ensures that pending damage reflects the current operation. */ 3724642e01fSmrg /* This is used by exa to optimize migration. */ 3734642e01fSmrg DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); 3744642e01fSmrg } 3754642e01fSmrg 3764642e01fSmrg pExaPixmap->area = NULL; 37705b261ecSmrg 37805b261ecSmrg /* None of the pixmap bits are valid initially */ 3794642e01fSmrg REGION_NULL(pScreen, &pExaPixmap->validSys); 3804642e01fSmrg REGION_NULL(pScreen, &pExaPixmap->validFB); 3814642e01fSmrg 3824642e01fSmrg exaSetAccelBlock(pExaScr, pExaPixmap, 3834642e01fSmrg w, h, bpp); 38405b261ecSmrg 38505b261ecSmrg return pPixmap; 38605b261ecSmrg} 38705b261ecSmrg 3884642e01fSmrgstatic Bool 3894642e01fSmrgexaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, 3904642e01fSmrg int bitsPerPixel, int devKind, pointer pPixData) 3914642e01fSmrg{ 3924642e01fSmrg ExaScreenPrivPtr pExaScr; 3934642e01fSmrg ExaPixmapPrivPtr pExaPixmap; 3944642e01fSmrg Bool ret; 3954642e01fSmrg 3964642e01fSmrg if (!pPixmap) 3974642e01fSmrg return FALSE; 3984642e01fSmrg 3994642e01fSmrg pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen); 4004642e01fSmrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 4014642e01fSmrg 4024642e01fSmrg if (pExaPixmap) { 4034642e01fSmrg if (pPixData) 4044642e01fSmrg pExaPixmap->sys_ptr = pPixData; 4054642e01fSmrg 4064642e01fSmrg if (devKind > 0) 4074642e01fSmrg pExaPixmap->sys_pitch = devKind; 4084642e01fSmrg 4094642e01fSmrg if (width > 0 && height > 0 && bitsPerPixel > 0) { 4104642e01fSmrg exaSetFbPitch(pExaScr, pExaPixmap, 4114642e01fSmrg width, height, bitsPerPixel); 4124642e01fSmrg 4134642e01fSmrg exaSetAccelBlock(pExaScr, pExaPixmap, 4144642e01fSmrg width, height, bitsPerPixel); 4154642e01fSmrg } 4164642e01fSmrg } 4174642e01fSmrg 4184642e01fSmrg 4194642e01fSmrg if (pExaScr->info->ModifyPixmapHeader) { 4204642e01fSmrg ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 4214642e01fSmrg bitsPerPixel, devKind, pPixData); 4224642e01fSmrg if (ret == TRUE) 4234642e01fSmrg return ret; 4244642e01fSmrg } 4254642e01fSmrg return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth, 4264642e01fSmrg bitsPerPixel, devKind, pPixData); 4274642e01fSmrg} 4284642e01fSmrg 42905b261ecSmrg/** 43005b261ecSmrg * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen 43105b261ecSmrg * memory, meaning that acceleration could probably be done to it, and that it 43205b261ecSmrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 43305b261ecSmrg * with the CPU. 43405b261ecSmrg * 43505b261ecSmrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 43605b261ecSmrg * deal with moving pixmaps in and out of system memory), EXA will give drivers 43705b261ecSmrg * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE. 43805b261ecSmrg * 43905b261ecSmrg * @return TRUE if the given drawable is in framebuffer memory. 44005b261ecSmrg */ 44105b261ecSmrgBool 44205b261ecSmrgexaPixmapIsOffscreen(PixmapPtr p) 44305b261ecSmrg{ 44405b261ecSmrg ScreenPtr pScreen = p->drawable.pScreen; 44505b261ecSmrg ExaScreenPriv(pScreen); 4464642e01fSmrg ExaPixmapPriv(p); 4474642e01fSmrg void *save_ptr; 4484642e01fSmrg Bool ret; 44905b261ecSmrg 4504642e01fSmrg save_ptr = p->devPrivate.ptr; 4514642e01fSmrg 4524642e01fSmrg if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) 4534642e01fSmrg p->devPrivate.ptr = ExaGetPixmapAddress(p); 45405b261ecSmrg 45505b261ecSmrg if (pExaScr->info->PixmapIsOffscreen) 4564642e01fSmrg ret = pExaScr->info->PixmapIsOffscreen(p); 4574642e01fSmrg else 4584642e01fSmrg ret = ((unsigned long) ((CARD8 *) p->devPrivate.ptr - 4594642e01fSmrg (CARD8 *) pExaScr->info->memoryBase) < 4604642e01fSmrg pExaScr->info->memorySize); 46105b261ecSmrg 4624642e01fSmrg p->devPrivate.ptr = save_ptr; 4634642e01fSmrg 4644642e01fSmrg return ret; 46505b261ecSmrg} 46605b261ecSmrg 46705b261ecSmrg/** 46805b261ecSmrg * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen(). 46905b261ecSmrg */ 47005b261ecSmrgBool 47105b261ecSmrgexaDrawableIsOffscreen (DrawablePtr pDrawable) 47205b261ecSmrg{ 47305b261ecSmrg return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable)); 47405b261ecSmrg} 47505b261ecSmrg 47605b261ecSmrg/** 47705b261ecSmrg * Returns the pixmap which backs a drawable, and the offsets to add to 47805b261ecSmrg * coordinates to make them address the same bits in the backing drawable. 47905b261ecSmrg */ 48005b261ecSmrgPixmapPtr 48105b261ecSmrgexaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 48205b261ecSmrg{ 48305b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 48405b261ecSmrg 48505b261ecSmrg exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); 48605b261ecSmrg 48705b261ecSmrg if (exaPixmapIsOffscreen (pPixmap)) 48805b261ecSmrg return pPixmap; 48905b261ecSmrg else 49005b261ecSmrg return NULL; 49105b261ecSmrg} 49205b261ecSmrg 49305b261ecSmrgvoid 4944642e01fSmrgExaDoPrepareAccess(DrawablePtr pDrawable, int index) 49505b261ecSmrg{ 49605b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 49705b261ecSmrg ExaScreenPriv (pScreen); 4984642e01fSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 4994642e01fSmrg Bool offscreen = exaPixmapIsOffscreen(pPixmap); 50005b261ecSmrg 5014642e01fSmrg /* Unhide pixmap pointer */ 5024642e01fSmrg if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 5034642e01fSmrg pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 5044642e01fSmrg } 50505b261ecSmrg 5064642e01fSmrg if (!offscreen) 50705b261ecSmrg return; 50805b261ecSmrg 5094642e01fSmrg exaWaitSync (pDrawable->pScreen); 51005b261ecSmrg 51105b261ecSmrg if (pExaScr->info->PrepareAccess == NULL) 51205b261ecSmrg return; 51305b261ecSmrg 5144642e01fSmrg if (index >= EXA_PREPARE_AUX0 && 5154642e01fSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 5164642e01fSmrg exaMoveOutPixmap (pPixmap); 5174642e01fSmrg return; 5184642e01fSmrg } 5194642e01fSmrg 52005b261ecSmrg if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 52105b261ecSmrg ExaPixmapPriv (pPixmap); 5224642e01fSmrg if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 52305b261ecSmrg FatalError("Driver failed PrepareAccess on a pinned pixmap\n"); 52405b261ecSmrg exaMoveOutPixmap (pPixmap); 52505b261ecSmrg } 52605b261ecSmrg} 52705b261ecSmrg 5284642e01fSmrgvoid 5294642e01fSmrgexaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg) 5304642e01fSmrg{ 5314642e01fSmrg ExaMigrationRec pixmaps[1]; 5324642e01fSmrg 5334642e01fSmrg pixmaps[0].as_dst = index == EXA_PREPARE_DEST; 5344642e01fSmrg pixmaps[0].as_src = index != EXA_PREPARE_DEST; 5354642e01fSmrg pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); 5364642e01fSmrg pixmaps[0].pReg = pReg; 5374642e01fSmrg 5384642e01fSmrg exaDoMigration(pixmaps, 1, FALSE); 5394642e01fSmrg 5404642e01fSmrg ExaDoPrepareAccess(pDrawable, index); 5414642e01fSmrg} 5424642e01fSmrg 5434642e01fSmrg/** 5444642e01fSmrg * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 5454642e01fSmrg * 5464642e01fSmrg * It deals with waiting for synchronization with the card, determining if 5474642e01fSmrg * PrepareAccess() is necessary, and working around PrepareAccess() failure. 5484642e01fSmrg */ 5494642e01fSmrgvoid 5504642e01fSmrgexaPrepareAccess(DrawablePtr pDrawable, int index) 5514642e01fSmrg{ 5524642e01fSmrg exaPrepareAccessReg(pDrawable, index, NULL); 5534642e01fSmrg} 5544642e01fSmrg 55505b261ecSmrg/** 55605b261ecSmrg * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 55705b261ecSmrg * 55805b261ecSmrg * It deals with calling the driver's FinishAccess() only if necessary. 55905b261ecSmrg */ 56005b261ecSmrgvoid 56105b261ecSmrgexaFinishAccess(DrawablePtr pDrawable, int index) 56205b261ecSmrg{ 56305b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 56405b261ecSmrg ExaScreenPriv (pScreen); 5654642e01fSmrg PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 5664642e01fSmrg ExaPixmapPriv (pPixmap); 56705b261ecSmrg 56805b261ecSmrg /* Rehide pixmap pointer if we're doing that. */ 5694642e01fSmrg if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 5704642e01fSmrg pPixmap->devPrivate.ptr = NULL; 57105b261ecSmrg } 57205b261ecSmrg 57305b261ecSmrg if (pExaScr->info->FinishAccess == NULL) 57405b261ecSmrg return; 57505b261ecSmrg 57605b261ecSmrg if (!exaPixmapIsOffscreen (pPixmap)) 57705b261ecSmrg return; 57805b261ecSmrg 5794642e01fSmrg if (index >= EXA_PREPARE_AUX0 && 5804642e01fSmrg !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 5814642e01fSmrg ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 5824642e01fSmrg "unsupported index EXA_PREPARE_AUX*\n"); 5834642e01fSmrg return; 5844642e01fSmrg } 5854642e01fSmrg 58605b261ecSmrg (*pExaScr->info->FinishAccess) (pPixmap, index); 58705b261ecSmrg} 58805b261ecSmrg 58905b261ecSmrg/** 59005b261ecSmrg * exaValidateGC() sets the ops to EXA's implementations, which may be 59105b261ecSmrg * accelerated or may sync the card and fall back to fb. 59205b261ecSmrg */ 59305b261ecSmrgstatic void 59405b261ecSmrgexaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 59505b261ecSmrg{ 59605b261ecSmrg /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 59705b261ecSmrg * Preempt fbValidateGC by doing its work and masking the change out, so 59805b261ecSmrg * that we can do the Prepare/FinishAccess. 59905b261ecSmrg */ 60005b261ecSmrg#ifdef FB_24_32BIT 60105b261ecSmrg if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 60205b261ecSmrg (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 60305b261ecSmrg fbGetRotatedPixmap(pGC) = 0; 60405b261ecSmrg } 60505b261ecSmrg 60605b261ecSmrg if (pGC->fillStyle == FillTiled) { 60705b261ecSmrg PixmapPtr pOldTile, pNewTile; 60805b261ecSmrg 60905b261ecSmrg pOldTile = pGC->tile.pixmap; 61005b261ecSmrg if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 61105b261ecSmrg { 61205b261ecSmrg pNewTile = fbGetRotatedPixmap(pGC); 61305b261ecSmrg if (!pNewTile || 61405b261ecSmrg pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 61505b261ecSmrg { 61605b261ecSmrg if (pNewTile) 61705b261ecSmrg (*pGC->pScreen->DestroyPixmap) (pNewTile); 61805b261ecSmrg /* fb24_32ReformatTile will do direct access of a newly- 61905b261ecSmrg * allocated pixmap. This isn't a problem yet, since we don't 62005b261ecSmrg * put pixmaps in FB until at least one accelerated EXA op. 62105b261ecSmrg */ 62205b261ecSmrg exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 62305b261ecSmrg pNewTile = fb24_32ReformatTile (pOldTile, 62405b261ecSmrg pDrawable->bitsPerPixel); 62505b261ecSmrg exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); 62605b261ecSmrg exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 62705b261ecSmrg } 62805b261ecSmrg if (pNewTile) 62905b261ecSmrg { 63005b261ecSmrg fbGetRotatedPixmap(pGC) = pOldTile; 63105b261ecSmrg pGC->tile.pixmap = pNewTile; 63205b261ecSmrg changes |= GCTile; 63305b261ecSmrg } 63405b261ecSmrg } 63505b261ecSmrg } 63605b261ecSmrg#endif 63705b261ecSmrg if (changes & GCTile) { 63805b261ecSmrg if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 63905b261ecSmrg pDrawable->bitsPerPixel)) 64005b261ecSmrg { 6414642e01fSmrg exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 64205b261ecSmrg fbPadPixmap (pGC->tile.pixmap); 6434642e01fSmrg exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 64405b261ecSmrg exaPixmapDirty(pGC->tile.pixmap, 0, 0, 64505b261ecSmrg pGC->tile.pixmap->drawable.width, 64605b261ecSmrg pGC->tile.pixmap->drawable.height); 64705b261ecSmrg } 64805b261ecSmrg /* Mask out the GCTile change notification, now that we've done FB's 64905b261ecSmrg * job for it. 65005b261ecSmrg */ 65105b261ecSmrg changes &= ~GCTile; 65205b261ecSmrg } 65305b261ecSmrg 6544642e01fSmrg exaPrepareAccessGC(pGC); 65505b261ecSmrg fbValidateGC (pGC, changes, pDrawable); 6564642e01fSmrg exaFinishAccessGC(pGC); 65705b261ecSmrg 65805b261ecSmrg pGC->ops = (GCOps *) &exaOps; 65905b261ecSmrg} 66005b261ecSmrg 66105b261ecSmrgstatic GCFuncs exaGCFuncs = { 66205b261ecSmrg exaValidateGC, 66305b261ecSmrg miChangeGC, 66405b261ecSmrg miCopyGC, 66505b261ecSmrg miDestroyGC, 66605b261ecSmrg miChangeClip, 66705b261ecSmrg miDestroyClip, 66805b261ecSmrg miCopyClip 66905b261ecSmrg}; 67005b261ecSmrg 67105b261ecSmrg/** 67205b261ecSmrg * exaCreateGC makes a new GC and hooks up its funcs handler, so that 67305b261ecSmrg * exaValidateGC() will get called. 67405b261ecSmrg */ 67505b261ecSmrgstatic int 67605b261ecSmrgexaCreateGC (GCPtr pGC) 67705b261ecSmrg{ 67805b261ecSmrg if (!fbCreateGC (pGC)) 67905b261ecSmrg return FALSE; 68005b261ecSmrg 68105b261ecSmrg pGC->funcs = &exaGCFuncs; 68205b261ecSmrg 68305b261ecSmrg return TRUE; 68405b261ecSmrg} 68505b261ecSmrg 6864642e01fSmrgstatic Bool 6874642e01fSmrgexaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 6884642e01fSmrg{ 6894642e01fSmrg Bool ret; 6904642e01fSmrg 6914642e01fSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 6924642e01fSmrg exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 6934642e01fSmrg 6944642e01fSmrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 6954642e01fSmrg exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 6964642e01fSmrg 6974642e01fSmrg ret = fbChangeWindowAttributes(pWin, mask); 6984642e01fSmrg 6994642e01fSmrg if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 7004642e01fSmrg exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 7014642e01fSmrg 7024642e01fSmrg if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 7034642e01fSmrg exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 7044642e01fSmrg 7054642e01fSmrg return ret; 7064642e01fSmrg} 7074642e01fSmrg 7084642e01fSmrgstatic RegionPtr 7094642e01fSmrgexaBitmapToRegion(PixmapPtr pPix) 7104642e01fSmrg{ 7114642e01fSmrg RegionPtr ret; 7124642e01fSmrg exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); 7134642e01fSmrg ret = fbPixmapToRegion(pPix); 7144642e01fSmrg exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); 7154642e01fSmrg return ret; 7164642e01fSmrg} 7174642e01fSmrg 7184642e01fSmrgstatic Bool 7194642e01fSmrgexaCreateScreenResources(ScreenPtr pScreen) 7204642e01fSmrg{ 7214642e01fSmrg ExaScreenPriv(pScreen); 7224642e01fSmrg PixmapPtr pScreenPixmap; 7234642e01fSmrg Bool b; 7244642e01fSmrg 7254642e01fSmrg pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources; 7264642e01fSmrg b = pScreen->CreateScreenResources(pScreen); 7274642e01fSmrg pScreen->CreateScreenResources = exaCreateScreenResources; 7284642e01fSmrg 7294642e01fSmrg if (!b) 7304642e01fSmrg return FALSE; 7314642e01fSmrg 7324642e01fSmrg pScreenPixmap = pScreen->GetScreenPixmap(pScreen); 7334642e01fSmrg 7344642e01fSmrg if (pScreenPixmap) { 7354642e01fSmrg ExaPixmapPriv(pScreenPixmap); 7364642e01fSmrg 7374642e01fSmrg exaSetAccelBlock(pExaScr, pExaPixmap, 7384642e01fSmrg pScreenPixmap->drawable.width, 7394642e01fSmrg pScreenPixmap->drawable.height, 7404642e01fSmrg pScreenPixmap->drawable.bitsPerPixel); 7414642e01fSmrg } 7424642e01fSmrg 7434642e01fSmrg return TRUE; 7444642e01fSmrg} 7454642e01fSmrg 74605b261ecSmrg/** 74705b261ecSmrg * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 74805b261ecSmrg * screen private, before calling down to the next CloseSccreen. 74905b261ecSmrg */ 75005b261ecSmrgstatic Bool 75105b261ecSmrgexaCloseScreen(int i, ScreenPtr pScreen) 75205b261ecSmrg{ 75305b261ecSmrg ExaScreenPriv(pScreen); 75405b261ecSmrg#ifdef RENDER 75505b261ecSmrg PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 75605b261ecSmrg#endif 75705b261ecSmrg 7584642e01fSmrg if (ps->Glyphs == exaGlyphs) 7594642e01fSmrg exaGlyphsFini(pScreen); 7604642e01fSmrg 76105b261ecSmrg pScreen->CreateGC = pExaScr->SavedCreateGC; 76205b261ecSmrg pScreen->CloseScreen = pExaScr->SavedCloseScreen; 76305b261ecSmrg pScreen->GetImage = pExaScr->SavedGetImage; 76405b261ecSmrg pScreen->GetSpans = pExaScr->SavedGetSpans; 76505b261ecSmrg pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; 76605b261ecSmrg pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap; 76705b261ecSmrg pScreen->CopyWindow = pExaScr->SavedCopyWindow; 7684642e01fSmrg pScreen->ChangeWindowAttributes = pExaScr->SavedChangeWindowAttributes; 7694642e01fSmrg pScreen->BitmapToRegion = pExaScr->SavedBitmapToRegion; 7704642e01fSmrg pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources; 77105b261ecSmrg#ifdef RENDER 77205b261ecSmrg if (ps) { 77305b261ecSmrg ps->Composite = pExaScr->SavedComposite; 77405b261ecSmrg ps->Glyphs = pExaScr->SavedGlyphs; 77505b261ecSmrg ps->Trapezoids = pExaScr->SavedTrapezoids; 7764642e01fSmrg ps->Triangles = pExaScr->SavedTriangles; 7774642e01fSmrg ps->AddTraps = pExaScr->SavedAddTraps; 77805b261ecSmrg } 77905b261ecSmrg#endif 78005b261ecSmrg 78105b261ecSmrg xfree (pExaScr); 78205b261ecSmrg 78305b261ecSmrg return (*pScreen->CloseScreen) (i, pScreen); 78405b261ecSmrg} 78505b261ecSmrg 78605b261ecSmrg/** 78705b261ecSmrg * This function allocates a driver structure for EXA drivers to fill in. By 78805b261ecSmrg * having EXA allocate the structure, the driver structure can be extended 78905b261ecSmrg * without breaking ABI between EXA and the drivers. The driver's 79005b261ecSmrg * responsibility is to check beforehand that the EXA module has a matching 79105b261ecSmrg * major number and sufficient minor. Drivers are responsible for freeing the 79205b261ecSmrg * driver structure using xfree(). 79305b261ecSmrg * 79405b261ecSmrg * @return a newly allocated, zero-filled driver structure 79505b261ecSmrg */ 79605b261ecSmrgExaDriverPtr 79705b261ecSmrgexaDriverAlloc(void) 79805b261ecSmrg{ 79905b261ecSmrg return xcalloc(1, sizeof(ExaDriverRec)); 80005b261ecSmrg} 80105b261ecSmrg 80205b261ecSmrg/** 80305b261ecSmrg * @param pScreen screen being initialized 80405b261ecSmrg * @param pScreenInfo EXA driver record 80505b261ecSmrg * 80605b261ecSmrg * exaDriverInit sets up EXA given a driver record filled in by the driver. 80705b261ecSmrg * pScreenInfo should have been allocated by exaDriverAlloc(). See the 80805b261ecSmrg * comments in _ExaDriver for what must be filled in and what is optional. 80905b261ecSmrg * 81005b261ecSmrg * @return TRUE if EXA was successfully initialized. 81105b261ecSmrg */ 81205b261ecSmrgBool 81305b261ecSmrgexaDriverInit (ScreenPtr pScreen, 81405b261ecSmrg ExaDriverPtr pScreenInfo) 81505b261ecSmrg{ 81605b261ecSmrg ExaScreenPrivPtr pExaScr; 81705b261ecSmrg#ifdef RENDER 81805b261ecSmrg PictureScreenPtr ps; 81905b261ecSmrg#endif 82005b261ecSmrg 82105b261ecSmrg if (!pScreenInfo) 82205b261ecSmrg return FALSE; 82305b261ecSmrg 8244642e01fSmrg if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 8254642e01fSmrg pScreenInfo->exa_minor > EXA_VERSION_MINOR) 8264642e01fSmrg { 8274642e01fSmrg LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 8284642e01fSmrg "(%d.%d) are incompatible with EXA version (%d.%d)\n", 8294642e01fSmrg pScreen->myNum, 8304642e01fSmrg pScreenInfo->exa_major, pScreenInfo->exa_minor, 8314642e01fSmrg EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 83205b261ecSmrg return FALSE; 83305b261ecSmrg } 83405b261ecSmrg 8354642e01fSmrg if (!pScreenInfo->CreatePixmap) { 8364642e01fSmrg if (!pScreenInfo->memoryBase) { 8374642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " 8384642e01fSmrg "must be non-zero\n", pScreen->myNum); 8394642e01fSmrg return FALSE; 8404642e01fSmrg } 84105b261ecSmrg 8424642e01fSmrg if (!pScreenInfo->memorySize) { 8434642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 8444642e01fSmrg "non-zero\n", pScreen->myNum); 8454642e01fSmrg return FALSE; 8464642e01fSmrg } 8474642e01fSmrg 8484642e01fSmrg if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 8494642e01fSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " 8504642e01fSmrg "be <= ExaDriverRec::memorySize\n", pScreen->myNum); 8514642e01fSmrg return FALSE; 8524642e01fSmrg } 85305b261ecSmrg } 85405b261ecSmrg 85505b261ecSmrg if (!pScreenInfo->PrepareSolid) { 85605b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 85705b261ecSmrg "non-NULL\n", pScreen->myNum); 85805b261ecSmrg return FALSE; 85905b261ecSmrg } 86005b261ecSmrg 86105b261ecSmrg if (!pScreenInfo->PrepareCopy) { 86205b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 86305b261ecSmrg "non-NULL\n", pScreen->myNum); 86405b261ecSmrg return FALSE; 86505b261ecSmrg } 86605b261ecSmrg 86705b261ecSmrg if (!pScreenInfo->WaitMarker) { 86805b261ecSmrg LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 86905b261ecSmrg "non-NULL\n", pScreen->myNum); 87005b261ecSmrg return FALSE; 87105b261ecSmrg } 87205b261ecSmrg 8734642e01fSmrg /* If the driver doesn't set any max pitch values, we'll just assume 8744642e01fSmrg * that there's a limitation by pixels, and that it's the same as 8754642e01fSmrg * maxX. 8764642e01fSmrg * 8774642e01fSmrg * We want maxPitchPixels or maxPitchBytes to be set so we can check 8784642e01fSmrg * pixmaps against the max pitch in exaCreatePixmap() -- it matters 8794642e01fSmrg * whether a pixmap is rejected because of its pitch or 8804642e01fSmrg * because of its width. 8814642e01fSmrg */ 8824642e01fSmrg if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) 88305b261ecSmrg { 8844642e01fSmrg pScreenInfo->maxPitchPixels = pScreenInfo->maxX; 88505b261ecSmrg } 88605b261ecSmrg 88705b261ecSmrg#ifdef RENDER 88805b261ecSmrg ps = GetPictureScreenIfSet(pScreen); 88905b261ecSmrg#endif 89005b261ecSmrg 89105b261ecSmrg pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1); 89205b261ecSmrg 89305b261ecSmrg if (!pExaScr) { 89405b261ecSmrg LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 89505b261ecSmrg pScreen->myNum); 89605b261ecSmrg return FALSE; 89705b261ecSmrg } 89805b261ecSmrg 89905b261ecSmrg pExaScr->info = pScreenInfo; 90005b261ecSmrg 9014642e01fSmrg dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); 90205b261ecSmrg 90305b261ecSmrg pExaScr->migration = ExaMigrationAlways; 90405b261ecSmrg 90505b261ecSmrg exaDDXDriverInit(pScreen); 90605b261ecSmrg 90705b261ecSmrg /* 90805b261ecSmrg * Replace various fb screen functions 90905b261ecSmrg */ 91005b261ecSmrg pExaScr->SavedCloseScreen = pScreen->CloseScreen; 91105b261ecSmrg pScreen->CloseScreen = exaCloseScreen; 91205b261ecSmrg 91305b261ecSmrg pExaScr->SavedCreateGC = pScreen->CreateGC; 91405b261ecSmrg pScreen->CreateGC = exaCreateGC; 91505b261ecSmrg 91605b261ecSmrg pExaScr->SavedGetImage = pScreen->GetImage; 91705b261ecSmrg pScreen->GetImage = exaGetImage; 91805b261ecSmrg 91905b261ecSmrg pExaScr->SavedGetSpans = pScreen->GetSpans; 9204642e01fSmrg pScreen->GetSpans = ExaCheckGetSpans; 92105b261ecSmrg 92205b261ecSmrg pExaScr->SavedCopyWindow = pScreen->CopyWindow; 92305b261ecSmrg pScreen->CopyWindow = exaCopyWindow; 92405b261ecSmrg 9254642e01fSmrg pExaScr->SavedChangeWindowAttributes = pScreen->ChangeWindowAttributes; 9264642e01fSmrg pScreen->ChangeWindowAttributes = exaChangeWindowAttributes; 9274642e01fSmrg 9284642e01fSmrg pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion; 9294642e01fSmrg pScreen->BitmapToRegion = exaBitmapToRegion; 93005b261ecSmrg 9314642e01fSmrg pExaScr->SavedCreateScreenResources = pScreen->CreateScreenResources; 9324642e01fSmrg pScreen->CreateScreenResources = exaCreateScreenResources; 93305b261ecSmrg 93405b261ecSmrg#ifdef RENDER 93505b261ecSmrg if (ps) { 93605b261ecSmrg pExaScr->SavedComposite = ps->Composite; 93705b261ecSmrg ps->Composite = exaComposite; 93805b261ecSmrg 9394642e01fSmrg if (pScreenInfo->PrepareComposite) { 9404642e01fSmrg pExaScr->SavedGlyphs = ps->Glyphs; 9414642e01fSmrg ps->Glyphs = exaGlyphs; 9424642e01fSmrg } 9434642e01fSmrg 9444642e01fSmrg pExaScr->SavedTriangles = ps->Triangles; 9454642e01fSmrg ps->Triangles = exaTriangles; 94605b261ecSmrg 94705b261ecSmrg pExaScr->SavedTrapezoids = ps->Trapezoids; 94805b261ecSmrg ps->Trapezoids = exaTrapezoids; 9494642e01fSmrg 9504642e01fSmrg pExaScr->SavedAddTraps = ps->AddTraps; 9514642e01fSmrg ps->AddTraps = ExaCheckAddTraps; 95205b261ecSmrg } 95305b261ecSmrg#endif 95405b261ecSmrg 95505b261ecSmrg#ifdef MITSHM 9564642e01fSmrg /* 9574642e01fSmrg * Don't allow shared pixmaps. 95805b261ecSmrg */ 9594642e01fSmrg ShmRegisterFuncs(pScreen, &exaShmFuncs); 96005b261ecSmrg#endif 96105b261ecSmrg /* 96205b261ecSmrg * Hookup offscreen pixmaps 96305b261ecSmrg */ 9644642e01fSmrg if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) 96505b261ecSmrg { 9664642e01fSmrg if (!dixRequestPrivate(exaPixmapPrivateKey, sizeof(ExaPixmapPrivRec))) { 96705b261ecSmrg LogMessage(X_WARNING, 96805b261ecSmrg "EXA(%d): Failed to allocate pixmap private\n", 96905b261ecSmrg pScreen->myNum); 97005b261ecSmrg return FALSE; 97105b261ecSmrg } 97205b261ecSmrg pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; 97305b261ecSmrg pScreen->CreatePixmap = exaCreatePixmap; 97405b261ecSmrg 97505b261ecSmrg pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap; 97605b261ecSmrg pScreen->DestroyPixmap = exaDestroyPixmap; 97705b261ecSmrg 9784642e01fSmrg pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader; 9794642e01fSmrg pScreen->ModifyPixmapHeader = exaModifyPixmapHeader; 9804642e01fSmrg if (!pExaScr->info->CreatePixmap) { 9814642e01fSmrg LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 9824642e01fSmrg pScreen->myNum, 9834642e01fSmrg pExaScr->info->memorySize - pExaScr->info->offScreenBase); 9844642e01fSmrg } else { 9854642e01fSmrg LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", 9864642e01fSmrg pScreen->myNum); 9874642e01fSmrg 9884642e01fSmrg } 98905b261ecSmrg } 99005b261ecSmrg else 99105b261ecSmrg LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 99205b261ecSmrg 9934642e01fSmrg if (!pExaScr->info->CreatePixmap) { 9944642e01fSmrg DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 9954642e01fSmrg pExaScr->info->memorySize)); 9964642e01fSmrg if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 9974642e01fSmrg if (!exaOffscreenInit (pScreen)) { 9984642e01fSmrg LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", 9994642e01fSmrg pScreen->myNum); 10004642e01fSmrg return FALSE; 10014642e01fSmrg } 10024642e01fSmrg } 100305b261ecSmrg } 100405b261ecSmrg 10054642e01fSmrg if (ps->Glyphs == exaGlyphs) 10064642e01fSmrg exaGlyphsInit(pScreen); 10074642e01fSmrg 100805b261ecSmrg LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 100905b261ecSmrg " operations:\n", pScreen->myNum); 101005b261ecSmrg assert(pScreenInfo->PrepareSolid != NULL); 101105b261ecSmrg LogMessage(X_INFO, " Solid\n"); 101205b261ecSmrg assert(pScreenInfo->PrepareCopy != NULL); 101305b261ecSmrg LogMessage(X_INFO, " Copy\n"); 101405b261ecSmrg if (pScreenInfo->PrepareComposite != NULL) { 101505b261ecSmrg LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 101605b261ecSmrg } 101705b261ecSmrg if (pScreenInfo->UploadToScreen != NULL) { 101805b261ecSmrg LogMessage(X_INFO, " UploadToScreen\n"); 101905b261ecSmrg } 102005b261ecSmrg if (pScreenInfo->DownloadFromScreen != NULL) { 102105b261ecSmrg LogMessage(X_INFO, " DownloadFromScreen\n"); 102205b261ecSmrg } 102305b261ecSmrg 102405b261ecSmrg return TRUE; 102505b261ecSmrg} 102605b261ecSmrg 102705b261ecSmrg/** 102805b261ecSmrg * exaDriverFini tears down EXA on a given screen. 102905b261ecSmrg * 103005b261ecSmrg * @param pScreen screen being torn down. 103105b261ecSmrg */ 103205b261ecSmrgvoid 103305b261ecSmrgexaDriverFini (ScreenPtr pScreen) 103405b261ecSmrg{ 103505b261ecSmrg /*right now does nothing*/ 103605b261ecSmrg} 103705b261ecSmrg 103805b261ecSmrg/** 103905b261ecSmrg * exaMarkSync() should be called after any asynchronous drawing by the hardware. 104005b261ecSmrg * 104105b261ecSmrg * @param pScreen screen which drawing occurred on 104205b261ecSmrg * 104305b261ecSmrg * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 104405b261ecSmrg * happened and a WaitSync() will be necessary before relying on the contents of 104505b261ecSmrg * offscreen memory from the CPU's perspective. It also calls an optional 104605b261ecSmrg * driver MarkSync() callback, the return value of which may be used to do partial 104705b261ecSmrg * synchronization with the hardware in the future. 104805b261ecSmrg */ 104905b261ecSmrgvoid exaMarkSync(ScreenPtr pScreen) 105005b261ecSmrg{ 105105b261ecSmrg ExaScreenPriv(pScreen); 105205b261ecSmrg 105305b261ecSmrg pExaScr->info->needsSync = TRUE; 105405b261ecSmrg if (pExaScr->info->MarkSync != NULL) { 105505b261ecSmrg pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); 105605b261ecSmrg } 105705b261ecSmrg} 105805b261ecSmrg 105905b261ecSmrg/** 106005b261ecSmrg * exaWaitSync() ensures that all drawing has been completed. 106105b261ecSmrg * 106205b261ecSmrg * @param pScreen screen being synchronized. 106305b261ecSmrg * 106405b261ecSmrg * Calls down into the driver to ensure that all previous drawing has completed. 106505b261ecSmrg * It should always be called before relying on the framebuffer contents 106605b261ecSmrg * reflecting previous drawing, from a CPU perspective. 106705b261ecSmrg */ 106805b261ecSmrgvoid exaWaitSync(ScreenPtr pScreen) 106905b261ecSmrg{ 107005b261ecSmrg ExaScreenPriv(pScreen); 107105b261ecSmrg 107205b261ecSmrg if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 107305b261ecSmrg (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 107405b261ecSmrg pExaScr->info->needsSync = FALSE; 107505b261ecSmrg } 107605b261ecSmrg} 1077