summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--exa/exa.c82
-rw-r--r--exa/exa.h538
-rw-r--r--exa/exa_offscreen.c49
-rw-r--r--exa/exa_priv.h3
5 files changed, 631 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index eb9fe1c88..0f9d695a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2006-03-09 Eric Anholt <anholt@FreeBSD.org>
+
+ * exa/exa.c:
+ * exa/exa.h:
+ * exa/exa_offscreen.c:
+ * exa/exa_priv.h:
+ * hw/xfree86/doc/devel/exa-driver.txt:
+ Do a first pass of doxygen documentation of EXA. This removes the
+ corresponding pieces of exa-driver.txt, which were becoming stale.
+ Hopefully the documentation will stay much more up-to-date this way.
+ Many thanks to jbarnes for writing exa-driver.txt which was used a lot
+ in writing this documentation.
+
2006-03-09 Matthias Hopf <mhopf@suse.de>
* configure.ac: Do Xorg configure checks for Xgl only as well
diff --git a/exa/exa.c b/exa/exa.c
index fd29aa09d..7d72954c5 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -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);
diff --git a/exa/exa.h b/exa/exa.h
index c65ec68c1..9af098ebe 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -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);