diff options
Diffstat (limited to 'exa')
-rw-r--r-- | exa/exa.c | 82 | ||||
-rw-r--r-- | exa/exa.h | 538 | ||||
-rw-r--r-- | exa/exa_offscreen.c | 49 | ||||
-rw-r--r-- | exa/exa_priv.h | 3 |
4 files changed, 618 insertions, 54 deletions
@@ -22,6 +22,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/** @file + * This file covers the initialization and teardown of EXA, and has various + * functions not responsible for performing rendering, pixmap migration, or + * memory management. + */ + #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif @@ -38,9 +44,15 @@ static int exaGeneration; int exaScreenPrivateIndex; int exaPixmapPrivateIndex; -/* Returns the offset (in bytes) within the framebuffer of the beginning of the - * given pixmap. May need to be extended in the future if we grow support for - * having multiple card-accessible areas at different offsets. +/** + * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of + * the beginning of the given pixmap. + * + * Note that drivers are free to, and often do, munge this offset as necessary + * for handing to the hardware -- for example, translating it into a different + * aperture. This function may need to be extended in the future if we grow + * support for having multiple card-accessible offscreen, such as an AGP memory + * pool alongside the framebuffer pool. */ unsigned long exaGetPixmapOffset(PixmapPtr pPix) @@ -51,16 +63,21 @@ exaGetPixmapOffset(PixmapPtr pPix) (unsigned long)pExaScr->info->memoryBase); } -/* Returns the pitch in bytes of the given pixmap. */ +/** + * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. + * + * This is a helper to make driver code more obvious, due to the rather obscure + * naming of the pitch field in the pixmap. + */ unsigned long exaGetPixmapPitch(PixmapPtr pPix) { return pPix->devKind; } -/* Returns the size in bytes of the given pixmap in - * video memory. Only valid when the vram storage has been - * allocated +/** + * exaGetPixmapSize() returns the size in bytes of the given pixmap in video + * memory. Only valid when the pixmap is currently in framebuffer. */ unsigned long exaGetPixmapSize(PixmapPtr pPix) @@ -73,6 +90,17 @@ exaGetPixmapSize(PixmapPtr pPix) return 0; } +/** + * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. + * + * @param pDrawable the drawable being requested. + * + * This function returns the backing pixmap for a drawable, whether it is a + * redirected window, unredirected window, or already a pixmap. Note that + * coordinate translation is needed when drawing to the backing pixmap of a + * redirected window, and the translation coordinates are provided by calling + * exaGetOffscreenPixmap() on the drawable. + */ PixmapPtr exaGetDrawablePixmap(DrawablePtr pDrawable) { @@ -82,6 +110,10 @@ exaGetDrawablePixmap(DrawablePtr pDrawable) return (PixmapPtr) pDrawable; } +/** + * exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for + * optimizations in pixmap migration when no changes have occurred. + */ void exaDrawableDirty (DrawablePtr pDrawable) { @@ -301,6 +333,8 @@ exaCloseScreen(int i, ScreenPtr pScreen) * responsibility is to check beforehand that the EXA module has a matching * major number and sufficient minor. Drivers are responsible for freeing the * driver structure using xfree(). + * + * @return a newly allocated, zero-filled driver structure */ ExaDriverPtr exaDriverAlloc(void) @@ -309,9 +343,14 @@ exaDriverAlloc(void) } /** + * @param pScreen screen being initialized + * @param pScreenInfo EXA driver record + * * exaDriverInit sets up EXA given a driver record filled in by the driver. - * See the comments in ExaDriverRec for what must be filled in and what is - * optional. + * pScreenInfo should have been allocated by exaDriverAlloc(). See the + * comments in _ExaDriver for what must be filled in and what is optional. + * + * @return TRUE if EXA was successfully initialized. */ Bool exaDriverInit (ScreenPtr pScreen, @@ -431,12 +470,28 @@ exaDriverInit (ScreenPtr pScreen, return TRUE; } +/** + * exaDriverFini tears down EXA on a given screen. + * + * @param pScreen screen being torn down. + */ void exaDriverFini (ScreenPtr pScreen) { /*right now does nothing*/ } +/** + * exaMarkSync() should be called after any asynchronous drawing by the hardware. + * + * @param pScreen screen which drawing occurred on + * + * exaMarkSync() sets a flag to indicate that some asynchronous drawing has + * happened and a WaitSync() will be necessary before relying on the contents of + * offscreen memory from the CPU's perspective. It also calls an optional + * driver MarkSync() callback, the return value of which may be used to do partial + * synchronization with the hardware in the future. + */ void exaMarkSync(ScreenPtr pScreen) { ExaScreenPriv(pScreen); @@ -447,6 +502,15 @@ void exaMarkSync(ScreenPtr pScreen) } } +/** + * exaWaitSync() ensures that all drawing has been completed. + * + * @param pScreen screen being synchronized. + * + * Calls down into the driver to ensure that all previous drawing has completed. + * It should always be called before relying on the framebuffer contents + * reflecting previous drawing, from a CPU perspective. + */ void exaWaitSync(ScreenPtr pScreen) { ExaScreenPriv(pScreen); @@ -23,6 +23,11 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ + +/** @file + * This is the header containing the public API of EXA for exa drivers. + */ + #ifndef EXA_H #define EXA_H @@ -73,47 +78,183 @@ typedef struct _ExaDriver { */ int exa_major, exa_minor; - /* These are here because I don't want to be adding more to - * ScrnInfoRec */ + /** + * memoryBase is the address of the beginning of framebuffer memory. + * The visible screen should be within memoryBase to memoryBase + + * memorySize. + */ CARD8 *memoryBase; + + /** + * offScreenBase is the offset from memoryBase of the beginning of the area + * to be managed by EXA's linear offscreen memory manager. + * + * In XFree86 DDX drivers, this is probably: + * (pScrn->displayWidth * cpp * pScrn->virtualY) + */ unsigned long offScreenBase; - /* It's fix.smem_len. - This one could be potentially substituted by ScrnInfoRec - videoRam member, but I do not want to be doing the silly - << 10, >>10 all over the place */ + /** + * memorySize is the length (in bytes) of framebuffer memory beginning + * from memoryBase. + * + * The offscreen memory manager will manage the area beginning at + * (memoryBase + offScreenBase), with a length of (memorySize - + * offScreenBase) + * + * In XFree86 DDX drivers, this is probably (pScrn->videoRam * 1024) + */ unsigned long memorySize; + /** + * pixmapOffsetAlign is the byte alignment necessary for pixmap offsets + * within framebuffer. + * + * Hardware typically has a required alignment of offsets, which may or may + * not be a power of two. EXA will ensure that pixmaps managed by the + * offscreen memory manager meet this alignment requirement. + */ int pixmapOffsetAlign; + + /** + * pixmapPitchAlign is the byte alignment necessary for pixmap pitches + * within the framebuffer. + * + * Hardware typically has a required alignment of pitches for acceleration. + * For 3D hardware, Composite acceleration often requires that source and + * mask pixmaps (textures) have a power-of-two pitch, which can be demanded + * using EXA_OFFSCREEN_ALIGN_POT. These pitch requirements only apply to + * pixmaps managed by the offscreen memory manager. Thus, it is up to the + * driver to ensure that the visible screen has an appropriate pitch for + * acceleration. + */ int pixmapPitchAlign; + + /** + * The flags field is bitfield of boolean values controlling EXA's behavior. + * + * The flags in clude EXA_OFFSCREEN_PIXMAPS, EXA_OFFSCREEN_ALIGN_POT, and + * EXA_TWO_BITBLT_DIRECTIONS. + */ int flags; - /* The coordinate limitations for rendering for this hardware. - * Exa breaks larger pixmaps into smaller pieces and calls Prepare multiple times - * to handle larger pixmaps + /** @{ */ + /** + * maxX controls the X coordinate limitation for rendering from the card. + * The driver should never receive a request for rendering beyond maxX + * in the X direction from the origin of a pixmap. */ int maxX; + + /** + * maxY controls the Y coordinate limitation for rendering from the card. + * The driver should never receive a request for rendering beyond maxY + * in the Y direction from the origin of a pixmap. + */ int maxY; + /** @} */ /* private */ ExaOffscreenArea *offScreenAreas; Bool needsSync; int lastMarker; - /* PrepareSolid may fail if the pixmaps can't be accelerated to/from. - * This is an important feature for handling strange corner cases - * in hardware that are poorly expressed through flags. + /** @name Solid + * @{ + */ + /** + * PrepareSolid sets up the driver for doing a solid fill. + * @param pPixmap Destination pixmap + * @param alu raster operation + * @param planemask write mask for the fill + * @param fg "foreground" color for the fill + * + * This call should set up the driver for doing a series of solid fills + * through the Solid call. The alu raster op is one of the GX* + * graphics functions listed in X.h, and typically maps to a similar + * single-byte "ROP" setting in all hardware. The planemask controls + * which bits of + * the destination should be affected, and will only represent the bits up + * to the depth of pPixmap. The fg is the pixel value of the foreground + * color referred to in ROP descriptions. + * + * Note that many drivers will need to store some of the data in the driver + * private record, for sending to the hardware with each drawing command. + * + * The PrepareSolid() call is required of all drivers, but it may fail for any + * reason. Failure results in a fallback to software rendering. */ Bool (*PrepareSolid) (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg); + + /** + * Solid performs a solid fill set up in the last PrepareSolid call. + * + * @param pPixmap destination pixmap + * @param x1 left coordinate + * @param y1 top coordinate + * @param x2 right coordinate + * @param y2 bottom coordinate + * + * Performs the fill set up by the last PrepareSolid() call, covering the + * area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are + * in the coordinate space of the destination pixmap, so the driver will + * need to set up the hardware's offset and pitch for the destination + * coordinates according to the pixmap's offset and pitch within + * framebuffer. This likely means using exaGetPixmapOffset() and + * exaGetPixmapPitch(). + * + * This call is required if PrepareSolid() ever succeeds. + */ void (*Solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2); + + /** + * DoneSolid finishes a set of solid fills. + * + * @param pPixmap destination pixmap. + * + * The DoneSolid call is called at the end of a set of a series of Solid() + * calls following a PrepareSolid() that was called. This allows drivers to + * finish up emitting drawing commands that were buffered. + * + * This call is required if PrepareSolid() ever succeeds. + */ void (*DoneSolid) (PixmapPtr pPixmap); + /** @} */ - /* PrepareSolid may fail if the pixmaps can't be accelerated to/from. - * This is an important feature for handling strange corner cases - * in hardware that are poorly expressed through flags. + /** @name Copy + * @{ + */ + /** + * PrepareCopy sets up the driver for doing a copy within offscreen memory. + * @param pSrcPixmap source pixmap + * @param pDstPixmap destination pixmap + * @param dx X copy direction + * @param dy Y copy direction + * @param alu raster operation + * @param planemask write mask for the fill + * + * This call should set up the driver for doing a series of copies from the + * the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the + * hardware should do the copy from the left to the right, and dy will be + * positive if the copy should be done from the top to the bottom. This + * is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap. + * If your hardware can only support blits that are (left to right, top to + * bottom) or (right to left, bottom to top), then you should set + * EXA_TWO_BITBLT_DIRECTIONS, and EXA will break down Copy operations to + * ones that meet those requirements. The alu raster op is one of the GX* + * graphics functions listed in X.h, and typically maps to a similar + * single-byte "ROP" setting in all hardware. The planemask controls which + * bits of the destination should be affected, and will only represent the + * bits up to the depth of pPixmap. + * + * Note that many drivers will need to store some of the data in the driver + * private record, for sending to the hardware with each drawing command. + * + * The PrepareCopy() call is required of all drivers, but it may fail for any + * reason. Failure results in a fallback to software rendering. */ Bool (*PrepareCopy) (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, @@ -121,6 +262,31 @@ typedef struct _ExaDriver { int dy, int alu, Pixel planemask); + + /** + * Copy performs a copy set up in the last PrepareCopy call. + * + * @param pDstPixmap destination pixmap + * @param srcX source X coordinate + * @param srcY source Y coordinate + * @param dstX destination X coordinate + * @param dstY destination Y coordinate + * @param width width of the rectangle to be copied + * @param height height of the rectangle to be copied. + * + * Performs the copy set up by the last PrepareCopy() call, copying the + * rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source + * pixmap to the same-sized rectangle at (dstX, dstY) in the destination + * pixmap. Those rectangles may overlap in memory, if + * pSrcPixmap == pDstPixmap. Note that this call does not receive the + * pSrcPixmap as an argument -- if it's needed in this function, it should + * be stored in the driver private during PrepareCopy(). As with Solid(), + * the coordinates are in the coordinate space of each pixmap, so the driver + * will need to set up source and destination pitches and offsets from those + * pixmaps, probably using exaGetPixmapOffset() and exaGetPixmapPitch(). + * + * This call is required if PrepareCopy ever succeeds. + */ void (*Copy) (PixmapPtr pDstPixmap, int srcX, int srcY, @@ -128,19 +294,106 @@ typedef struct _ExaDriver { int dstY, int width, int height); + + /** + * DoneCopy finishes a set of copies. + * + * @param pPixmap destination pixmap. + * + * The DoneCopy call is called at the end of a set of a series of Copy() + * calls following a PrepareCopy() that was called. This allows drivers to + * finish up emitting drawing commands that were buffered. + * + * This call is required if PrepareCopy ever succeeds. + */ void (*DoneCopy) (PixmapPtr pDstPixmap); + /** @} */ - /* The Composite hooks are a wrapper around the Composite operation. - * The CheckComposite occurs before pixmap migration occurs, - * and may fail for many hardware-dependent reasons. - * PrepareComposite should not fail, and the Bool return may - * not be necessary if we can - * adequately represent pixmap location/pitch limitations.. + /** @name Composite + * @{ + */ + /** + * CheckComposite checks to see if a composite operation could be accelerated. + * + * @param op Render operation + * @param pSrcPicture source Picture + * @param pMaskPicture mask picture + * @param pDstPicture destination Picture + * + * The CheckComposite call checks if the driver could handle acceleration of + * op with the given source, mask, and destination pictures. This allows + * drivers to check source and destination formats, supported operations, + * transformations, and component alpha state, and send operations it can't + * support to software rendering early on. This avoids costly pixmap + * migration to the wrong places when the driver can't accelerate + * operations. Note that because migration hasn't happened, the driver + * can't know during CheckComposite what the pitches and offsets of the + * pixmaps are going to be. + * + * See PrepareComposite() for more details on likely issues that drivers + * will have in accelerating Composite operations. + * + * The CheckComposite call is recommended if PrepareComposite() is + * implemented, but is not required. */ Bool (*CheckComposite) (int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture); + + /** + * PrepareComposite sets up the driver for doing a Composite operations + * described in the Render extension protocol spec. + * + * @param op Render operation + * @param pSrcPicture source Picture + * @param pMaskPicture mask picture + * @param pDstPicture destination Picture + * @param pSrc source pixmap + * @param pMask mask pixmap + * @param pDst destination pixmap + * + * This call should set up the driver for doing a series of Composite + * operations, as described in the Render protocol spec, with the given + * pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and + * pDst are the pixmaps containing the pixel data, and should be used for + * setting the offset and pitch used for the coordinate spaces for each of + * the Pictures. + * + * Notes on interpreting Picture structures: + * - The Picture structures will always have a valid pDrawable. + * - The Picture structures will never have alphaMap set. + * - The mask Picture (and therefore pMask) may be NULL, in which case the + * operation is simply src OP dst instead of src IN mask OP dst, and + * mask coordinates should be ignored. + * - pMarkPicture may have componentAlpha set, which greatly changes + * the behavior of the Composite operation. componentAlpha has no effect + * when set on pSrcPicture or pDstPicture. + * - The source and mask Pictures may have a transformation set + * (Picture->transform != NULL), which means that the source coordinates + * should be transformed by that transformation, resulting in scaling, + * rotation, etc. The PictureTransformPoint() call can transform + * coordinates for you. Transforms have no effect on Pictures when used + * as a destination. + * - The source and mask pictures may have a filter set. PictFilterNearest + * and PictFilterBilinear are defined in the Render protocol, but others + * may be encountered, and must be handled correctly (usually by + * PrepareComposite failing, and falling back to software). Filters have + * no effect on Pictures when used as a destination. + * - The source and mask Pictures may have repeating set, which must be + * respected. Many chipsets will be unable to support repeating on + * pixmaps that have a width or height that is not a power of two. + * + * If your hardware can't support source pictures (textures) with + * non-power-of-two pitches, you should set EXA_OFFSCREEN_ALIGN_POT. + * + * Note that many drivers will need to store some of the data in the driver + * private record, for sending to the hardware with each drawing command. + * + * The PrepareCopy call is not required. However, it is highly recommended + * for performance of antialiased font rendering and performance of cairo + * applications. Failure results in a fallback to software rendering. + */ Bool (*PrepareComposite) (int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, @@ -148,6 +401,31 @@ typedef struct _ExaDriver { PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + + /** + * Composite performs a Composite operation set up in the last + * PrepareComposite call. + * + * @param pDstPixmap destination pixmap + * @param srcX source X coordinate + * @param srcY source Y coordinate + * @param maskX source X coordinate + * @param maskY source Y coordinate + * @param dstX destination X coordinate + * @param dstY destination Y coordinate + * @param width destination rectangle width + * @param height destination rectangle height + * + * Performs the Composite operation set up by the last PrepareComposite + * call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height) + * in the destination Pixmap. Note that if a transformation was set on + * the source or mask Pictures, the source rectangles may not be the same + * size as the destination rectangles and filtering. Getting the coordinate + * transformation right at the subpixel level can be tricky, and rendercheck + * can test this for you. + * + * This call is required if PrepareComposite ever succeeds. + */ void (*Composite) (PixmapPtr pDst, int srcX, int srcY, @@ -157,10 +435,51 @@ typedef struct _ExaDriver { int dstY, int width, int height); + + /** + * DoneComposite finishes a set of Composite operations. + * + * @param pPixmap destination pixmap. + * + * The DoneComposite call is called at the end of a set of a series of + * Composite() calls following a PrepareCopy() that was called. This allows + * drivers to finish up emitting drawing commands that were buffered. + * + * This call is required if PrepareComposite ever succeeds. + */ void (*DoneComposite) (PixmapPtr pDst); + /** @} */ - /* Attempt to upload the data from src into the rectangle of the - * in-framebuffer pDst beginning at x,y and of width w,h. May fail. + /** + * UploadToScreen() loads a rectangle of data from src into pDst. + * + * @param pDst destination pixmap + * @param x destination X coordinate. + * @param y destination Y coordinate + * @param width width of the rectangle to be copied + * @param height height of the rectangle to be copied + * @param src pointer to the beginning of the source data + * @param src_pitch pitch (in bytes) of the lines of source data. + * + * UploadToScreen() copies data in system memory beginning at src (with + * pitch src_pitch) into the destination pixmap from (x, y) to + * (x + width, y + height). This is typically done with hostdata uploads, + * where the CPU sets up a blit command on the hardware with instructions + * that the blit data will be fed through some sort of aperture on the card. + * + * If UploadToScreen is performed asynchronously, it is up to the driver to + * call exaMarkSync(). This is in contrast to most other acceleration calls + * in EXA. + * + * UploadToScreen can aid in pixmap migration, but is most important for + * the performance of exaGlyphs (antialiased font drawing) by allowing + * pipelining of data uploads, avoiding a sync of the card after each glyph. + * + * @return TRUE if the driver successfully uploaded the data. FALSE + * indicates that EXA should fall back to doing the upload in software. + * + * UploadToScreen() is not required, but is recommended if Composite + * acceleration is supported. */ Bool (*UploadToScreen) (PixmapPtr pDst, int x, @@ -169,13 +488,63 @@ typedef struct _ExaDriver { int h, char *src, int src_pitch); + + /** + * UploadToScratch() is used to upload a pixmap to a scratch area for + * acceleration. + * + * @param pSrc source pixmap in host memory + * @param pDst fake, scratch pixmap to be set up in offscreen memory. + * + * The UploadToScratch() call was added to support Xati before Xati had + * support for hostdata uploads and before exaGlyphs() was written. It + * behaves incorrectly (uses an invalid pixmap as pDst), and UploadToScreen() + * should be implemented instead. + * + * Drivers implementing UploadToScratch() had to set up space (likely in a + * statically allocated area) in offscreen memory, copy pSrc to that + * scratch area, and adust pDst->devKind for the pitch and + * pDst->devPrivate.ptr for the pointer to that scratch area. The driver + * was responsible for syncing (as it was implemented using memcpy() in + * Xati), and only the data from the last UploadToScratch() was guaranteed to + * be valid at any given time. + * + * UploadToScratch() should not be implemented by drivers, and will likely be + * removed in a future version of EXA. + */ Bool (*UploadToScratch) (PixmapPtr pSrc, PixmapPtr pDst); - /* Attempt to download the rectangle from the in-framebuffer pSrc into - * dst, given the pitch. May fail. Since it is likely - * accelerated, a markSync will follow it as with other acceleration - * hooks. + /** + * DownloadFromScreen loads a rectangle of data from @param pSrc into + * @param dst + * + * @param pSrc source pixmap + * @param x source X coordinate. + * @param y source Y coordinate + * @param width width of the rectangle to be copied + * @param height height of the rectangle to be copied + * @param dst pointer to the beginning of the destination data + * @param dst_pitch pitch (in bytes) of the lines of destination data. + * + * DownloadFromScreen copies data from offscreen memory in pSrc from + * (x, y) to (x + width, y + height), to system memory starting at + * dst (with pitch dst_pitch). This would usually be done + * using scatter-gather DMA, supported by a DRM call, or by blitting to AGP + * and then synchronously reading from AGP. Because the implementation + * might be synchronous, EXA leaves it up to the driver to call + * exaMarkSync() if DownloadFromScreen was asynchronous. This is in + * contrast to most other acceleration calls in EXA. + * + * DownloadFromScreen can aid in the largest bottleneck in pixmap migration, + * which is the read from framebuffer when evicting pixmaps from framebuffer + * memory. Thus, it is highly recommended, even though implementations are + * typically complicated. + * + * @return TRUE if the driver successfully downloaded the data. FALSE + * indicates that EXA should fall back to doing the download in software. + * + * UploadToScreen is not required, but is highly recommended. */ Bool (*DownloadFromScreen)(PixmapPtr pSrc, int x, int y, @@ -183,34 +552,116 @@ typedef struct _ExaDriver { char *dst, int dst_pitch); /* Should return a hrdware-dependent marker number which can - * be waited for with WaitMarker. It can be not implemented in which - * case WaitMarker must wait for idle on any given marker + * be waited for with WaitMarker(). It can be not implemented in which + * case WaitMarker() must wait for idle on any given marker * number. */ + /** + * MarkSync() requests that the driver mark a synchronization point, returning + * an driver-devined integer marker which could be requested for + * synchronization to later in WaitMarker(). This might be used in the future + * to avoid waiting for full hardware stalls before accessing pixmap data + * with the CPU, but is not important in the current incarnation of EXA. + * + * MarkSync() is optional. + */ int (*MarkSync) (ScreenPtr pScreen); + + /** + * WaitMarker() waits for all rendering before the given marker to have + * completed. If the driver does not implement MarkSync(), marker is + * meaningless, and all rendering by the hardware should be completed before + * WaitMarker() returns. + * + * WaitMarker() is required of all drivers. + */ void (*WaitMarker) (ScreenPtr pScreen, int marker); - /* These are wrapping all fb or composite operations that will cause - * a direct access to the framebuffer. You can use them to update - * endian swappers, force migration to RAM, or whatever else you find - * useful at this point. EXA can stack up to 3 calls to Prepare/Finish - * access, though they will have a different index. If your hardware - * doesn't have enough separate configurable swapper, you can return - * FALSE from PrepareAccess() to force EXA to migrate the pixmap to RAM. - * Note that DownloadFromScreen and UploadToScreen can both be called - * between PrepareAccess() and FinishAccess(). If they need to use a - * swapper, they should save & restore its setting. + /** @{ */ + /** + * PrepareAccess() is called before CPU access to an offscreen pixmap. + * + * @param pPix the pixmap being accessed + * @param index the index of the pixmap being accessed. + * + * PrepareAccess() will be called before CPU access to an offscreen pixmap. + * This can be used to set up hardware surfaces for byteswapping or + * untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of + * making CPU access use a different aperture. + * + * The index is one of EXA_PREPARE_DEST, EXA_PREPARE_SRC, or EXA_PREPARE_MASK, + * indicating which pixmap is in question. Since only up to three + * pixmaps will have PrepareAccess() called on them per operation, drivers + * can have a small, statically-allocated space to maintain state + * for PrepareAccess() and FinishAccess() in. Note that the same pixmap may have + * PrepareAccess() called on it more than once, for example when doing a copy + * within the same pixmap (so it gets PrepareAccess as EXA_PREPARE_DEST and + * then as EXA_PREPARE_SRC). + * + * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU + * drawing. Failure means that EXA should migrate the pixmap out of + * offscreen memory, but this code path is currently broken. Note that + * DownloadFromScreen() will be called in case of a PrepareAccess() failure. + * Also, PrepareAccess() may not fail on a pixmap representing the front + * buffer, because the front buffer may not be migrated. */ Bool (*PrepareAccess)(PixmapPtr pPix, int index); + + /** + * FinishAccess() is called after CPU access to an offscreen pixmap. + * + * @param pPix the pixmap being accessed + * @param index the index of the pixmap being accessed. + * + * FinishAccess() will be called after finishing CPU access of an offscreen + * pixmap set up by PrepareAccess(). Note that the FinishAccess() will not be + * called if PrepareAccess() failed and the pixmap was migrated out. + */ void (*FinishAccess)(PixmapPtr pPix, int index); + + /** @name PrepareAccess() and FinishAccess() indices + * @{ + */ + /** + * EXA_PREPARE_DEST is the index for a pixmap that may be drawn to or + * read from. + */ #define EXA_PREPARE_DEST 0 + /** + * EXA_PREPARE_SRC is the index for a pixmap that may be read from + */ #define EXA_PREPARE_SRC 1 + /** + * EXA_PREPARE_SRC is the index for a second pixmap that may be read + * from. + */ #define EXA_PREPARE_MASK 2 + /** @} */ + /** @} */ } ExaDriverRec, *ExaDriverPtr; -#define EXA_OFFSCREEN_PIXMAPS (1 << 0) -#define EXA_OFFSCREEN_ALIGN_POT (1 << 1) -#define EXA_TWO_BITBLT_DIRECTIONS (1 << 2) +/** @name EXA driver flags + * @{ + */ +/** + * EXA_OFFSCREEN_PIXMAPS indicates to EXA that the driver can support + * offscreen pixmaps. + */ +#define EXA_OFFSCREEN_PIXMAPS (1 << 0) + +/** + * EXA_OFFSCREEN_ALIGN_POT indicates to EXA that the driver needs pixmaps + * to have a power-of-two pitch. + */ +#define EXA_OFFSCREEN_ALIGN_POT (1 << 1) + +/** + * EXA_TWO_BITBLT_DIRECTIONS indicates to EXA that the driver can only + * support copies that are (left-to-right, top-to-bottom) or + * (right-to-left, bottom-to-top). + */ +#define EXA_TWO_BITBLT_DIRECTIONS (1 << 2) +/** @} */ ExaDriverPtr exaDriverAlloc(void); @@ -227,9 +678,6 @@ exaMarkSync(ScreenPtr pScreen); void exaWaitSync(ScreenPtr pScreen); -Bool -exaOffscreenInit(ScreenPtr pScreen); - ExaOffscreenArea * exaOffscreenAlloc(ScreenPtr pScreen, int size, int align, Bool locked, diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c index f3d9c7d6e..861093381 100644 --- a/exa/exa_offscreen.c +++ b/exa/exa_offscreen.c @@ -20,6 +20,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/** @file + * This allocator allocates blocks of memory by maintaining a list of areas + * and a score for each area. As an area is marked used, its score is + * incremented, and periodically all of the areas have their scores decayed by + * a fraction. When allocating, the contiguous block of areas with the minimum + * score is found and evicted in order to make room for the new allocation. + */ + #include "exa_priv.h" #include <limits.h> @@ -63,6 +71,26 @@ ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area) return exaOffscreenFree (pScreen, area); } +/** + * exaOffscreenAlloc allocates offscreen memory + * + * @param pScreen current screen + * @param size size in bytes of the allocation + * @param align byte alignment requirement for the offset of the allocated area + * @param locked whether the allocated area is locked and can't be kicked out + * @param save callback for when the area is evicted from memory + * @param privdata private data for the save callback. + * + * Allocates offscreen memory from the device associated with pScreen. size and + * align deteremine where and how large the allocated area is, and locked will + * mark whether it should be held in card memory. privdata may be any pointer + * for the save callback when the area is removed. + * + * Note that locked areas do get evicted on VT switch, because during that time + * all offscreen memory becomes inaccessible. This may change in the future, + * but drivers should be aware of this and provide a callback to mark that their + * locked allocation was evicted, and then restore it if necessary on EnterVT. + */ ExaOffscreenArea * exaOffscreenAlloc (ScreenPtr pScreen, int size, int align, Bool locked, @@ -289,6 +317,19 @@ ExaOffscreenMerge (ExaOffscreenArea *area) xfree (next); } +/** + * exaOffscreenFree frees an allocation. + * + * @param pScreen current screen + * @param area offscreen area to free + * + * exaOffscreenFree frees an allocation created by exaOffscreenAlloc. Note that + * the save callback of the area is not called, and it is up to the driver to + * do any cleanup necessary as a result. + * + * @return pointer to the newly freed area. This behavior should not be relied + * on. + */ ExaOffscreenArea * exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area) { @@ -352,6 +393,14 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap) } } +/** + * exaOffscreenInit initializes the offscreen memory manager. + * + * @param pScreen current screen + * + * exaOffscreenInit is called by exaDriverInit to set up the memory manager for + * the screen, if any offscreen memory is available. + */ Bool exaOffscreenInit (ScreenPtr pScreen) { diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 25bbbde5e..048566e00 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -281,6 +281,9 @@ ExaOffscreenSwapOut (ScreenPtr pScreen); void ExaOffscreenSwapIn (ScreenPtr pScreen); +Bool +exaOffscreenInit(ScreenPtr pScreen); + void ExaOffscreenFini (ScreenPtr pScreen); |