xf86-video-intel: Branch 'drm-gem' - 11 commits - configure.ac Makefile.am src/i830_accel.c src/i830_batchbuffer.h src/i830_debug.c src/i830_dri.c src/i830_dri.h src/i830_driver.c src/i830_exa.c src/i830.h src/i830_memory.c src/i830_render.c src/i830_video.c src/i915_render.c src/i915_video.c src/Makefile.am uxa/Makefile.am uxa/uxa-accel.c uxa/uxa.c uxa/uxa-glyphs.c uxa/uxa.h uxa/uxa-priv.h uxa/uxa-render.c uxa/uxa-unaccel.c
Keith Packard
keithp at kemper.freedesktop.org
Wed Aug 6 00:17:54 PDT 2008
Makefile.am | 2
configure.ac | 1
src/Makefile.am | 6
src/i830.h | 36 +
src/i830_accel.c | 79 +++
src/i830_batchbuffer.h | 22 -
src/i830_debug.c | 2
src/i830_dri.c | 13
src/i830_dri.h | 1
src/i830_driver.c | 173 +++++---
src/i830_exa.c | 324 ++++++++++++---
src/i830_memory.c | 85 +---
src/i830_render.c | 15
src/i830_video.c | 4
src/i915_render.c | 8
src/i915_video.c | 2
uxa/Makefile.am | 20
uxa/uxa-accel.c | 1032 +++++++++++++++++++++++++++++++++++++++++++++++++
uxa/uxa-glyphs.c | 880 +++++++++++++++++++++++++++++++++++++++++
uxa/uxa-priv.h | 443 +++++++++++++++++++++
uxa/uxa-render.c | 1015 ++++++++++++++++++++++++++++++++++++++++++++++++
uxa/uxa-unaccel.c | 370 +++++++++++++++++
uxa/uxa.c | 510 ++++++++++++++++++++++++
uxa/uxa.h | 528 +++++++++++++++++++++++++
24 files changed, 5348 insertions(+), 223 deletions(-)
New commits:
commit fc3e287e6b6db21b113aa40ec4d397802c067f8b
Author: Keith Packard <keithp at keithp.com>
Date: Tue Aug 5 22:50:01 2008 -0700
[uxa] Remove unused pixmap size limits.
All size-related rendering limits should be managed by the driver in the
pixmap_is_offscreen call. There's no need for uxa to even know these values.
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 87a7e6c..2041741 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -720,9 +720,6 @@ i830_uxa_init (ScreenPtr pScreen)
i830->uxa_driver->uxa_major = 1;
i830->uxa_driver->uxa_minor = 0;
- i830->uxa_driver->max_x = i830->accel_max_x;
- i830->uxa_driver->max_y = i830->accel_max_y;
-
/* Solid fill */
i830->uxa_driver->prepare_solid = I830EXAPrepareSolid;
i830->uxa_driver->solid = I830EXASolid;
diff --git a/uxa/uxa.c b/uxa/uxa.c
index c76cb1d..aac3d68 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -408,20 +408,6 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
return FALSE;
}
- /* If the driver doesn't set any max pitch values, we'll just assume
- * that there's a limitation by pixels, and that it's the same as
- * maxX.
- *
- * We want max_pitch_pixels or max_pitch_bytes to be set so we can check
- * pixmaps against the max pitch in uxaCreatePixmap() -- it matters
- * whether a pixmap is rejected because of its pitch or
- * because of its width.
- */
- if (!uxa_driver->max_pitch_pixels && !uxa_driver->max_pitch_bytes)
- {
- uxa_driver->max_pitch_pixels = uxa_driver->max_x;
- }
-
#ifdef RENDER
ps = GetPictureScreenIfSet(screen);
#endif
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 22889b7..f1c1cfa 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -68,26 +68,6 @@ typedef struct _UxaDriver {
*/
int flags;
- /** @{ */
- /**
- * max_x controls the X coordinate limitation for rendering from the card.
- * The driver should never receive a request for rendering beyond max_x
- * in the X direction from the origin of a pixmap.
- */
- int max_x;
-
- /**
- * max_y controls the Y coordinate limitation for rendering from the card.
- * The driver should never receive a request for rendering beyond max_y
- * in the Y direction from the origin of a pixmap.
- */
- int max_y;
- /** @} */
-
- /* private */
- Bool needsSync;
- int lastMarker;
-
/** @name solid
* @{
*/
@@ -510,36 +490,6 @@ typedef struct _UxaDriver {
*/
Bool (*pixmap_is_offscreen)(PixmapPtr pPix);
- /**
- * max_pitch_pixels controls the pitch limitation for rendering from
- * the card.
- * The driver should never receive a request for rendering a pixmap
- * that has a pitch (in pixels) beyond max_pitch_pixels.
- *
- * Setting this field is optional -- if your hardware doesn't have
- * a pitch limitation in pixels, don't set this. If neither this value
- * nor max_pitch_bytes is set, then max_pitch_pixels is set to max_x.
- * If set, it must not be smaller than max_x.
- *
- * @sa max_pitch_bytes
- */
- int max_pitch_pixels;
-
- /**
- * max_pitch_bytes controls the pitch limitation for rendering from
- * the card.
- * The driver should never receive a request for rendering a pixmap
- * that has a pitch (in bytes) beyond max_pitch_bytes.
- *
- * Setting this field is optional -- if your hardware doesn't have
- * a pitch limitation in bytes, don't set this.
- * If set, it must not be smaller than max_x * 4.
- * There's no default value for max_pitch_bytes.
- *
- * @sa max_pitch_pixels
- */
- int max_pitch_bytes;
-
/** @} */
} uxa_driver_t;
commit 68f0872db6ec4d5dc3b524ee08ecad0aa125acd9
Author: Keith Packard <keithp at keithp.com>
Date: Tue Aug 5 22:36:03 2008 -0700
[uxa] Check xalloc returns and deal with failure
Failing xalloc in a rendering function means just dropping the drawing on
the floor (that's what we've always done).
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index edc68f2..b25a8fa 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -508,6 +508,8 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
}
prect = xalloc(sizeof(xRectangle) * npt);
+ if (!prect)
+ return;
for (i = 0; i < npt; i++) {
prect[i].x = ppt[i].x;
prect[i].y = ppt[i].y;
@@ -543,6 +545,8 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
}
prect = xalloc(sizeof(xRectangle) * (npt - 1));
+ if (!prect)
+ return;
x1 = ppt[0].x;
y1 = ppt[0].y;
/* If we have any non-horizontal/vertical, fall back. */
@@ -612,6 +616,8 @@ uxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
}
prect = xalloc(sizeof(xRectangle) * nseg);
+ if (!prect)
+ return;
for (i = 0; i < nseg; i++) {
if (pSeg[i].x1 < pSeg[i].x2) {
prect[i].x = pSeg[i].x1;
commit 8f10bfb127bfe73d83d58f1f306fb9a4dfd825d6
Author: Keith Packard <keithp at keithp.com>
Date: Tue Aug 5 22:34:24 2008 -0700
Use EXA by default instead of UXA until we have GTT mapping
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 6b8f998..6cc2352 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1582,12 +1582,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
#ifdef I830_USE_XAA
pI830->accel = ACCEL_XAA;
#endif
-#ifdef I830_USE_EXA
- pI830->accel = ACCEL_EXA;
-#endif
#ifdef I830_USE_UXA
pI830->accel = ACCEL_UXA;
#endif
+#ifdef I830_USE_EXA
+ pI830->accel = ACCEL_EXA;
+#endif
#if I830_USE_XAA + I830_USE_EXA + I830_USE_UXA >= 2
from = X_DEFAULT;
if ((s = (char *)xf86GetOptValString(pI830->Options,
commit b2d058d80ccd08d9e02ef866ee7a95b58686f6a3
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 23:43:13 2008 -0700
Rename uxa using _ instead of caps
diff --git a/src/i830.h b/src/i830.h
index dbcf3c0..d87e5d9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -538,6 +538,7 @@ typedef struct _I830Rec {
#ifdef I830_USE_UXA
uxa_driver_t *uxa_driver;
Bool need_flush;
+ Bool need_sync;
#endif
#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
PixmapPtr pSrcPixmap;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index bef3bb8..6b8f998 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3887,9 +3887,9 @@ i830WaitSync(ScrnInfoPtr pScrn)
#endif
#ifdef I830_USE_UXA
case ACCEL_UXA:
- if (pI830->uxa_driver) {
- ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
- uxa_wait_sync(pScreen);
+ if (pI830->uxa_driver && pI830->need_sync) {
+ pI830->need_sync = FALSE;
+ I830Sync(pScrn);
}
break;
#endif
@@ -3920,10 +3920,8 @@ i830MarkSync(ScrnInfoPtr pScrn)
#endif
#ifdef I830_USE_UXA
case ACCEL_UXA:
- if (pI830->uxa_driver) {
- ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
- exaMarkSync(pScreen);
- }
+ if (pI830->uxa_driver)
+ pI830->need_sync = TRUE;
break;
#endif
default:
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 08d73b5..87a7e6c 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,6 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#define ALWAYS_SYNC 0
+#define ALWAYS_FLUSH 0
#ifdef DEBUG_I830FALLBACK
#define I830FALLBACK(s, arg...) \
@@ -247,11 +248,16 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
static void
I830EXADoneSolid(PixmapPtr pPixmap)
{
-#if ALWAYS_SYNC
+#if ALWAYS_SYNC || ALWAYS_FLUSH || 1
ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+#if ALWAYS_FLUSH || 1
+ intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
I830Sync(pScrn);
#endif
+#endif
}
/**
@@ -343,11 +349,37 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
static void
I830EXADoneCopy(PixmapPtr pDstPixmap)
{
-#if ALWAYS_SYNC
+#if ALWAYS_SYNC || ALWAYS_FLUSH
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+#if ALWAYS_FLUSH
+ intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
+ I830Sync(pScrn);
+#endif
+#endif
+}
+
+
+/**
+ * Do any cleanup from the Composite operation.
+ *
+ * This is shared between i830 through i965.
+ */
+void
+i830_done_composite(PixmapPtr pDst)
+{
+#if ALWAYS_SYNC || ALWAYS_FLUSH
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+
+#if ALWAYS_FLUSH
+ intel_batch_flush(pScrn);
+#endif
+#if ALWAYS_SYNC
I830Sync(pScrn);
#endif
+#endif
}
#define xFixedToFloat(val) \
@@ -558,7 +590,15 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo) {
- intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+
+ intel_batch_flush(scrn);
+ if (i830->need_sync) {
+ I830Sync(scrn);
+ i830->need_sync = FALSE;
+ }
if (dri_bo_map (bo, access == UXA_ACCESS_RW) != 0)
return FALSE;
pixmap->devPrivate.ptr = bo->virtual;
@@ -680,47 +720,42 @@ i830_uxa_init (ScreenPtr pScreen)
i830->uxa_driver->uxa_major = 1;
i830->uxa_driver->uxa_minor = 0;
- i830->uxa_driver->maxX = i830->accel_max_x;
- i830->uxa_driver->maxY = i830->accel_max_y;
-
- /* Sync */
- i830->uxa_driver->WaitMarker = I830EXASync;
+ i830->uxa_driver->max_x = i830->accel_max_x;
+ i830->uxa_driver->max_y = i830->accel_max_y;
/* Solid fill */
- i830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
- i830->uxa_driver->Solid = I830EXASolid;
- i830->uxa_driver->DoneSolid = I830EXADoneSolid;
+ i830->uxa_driver->prepare_solid = I830EXAPrepareSolid;
+ i830->uxa_driver->solid = I830EXASolid;
+ i830->uxa_driver->done_solid = I830EXADoneSolid;
/* Copy */
- i830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
- i830->uxa_driver->Copy = I830EXACopy;
- i830->uxa_driver->DoneCopy = I830EXADoneCopy;
+ i830->uxa_driver->prepare_copy = I830EXAPrepareCopy;
+ i830->uxa_driver->copy = I830EXACopy;
+ i830->uxa_driver->done_copy = I830EXADoneCopy;
-#if 0
/* Composite */
if (!IS_I9XX(i830)) {
- i830->uxa_driver->CheckComposite = i830_check_composite;
- i830->uxa_driver->PrepareComposite = i830_prepare_composite;
- i830->uxa_driver->Composite = i830_composite;
- i830->uxa_driver->DoneComposite = i830_done_composite;
+ i830->uxa_driver->check_composite = i830_check_composite;
+ i830->uxa_driver->prepare_composite = i830_prepare_composite;
+ i830->uxa_driver->composite = i830_composite;
+ i830->uxa_driver->done_composite = i830_done_composite;
} else if (IS_I915G(i830) || IS_I915GM(i830) ||
IS_I945G(i830) || IS_I945GM(i830) || IS_G33CLASS(i830))
{
- i830->uxa_driver->CheckComposite = i915_check_composite;
- i830->uxa_driver->PrepareComposite = i915_prepare_composite;
- i830->uxa_driver->Composite = i830_composite;
- i830->uxa_driver->DoneComposite = i830_done_composite;
+ i830->uxa_driver->check_composite = i915_check_composite;
+ i830->uxa_driver->prepare_composite = i915_prepare_composite;
+ i830->uxa_driver->composite = i830_composite;
+ i830->uxa_driver->done_composite = i830_done_composite;
} else {
- i830->uxa_driver->CheckComposite = i965_check_composite;
- i830->uxa_driver->PrepareComposite = i965_prepare_composite;
- i830->uxa_driver->Composite = i965_composite;
- i830->uxa_driver->DoneComposite = i830_done_composite;
+ i830->uxa_driver->check_composite = i965_check_composite;
+ i830->uxa_driver->prepare_composite = i965_prepare_composite;
+ i830->uxa_driver->composite = i965_composite;
+ i830->uxa_driver->done_composite = i830_done_composite;
}
-#endif
- i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
- i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
- i830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+ i830->uxa_driver->prepare_access = i830_uxa_prepare_access;
+ i830->uxa_driver->finish_access = i830_uxa_finish_access;
+ i830->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen;
if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
diff --git a/src/i830_render.c b/src/i830_render.c
index 4b42ea3..c1ce856 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -733,14 +733,3 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
ADVANCE_BATCH();
}
-
-/**
- * Do any cleanup from the Composite operation.
- *
- * This is shared between i830 through i965.
- */
-void
-i830_done_composite(PixmapPtr pDst)
-{
- /* NO-OP */
-}
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 20a5657..edc68f2 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -37,7 +37,7 @@
static void
uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
- DDXPointPtr ppt, int *pwidth, int fSorted)
+ DDXPointPtr ppt, int *pwidth, int fSorted)
{
ScreenPtr pScreen = pDrawable->pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
@@ -52,10 +52,10 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
!(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) ||
- !(*uxa_screen->info->PrepareSolid) (pPixmap,
- pGC->alu,
- pGC->planemask,
- pGC->fgPixel))
+ !(*uxa_screen->info->prepare_solid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
{
uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
@@ -89,9 +89,9 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
nbox = REGION_NUM_RECTS (pClip);
if (nbox == 1)
{
- (*uxa_screen->info->Solid) (pPixmap,
- fullX1 + off_x, fullY1 + off_y,
- fullX2 + off_x, fullY1 + 1 + off_y);
+ (*uxa_screen->info->solid) (pPixmap,
+ fullX1 + off_x, fullY1 + off_y,
+ fullX2 + off_x, fullY1 + 1 + off_y);
}
else
{
@@ -107,22 +107,21 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
if (partX2 > fullX2)
partX2 = fullX2;
if (partX2 > partX1) {
- (*uxa_screen->info->Solid) (pPixmap,
- partX1 + off_x, fullY1 + off_y,
- partX2 + off_x, fullY1 + 1 + off_y);
+ (*uxa_screen->info->solid) (pPixmap,
+ partX1 + off_x, fullY1 + off_y,
+ partX2 + off_x, fullY1 + 1 + off_y);
}
}
pbox++;
}
}
}
- (*uxa_screen->info->DoneSolid) (pPixmap);
- uxa_mark_sync(pScreen);
+ (*uxa_screen->info->done_solid) (pPixmap);
}
static Bool
uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
- int w, int h, int format, char *bits, int src_stride)
+ int w, int h, int format, char *bits, int src_stride)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
@@ -146,7 +145,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
- if (!pPix || !uxa_screen->info->UploadToScreen)
+ if (!pPix || !uxa_screen->info->put_image)
return FALSE;
x += pDrawable->x;
@@ -177,8 +176,8 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
continue;
src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
- ok = uxa_screen->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
- x2 - x1, y2 - y1, src, src_stride);
+ ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff,
+ x2 - x1, y2 - y1, src, src_stride);
/* If we fail to accelerate the upload, fall back to using unaccelerated
* fb calls.
*/
@@ -210,8 +209,6 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (access_prepared)
uxa_finish_access(pDrawable);
- else
- uxa_mark_sync(pDrawable->pScreen);
return TRUE;
}
@@ -226,8 +223,8 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
int src_stride = PixmapBytePad(w, depth);
if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
- sy * src_stride + sx * BitsPerPixel(depth) / 8,
- src_stride))
+ sy * src_stride + sx * BitsPerPixel(depth) / 8,
+ src_stride))
return TRUE;
if (format == ZPixmap)
@@ -235,12 +232,12 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
PixmapPtr pPixmap;
pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
- BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
+ BitsPerPixel(depth), PixmapBytePad(w, depth),
+ (pointer)data);
if (!pPixmap)
return FALSE;
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
-
fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
uxa_finish_access(pDrawable);
@@ -260,11 +257,11 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
*/
void
uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
- int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
- char *data)
+ int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+ char *data)
{
if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
- dx, dy, data)) {
+ dx, dy, data)) {
uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
data);
@@ -316,9 +313,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
/* Do a xdir = ydir = -1 blit instead. */
if (dirsetup != -1) {
if (dirsetup != 0)
- uxa_screen->info->DoneCopy(pDstPixmap);
+ uxa_screen->info->done_copy(pDstPixmap);
dirsetup = -1;
- if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
pDstPixmap,
-1, -1,
pGC ? pGC->alu : GXcopy,
@@ -326,7 +323,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
FB_ALLONES))
return FALSE;
}
- (*uxa_screen->info->Copy)(pDstPixmap,
+ (*uxa_screen->info->copy)(pDstPixmap,
src_off_x + pbox->x1 + dx,
src_off_y + pbox->y1 + dy,
dst_off_x + pbox->x1,
@@ -337,9 +334,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
/* Do a xdir = ydir = 1 blit instead. */
if (dirsetup != 1) {
if (dirsetup != 0)
- uxa_screen->info->DoneCopy(pDstPixmap);
+ uxa_screen->info->done_copy(pDstPixmap);
dirsetup = 1;
- if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
pDstPixmap,
1, 1,
pGC ? pGC->alu : GXcopy,
@@ -347,7 +344,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
FB_ALLONES))
return FALSE;
}
- (*uxa_screen->info->Copy)(pDstPixmap,
+ (*uxa_screen->info->copy)(pDstPixmap,
src_off_x + pbox->x1 + dx,
src_off_y + pbox->y1 + dy,
dst_off_x + pbox->x1,
@@ -362,9 +359,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
int i;
if (dirsetup != 1) {
if (dirsetup != 0)
- uxa_screen->info->DoneCopy(pDstPixmap);
+ uxa_screen->info->done_copy(pDstPixmap);
dirsetup = 1;
- if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
pDstPixmap,
1, 1,
pGC ? pGC->alu : GXcopy,
@@ -373,7 +370,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
return FALSE;
}
for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
- (*uxa_screen->info->Copy)(pDstPixmap,
+ (*uxa_screen->info->copy)(pDstPixmap,
src_off_x + pbox->x1 + dx,
src_off_y + pbox->y1 + dy + i,
dst_off_x + pbox->x1,
@@ -387,9 +384,9 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
int i;
if (dirsetup != -1) {
if (dirsetup != 0)
- uxa_screen->info->DoneCopy(pDstPixmap);
+ uxa_screen->info->done_copy(pDstPixmap);
dirsetup = -1;
- if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
pDstPixmap,
-1, -1,
pGC ? pGC->alu : GXcopy,
@@ -398,7 +395,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
return FALSE;
}
for (i = 0; i < pbox->y2 - pbox->y1; i++)
- (*uxa_screen->info->Copy)(pDstPixmap,
+ (*uxa_screen->info->copy)(pDstPixmap,
src_off_x + pbox->x1 + dx,
src_off_y + pbox->y1 + dy + i,
dst_off_x + pbox->x1,
@@ -407,8 +404,7 @@ uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
}
}
if (dirsetup != 0)
- uxa_screen->info->DoneCopy(pDstPixmap);
- uxa_mark_sync(pDstDrawable->pScreen);
+ uxa_screen->info->done_copy(pDstPixmap);
return TRUE;
}
@@ -447,7 +443,7 @@ uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
if (!uxa_pixmap_is_offscreen(pSrcPixmap) ||
!uxa_pixmap_is_offscreen(pDstPixmap) ||
- !(*uxa_screen->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ !(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
upsidedown ? -1 : 1,
pGC ? pGC->alu : GXcopy,
pGC ? pGC->planemask : FB_ALLONES)) {
@@ -456,7 +452,7 @@ uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
while (nbox--)
{
- (*uxa_screen->info->Copy) (pDstPixmap,
+ (*uxa_screen->info->copy) (pDstPixmap,
pbox->x1 + dx + src_off_x,
pbox->y1 + dy + src_off_y,
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
@@ -464,8 +460,7 @@ uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
pbox++;
}
- (*uxa_screen->info->DoneCopy) (pDstPixmap);
- uxa_mark_sync (pDstDrawable->pScreen);
+ (*uxa_screen->info->done_copy) (pDstPixmap);
return;
@@ -704,7 +699,7 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
}
if (!uxa_pixmap_is_offscreen (pPixmap) ||
- !(*uxa_screen->info->PrepareSolid) (pPixmap,
+ !(*uxa_screen->info->prepare_solid) (pPixmap,
pGC->alu,
pGC->planemask,
pGC->fgPixel))
@@ -747,7 +742,7 @@ fallback:
n = REGION_NUM_RECTS (pClip);
if (n == 1)
{
- (*uxa_screen->info->Solid) (pPixmap,
+ (*uxa_screen->info->solid) (pPixmap,
fullX1 + xoff, fullY1 + yoff,
fullX2 + xoff, fullY2 + yoff);
}
@@ -777,15 +772,14 @@ fallback:
pbox++;
if (partX1 < partX2 && partY1 < partY2) {
- (*uxa_screen->info->Solid) (pPixmap,
+ (*uxa_screen->info->solid) (pPixmap,
partX1 + xoff, partY1 + yoff,
partX2 + xoff, partY2 + yoff);
}
}
}
}
- (*uxa_screen->info->DoneSolid) (pPixmap);
- uxa_mark_sync(pDrawable->pScreen);
+ (*uxa_screen->info->done_solid) (pPixmap);
out:
REGION_UNINIT(pScreen, pReg);
@@ -858,7 +852,7 @@ uxa_fill_region_solid (DrawablePtr pDrawable,
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (uxa_pixmap_is_offscreen (pPixmap) &&
- (*uxa_screen->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+ (*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel))
{
int nbox;
BoxPtr pBox;
@@ -868,12 +862,11 @@ uxa_fill_region_solid (DrawablePtr pDrawable,
while (nbox--)
{
- (*uxa_screen->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
pBox->y2);
pBox++;
}
- (*uxa_screen->info->DoneSolid) (pPixmap);
- uxa_mark_sync(pDrawable->pScreen);
+ (*uxa_screen->info->done_solid) (pPixmap);
ret = TRUE;
}
@@ -906,7 +899,7 @@ uxa_fill_region_tiled (DrawablePtr pDrawable,
tileHeight = pTile->drawable.height;
/* If we're filling with a solid color, grab it out and go to
- * FillRegionSolid, saving numerous copies.
+ * FillRegionsolid, saving numerous copies.
*/
if (tileWidth == 1 && tileHeight == 1)
return uxa_fill_region_solid(pDrawable, pRegion,
@@ -922,7 +915,7 @@ uxa_fill_region_tiled (DrawablePtr pDrawable,
if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
goto out;
- if ((*uxa_screen->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+ if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask))
{
while (nbox--)
{
@@ -951,7 +944,7 @@ uxa_fill_region_tiled (DrawablePtr pDrawable,
w = width;
width -= w;
- (*uxa_screen->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
+ (*uxa_screen->info->copy) (pPixmap, tileX, tileY, dstX, dstY,
w, h);
dstX += w;
tileX = 0;
@@ -961,8 +954,7 @@ uxa_fill_region_tiled (DrawablePtr pDrawable,
}
pBox++;
}
- (*uxa_screen->info->DoneCopy) (pPixmap);
- uxa_mark_sync(pDrawable->pScreen);
+ (*uxa_screen->info->done_copy) (pPixmap);
ret = TRUE;
}
@@ -1003,7 +995,7 @@ uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
- if (pPix == NULL || uxa_screen->info->DownloadFromScreen == NULL)
+ if (pPix == NULL || uxa_screen->info->get_image == NULL)
goto fallback;
/* Only cover the ZPixmap, solid copy case. */
@@ -1016,13 +1008,11 @@ uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
if (pDrawable->bitsPerPixel < 8)
goto fallback;
- ok = uxa_screen->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+ ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff,
pDrawable->y + y + yoff, w, h, d,
PixmapBytePad(w, pDrawable->depth));
- if (ok) {
- uxa_wait_sync(pDrawable->pScreen);
- goto out;
- }
+ if (ok)
+ return;
fallback:
UXA_FALLBACK(("from %p (%c)\n", pDrawable,
@@ -1032,6 +1022,5 @@ fallback:
fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
uxa_finish_access (pDrawable);
-out:
return;
}
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
index 3c44640..364fcfb 100644
--- a/uxa/uxa-glyphs.c
+++ b/uxa/uxa-glyphs.c
@@ -362,7 +362,7 @@ uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
int cacheXoff, cacheYoff;
- if (!uxa_screen->info->UploadToScreen || uxa_screen->swappedOut)
+ if (!uxa_screen->info->put_image || uxa_screen->swappedOut)
return FALSE;
/* If the glyph pixmap is already uploaded, no point in doing
@@ -378,13 +378,13 @@ uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
if (!pCachePixmap)
return FALSE;
- if (!uxa_screen->info->UploadToScreen(pCachePixmap,
- CACHE_X(pos) + cacheXoff,
- CACHE_Y(pos) + cacheYoff,
- pGlyph->info.width,
- pGlyph->info.height,
- (char *)pGlyphPixmap->devPrivate.ptr,
- pGlyphPixmap->devKind))
+ if (!uxa_screen->info->put_image(pCachePixmap,
+ CACHE_X(pos) + cacheXoff,
+ CACHE_Y(pos) + cacheYoff,
+ pGlyph->info.width,
+ pGlyph->info.height,
+ (char *)pGlyphPixmap->devPrivate.ptr,
+ pGlyphPixmap->devKind))
return FALSE;
return TRUE;
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index 1e4f4ea..c50ab3a 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -117,7 +117,6 @@ typedef struct {
#define UXA_NUM_GLYPH_CACHES 4
-typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
typedef struct {
uxa_driver_t *info;
CreateGCProcPtr SavedCreateGC;
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 9c79fce..94e18a5 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -291,7 +291,7 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
return -1;
}
- if (!(*uxa_screen->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
+ if (!(*uxa_screen->info->prepare_solid) (pDstPix, GXcopy, 0xffffffff, pixel))
{
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
return -1;
@@ -302,60 +302,46 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
while (nbox--)
{
- (*uxa_screen->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+ (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
pbox++;
}
- (*uxa_screen->info->DoneSolid) (pDstPix);
- uxa_mark_sync(pDst->pDrawable->pScreen);
+ (*uxa_screen->info->done_solid) (pDstPix);
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
return 1;
}
static int
-uxa_try_driver_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- int nrect,
- uxa_composite_rect_t *rects)
+uxa_try_driver_composite_rects(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ int nrect,
+ uxa_composite_rect_t *rects)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
int src_off_x, src_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pDstPix;
- struct _Pixmap scratch;
- if (!uxa_screen->info->PrepareComposite)
+ if (!uxa_screen->info->prepare_composite)
return -1;
- pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
-
- pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
-
- if (uxa_screen->info->CheckComposite &&
- !(*uxa_screen->info->CheckComposite) (op, pSrc, NULL, pDst))
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst))
{
return -1;
}
- uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
-
- pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!uxa_pixmap_is_offscreen(pDstPix))
+ pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix)
return 0;
-
- if (!pSrcPix && uxa_screen->info->UploadToScratch)
- {
- pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
- if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
- pSrcPix = &scratch;
- }
+ pSrcPix = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
if (!pSrcPix)
return 0;
- if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
- NULL, pDstPix))
+ if (!(*uxa_screen->info->prepare_composite) (op, pSrc, NULL, pDst, pSrcPix,
+ NULL, pDstPix))
return -1;
while (nrect--)
@@ -384,14 +370,14 @@ uxa_try_driver_composite_rects(CARD8 op,
while (nbox--)
{
- (*uxa_screen->info->Composite) (pDstPix,
- pbox->x1 + xSrc,
- pbox->y1 + ySrc,
- 0, 0,
- pbox->x1,
- pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
+ (*uxa_screen->info->composite) (pDstPix,
+ pbox->x1 + xSrc,
+ pbox->y1 + ySrc,
+ 0, 0,
+ pbox->x1,
+ pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
pbox++;
}
@@ -400,9 +386,7 @@ uxa_try_driver_composite_rects(CARD8 op,
rects++;
}
-
- (*uxa_screen->info->DoneComposite) (pDstPix);
- uxa_mark_sync(pDst->pDrawable->pScreen);
+ (*uxa_screen->info->done_composite) (pDstPix);
return 1;
}
@@ -467,12 +451,6 @@ uxa_try_driver_composite(CARD8 op,
int nbox;
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
- struct _Pixmap scratch;
-
- pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
- pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
- if (pMask)
- pMaskPix = uxa_get_drawable_pixmap(pMask->pDrawable);
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
@@ -485,8 +463,8 @@ uxa_try_driver_composite(CARD8 op,
xSrc += pSrc->pDrawable->x;
ySrc += pSrc->pDrawable->y;
- if (uxa_screen->info->CheckComposite &&
- !(*uxa_screen->info->CheckComposite) (op, pSrc, pMask, pDst))
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst))
{
return -1;
}
@@ -496,37 +474,23 @@ uxa_try_driver_composite(CARD8 op,
width, height))
return 1;
- uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
-
- REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
+ pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+
if (pMask)
pMaskPix = uxa_get_offscreen_pixmap (pMask->pDrawable, &mask_off_x,
- &mask_off_y);
+ &mask_off_y);
- if (!uxa_pixmap_is_offscreen(pDstPix)) {
+ if (!pDstPix || !pSrcPix || (pMask && !pMaskPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
return 0;
}
- if (!pSrcPix && (!pMask || pMaskPix) && uxa_screen->info->UploadToScratch) {
- pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
- if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
- pSrcPix = &scratch;
- } else if (pSrcPix && pMask && !pMaskPix && uxa_screen->info->UploadToScratch) {
- pMaskPix = uxa_get_drawable_pixmap (pMask->pDrawable);
- if ((*uxa_screen->info->UploadToScratch) (pMaskPix, &scratch))
- pMaskPix = &scratch;
- }
-
- if (!pSrcPix || (pMask && !pMaskPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
- return 0;
- }
+ REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
- if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
- pMaskPix, pDstPix))
+ if (!(*uxa_screen->info->prepare_composite) (op, pSrc, pMask, pDst, pSrcPix,
+ pMaskPix, pDstPix))
{
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
return -1;
@@ -543,19 +507,18 @@ uxa_try_driver_composite(CARD8 op,
while (nbox--)
{
- (*uxa_screen->info->Composite) (pDstPix,
- pbox->x1 + xSrc,
- pbox->y1 + ySrc,
- pbox->x1 + xMask,
- pbox->y1 + yMask,
- pbox->x1,
- pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
+ (*uxa_screen->info->composite) (pDstPix,
+ pbox->x1 + xSrc,
+ pbox->y1 + ySrc,
+ pbox->x1 + xMask,
+ pbox->y1 + yMask,
+ pbox->x1,
+ pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
pbox++;
}
- (*uxa_screen->info->DoneComposite) (pDstPix);
- uxa_mark_sync(pDst->pDrawable->pScreen);
+ (*uxa_screen->info->done_composite) (pDstPix);
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
return 1;
@@ -628,10 +591,10 @@ uxa_try_magic_two_pass_composite_helper(CARD8 op,
assert(op == PictOpOver);
- if (uxa_screen->info->CheckComposite &&
- (!(*uxa_screen->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
+ if (uxa_screen->info->check_composite &&
+ (!(*uxa_screen->info->check_composite)(PictOpOutReverse, pSrc, pMask,
pDst) ||
- !(*uxa_screen->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))
+ !(*uxa_screen->info->check_composite)(PictOpAdd, pSrc, pMask, pDst)))
{
return -1;
}
@@ -735,7 +698,7 @@ uxa_composite(CARD8 op,
DDXPointRec patOrg;
/* Let's see if the driver can do the repeat in one go */
- if (uxa_screen->info->PrepareComposite && !pSrc->alphaMap &&
+ if (uxa_screen->info->prepare_composite && !pSrc->alphaMap &&
!pDst->alphaMap)
{
ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
@@ -779,7 +742,7 @@ uxa_composite(CARD8 op,
(yMask + height) <= pMask->pDrawable->height)
pMask->repeat = 0;
- if (uxa_screen->info->PrepareComposite &&
+ if (uxa_screen->info->prepare_composite &&
!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
{
Bool isSrcSolid;
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 5fe0f32..c76cb1d 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -100,8 +100,8 @@ uxa_pixmap_is_offscreen(PixmapPtr p)
ScreenPtr pScreen = p->drawable.pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- if (uxa_screen->info->PixmapIsOffscreen)
- return uxa_screen->info->PixmapIsOffscreen(p);
+ if (uxa_screen->info->pixmap_is_offscreen)
+ return uxa_screen->info->pixmap_is_offscreen(p);
return FALSE;
}
@@ -151,14 +151,14 @@ uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
if (!offscreen)
return;
- if (uxa_screen->info->PrepareAccess)
- (*uxa_screen->info->PrepareAccess) (pPixmap, access);
+ if (uxa_screen->info->prepare_access)
+ (*uxa_screen->info->prepare_access) (pPixmap, access);
}
/**
- * uxa_finish_access() is UXA's wrapper for the driver's FinishAccess() handler.
+ * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
*
- * It deals with calling the driver's FinishAccess() only if necessary.
+ * It deals with calling the driver's finish_access() only if necessary.
*/
void
uxa_finish_access(DrawablePtr pDrawable)
@@ -167,13 +167,13 @@ uxa_finish_access(DrawablePtr pDrawable)
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
- if (uxa_screen->info->FinishAccess == NULL)
+ if (uxa_screen->info->finish_access == NULL)
return;
if (!uxa_pixmap_is_offscreen (pPixmap))
return;
- (*uxa_screen->info->FinishAccess) (pPixmap);
+ (*uxa_screen->info->finish_access) (pPixmap);
}
/**
@@ -185,7 +185,7 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
/* fbValidateGC will do direct access to pixmaps if the tiling has changed.
* Preempt fbValidateGC by doing its work and masking the change out, so
- * that we can do the Prepare/FinishAccess.
+ * that we can do the Prepare/finish_access.
*/
#ifdef FB_24_32BIT
if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
@@ -396,20 +396,14 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
return FALSE;
}
- if (!uxa_driver->PrepareSolid) {
- LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareSolid must be "
+ if (!uxa_driver->prepare_solid) {
+ LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_solid must be "
"non-NULL\n", screen->myNum);
return FALSE;
}
- if (!uxa_driver->PrepareCopy) {
- LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareCopy must be "
- "non-NULL\n", screen->myNum);
- return FALSE;
- }
-
- if (!uxa_driver->WaitMarker) {
- LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::WaitMarker must be "
+ if (!uxa_driver->prepare_copy) {
+ LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_copy must be "
"non-NULL\n", screen->myNum);
return FALSE;
}
@@ -418,14 +412,14 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
* that there's a limitation by pixels, and that it's the same as
* maxX.
*
- * We want maxPitchPixels or maxPitchBytes to be set so we can check
+ * We want max_pitch_pixels or max_pitch_bytes to be set so we can check
* pixmaps against the max pitch in uxaCreatePixmap() -- it matters
* whether a pixmap is rejected because of its pitch or
* because of its width.
*/
- if (!uxa_driver->maxPitchPixels && !uxa_driver->maxPitchBytes)
+ if (!uxa_driver->max_pitch_pixels && !uxa_driver->max_pitch_bytes)
{
- uxa_driver->maxPitchPixels = uxa_driver->maxX;
+ uxa_driver->max_pitch_pixels = uxa_driver->max_x;
}
#ifdef RENDER
@@ -501,18 +495,18 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
LogMessage(X_INFO, "UXA(%d): Driver registered support for the following"
" operations:\n", screen->myNum);
- assert(uxa_driver->PrepareSolid != NULL);
- LogMessage(X_INFO, " Solid\n");
- assert(uxa_driver->PrepareCopy != NULL);
- LogMessage(X_INFO, " Copy\n");
- if (uxa_driver->PrepareComposite != NULL) {
- LogMessage(X_INFO, " Composite (RENDER acceleration)\n");
+ assert(uxa_driver->prepare_solid != NULL);
+ LogMessage(X_INFO, " solid\n");
+ assert(uxa_driver->prepare_copy != NULL);
+ LogMessage(X_INFO, " copy\n");
+ if (uxa_driver->prepare_composite != NULL) {
+ LogMessage(X_INFO, " composite (RENDER acceleration)\n");
}
- if (uxa_driver->UploadToScreen != NULL) {
- LogMessage(X_INFO, " UploadToScreen\n");
+ if (uxa_driver->put_image != NULL) {
+ LogMessage(X_INFO, " put_image\n");
}
- if (uxa_driver->DownloadFromScreen != NULL) {
- LogMessage(X_INFO, " DownloadFromScreen\n");
+ if (uxa_driver->get_image != NULL) {
+ LogMessage(X_INFO, " get_image\n");
}
return TRUE;
@@ -528,43 +522,3 @@ uxa_driver_fini (ScreenPtr pScreen)
{
/*right now does nothing*/
}
-
-/**
- * uxa_mark_sync() should be called after any asynchronous drawing by the hardware.
- *
- * @param pScreen screen which drawing occurred on
- *
- * uxa_mark_sync() 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 uxa_mark_sync(ScreenPtr pScreen)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
-
- uxa_screen->info->needsSync = TRUE;
- if (uxa_screen->info->MarkSync != NULL) {
- uxa_screen->info->lastMarker = (*uxa_screen->info->MarkSync)(pScreen);
- }
-}
-
-/**
- * uxa_wait_sync() 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 uxa_wait_sync(ScreenPtr pScreen)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
-
- if (uxa_screen->info->needsSync && !uxa_screen->swappedOut) {
- (*uxa_screen->info->WaitMarker)(pScreen, uxa_screen->info->lastMarker);
- uxa_screen->info->needsSync = FALSE;
- }
-}
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 32d5a5a..22889b7 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -70,36 +70,36 @@ typedef struct _UxaDriver {
/** @{ */
/**
- * maxX controls the X coordinate limitation for rendering from the card.
- * The driver should never receive a request for rendering beyond maxX
+ * max_x controls the X coordinate limitation for rendering from the card.
+ * The driver should never receive a request for rendering beyond max_x
* in the X direction from the origin of a pixmap.
*/
- int maxX;
+ int max_x;
/**
- * maxY controls the Y coordinate limitation for rendering from the card.
- * The driver should never receive a request for rendering beyond maxY
+ * max_y controls the Y coordinate limitation for rendering from the card.
+ * The driver should never receive a request for rendering beyond max_y
* in the Y direction from the origin of a pixmap.
*/
- int maxY;
+ int max_y;
/** @} */
/* private */
Bool needsSync;
int lastMarker;
- /** @name Solid
+ /** @name solid
* @{
*/
/**
- * PrepareSolid() sets up the driver for doing a solid fill.
+ * prepare_solid() 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*
+ * 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
@@ -109,16 +109,16 @@ typedef struct _UxaDriver {
* 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
+ * The prepare_solid() 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,
+ Bool (*prepare_solid) (PixmapPtr pPixmap,
int alu,
Pixel planemask,
Pixel fg);
/**
- * Solid() performs a solid fill set up in the last PrepareSolid() call.
+ * solid() performs a solid fill set up in the last prepare_solid() call.
*
* @param pPixmap destination pixmap
* @param x1 left coordinate
@@ -126,37 +126,37 @@ typedef struct _UxaDriver {
* @param x2 right coordinate
* @param y2 bottom coordinate
*
- * Performs the fill set up by the last PrepareSolid() call, covering the
+ * Performs the fill set up by the last prepare_solid() 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 call is required if PrepareSolid() ever succeeds.
+ * This call is required if prepare_solid() ever succeeds.
*/
- void (*Solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
+ void (*solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
/**
- * DoneSolid() finishes a set of solid fills.
+ * done_solid() finishes a set of solid fills.
*
* @param pPixmap destination pixmap.
*
- * The DoneSolid() call is called at the end of a series of consecutive
- * Solid() calls following a successful PrepareSolid(). This allows drivers
+ * The done_solid() call is called at the end of a series of consecutive
+ * solid() calls following a successful prepare_solid(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
- * state from PrepareSolid().
+ * state from prepare_solid().
*
- * This call is required if PrepareSolid() ever succeeds.
+ * This call is required if prepare_solid() ever succeeds.
*/
- void (*DoneSolid) (PixmapPtr pPixmap);
+ void (*done_solid) (PixmapPtr pPixmap);
/** @} */
- /** @name Copy
+ /** @name copy
* @{
*/
/**
- * PrepareCopy() sets up the driver for doing a copy within video
+ * prepare_copy() sets up the driver for doing a copy within video
* memory.
*
* @param pSrcPixmap source pixmap
@@ -173,7 +173,7 @@ typedef struct _UxaDriver {
* 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
- * #UXA_TWO_BITBLT_DIRECTIONS, and UXA will break down Copy operations to
+ * #UXA_TWO_BITBLT_DIRECTIONS, and UXA 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
@@ -183,10 +183,10 @@ typedef struct _UxaDriver {
* 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
+ * The prepare_copy() 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,
+ Bool (*prepare_copy) (PixmapPtr pSrcPixmap,
PixmapPtr pDstPixmap,
int dx,
int dy,
@@ -194,7 +194,7 @@ typedef struct _UxaDriver {
Pixel planemask);
/**
- * Copy() performs a copy set up in the last PrepareCopy call.
+ * copy() performs a copy set up in the last prepare_copy call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
@@ -204,20 +204,20 @@ typedef struct _UxaDriver {
* @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
+ * Performs the copy set up by the last prepare_copy() 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(),
+ * be stored in the driver private during prepare_copy(). 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 uxaGetPixmapOffset() and uxa_get_pixmap_pitch().
*
- * This call is required if PrepareCopy ever succeeds.
+ * This call is required if prepare_copy ever succeeds.
*/
- void (*Copy) (PixmapPtr pDstPixmap,
+ void (*copy) (PixmapPtr pDstPixmap,
int srcX,
int srcY,
int dstX,
@@ -226,25 +226,25 @@ typedef struct _UxaDriver {
int height);
/**
- * DoneCopy() finishes a set of copies.
+ * done_copy() finishes a set of copies.
*
* @param pPixmap destination pixmap.
*
- * The DoneCopy() call is called at the end of a series of consecutive
- * Copy() calls following a successful PrepareCopy(). This allows drivers
+ * The done_copy() call is called at the end of a series of consecutive
+ * copy() calls following a successful prepare_copy(). This allows drivers
* to finish up emitting drawing commands that were buffered, or clean up
- * state from PrepareCopy().
+ * state from prepare_copy().
*
- * This call is required if PrepareCopy() ever succeeds.
+ * This call is required if prepare_copy() ever succeeds.
*/
- void (*DoneCopy) (PixmapPtr pDstPixmap);
+ void (*done_copy) (PixmapPtr pDstPixmap);
/** @} */
- /** @name Composite
+ /** @name composite
* @{
*/
/**
- * CheckComposite() checks to see if a composite operation could be
+ * check_composite() checks to see if a composite operation could be
* accelerated.
*
* @param op Render operation
@@ -252,25 +252,25 @@ typedef struct _UxaDriver {
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
*
- * The CheckComposite() call checks if the driver could handle acceleration
+ * The check_composite() 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.
*
- * See PrepareComposite() for more details on likely issues that drivers
- * will have in accelerating Composite operations.
+ * See prepare_composite() for more details on likely issues that drivers
+ * will have in accelerating composite operations.
*
- * The CheckComposite() call is recommended if PrepareComposite() is
+ * The check_composite() call is recommended if prepare_composite() is
* implemented, but is not required.
*/
- Bool (*CheckComposite) (int op,
+ Bool (*check_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
PicturePtr pDstPicture);
/**
- * PrepareComposite() sets up the driver for doing a Composite operation
+ * prepare_composite() sets up the driver for doing a composite operation
* described in the Render extension protocol spec.
*
* @param op Render operation
@@ -281,7 +281,7 @@ typedef struct _UxaDriver {
* @param pMask mask pixmap
* @param pDst destination pixmap
*
- * This call should set up the driver for doing a series of Composite
+ * 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
@@ -295,7 +295,7 @@ typedef struct _UxaDriver {
* 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
+ * 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
@@ -306,7 +306,7 @@ typedef struct _UxaDriver {
* - 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
+ * prepare_composite 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
@@ -318,12 +318,12 @@ typedef struct _UxaDriver {
* 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 PrepareComposite() call is not required. However, it is highly
+ * The prepare_composite() 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,
+ Bool (*prepare_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
PicturePtr pDstPicture,
@@ -332,8 +332,8 @@ typedef struct _UxaDriver {
PixmapPtr pDst);
/**
- * Composite() performs a Composite operation set up in the last
- * PrepareComposite() call.
+ * composite() performs a composite operation set up in the last
+ * prepare_composite() call.
*
* @param pDstPixmap destination pixmap
* @param srcX source X coordinate
@@ -345,7 +345,7 @@ typedef struct _UxaDriver {
* @param width destination rectangle width
* @param height destination rectangle height
*
- * Performs the Composite operation set up by the last PrepareComposite()
+ * Performs the composite operation set up by the last prepare_composite()
* 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
@@ -353,9 +353,9 @@ typedef struct _UxaDriver {
* transformation right at the subpixel level can be tricky, and rendercheck
* can test this for you.
*
- * This call is required if PrepareComposite() ever succeeds.
+ * This call is required if prepare_composite() ever succeeds.
*/
- void (*Composite) (PixmapPtr pDst,
+ void (*composite) (PixmapPtr pDst,
int srcX,
int srcY,
int maskX,
@@ -366,22 +366,22 @@ typedef struct _UxaDriver {
int height);
/**
- * DoneComposite() finishes a set of Composite operations.
+ * done_composite() finishes a set of composite operations.
*
* @param pPixmap destination pixmap.
*
- * The DoneComposite() call is called at the end of a series of consecutive
- * Composite() calls following a successful PrepareComposite(). This allows
+ * The done_composite() call is called at the end of a series of consecutive
+ * composite() calls following a successful prepare_composite(). This allows
* drivers to finish up emitting drawing commands that were buffered, or
- * clean up state from PrepareComposite().
+ * clean up state from prepare_composite().
*
- * This call is required if PrepareComposite() ever succeeds.
+ * This call is required if prepare_composite() ever succeeds.
*/
- void (*DoneComposite) (PixmapPtr pDst);
+ void (*done_composite) (PixmapPtr pDst);
/** @} */
/**
- * UploadToScreen() loads a rectangle of data from src into pDst.
+ * put_image() loads a rectangle of data from src into pDst.
*
* @param pDst destination pixmap
* @param x destination X coordinate.
@@ -391,27 +391,23 @@ typedef struct _UxaDriver {
* @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
+ * put_image() 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 uxa_mark_sync(). This is in contrast to most other acceleration
- * calls in UXA.
- *
- * UploadToScreen() can aid in pixmap migration, but is most important for
- * the performance of uxa_glyphs() (antialiased font drawing) by allowing
- * pipelining of data uploads, avoiding a sync of the card after each glyph.
+ * put_image() is most important for the performance of uxa_glyphs()
+ * (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 UXA should fall back to doing the upload in software.
*
- * UploadToScreen() is not required, but is recommended if Composite
+ * put_image() is not required, but is recommended if composite
* acceleration is supported.
*/
- Bool (*UploadToScreen) (PixmapPtr pDst,
+ Bool (*put_image) (PixmapPtr pDst,
int x,
int y,
int w,
@@ -420,33 +416,7 @@ typedef struct _UxaDriver {
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 uxa_glyphs() 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 UXA.
- */
- Bool (*UploadToScratch) (PixmapPtr pSrc,
- PixmapPtr pDst);
-
- /**
- * DownloadFromScreen() loads a rectangle of data from pSrc into dst
+ * get_image() loads a rectangle of data from pSrc into dst
*
* @param pSrc source pixmap
* @param x source X coordinate.
@@ -456,108 +426,72 @@ typedef struct _UxaDriver {
* @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
+ * get_image() 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, UXA leaves it up to the driver to call
- * uxa_mark_sync() if DownloadFromScreen() was asynchronous. This is in
+ * uxa_mark_sync() if get_image() was asynchronous. This is in
* contrast to most other acceleration calls in UXA.
*
- * 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 UXA should fall back to doing the download in software.
*
- * DownloadFromScreen() is not required, but is highly recommended.
+ * get_image() is not required, but is highly recommended.
*/
- Bool (*DownloadFromScreen)(PixmapPtr pSrc,
+ Bool (*get_image)(PixmapPtr pSrc,
int x, int y,
int w, int h,
char *dst, int dst_pitch);
- /**
- * MarkSync() requests that the driver mark a synchronization point,
- * returning an driver-defined 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
- * UXA.
- *
- * Note that drivers should call uxa_mark_sync() when they have done some
- * acceleration, rather than their own MarkSync() handler, as otherwise UXA
- * will be unaware of the driver's acceleration and not sync to it during
- * fallbacks.
- *
- * 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.
- *
- * Note that drivers should call uxa_wait_sync() to wait for all acceleration
- * to finish, as otherwise UXA will be unaware of the driver having
- * synchronized, resulting in excessive WaitMarker() calls.
- *
- * WaitMarker() is required of all drivers.
- */
- void (*WaitMarker) (ScreenPtr pScreen, int marker);
-
/** @{ */
/**
- * PrepareAccess() is called before CPU access to an offscreen pixmap.
+ * prepare_access() 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.
+ * prepare_access() 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 #UXA_PREPARE_DEST, #UXA_PREPARE_SRC, or
* #UXA_PREPARE_MASK, indicating which pixmap is in question. Since only up
- * to three pixmaps will have PrepareAccess() called on them per operation,
+ * to three pixmaps will have prepare_access() 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 uxample when doing
- * a copy within the same pixmap (so it gets PrepareAccess as()
+ * for prepare_access() and finish_access() in. Note that the same pixmap may
+ * have prepare_access() called on it more than once, for uxample when doing
+ * a copy within the same pixmap (so it gets prepare_access as()
* #UXA_PREPARE_DEST and then as #UXA_PREPARE_SRC).
*
- * PrepareAccess() may fail. An uxample might be the case of hardware that
- * can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
+ * prepare_access() may fail. An uxample might be the case of hardware that
+ * can set up 1 or 2 surfaces for CPU access, but not 3. If prepare_access()
* fails, UXA will migrate the pixmap to system memory.
- * DownloadFromScreen() must be implemented and must not fail if a driver
- * wishes to fail in PrepareAccess(). PrepareAccess() must not fail when
+ * get_image() must be implemented and must not fail if a driver
+ * wishes to fail in prepare_access(). prepare_access() must not fail when
* pPix is the visible screen, because the visible screen can not be
* migrated.
*
- * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
+ * @return TRUE if prepare_access() successfully prepared the pixmap for CPU
* drawing.
- * @return FALSE if PrepareAccess() is unsuccessful and UXA should use
- * DownloadFromScreen() to migate the pixmap out.
+ * @return FALSE if prepare_access() is unsuccessful and UXA should use
+ * get_image() to migate the pixmap out.
*/
- Bool (*PrepareAccess)(PixmapPtr pPix, uxa_access_t access);
+ Bool (*prepare_access)(PixmapPtr pPix, uxa_access_t access);
/**
- * FinishAccess() is called after CPU access to an offscreen pixmap.
+ * finish_access() 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.
+ * finish_access() will be called after finishing CPU access of an offscreen
+ * pixmap set up by prepare_access(). Note that the finish_access() will not be
+ * called if prepare_access() failed.
*/
- void (*FinishAccess)(PixmapPtr pPix);
+ void (*finish_access)(PixmapPtr pPix);
/**
* PixmapIsOffscreen() is an optional driver replacement to
@@ -569,42 +503,42 @@ typedef struct _UxaDriver {
*
* uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
- * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * will need to be wrapped by prepare_access()/finish_access() when accessing it
* with the CPU.
*
*
*/
- Bool (*PixmapIsOffscreen)(PixmapPtr pPix);
+ Bool (*pixmap_is_offscreen)(PixmapPtr pPix);
/**
- * maxPitchPixels controls the pitch limitation for rendering from
+ * max_pitch_pixels controls the pitch limitation for rendering from
* the card.
* The driver should never receive a request for rendering a pixmap
- * that has a pitch (in pixels) beyond maxPitchPixels.
+ * that has a pitch (in pixels) beyond max_pitch_pixels.
*
* Setting this field is optional -- if your hardware doesn't have
* a pitch limitation in pixels, don't set this. If neither this value
- * nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
- * If set, it must not be smaller than maxX.
+ * nor max_pitch_bytes is set, then max_pitch_pixels is set to max_x.
+ * If set, it must not be smaller than max_x.
*
- * @sa maxPitchBytes
+ * @sa max_pitch_bytes
*/
- int maxPitchPixels;
+ int max_pitch_pixels;
/**
- * maxPitchBytes controls the pitch limitation for rendering from
+ * max_pitch_bytes controls the pitch limitation for rendering from
* the card.
* The driver should never receive a request for rendering a pixmap
- * that has a pitch (in bytes) beyond maxPitchBytes.
+ * that has a pitch (in bytes) beyond max_pitch_bytes.
*
* Setting this field is optional -- if your hardware doesn't have
* a pitch limitation in bytes, don't set this.
- * If set, it must not be smaller than maxX * 4.
- * There's no default value for maxPitchBytes.
+ * If set, it must not be smaller than max_x * 4.
+ * There's no default value for max_pitch_bytes.
*
- * @sa maxPitchPixels
+ * @sa max_pitch_pixels
*/
- int maxPitchBytes;
+ int max_pitch_bytes;
/** @} */
} uxa_driver_t;
@@ -630,15 +564,6 @@ uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver);
void
uxa_driver_fini(ScreenPtr pScreen);
-void
-uxa_mark_sync(ScreenPtr pScreen);
-
-void
-uxa_wait_sync(ScreenPtr pScreen);
-
-void
-uxaEnableDisableFBAccess (int index, Bool enable);
-
CARD32
uxa_get_pixmap_first_pixel (PixmapPtr pPixmap);
commit fc4d9c55a7fa8001786c1e4da10f005406c57ece
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 18:17:20 2008 -0700
Change PrepareAccess to take access mode rather than index
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 7609239..08d73b5 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -553,33 +553,21 @@ i830_uxa_get_pixmap_bo (PixmapPtr pixmap)
}
static Bool
-i830_uxa_prepare_access (PixmapPtr pixmap, int index)
+i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
{
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo) {
intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
- if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
+ if (dri_bo_map (bo, access == UXA_ACCESS_RW) != 0)
return FALSE;
pixmap->devPrivate.ptr = bo->virtual;
}
return TRUE;
}
-void
-i830_uxa_block_handler (ScreenPtr screen)
-{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- I830Ptr i830 = I830PTR(scrn);
-
- if (i830->need_flush) {
- dri_bo_wait_rendering (i830->front_buffer->bo);
- i830->need_flush = FALSE;
- }
-}
-
static void
-i830_uxa_finish_access (PixmapPtr pixmap, int index)
+i830_uxa_finish_access (PixmapPtr pixmap)
{
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
@@ -589,11 +577,24 @@ i830_uxa_finish_access (PixmapPtr pixmap, int index)
I830Ptr i830 = I830PTR(scrn);
dri_bo_unmap (bo);
+ pixmap->devPrivate.ptr = NULL;
if (bo == i830->front_buffer->bo)
i830->need_flush = TRUE;
}
}
+void
+i830_uxa_block_handler (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+
+ if (i830->need_flush) {
+ dri_bo_wait_rendering (i830->front_buffer->bo);
+ i830->need_flush = FALSE;
+ }
+}
+
static Bool
i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
{
@@ -626,16 +627,8 @@ i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usag
return NullPixmap;
}
- if (dri_bo_map (bo, FALSE) != 0) {
- fbDestroyPixmap (pixmap);
- dri_bo_unreference (bo);
- return NullPixmap;
- }
-
- screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride,
- (pointer) bo->virtual);
+ screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride, NULL);
- dri_bo_unmap (bo);
i830_uxa_set_pixmap_bo (pixmap, bo);
}
@@ -648,10 +641,8 @@ i830_uxa_destroy_pixmap (PixmapPtr pixmap)
if (pixmap->refcnt == 1) {
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
- if (bo) {
- dri_bo_unmap (bo);
+ if (bo)
dri_bo_unreference (bo);
- }
}
fbDestroyPixmap (pixmap);
return TRUE;
@@ -705,6 +696,7 @@ i830_uxa_init (ScreenPtr pScreen)
i830->uxa_driver->Copy = I830EXACopy;
i830->uxa_driver->DoneCopy = I830EXADoneCopy;
+#if 0
/* Composite */
if (!IS_I9XX(i830)) {
i830->uxa_driver->CheckComposite = i830_check_composite;
@@ -724,6 +716,7 @@ i830_uxa_init (ScreenPtr pScreen)
i830->uxa_driver->Composite = i965_composite;
i830->uxa_driver->DoneComposite = i830_done_composite;
}
+#endif
i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
index 7c7b3e9..20a5657 100644
--- a/uxa/uxa-accel.c
+++ b/uxa/uxa-accel.c
@@ -189,8 +189,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int dstXoff, dstYoff;
if (!access_prepared) {
- uxa_prepare_access(pDrawable, UXA_PREPARE_DEST);
-
+ uxa_prepare_access(pDrawable, UXA_ACCESS_RW);
access_prepared = TRUE;
}
@@ -210,7 +209,7 @@ uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
}
if (access_prepared)
- uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pDrawable);
else
uxa_mark_sync(pDrawable->pScreen);
@@ -240,10 +239,10 @@ uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
if (!pPixmap)
return FALSE;
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
- uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pDrawable);
FreeScratchPixmapHeader(pPixmap);
@@ -266,10 +265,10 @@ uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int form
{
if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
dx, dy, data)) {
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
data);
- uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pDrawable);
}
}
@@ -474,12 +473,12 @@ fallback:
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
uxa_drawable_location(pSrcDrawable),
uxa_drawable_location(pDstDrawable)));
- uxa_prepare_access (pDstDrawable, UXA_PREPARE_DEST);
- uxa_prepare_access (pSrcDrawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDstDrawable, UXA_ACCESS_RW);
+ uxa_prepare_access (pSrcDrawable, UXA_ACCESS_RO);
fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
upsidedown, bitplane, closure);
- uxa_finish_access (pSrcDrawable, UXA_PREPARE_SRC);
- uxa_finish_access (pDstDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pSrcDrawable);
+ uxa_finish_access (pDstDrawable);
}
RegionPtr
@@ -1029,9 +1028,9 @@ fallback:
UXA_FALLBACK(("from %p (%c)\n", pDrawable,
uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RO);
fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
- uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+ uxa_finish_access (pDrawable);
out:
return;
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
index acc82bb..1e4f4ea 100644
--- a/uxa/uxa-priv.h
+++ b/uxa/uxa-priv.h
@@ -350,10 +350,10 @@ uxa_check_composite (CARD8 op,
/* uxa.c */
void
-uxa_prepare_access(DrawablePtr pDrawable, int index);
+uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access);
void
-uxa_finish_access(DrawablePtr pDrawable, int index);
+uxa_finish_access(DrawablePtr pDrawable);
void
uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 38e6088..9c79fce 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -926,12 +926,12 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
xoff += pDraw->x;
yoff += pDraw->y;
- uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+ uxa_prepare_access(pDraw, UXA_ACCESS_RW);
for (; ntrap; ntrap--, traps++)
(*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
- uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+ uxa_finish_access(pDraw);
}
else if (maskFormat)
{
@@ -948,11 +948,11 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
if (!pPicture)
return;
- uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
for (; ntrap; ntrap--, traps++)
(*ps->RasterizeTrapezoid) (pPicture, traps,
-bounds.x1, -bounds.y1);
- uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pPicture->pDrawable);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
@@ -1009,9 +1009,9 @@ uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
if (direct)
{
DrawablePtr pDraw = pDst->pDrawable;
- uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+ uxa_prepare_access(pDraw, UXA_ACCESS_RW);
(*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
- uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+ uxa_finish_access(pDraw);
}
else if (maskFormat)
{
@@ -1028,9 +1028,9 @@ uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
if (!pPicture)
return;
- uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
(*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
- uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pPicture->pDrawable);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
diff --git a/uxa/uxa-unaccel.c b/uxa/uxa-unaccel.c
index 2719420..01c1322 100644
--- a/uxa/uxa-unaccel.c
+++ b/uxa/uxa-unaccel.c
@@ -45,9 +45,9 @@ void
uxa_prepare_access_gc(GCPtr pGC)
{
if (pGC->stipple)
- uxa_prepare_access(&pGC->stipple->drawable, UXA_PREPARE_MASK);
+ uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RO);
if (pGC->fillStyle == FillTiled)
- uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RO);
}
/**
@@ -57,9 +57,9 @@ void
uxa_finish_access_gc(GCPtr pGC)
{
if (pGC->fillStyle == FillTiled)
- uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_MASK);
+ uxa_finish_access(&pGC->tile.pixmap->drawable);
if (pGC->stipple)
- uxa_finish_access(&pGC->stipple->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pGC->stipple->drawable);
}
#if DEBUG_TRACE_FALL
@@ -75,11 +75,11 @@ uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -87,9 +87,9 @@ uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -98,9 +98,9 @@ uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
char *bits)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
RegionPtr
@@ -111,11 +111,11 @@ uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
- uxa_prepare_access (pDst, UXA_PREPARE_DEST);
- uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDst, UXA_ACCESS_RW);
+ uxa_prepare_access (pSrc, UXA_ACCESS_RO);
ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
- uxa_finish_access (pSrc, UXA_PREPARE_SRC);
- uxa_finish_access (pDst, UXA_PREPARE_DEST);
+ uxa_finish_access (pSrc);
+ uxa_finish_access (pDst);
return ret;
}
@@ -129,12 +129,12 @@ uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
- uxa_prepare_access (pDst, UXA_PREPARE_DEST);
- uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDst, UXA_ACCESS_RW);
+ uxa_prepare_access (pSrc, UXA_ACCESS_RO);
ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
bitPlane);
- uxa_finish_access (pSrc, UXA_PREPARE_SRC);
- uxa_finish_access (pDst, UXA_PREPARE_DEST);
+ uxa_finish_access (pSrc);
+ uxa_finish_access (pDst);
return ret;
}
@@ -144,9 +144,9 @@ uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr pptInit)
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -158,11 +158,11 @@ uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
pGC->lineWidth, mode, npt));
if (pGC->lineWidth == 0) {
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyLine (pDrawable, pGC, mode, npt, ppt);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
return;
}
/* fb calls mi functions in the lineWidth != 0 case. */
@@ -176,11 +176,11 @@ uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
uxa_drawable_location(pDrawable), pGC->lineWidth, nsegInit));
if (pGC->lineWidth == 0) {
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
return;
}
/* fb calls mi functions in the lineWidth != 0 case. */
@@ -200,11 +200,11 @@ uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
#if 0
if (pGC->lineWidth == 0)
{
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyArc (pDrawable, pGC, narcs, pArcs);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
return;
}
#endif
@@ -217,11 +217,11 @@ uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyFillRect (pDrawable, pGC, nrect, prect);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -231,11 +231,11 @@ uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
{
UXA_FALLBACK(("to %p (%c)\n", pDrawable,
uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -245,11 +245,11 @@ uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
{
UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
uxa_drawable_location(pDrawable), pGC->fillStyle, pGC->alu));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
uxa_prepare_access_gc (pGC);
fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
uxa_finish_access_gc (pGC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pDrawable);
}
void
@@ -260,13 +260,13 @@ uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
uxa_drawable_location(&pBitmap->drawable),
uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
- uxa_prepare_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RW);
+ uxa_prepare_access (&pBitmap->drawable, UXA_ACCESS_RO);
uxa_prepare_access_gc (pGC);
fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
uxa_finish_access_gc (pGC);
- uxa_finish_access (&pBitmap->drawable, UXA_PREPARE_SRC);
- uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (&pBitmap->drawable);
+ uxa_finish_access (pDrawable);
}
void
@@ -278,9 +278,9 @@ uxa_check_get_spans (DrawablePtr pDrawable,
char *pdstStart)
{
UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
- uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (pDrawable, UXA_ACCESS_RO);
fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
- uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+ uxa_finish_access (pDrawable);
}
void
@@ -300,11 +300,11 @@ uxa_check_composite (CARD8 op,
UXA_FALLBACK(("from picts %p/%p to pict %p\n",
pSrc, pMask, pDst));
- uxa_prepare_access (pDst->pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pDst->pDrawable, UXA_ACCESS_RW);
if (pSrc->pDrawable != NULL)
- uxa_prepare_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (pSrc->pDrawable, UXA_ACCESS_RO);
if (pMask && pMask->pDrawable != NULL)
- uxa_prepare_access (pMask->pDrawable, UXA_PREPARE_MASK);
+ uxa_prepare_access (pMask->pDrawable, UXA_ACCESS_RO);
fbComposite (op,
pSrc,
pMask,
@@ -318,10 +318,10 @@ uxa_check_composite (CARD8 op,
width,
height);
if (pMask && pMask->pDrawable != NULL)
- uxa_finish_access (pMask->pDrawable, UXA_PREPARE_MASK);
+ uxa_finish_access (pMask->pDrawable);
if (pSrc->pDrawable != NULL)
- uxa_finish_access (pSrc->pDrawable, UXA_PREPARE_SRC);
- uxa_finish_access (pDst->pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access (pSrc->pDrawable);
+ uxa_finish_access (pDst->pDrawable);
}
void
@@ -333,9 +333,9 @@ uxa_check_add_traps (PicturePtr pPicture,
{
UXA_FALLBACK(("to pict %p (%c)\n",
uxa_drawable_location(pPicture->pDrawable)));
- uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW);
fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
- uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ uxa_finish_access(pPicture->pDrawable);
}
/**
@@ -350,7 +350,7 @@ uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
CARD32 pixel;
void *fb;
- uxa_prepare_access (&pPixmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access (&pPixmap->drawable, UXA_ACCESS_RO);
fb = pPixmap->devPrivate.ptr;
switch (pPixmap->drawable.bitsPerPixel) {
@@ -364,7 +364,7 @@ uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
pixel = *(CARD8 *)fb;
break;
}
- uxa_finish_access(&pPixmap->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pPixmap->drawable);
return pixel;
}
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 7201e7c..5fe0f32 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -141,7 +141,7 @@ uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp)
* PrepareAccess() is necessary, and working around PrepareAccess() failure.
*/
void
-uxa_prepare_access(DrawablePtr pDrawable, int index)
+uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
{
ScreenPtr pScreen = pDrawable->pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
@@ -152,7 +152,7 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
return;
if (uxa_screen->info->PrepareAccess)
- (*uxa_screen->info->PrepareAccess) (pPixmap, index);
+ (*uxa_screen->info->PrepareAccess) (pPixmap, access);
}
/**
@@ -161,7 +161,7 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
* It deals with calling the driver's FinishAccess() only if necessary.
*/
void
-uxa_finish_access(DrawablePtr pDrawable, int index)
+uxa_finish_access(DrawablePtr pDrawable)
{
ScreenPtr pScreen = pDrawable->pScreen;
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
@@ -173,7 +173,7 @@ uxa_finish_access(DrawablePtr pDrawable, int index)
if (!uxa_pixmap_is_offscreen (pPixmap))
return;
- (*uxa_screen->info->FinishAccess) (pPixmap, index);
+ (*uxa_screen->info->FinishAccess) (pPixmap);
}
/**
@@ -209,10 +209,10 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
* allocated pixmap. This isn't a problem yet, since we don't
* put pixmaps in FB until at least one accelerated UXA op.
*/
- uxa_prepare_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pOldTile->drawable, UXA_ACCESS_RO);
pNewTile = fb24_32ReformatTile (pOldTile,
pDrawable->bitsPerPixel);
- uxa_finish_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pOldTile->drawable);
}
if (pNewTile)
{
@@ -227,9 +227,9 @@ uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
pDrawable->bitsPerPixel))
{
- uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
fbPadPixmap (pGC->tile.pixmap);
- uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pGC->tile.pixmap->drawable);
}
/* Mask out the GCTile change notification, now that we've done FB's
* job for it.
@@ -273,20 +273,20 @@ void
uxa_prepare_access_window(WindowPtr pWin)
{
if (pWin->backgroundState == BackgroundPixmap)
- uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
if (pWin->borderIsPixel == FALSE)
- uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
}
void
uxa_finish_access_window(WindowPtr pWin)
{
if (pWin->backgroundState == BackgroundPixmap)
- uxa_finish_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pWin->background.pixmap->drawable);
if (pWin->borderIsPixel == FALSE)
- uxa_finish_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pWin->border.pixmap->drawable);
}
static Bool
@@ -304,9 +304,9 @@ static RegionPtr
uxa_bitmap_to_region(PixmapPtr pPix)
{
RegionPtr ret;
- uxa_prepare_access(&pPix->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO);
ret = fbPixmapToRegion(pPix);
- uxa_finish_access(&pPix->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access(&pPix->drawable);
return ret;
}
diff --git a/uxa/uxa.h b/uxa/uxa.h
index 57e84f3..32d5a5a 100644
--- a/uxa/uxa.h
+++ b/uxa/uxa.h
@@ -43,6 +43,11 @@
#define UXA_VERSION_MINOR 0
#define UXA_VERSION_RELEASE 0
+typedef enum {
+ UXA_ACCESS_RO,
+ UXA_ACCESS_RW
+} uxa_access_t;
+
/**
* The UxaDriver structure is allocated through uxa_driver_alloc(), and then
* fllled in by drivers.
@@ -251,11 +256,7 @@ typedef struct _UxaDriver {
* 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 offsets and pitches of the
- * pixmaps are going to be.
+ * support to software rendering early on.
*
* See PrepareComposite() for more details on likely issues that drivers
* will have in accelerating Composite operations.
@@ -544,7 +545,7 @@ typedef struct _UxaDriver {
* @return FALSE if PrepareAccess() is unsuccessful and UXA should use
* DownloadFromScreen() to migate the pixmap out.
*/
- Bool (*PrepareAccess)(PixmapPtr pPix, int index);
+ Bool (*PrepareAccess)(PixmapPtr pPix, uxa_access_t access);
/**
* FinishAccess() is called after CPU access to an offscreen pixmap.
@@ -554,9 +555,9 @@ typedef struct _UxaDriver {
*
* 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.
+ * called if PrepareAccess() failed.
*/
- void (*FinishAccess)(PixmapPtr pPix, int index);
+ void (*FinishAccess)(PixmapPtr pPix);
/**
* PixmapIsOffscreen() is an optional driver replacement to
@@ -575,25 +576,6 @@ typedef struct _UxaDriver {
*/
Bool (*PixmapIsOffscreen)(PixmapPtr pPix);
- /** @name PrepareAccess() and FinishAccess() indices
- * @{
- */
- /**
- * UXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
- * read from.
- */
- #define UXA_PREPARE_DEST 0
- /**
- * UXA_PREPARE_SRC is the index for a pixmap that may be read from
- */
- #define UXA_PREPARE_SRC 1
- /**
- * UXA_PREPARE_SRC is the index for a second pixmap that may be read
- * from.
- */
- #define UXA_PREPARE_MASK 2
- /** @} */
-
/**
* maxPitchPixels controls the pitch limitation for rendering from
* the card.
commit c155bb3cb17a3bd3b2e90be52cd1fc90147c4e17
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 04:11:13 2008 -0700
Add batch flush in i830_uxa_prepare_access
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 72a1e8d..7609239 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -179,7 +179,6 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
I830Ptr pI830 = I830PTR(pScrn);
unsigned long pitch;
- I830FALLBACK("solid");
if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
I830FALLBACK("planemask is not solid");
@@ -266,7 +265,6 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
- I830FALLBACK("copy");
if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
I830FALLBACK("planemask is not solid");
@@ -560,10 +558,10 @@ i830_uxa_prepare_access (PixmapPtr pixmap, int index)
dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
if (bo) {
+ intel_batch_flush(xf86Screens[pixmap->drawable.pScreen->myNum]);
if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
return FALSE;
- assert (pixmap->devPrivate.ptr == bo->virtual);
- pixmap->devPrivate.ptr = bo->virtual;
+ pixmap->devPrivate.ptr = bo->virtual;
}
return TRUE;
}
@@ -597,9 +595,9 @@ i830_uxa_finish_access (PixmapPtr pixmap, int index)
}
static Bool
-i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
+i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
{
- return i830_uxa_get_pixmap_bo (pPixmap) != NULL;
+ return i830_uxa_get_pixmap_bo (pixmap) != NULL;
}
static PixmapPtr
@@ -667,9 +665,6 @@ void i830_uxa_create_screen_resources(ScreenPtr pScreen)
if (bo != NULL) {
PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
- dri_bo_map (bo, i830->front_buffer->alignment);
- pixmap->devPrivate.ptr = bo->virtual;
- dri_bo_unmap (bo);
i830_uxa_set_pixmap_bo (pixmap, bo);
}
}
diff --git a/src/i915_render.c b/src/i915_render.c
index 7837635..970c42a 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -322,8 +322,6 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
Bool is_affine_src, is_affine_mask;
Bool is_nearest = FALSE;
- return FALSE;
-
i830_exa_check_pitch_3d(pSrc);
if (pMask)
i830_exa_check_pitch_3d(pMask);
commit 66706718553cd272eab6f817b5a059df3e0a4347
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 04:10:21 2008 -0700
Add throttling
diff --git a/src/i830_driver.c b/src/i830_driver.c
index a810f11..bef3bb8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2531,6 +2531,10 @@ I830BlockHandler(int i,
* fashion.
*/
intel_batch_flush(pScrn);
+#ifdef XF86DRI
+ if (pI830->memory_manager)
+ drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
+#endif
pI830->need_mi_flush = FALSE;
#ifdef XF86DRI
commit 12df8f40d2fb41f5446db1b49beeb442da18bee2
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 01:43:44 2008 -0700
Use dri_bo for all object allocations, including pixmaps under uxa
diff --git a/src/i830.h b/src/i830.h
index fe25919..dbcf3c0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -80,15 +80,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#include "dri_bufmgr.h"
#include "intel_bufmgr.h"
+#include "i915_drm.h"
#ifdef I830_USE_EXA
#include "exa.h"
-#include "uxa.h"
Bool I830EXAInit(ScreenPtr pScreen);
-Bool i830_uxa_init(ScreenPtr pScreen);
unsigned long long I830TexOffsetStart(PixmapPtr pPix);
#endif
+#ifdef I830_USE_UXA
+#include "uxa.h"
+Bool i830_uxa_init(ScreenPtr pScreen);
+dri_bo *i830_uxa_get_pixmap_bo (PixmapPtr pixmap);
+void i830_uxa_create_screen_resources(ScreenPtr pScreen);
+void i830_uxa_block_handler (ScreenPtr pScreen);
+#endif
+
#ifdef I830_USE_XAA
Bool I830XAAInit(ScreenPtr pScreen);
#endif
@@ -194,7 +201,7 @@ struct _i830_memory {
i830_memory *prev;
/** @} */
- uint32_t gem_handle;
+ dri_bo *bo;
uint32_t alignment;
uint32_t gem_name;
Bool lifetime_fixed_offset;
@@ -530,6 +537,7 @@ typedef struct _I830Rec {
#endif
#ifdef I830_USE_UXA
uxa_driver_t *uxa_driver;
+ Bool need_flush;
#endif
#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
PixmapPtr pSrcPixmap;
@@ -818,6 +826,7 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_texture_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_pwrctx(ScrnInfoPtr pScrn);
Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
+void i830_init_bufmgr(ScrnInfoPtr pScrn);
#ifdef INTEL_XVMC
Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name,
i830_memory **buffer, unsigned long size, int flags);
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 0ef565b..a301818 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -67,7 +67,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
unsigned long
intel_get_pixmap_offset(PixmapPtr pPix)
{
-#ifdef I830_USE_EXA
+#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index c9b8421..4c1198d 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -74,12 +74,24 @@ intel_batch_emit_reloc (I830Ptr pI830,
}
static inline void
-intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
+intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap,
+ uint32_t read_domains, uint32_t write_domain,
+ uint32_t delta)
{
+#if I830_USE_UXA
+ dri_bo *bo = i830_uxa_get_pixmap_bo(pPixmap);
+#endif
+ uint32_t offset;
assert(pI830->batch_ptr != NULL);
assert(intel_batch_space(pI830) >= 4);
- *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) =
- intel_get_pixmap_offset(pPixmap) + delta;
+#if I830_USE_UXA
+ if (bo) {
+ intel_batch_emit_reloc(pI830, bo, read_domains, write_domain, delta);
+ return;
+ }
+#endif
+ offset = intel_get_pixmap_offset(pPixmap);
+ *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = offset + delta;
pI830->batch_used += 4;
}
@@ -88,8 +100,8 @@ intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
#define OUT_RELOC(bo, read_domains, write_domains, delta) \
intel_batch_emit_reloc (pI830, bo, read_domains, write_domains, delta)
-#define OUT_RELOC_PIXMAP(pPixmap, delta) \
- intel_batch_emit_reloc_pixmap(pI830, pPixmap, delta)
+#define OUT_RELOC_PIXMAP(pPixmap, reads, write, delta) \
+ intel_batch_emit_reloc_pixmap(pI830, pPixmap, reads, write, delta)
union intfloat {
float f;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0e5d81d..d40ada5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1514,23 +1514,18 @@ I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
static int
i830_name_buffer (ScrnInfoPtr pScrn, i830_memory *mem)
{
- if (mem && mem->gem_handle)
+ if (mem && mem->bo)
{
- I830Ptr pI830 = I830PTR(pScrn);
- struct drm_gem_flink flink;
- int ret;
-
if (!mem->gem_name)
{
- flink.handle = mem->gem_handle;
- ret = ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_FLINK, &flink);
+ int ret;
+ ret = intel_bo_flink(mem->bo, &mem->gem_name);
if (ret != 0)
{
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[drm] failed to name buffer %d\n", -errno);
return -1;
}
- mem->gem_name = flink.name;
}
return mem->gem_name;
}
diff --git a/src/i830_dri.h b/src/i830_dri.h
index b6a8366..83ddd85 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -59,5 +59,4 @@ typedef struct {
int dummy;
} I830DRIContextRec, *I830DRIContextPtr;
-
#endif
diff --git a/src/i830_driver.c b/src/i830_driver.c
index ed974ce..a810f11 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -849,7 +849,7 @@ i830_update_front_offset(ScrnInfoPtr pScrn)
/* If we are still in ScreenInit, there is no screen pixmap to be updated
* yet. We'll fix it up at CreateScreenResources.
*/
- if (!pI830->starting) {
+ if (!pI830->starting && pI830->accel != ACCEL_UXA) {
if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
-1, -1, -1, -1, -1,
(pointer)(pI830->FbBase +
@@ -876,6 +876,10 @@ i830CreateScreenResources(ScreenPtr pScreen)
i830_update_front_offset(pScrn);
+#ifdef I830_USE_UXA
+ if (pI830->accel == ACCEL_UXA)
+ i830_uxa_create_screen_resources(pScreen);
+#endif
return TRUE;
}
@@ -2534,6 +2538,8 @@ I830BlockHandler(int i,
#endif
}
+ if (pI830->accel == ACCEL_UXA)
+ i830_uxa_block_handler (pScreen);
/*
* Check for FIFO underruns at block time (which amounts to just
* periodically). If this happens, it means our DSPARB or some other
@@ -2774,12 +2780,13 @@ i830_fake_fence_wait(void *priv, unsigned int fence)
return 0;
}
-static void
+void
i830_init_bufmgr(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
- assert(pI830->FbBase != NULL);
+ if (pI830->bufmgr) return;
+
if (pI830->memory_manager) {
int batch_size;
@@ -2792,6 +2799,7 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
intel_bufmgr_gem_enable_reuse(pI830->bufmgr);
} else {
+ assert(pI830->FbBase != NULL);
pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
pI830->FbBase +
pI830->fake_bufmgr_mem->offset,
@@ -3412,7 +3420,7 @@ I830LeaveVT(int scrnIndex, int flags)
}
#endif /* XF86DRI */
- if (pI830->useEXA && IS_I965G(pI830))
+ if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
gen4_render_state_cleanup(pScrn);
if (pI830->AccelInfoRec)
@@ -3465,7 +3473,7 @@ I830EnterVT(int scrnIndex, int flags)
intel_batch_init(pScrn);
- if (pI830->useEXA && IS_I965G(pI830))
+ if ((pI830->accel == ACCEL_EXA || pI830->accel == ACCEL_UXA) && IS_I965G(pI830))
gen4_render_state_init(pScrn);
if (i830_check_error_state(pScrn)) {
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f00e4f9..72a1e8d 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -179,6 +179,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
I830Ptr pI830 = I830PTR(pScrn);
unsigned long pitch;
+ I830FALLBACK("solid");
if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
I830FALLBACK("planemask is not solid");
@@ -238,7 +239,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
OUT_BATCH(pI830->BR[13] | pitch);
OUT_BATCH((y1 << 16) | (x1 & 0xffff));
OUT_BATCH((y2 << 16) | (x2 & 0xffff));
- OUT_RELOC_PIXMAP(pPixmap, 0);
+ OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(pI830->BR[16]);
ADVANCE_BATCH();
}
@@ -265,6 +266,7 @@ I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
+ I830FALLBACK("copy");
if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
I830FALLBACK("planemask is not solid");
@@ -331,10 +333,10 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
OUT_BATCH(pI830->BR[13] | dst_pitch);
OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
- OUT_RELOC_PIXMAP(pDstPixmap, 0);
+ OUT_RELOC_PIXMAP(pDstPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
OUT_BATCH(src_pitch);
- OUT_RELOC_PIXMAP(pI830->pSrcPixmap, 0);
+ OUT_RELOC_PIXMAP(pI830->pSrcPixmap, I915_GEM_DOMAIN_RENDER, 0, 0);
ADVANCE_BATCH();
}
@@ -538,129 +540,212 @@ I830EXAInit(ScreenPtr pScreen)
return TRUE;
}
+static DevPrivateKey uxa_pixmap_key = &uxa_pixmap_key;
+
+static void
+i830_uxa_set_pixmap_bo (PixmapPtr pixmap, dri_bo *bo)
+{
+ dixSetPrivate(&pixmap->devPrivates, uxa_pixmap_key, bo);
+}
+
+dri_bo *
+i830_uxa_get_pixmap_bo (PixmapPtr pixmap)
+{
+ return dixLookupPrivate(&pixmap->devPrivates, uxa_pixmap_key);
+}
+
+static Bool
+i830_uxa_prepare_access (PixmapPtr pixmap, int index)
+{
+ dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
+
+ if (bo) {
+ if (dri_bo_map (bo, index == UXA_PREPARE_DEST) != 0)
+ return FALSE;
+ assert (pixmap->devPrivate.ptr == bo->virtual);
+ pixmap->devPrivate.ptr = bo->virtual;
+ }
+ return TRUE;
+}
+
+void
+i830_uxa_block_handler (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+
+ if (i830->need_flush) {
+ dri_bo_wait_rendering (i830->front_buffer->bo);
+ i830->need_flush = FALSE;
+ }
+}
+
+static void
+i830_uxa_finish_access (PixmapPtr pixmap, int index)
+{
+ dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
+
+ if (bo) {
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+
+ dri_bo_unmap (bo);
+ if (bo == i830->front_buffer->bo)
+ i830->need_flush = TRUE;
+ }
+}
+
static Bool
i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
{
- ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
- I830Ptr pI830 = I830PTR(pScrn);
+ return i830_uxa_get_pixmap_bo (pPixmap) != NULL;
+}
- /* XXX for now, eventually we'll support 'real' off-screen pixmaps */
- if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
- (void *)pPixmap->devPrivate.ptr <
- (void *)(pI830->FbBase + pI830->FbMapSize))
+static PixmapPtr
+i830_uxa_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+ dri_bo *bo;
+ int stride;
+ PixmapPtr pixmap;
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
+
+ if (w && h)
{
- return TRUE;
- } else {
- return FALSE;
+ stride = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
+ i830->accel_pixmap_pitch_alignment);
+
+ bo = dri_bo_alloc (i830->bufmgr, "pixmap", stride * h,
+ i830->accel_pixmap_offset_alignment);
+ if (!bo) {
+ fbDestroyPixmap (pixmap);
+ return NullPixmap;
+ }
+
+ if (dri_bo_map (bo, FALSE) != 0) {
+ fbDestroyPixmap (pixmap);
+ dri_bo_unreference (bo);
+ return NullPixmap;
+ }
+
+ screen->ModifyPixmapHeader (pixmap, w, h, 0, 0, stride,
+ (pointer) bo->virtual);
+
+ dri_bo_unmap (bo);
+ i830_uxa_set_pixmap_bo (pixmap, bo);
}
+
+ return pixmap;
}
+static Bool
+i830_uxa_destroy_pixmap (PixmapPtr pixmap)
+{
+ if (pixmap->refcnt == 1) {
+ dri_bo *bo = i830_uxa_get_pixmap_bo (pixmap);
+
+ if (bo) {
+ dri_bo_unmap (bo);
+ dri_bo_unreference (bo);
+ }
+ }
+ fbDestroyPixmap (pixmap);
+ return TRUE;
+}
+
+void i830_uxa_create_screen_resources(ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
+ dri_bo *bo = i830->front_buffer->bo;
+
+ if (bo != NULL) {
+ PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
+ dri_bo_map (bo, i830->front_buffer->alignment);
+ pixmap->devPrivate.ptr = bo->virtual;
+ dri_bo_unmap (bo);
+ i830_uxa_set_pixmap_bo (pixmap, bo);
+ }
+}
Bool
i830_uxa_init (ScreenPtr pScreen)
{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- I830Ptr pI830 = I830PTR(pScrn);
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ I830Ptr i830 = I830PTR(scrn);
- pI830->uxa_driver = uxa_driver_alloc();
- if (pI830->uxa_driver == NULL) {
- pI830->accel = ACCEL_NONE;
+ if (!dixRequestPrivate(uxa_pixmap_key, 0))
+ return FALSE;
+
+ i830->uxa_driver = uxa_driver_alloc();
+ if (i830->uxa_driver == NULL) {
+ i830->accel = ACCEL_NONE;
return FALSE;
}
- memset(pI830->uxa_driver, 0, sizeof(*pI830->uxa_driver));
+ memset(i830->uxa_driver, 0, sizeof(*i830->uxa_driver));
- pI830->bufferOffset = 0;
- pI830->uxa_driver->uxa_major = 1;
- pI830->uxa_driver->uxa_minor = 0;
-
- /* Limits are described in the BLT engine chapter under Graphics Data Size
- * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
- * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
- *
- * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
- *
- * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
- * i965 limits 3D surface to 4kB-aligned offset if tiled.
- * i965 limits 3D surfaces to w,h of ?,8192.
- * i965 limits 3D surface to pitch of 1B - 128kB.
- * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
- * i965 limits 3D surface pitch alignment to 512B if tiled.
- * i965 limits 3D destination drawing rect to w,h of 8192,8192.
- *
- * i915 limits 3D textures to 4B-aligned offset if un-tiled.
- * i915 limits 3D textures to ~4kB-aligned offset if tiled.
- * i915 limits 3D textures to width,height of 2048,2048.
- * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
- * i915 limits 3D destination to ~4kB-aligned offset if tiled.
- * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
- * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
- * i915 limits 3D destination to POT aligned pitch if tiled.
- * i915 limits 3D destination drawing rect to w,h of 2048,2048.
- *
- * i845 limits 3D textures to 4B-aligned offset if un-tiled.
- * i845 limits 3D textures to ~4kB-aligned offset if tiled.
- * i845 limits 3D textures to width,height of 2048,2048.
- * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
- * i845 limits 3D destination to 4B-aligned offset if un-tiled.
- * i845 limits 3D destination to ~4kB-aligned offset if tiled.
- * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
- * i845 limits 3D destination drawing rect to w,h of 2048,2048.
- *
- * For the tiled issues, the only tiled buffer we draw to should be
- * the front, which will have an appropriate pitch/offset already set up,
- * so EXA doesn't need to worry.
- */
- if (IS_I965G(pI830)) {
- pI830->uxa_driver->maxX = 8192;
- pI830->uxa_driver->maxY = 8192;
- } else {
- pI830->uxa_driver->maxX = 2048;
- pI830->uxa_driver->maxY = 2048;
- }
+ i830->bufferOffset = 0;
+ i830->uxa_driver->uxa_major = 1;
+ i830->uxa_driver->uxa_minor = 0;
+
+ i830->uxa_driver->maxX = i830->accel_max_x;
+ i830->uxa_driver->maxY = i830->accel_max_y;
/* Sync */
- pI830->uxa_driver->WaitMarker = I830EXASync;
+ i830->uxa_driver->WaitMarker = I830EXASync;
/* Solid fill */
- pI830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
- pI830->uxa_driver->Solid = I830EXASolid;
- pI830->uxa_driver->DoneSolid = I830EXADoneSolid;
+ i830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
+ i830->uxa_driver->Solid = I830EXASolid;
+ i830->uxa_driver->DoneSolid = I830EXADoneSolid;
/* Copy */
- pI830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
- pI830->uxa_driver->Copy = I830EXACopy;
- pI830->uxa_driver->DoneCopy = I830EXADoneCopy;
+ i830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
+ i830->uxa_driver->Copy = I830EXACopy;
+ i830->uxa_driver->DoneCopy = I830EXADoneCopy;
/* Composite */
- if (!IS_I9XX(pI830)) {
- pI830->uxa_driver->CheckComposite = i830_check_composite;
- pI830->uxa_driver->PrepareComposite = i830_prepare_composite;
- pI830->uxa_driver->Composite = i830_composite;
- pI830->uxa_driver->DoneComposite = i830_done_composite;
- } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
- IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ if (!IS_I9XX(i830)) {
+ i830->uxa_driver->CheckComposite = i830_check_composite;
+ i830->uxa_driver->PrepareComposite = i830_prepare_composite;
+ i830->uxa_driver->Composite = i830_composite;
+ i830->uxa_driver->DoneComposite = i830_done_composite;
+ } else if (IS_I915G(i830) || IS_I915GM(i830) ||
+ IS_I945G(i830) || IS_I945GM(i830) || IS_G33CLASS(i830))
{
- pI830->uxa_driver->CheckComposite = i915_check_composite;
- pI830->uxa_driver->PrepareComposite = i915_prepare_composite;
- pI830->uxa_driver->Composite = i830_composite;
- pI830->uxa_driver->DoneComposite = i830_done_composite;
+ i830->uxa_driver->CheckComposite = i915_check_composite;
+ i830->uxa_driver->PrepareComposite = i915_prepare_composite;
+ i830->uxa_driver->Composite = i830_composite;
+ i830->uxa_driver->DoneComposite = i830_done_composite;
} else {
- pI830->uxa_driver->CheckComposite = i965_check_composite;
- pI830->uxa_driver->PrepareComposite = i965_prepare_composite;
- pI830->uxa_driver->Composite = i965_composite;
- pI830->uxa_driver->DoneComposite = i830_done_composite;
+ i830->uxa_driver->CheckComposite = i965_check_composite;
+ i830->uxa_driver->PrepareComposite = i965_prepare_composite;
+ i830->uxa_driver->Composite = i965_composite;
+ i830->uxa_driver->DoneComposite = i830_done_composite;
}
- pI830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
- if(!uxa_driver_init(pScreen, pI830->uxa_driver)) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ i830->uxa_driver->PrepareAccess = i830_uxa_prepare_access;
+ i830->uxa_driver->FinishAccess = i830_uxa_finish_access;
+ i830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+
+ if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
"UXA initialization failed\n");
- xfree(pI830->uxa_driver);
- pI830->accel = ACCEL_NONE;
+ xfree(i830->uxa_driver);
+ i830->accel = ACCEL_NONE;
return FALSE;
}
- I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+ pScreen->CreatePixmap = i830_uxa_create_pixmap;
+ pScreen->DestroyPixmap = i830_uxa_destroy_pixmap;
+
+ I830SelectBuffer(scrn, I830_SELECT_FRONT);
return TRUE;
}
diff --git a/src/i830_memory.c b/src/i830_memory.c
index c1748b3..ff5def6 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -166,24 +166,16 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
return TRUE;
#ifdef XF86DRI
- if (mem->gem_handle != 0) {
- I830Ptr pI830 = I830PTR(pScrn);
- struct drm_i915_gem_pin pin;
- int ret;
-
- pin.handle = mem->gem_handle;
- pin.alignment = mem->alignment;
-
- ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_PIN, &pin);
- if (ret != 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Failed to pin %s: %s\n",
- mem->name, strerror(errno));
+ if (mem->bo != NULL) {
+ if (intel_bo_pin (mem->bo, mem->alignment) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to pin %s: %s\n",
+ mem->name, strerror(errno));
return FALSE;
}
mem->bound = TRUE;
- mem->offset = pin.offset;
+ mem->offset = mem->bo->offset;
mem->end = mem->offset + mem->size;
}
#endif
@@ -219,15 +211,8 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
i830_clear_tiling(pScrn, mem->fence_nr);
#ifdef XF86DRI
- if (mem->gem_handle != 0) {
- I830Ptr pI830 = I830PTR(pScrn);
- struct drm_i915_gem_unpin unpin;
- int ret;
-
- unpin.handle = mem->gem_handle;
- ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
-
- if (ret == 0) {
+ if (mem->bo != NULL) {
+ if (intel_bo_unpin (mem->bo) == 0) {
mem->bound = FALSE;
/* Give buffer obviously wrong offset/end until it's re-pinned. */
mem->offset = -1;
@@ -257,12 +242,9 @@ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
i830_unbind_memory(pScrn, mem);
#ifdef XF86DRI
- if (mem->gem_handle != 0) {
+ if (mem->bo != NULL) {
I830Ptr pI830 = I830PTR(pScrn);
- struct drm_gem_close close;
-
- close.handle = mem->gem_handle;
- ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
+ dri_bo_unreference (mem->bo);
if (pI830->bo_list == mem) {
pI830->bo_list = mem->next;
if (mem->next)
@@ -493,6 +475,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
i830_free_memory(pScrn, pI830->memory_manager);
pI830->memory_manager = NULL;
}
+ i830_init_bufmgr(pScrn);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to allocate space for kernel memory manager\n");
@@ -735,8 +718,6 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
{
I830Ptr pI830 = I830PTR(pScrn);
i830_memory *mem;
- int ret;
- struct drm_i915_gem_create create;
assert((flags & NEED_PHYSICAL_ADDR) == 0);
@@ -754,16 +735,13 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
return NULL;
}
- memset(&create, 0, sizeof(create));
- create.size = size;
+ mem->bo = dri_bo_alloc (pI830->bufmgr, name, size, align);
- ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_CREATE, &create);
- if (ret) {
+ if (!mem->bo) {
xfree(mem->name);
xfree(mem);
return NULL;
}
- mem->gem_handle = create.handle;
/* Give buffer obviously wrong offset/end until it's pinned. */
mem->offset = -1;
@@ -777,10 +755,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
/* Bind it if we currently control the VT */
if (pScrn->vtSema) {
if (!i830_bind_memory(pScrn, mem)) {
- struct drm_gem_close close;
-
- close.handle = mem->gem_handle;
- ioctl(pI830->drmSubFD, DRM_IOCTL_GEM_CLOSE, &close);
+ dri_bo_unreference (mem->bo);
xfree(mem->name);
xfree(mem);
return NULL;
@@ -908,19 +883,17 @@ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
mem->fence_nr = -1;
#ifdef XF86DRI
- if (mem->gem_handle != 0) {
- struct drm_i915_gem_set_tiling set_tiling;
- int ret;
+ if (mem->bo != 0) {
+ uint32_t tiling_mode = I915_TILING_NONE;
+ int ret;
- set_tiling.handle = mem->gem_handle;
if (tile_format == TILE_XMAJOR)
- set_tiling.tiling_mode = I915_TILING_X;
+ tiling_mode = I915_TILING_X;
else
- set_tiling.tiling_mode = I915_TILING_Y;
+ tiling_mode = I915_TILING_Y;
- ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_SET_TILING,
- &set_tiling);
- if (ret != 0 || set_tiling.tiling_mode == I915_TILING_NONE) {
+ ret = intel_bo_set_tiling (mem->bo, &tiling_mode);
+ if (ret != 0 || tiling_mode == I915_TILING_NONE) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to set tiling on %s: %s\n",
mem->name,
diff --git a/src/i830_render.c b/src/i830_render.c
index d5cab3f..4b42ea3 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -313,7 +313,7 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
BEGIN_BATCH(10);
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
- OUT_RELOC_PIXMAP(pPix, TM0S0_USE_FENCE);
+ OUT_RELOC_PIXMAP(pPix, I915_GEM_DOMAIN_SAMPLER, 0, TM0S0_USE_FENCE);
OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
@@ -444,7 +444,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
BUF_3D_PITCH(dst_pitch));
- OUT_RELOC_PIXMAP(pDst, 0);
+ OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(MI_NOOP);
OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
diff --git a/src/i915_render.c b/src/i915_render.c
index 54197bf..7837635 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -322,6 +322,8 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
Bool is_affine_src, is_affine_mask;
Bool is_nearest = FALSE;
+ return FALSE;
+
i830_exa_check_pitch_3d(pSrc);
if (pMask)
i830_exa_check_pitch_3d(pMask);
@@ -360,7 +362,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
BEGIN_BATCH(10);
OUT_BATCH(_3DSTATE_MAP_STATE | 3);
OUT_BATCH(0x00000001); /* map 0 */
- OUT_RELOC_PIXMAP(pSrc, 0);
+ OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[1]);
OUT_BATCH(pI830->mapstate[2]);
@@ -374,10 +376,10 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
BEGIN_BATCH(16);
OUT_BATCH(_3DSTATE_MAP_STATE | 6);
OUT_BATCH(0x00000003); /* map 0,1 */
- OUT_RELOC_PIXMAP(pSrc, 0);
+ OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[1]);
OUT_BATCH(pI830->mapstate[2]);
- OUT_RELOC_PIXMAP(pMask, 0);
+ OUT_RELOC_PIXMAP(pMask, I915_GEM_DOMAIN_SAMPLER, 0, 0);
OUT_BATCH(pI830->mapstate[4]);
OUT_BATCH(pI830->mapstate[5]);
@@ -398,7 +400,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
BUF_3D_PITCH(dst_pitch));
- OUT_RELOC_PIXMAP(pDst, 0);
+ OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
OUT_BATCH(dst_format);
diff --git a/src/i915_video.c b/src/i915_video.c
index e2954a7..7761a45 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -130,7 +130,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
- OUT_RELOC_PIXMAP(pPixmap, 0);
+ OUT_RELOC_PIXMAP(pPixmap, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
ADVANCE_BATCH();
if (!planar) {
commit 4cc20b7f6e25f4be4598f8edbe0077117126b4ee
Author: Keith Packard <keithp at keithp.com>
Date: Mon Aug 4 01:42:48 2008 -0700
Don't call sync on prepare_access -- just let the driver deal with it.
Let the driver do whatever sync is necessary from the prepare_access hook
rather than forcing a full sync.
diff --git a/uxa/uxa.c b/uxa/uxa.c
index 9745f8b..7201e7c 100644
--- a/uxa/uxa.c
+++ b/uxa/uxa.c
@@ -151,9 +151,6 @@ uxa_prepare_access(DrawablePtr pDrawable, int index)
if (!offscreen)
return;
- /* XXX should be pPixmap eventually */
- uxa_wait_sync (pScreen);
-
if (uxa_screen->info->PrepareAccess)
(*uxa_screen->info->PrepareAccess) (pPixmap, index);
}
commit b0b0998b5d52d105eb1e631f688aa8f1bd55ef39
Author: Keith Packard <keithp at keithp.com>
Date: Wed Jul 30 16:15:37 2008 -0700
Make EXA functions work for UXA as well
EXA and UXA have the same acceleration interface, but UXA doesn't provide
pixmap stride information as it doesn't manage pixmaps. Move all of that
into the driver structure so that the acceleration functions needn't
reference the EXA structure.
diff --git a/src/i830.h b/src/i830.h
index 2fb8efa..fe25919 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -527,9 +527,17 @@ typedef struct _I830Rec {
#ifdef I830_USE_EXA
ExaDriverPtr EXADriverPtr;
+#endif
+#ifdef I830_USE_UXA
uxa_driver_t *uxa_driver;
+#endif
+#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
PixmapPtr pSrcPixmap;
#endif
+ int accel_pixmap_pitch_alignment;
+ int accel_pixmap_offset_alignment;
+ int accel_max_x;
+ int accel_max_y;
I830WriteIndexedByteFunc writeControl;
I830ReadIndexedByteFunc readControl;
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 579de31..0ef565b 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -282,6 +282,54 @@ I830AccelInit(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
+ /* Limits are described in the BLT engine chapter under Graphics Data Size
+ * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+ * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+ *
+ * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+ *
+ * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+ * i965 limits 3D surface to 4kB-aligned offset if tiled.
+ * i965 limits 3D surfaces to w,h of ?,8192.
+ * i965 limits 3D surface to pitch of 1B - 128kB.
+ * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+ * i965 limits 3D surface pitch alignment to 512B if tiled.
+ * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+ *
+ * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i915 limits 3D textures to width,height of 2048,2048.
+ * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+ * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+ * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+ * i915 limits 3D destination to POT aligned pitch if tiled.
+ * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i845 limits 3D textures to width,height of 2048,2048.
+ * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+ * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+ * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+ * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * For the tiled issues, the only tiled buffer we draw to should be
+ * the front, which will have an appropriate pitch/offset already set up,
+ * so EXA doesn't need to worry.
+ */
+ if (IS_I965G(pI830)) {
+ pI830->accel_pixmap_offset_alignment = 4 * 2;
+ pI830->accel_pixmap_pitch_alignment = 16;
+ pI830->accel_max_x = 8192;
+ pI830->accel_max_y = 8192;
+ } else {
+ pI830->accel_pixmap_offset_alignment = 4;
+ pI830->accel_pixmap_pitch_alignment = 16;
+ pI830->accel_max_x = 2048;
+ pI830->accel_max_y = 2048;
+ }
switch (pI830->accel) {
#ifdef I830_USE_UXA
case ACCEL_UXA:
diff --git a/src/i830_exa.c b/src/i830_exa.c
index a6705f4..f00e4f9 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -121,6 +121,21 @@ i830_pixmap_tiled(PixmapPtr pPixmap)
return FALSE;
}
+static unsigned long
+i830_pixmap_pitch(PixmapPtr pixmap)
+{
+ return pixmap->devKind;
+}
+
+static int
+i830_pixmap_pitch_is_aligned(PixmapPtr pixmap)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ return i830_pixmap_pitch(pixmap) % pI830->accel_pixmap_pitch_alignment == 0;
+}
+
static Bool
i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
{
@@ -172,9 +187,9 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
i830_exa_check_pitch_2d(pPixmap);
- pitch = exaGetPixmapPitch(pPixmap);
+ pitch = i830_pixmap_pitch(pPixmap);
- if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
+ if (!i830_pixmap_pitch_is_aligned(pPixmap))
I830FALLBACK("pixmap pitch not aligned");
pI830->BR[13] = (I830PatternROP[alu] & 0xff) << 16 ;
@@ -202,7 +217,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
unsigned long pitch;
uint32_t cmd;
- pitch = exaGetPixmapPitch(pPixmap);
+ pitch = i830_pixmap_pitch(pPixmap);
{
BEGIN_BATCH(6);
@@ -286,8 +301,8 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
dst_x2 = dst_x1 + w;
dst_y2 = dst_y1 + h;
- dst_pitch = exaGetPixmapPitch(pDstPixmap);
- src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
+ dst_pitch = i830_pixmap_pitch(pDstPixmap);
+ src_pitch = i830_pixmap_pitch(pI830->pSrcPixmap);
{
BEGIN_BATCH(8);
@@ -466,55 +481,10 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr->offScreenBase,
pI830->EXADriverPtr->memorySize);
-
- /* Limits are described in the BLT engine chapter under Graphics Data Size
- * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
- * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
- *
- * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
- *
- * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
- * i965 limits 3D surface to 4kB-aligned offset if tiled.
- * i965 limits 3D surfaces to w,h of ?,8192.
- * i965 limits 3D surface to pitch of 1B - 128kB.
- * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
- * i965 limits 3D surface pitch alignment to 512B if tiled.
- * i965 limits 3D destination drawing rect to w,h of 8192,8192.
- *
- * i915 limits 3D textures to 4B-aligned offset if un-tiled.
- * i915 limits 3D textures to ~4kB-aligned offset if tiled.
- * i915 limits 3D textures to width,height of 2048,2048.
- * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
- * i915 limits 3D destination to ~4kB-aligned offset if tiled.
- * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
- * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
- * i915 limits 3D destination to POT aligned pitch if tiled.
- * i915 limits 3D destination drawing rect to w,h of 2048,2048.
- *
- * i845 limits 3D textures to 4B-aligned offset if un-tiled.
- * i845 limits 3D textures to ~4kB-aligned offset if tiled.
- * i845 limits 3D textures to width,height of 2048,2048.
- * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
- * i845 limits 3D destination to 4B-aligned offset if un-tiled.
- * i845 limits 3D destination to ~4kB-aligned offset if tiled.
- * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
- * i845 limits 3D destination drawing rect to w,h of 2048,2048.
- *
- * For the tiled issues, the only tiled buffer we draw to should be
- * the front, which will have an appropriate pitch/offset already set up,
- * so EXA doesn't need to worry.
- */
- if (IS_I965G(pI830)) {
- pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
- pI830->EXADriverPtr->pixmapPitchAlign = 16;
- pI830->EXADriverPtr->maxX = 8192;
- pI830->EXADriverPtr->maxY = 8192;
- } else {
- pI830->EXADriverPtr->pixmapOffsetAlign = 4;
- pI830->EXADriverPtr->pixmapPitchAlign = 16;
- pI830->EXADriverPtr->maxX = 2048;
- pI830->EXADriverPtr->maxY = 2048;
- }
+ pI830->EXADriverPtr->pixmapOffsetAlign = pI830->accel_pixmap_offset_alignment;
+ pI830->EXADriverPtr->pixmapPitchAlign = pI830->accel_pixmap_pitch_alignment;
+ pI830->EXADriverPtr->maxX = pI830->accel_max_x;
+ pI830->EXADriverPtr->maxY = pI830->accel_max_y;
/* Sync */
pI830->EXADriverPtr->WaitMarker = I830EXASync;
commit 59774e9aca2d743e82d616bb644d20ff6d60d492
Author: Keith Packard <keithp at keithp.com>
Date: Tue Jul 29 22:57:09 2008 -0700
Add UXA - the unified memory acceleration architecture.
This eliminates the cost of EXA migration management while providing full
pixmap allocation control to the driver. The goal is to make something
useful for UMA drivers.
diff --git a/Makefile.am b/Makefile.am
index b2398a8..5db07de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
-SUBDIRS = src man
+SUBDIRS = uxa src man
EXTRA_DIST = README
DISTCLEANFILES = doltcompile
diff --git a/configure.ac b/configure.ac
index db16c35..b24a154 100644
--- a/configure.ac
+++ b/configure.ac
@@ -251,6 +251,7 @@ XORG_CHECK_LINUXDOC
AC_OUTPUT([
Makefile
+ uxa/Makefile
src/Makefile
src/xvmc/Makefile
src/bios_reader/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 2932233..dd92c8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,13 +31,13 @@ SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER)
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
- @PCIACCESS_CFLAGS@ \
- @XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA
+ @PCIACCESS_CFLAGS@ -I../uxa \
+ @XMODES_CFLAGS@ -DI830_XV -DI830_USE_XAA -DI830_USE_EXA -DI830_USE_UXA
intel_drv_la_LTLIBRARIES = intel_drv.la
intel_drv_la_LDFLAGS = -module -avoid-version
intel_drv_ladir = @moduledir@/drivers
-intel_drv_la_LIBADD = -lm
+intel_drv_la_LIBADD = -lm ../uxa/libuxa.la
if XSERVER_LIBPCIACCESS
intel_drv_la_LIBADD += @PCIACCESS_LIBS@
endif
diff --git a/src/i830.h b/src/i830.h
index a8ab8c6..2fb8efa 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -83,7 +83,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef I830_USE_EXA
#include "exa.h"
+#include "uxa.h"
Bool I830EXAInit(ScreenPtr pScreen);
+Bool i830_uxa_init(ScreenPtr pScreen);
unsigned long long I830TexOffsetStart(PixmapPtr pPix);
#endif
@@ -355,6 +357,14 @@ enum backlight_control {
BCM_KERNEL,
};
+typedef enum accel_method {
+ ACCEL_UNINIT = 0,
+ ACCEL_NONE,
+ ACCEL_XAA,
+ ACCEL_EXA,
+ ACCEL_UXA
+} accel_method_t;
+
typedef struct _I830Rec {
unsigned char *MMIOBase;
unsigned char *GTTBase;
@@ -496,8 +506,7 @@ typedef struct _I830Rec {
Bool fence_used[FENCE_NEW_NR];
- Bool useEXA;
- Bool noAccel;
+ accel_method_t accel;
Bool SWCursor;
#ifdef I830_USE_XAA
XAAInfoRecPtr AccelInfoRec;
@@ -518,6 +527,7 @@ typedef struct _I830Rec {
#ifdef I830_USE_EXA
ExaDriverPtr EXADriverPtr;
+ uxa_driver_t *uxa_driver;
PixmapPtr pSrcPixmap;
#endif
@@ -902,7 +912,7 @@ static inline int i830_fb_compression_supported(I830Ptr pI830)
/* fbc depends on tiled surface. And we don't support tiled
* front buffer with XAA now.
*/
- if (!pI830->tiling || (IS_I965G(pI830) && !pI830->useEXA))
+ if (!pI830->tiling || (IS_I965G(pI830) && pI830->accel <= ACCEL_XAA))
return FALSE;
return TRUE;
}
diff --git a/src/i830_accel.c b/src/i830_accel.c
index c3cd08e..579de31 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -67,12 +67,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
unsigned long
intel_get_pixmap_offset(PixmapPtr pPix)
{
+#ifdef I830_USE_EXA
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
-#ifdef I830_USE_EXA
- if (pI830->useEXA)
+ if (pI830->accel == ACCEL_EXA)
return exaGetPixmapOffset(pPix);
#endif
return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
@@ -81,17 +81,15 @@ intel_get_pixmap_offset(PixmapPtr pPix)
unsigned long
intel_get_pixmap_pitch(PixmapPtr pPix)
{
+#ifdef I830_USE_EXA
ScreenPtr pScreen = pPix->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
-#ifdef I830_USE_EXA
- if (pI830->useEXA)
+ if (pI830->accel == ACCEL_EXA)
return exaGetPixmapPitch(pPix);
#endif
-#ifdef I830_USE_XAA
return (unsigned long)pPix->devKind;
-#endif
}
int
@@ -151,6 +149,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
#ifdef I830_USE_EXA
pI830->EXADriverPtr = NULL;
#endif
+#ifdef I830_USE_UXA
+ pI830->uxa_driver = NULL;
+#endif
FatalError("lockup\n");
}
@@ -176,7 +177,7 @@ I830Sync(ScrnInfoPtr pScrn)
if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
ErrorF("I830Sync\n");
- if (pI830->noAccel)
+ if (pI830->accel == ACCEL_NONE)
return;
#ifdef XF86DRI
@@ -278,15 +279,25 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer)
Bool
I830AccelInit(ScreenPtr pScreen)
{
-#ifdef I830_USE_EXA
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
- if (pI830->useEXA)
+ switch (pI830->accel) {
+#ifdef I830_USE_UXA
+ case ACCEL_UXA:
+ return i830_uxa_init(pScreen);
+#endif
+#ifdef I830_USE_EXA
+ case ACCEL_EXA:
return I830EXAInit(pScreen);
#endif
#ifdef I830_USE_XAA
- return I830XAAInit(pScreen);
+ case ACCEL_XAA:
+ return I830XAAInit(pScreen);
#endif
+ case ACCEL_UNINIT:
+ case ACCEL_NONE:
+ break;
+ }
return FALSE;
}
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 1671e25..f1205cc 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -1314,6 +1314,8 @@ i830_valid_command (uint32_t cmd)
if (!mi_cmds[opcode])
return -1;
break;
+ case 1:
+ return -1;
case 2: /* 2D */
count = (cmd & 0x1f) + 2;
opcode = (cmd >> 22) & 0x7f;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 4678372..0e5d81d 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -589,7 +589,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
#if DRIINFO_MAJOR_VERSION > 5 || \
(DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
- if (pI830->useEXA)
+ if (pI830->accel == ACCEL_EXA)
pDRIInfo->texOffsetStart = I830TexOffsetStart;
#endif
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b6fac9f..ed974ce 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -290,9 +290,7 @@ static PciChipsets I830PciChipsets[] = {
*/
typedef enum {
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
OPTION_ACCELMETHOD,
-#endif
OPTION_NOACCEL,
OPTION_SW_CURSOR,
OPTION_CACHE_LINES,
@@ -318,9 +316,7 @@ typedef enum {
} I830Opts;
static OptionInfoRec I830Options[] = {
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
{OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE},
-#endif
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
@@ -1338,6 +1334,15 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
return TRUE;
}
+static const char *accel_name[] =
+{
+ "unspecified",
+ "no",
+ "XAA",
+ "EXA",
+ "UXA",
+};
+
/**
* This is called per zaphod head (so usually just once) to do initialization
* before the Screen is created.
@@ -1554,7 +1559,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
num_pipe, num_pipe > 1 ? "s" : "");
if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
- pI830->noAccel = TRUE;
+ pI830->accel = ACCEL_NONE;
}
/*
@@ -1568,29 +1573,38 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
* All this *could* go away if we removed XAA support from this driver,
* for example. :)
*/
- if (!pI830->noAccel) {
+ if (pI830->accel == ACCEL_UNINIT) {
+ pI830->accel = ACCEL_NONE;
+#ifdef I830_USE_XAA
+ pI830->accel = ACCEL_XAA;
+#endif
#ifdef I830_USE_EXA
- pI830->useEXA = TRUE;
-#else
- pI830->useEXA = FALSE;
+ pI830->accel = ACCEL_EXA;
+#endif
+#ifdef I830_USE_UXA
+ pI830->accel = ACCEL_UXA;
#endif
-#if defined(I830_USE_XAA) && defined(I830_USE_EXA)
+#if I830_USE_XAA + I830_USE_EXA + I830_USE_UXA >= 2
from = X_DEFAULT;
if ((s = (char *)xf86GetOptValString(pI830->Options,
OPTION_ACCELMETHOD))) {
if (!xf86NameCmp(s, "EXA")) {
from = X_CONFIG;
- pI830->useEXA = TRUE;
+ pI830->accel = ACCEL_EXA;
}
else if (!xf86NameCmp(s, "XAA")) {
from = X_CONFIG;
- pI830->useEXA = FALSE;
+ pI830->accel = ACCEL_XAA;
+ }
+ else if (!xf86NameCmp(s, "UXA")) {
+ from = X_CONFIG;
+ pI830->accel = ACCEL_UXA;
}
}
#endif
- xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
- pI830->useEXA ? "EXA" : "XAA");
}
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
+ accel_name[pI830->accel]);
if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
pI830->SWCursor = TRUE;
@@ -1601,7 +1615,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
#ifdef XF86DRI
if (!pI830->directRenderingDisabled) {
- if (pI830->noAccel || pI830->SWCursor) {
+ if (pI830->accel == ACCEL_NONE || pI830->SWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"needs HW cursor and 2D acceleration.\n");
pI830->directRenderingDisabled = TRUE;
@@ -1774,7 +1788,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
if (!IS_I965G(pI830) && pScrn->virtualY > 2048) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n");
- pI830->noAccel = TRUE;
+ pI830->accel = ACCEL_NONE;
}
/* Set display resolution */
@@ -1788,18 +1802,19 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
xf86LoaderReqSymLists(I810fbSymbols, NULL);
+ switch (pI830->accel) {
#ifdef I830_USE_XAA
- if (!pI830->noAccel && !pI830->useEXA) {
+ case ACCEL_XAA:
if (!xf86LoadSubModule(pScrn, "xaa")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810xaaSymbols, NULL);
- }
+ break;
#endif
#ifdef I830_USE_EXA
- if (!pI830->noAccel && pI830->useEXA) {
+ case ACCEL_EXA: {
XF86ModReqInfo req;
int errmaj, errmin;
@@ -1817,8 +1832,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
xf86LoaderReqSymLists(I830exaSymbols, NULL);
+ break;
}
#endif
+ default:
+ break;
+ }
if (!pI830->SWCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
PreInitCleanup(pScrn);
@@ -1878,7 +1897,7 @@ i830_stop_ring(ScrnInfoPtr pScrn, Bool flush)
pI830->entityPrivate->RingRunning = 0;
/* Flush the ring buffer (if enabled), then disable it. */
- if (!pI830->noAccel) {
+ if (pI830->accel != ACCEL_NONE) {
temp = INREG(LP_RING + RING_LEN);
if (temp & RING_VALID) {
i830_refresh_ring(pScrn);
@@ -1900,7 +1919,7 @@ i830_start_ring(ScrnInfoPtr pScrn)
DPRINTF(PFX, "SetRingRegs\n");
- if (pI830->noAccel)
+ if (pI830->accel == ACCEL_NONE)
return;
if (!I830IsPrimary(pScrn)) return;
@@ -2441,7 +2460,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn)
I830Ptr pI830 = I830PTR(pScrn);
uint32_t ctx_addr;
- if (pI830->noAccel)
+ if (pI830->accel == ACCEL_NONE)
return;
#ifdef XF86DRI
@@ -2496,12 +2515,12 @@ I830BlockHandler(int i,
pI830->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = I830BlockHandler;
- if (pScrn->vtSema && !pI830->noAccel) {
+ if (pScrn->vtSema && pI830->accel != ACCEL_NONE) {
/* Emit a flush of the rendering cache, or on the 965 and beyond
* rendering results may not hit the framebuffer until significantly
* later.
*/
- if (!pI830->noAccel && (pI830->need_mi_flush || pI830->batch_used))
+ if (pI830->accel != ACCEL_NONE && (pI830->need_mi_flush || pI830->batch_used))
I830EmitFlush(pScrn);
/* Flush the batch, so that any rendering is executed in a timely
@@ -3001,12 +3020,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->XvEnabled = !pI830->XvDisabled;
if (pI830->XvEnabled) {
if (!I830IsPrimary(pScrn)) {
- if (!pI8301->XvEnabled || pI830->noAccel) {
+ if (!pI8301->XvEnabled || pI830->accel == ACCEL_NONE) {
pI830->XvEnabled = FALSE;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
}
} else
- if (pI830->noAccel || pI830->StolenOnly) {
+ if (pI830->accel == ACCEL_NONE || pI830->StolenOnly) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
"needs 2D accel and AGPGART.\n");
pI830->XvEnabled = FALSE;
@@ -3016,18 +3035,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI830->XvEnabled = FALSE;
#endif
- if (!pI830->noAccel) {
+ if (pI830->accel != ACCEL_NONE) {
if (pI830->memory_manager == NULL && pI830->LpRing->mem->size == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling acceleration because the ring buffer "
"allocation failed.\n");
- pI830->noAccel = TRUE;
+ pI830->accel = ACCEL_NONE;
}
}
#ifdef I830_XV
if (pI830->XvEnabled) {
- if (pI830->noAccel) {
+ if (pI830->accel == ACCEL_NONE) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
"needs 2D acceleration.\n");
pI830->XvEnabled = FALSE;
@@ -3049,7 +3068,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
*/
if (pI830->directRenderingEnabled) {
- if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
+ if (pI830->accel == ACCEL_NONE || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
"needs HW cursor, 2D accel and AGPGART.\n");
pI830->directRenderingEnabled = FALSE;
@@ -3123,7 +3142,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n");
- if (!pI830->useEXA) {
+ if (pI830->accel <= ACCEL_XAA) {
if (I830IsPrimary(pScrn)) {
if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -3171,7 +3190,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
DPRINTF(PFX,
"assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
- if (!pI830->noAccel) {
+ if (pI830->accel != ACCEL_NONE) {
if (!I830AccelInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware acceleration initialization failed\n");
@@ -3596,12 +3615,19 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
}
#endif
#ifdef I830_USE_EXA
- if (pI830->useEXA && pI830->EXADriverPtr) {
+ if (pI830->EXADriverPtr) {
exaDriverFini(pScreen);
xfree(pI830->EXADriverPtr);
pI830->EXADriverPtr = NULL;
}
#endif
+#ifdef I830_USE_UXA
+ if (pI830->uxa_driver) {
+ uxa_driver_fini (pScreen);
+ xfree (pI830->uxa_driver);
+ pI830->uxa_driver = NULL;
+ }
+#endif
xf86_cursors_fini (pScreen);
i830_allocator_fini(pScrn);
@@ -3830,19 +3856,34 @@ i830WaitSync(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
+ switch (pI830->accel) {
#ifdef I830_USE_XAA
- if (!pI830->noAccel && !pI830->useEXA && pI830->AccelInfoRec
- && pI830->AccelInfoRec->NeedToSync) {
- (*pI830->AccelInfoRec->Sync)(pScrn);
- pI830->AccelInfoRec->NeedToSync = FALSE;
- }
+ case ACCEL_XAA:
+ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+ (*pI830->AccelInfoRec->Sync)(pScrn);
+ pI830->AccelInfoRec->NeedToSync = FALSE;
+ }
+ break;
#endif
#ifdef I830_USE_EXA
- if (!pI830->noAccel && pI830->useEXA && pI830->EXADriverPtr) {
- ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
- exaWaitSync(pScreen);
- }
+ case ACCEL_EXA:
+ if (pI830->EXADriverPtr) {
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ exaWaitSync(pScreen);
+ }
+ break;
#endif
+#ifdef I830_USE_UXA
+ case ACCEL_UXA:
+ if (pI830->uxa_driver) {
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ uxa_wait_sync(pScreen);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
}
void
@@ -3850,16 +3891,32 @@ i830MarkSync(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
+ switch (pI830->accel) {
#ifdef I830_USE_XAA
- if (!pI830->useEXA && pI830->AccelInfoRec)
- pI830->AccelInfoRec->NeedToSync = TRUE;
+ case ACCEL_XAA:
+ if (pI830->AccelInfoRec)
+ pI830->AccelInfoRec->NeedToSync = TRUE;
+ break;
#endif
#ifdef I830_USE_EXA
- if (pI830->useEXA && pI830->EXADriverPtr) {
- ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
- exaMarkSync(pScreen);
- }
+ case ACCEL_EXA:
+ if (pI830->EXADriverPtr) {
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ exaMarkSync(pScreen);
+ }
+ break;
+#endif
+#ifdef I830_USE_UXA
+ case ACCEL_UXA:
+ if (pI830->uxa_driver) {
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ exaMarkSync(pScreen);
+ }
+ break;
#endif
+ default:
+ break;
+ }
}
void
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 75ccd74..a6705f4 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -430,7 +430,7 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr = exaDriverAlloc();
if (pI830->EXADriverPtr == NULL) {
- pI830->noAccel = TRUE;
+ pI830->accel = ACCEL_NONE;
return FALSE;
}
memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
@@ -558,7 +558,7 @@ I830EXAInit(ScreenPtr pScreen)
pI830->EXADriverPtr->exa_minor = 0;
if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
xfree(pI830->EXADriverPtr);
- pI830->noAccel = TRUE;
+ pI830->accel = ACCEL_NONE;
return FALSE;
}
}
@@ -568,6 +568,133 @@ I830EXAInit(ScreenPtr pScreen)
return TRUE;
}
+static Bool
+i830_uxa_pixmap_is_offscreen(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* XXX for now, eventually we'll support 'real' off-screen pixmaps */
+ if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
+ (void *)pPixmap->devPrivate.ptr <
+ (void *)(pI830->FbBase + pI830->FbMapSize))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+Bool
+i830_uxa_init (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->uxa_driver = uxa_driver_alloc();
+ if (pI830->uxa_driver == NULL) {
+ pI830->accel = ACCEL_NONE;
+ return FALSE;
+ }
+ memset(pI830->uxa_driver, 0, sizeof(*pI830->uxa_driver));
+
+ pI830->bufferOffset = 0;
+ pI830->uxa_driver->uxa_major = 1;
+ pI830->uxa_driver->uxa_minor = 0;
+
+ /* Limits are described in the BLT engine chapter under Graphics Data Size
+ * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+ * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+ *
+ * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+ *
+ * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+ * i965 limits 3D surface to 4kB-aligned offset if tiled.
+ * i965 limits 3D surfaces to w,h of ?,8192.
+ * i965 limits 3D surface to pitch of 1B - 128kB.
+ * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+ * i965 limits 3D surface pitch alignment to 512B if tiled.
+ * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+ *
+ * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i915 limits 3D textures to width,height of 2048,2048.
+ * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+ * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+ * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+ * i915 limits 3D destination to POT aligned pitch if tiled.
+ * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i845 limits 3D textures to width,height of 2048,2048.
+ * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+ * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+ * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+ * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * For the tiled issues, the only tiled buffer we draw to should be
+ * the front, which will have an appropriate pitch/offset already set up,
+ * so EXA doesn't need to worry.
+ */
+ if (IS_I965G(pI830)) {
+ pI830->uxa_driver->maxX = 8192;
+ pI830->uxa_driver->maxY = 8192;
+ } else {
+ pI830->uxa_driver->maxX = 2048;
+ pI830->uxa_driver->maxY = 2048;
+ }
+
+ /* Sync */
+ pI830->uxa_driver->WaitMarker = I830EXASync;
+
+ /* Solid fill */
+ pI830->uxa_driver->PrepareSolid = I830EXAPrepareSolid;
+ pI830->uxa_driver->Solid = I830EXASolid;
+ pI830->uxa_driver->DoneSolid = I830EXADoneSolid;
+
+ /* Copy */
+ pI830->uxa_driver->PrepareCopy = I830EXAPrepareCopy;
+ pI830->uxa_driver->Copy = I830EXACopy;
+ pI830->uxa_driver->DoneCopy = I830EXADoneCopy;
+
+ /* Composite */
+ if (!IS_I9XX(pI830)) {
+ pI830->uxa_driver->CheckComposite = i830_check_composite;
+ pI830->uxa_driver->PrepareComposite = i830_prepare_composite;
+ pI830->uxa_driver->Composite = i830_composite;
+ pI830->uxa_driver->DoneComposite = i830_done_composite;
+ } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+ IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ {
+ pI830->uxa_driver->CheckComposite = i915_check_composite;
+ pI830->uxa_driver->PrepareComposite = i915_prepare_composite;
+ pI830->uxa_driver->Composite = i830_composite;
+ pI830->uxa_driver->DoneComposite = i830_done_composite;
+ } else {
+ pI830->uxa_driver->CheckComposite = i965_check_composite;
+ pI830->uxa_driver->PrepareComposite = i965_prepare_composite;
+ pI830->uxa_driver->Composite = i965_composite;
+ pI830->uxa_driver->DoneComposite = i830_done_composite;
+ }
+ pI830->uxa_driver->PixmapIsOffscreen = i830_uxa_pixmap_is_offscreen;
+
+ if(!uxa_driver_init(pScreen, pI830->uxa_driver)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "UXA initialization failed\n");
+ xfree(pI830->uxa_driver);
+ pI830->accel = ACCEL_NONE;
+ return FALSE;
+ }
+
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+ return TRUE;
+}
+
#ifdef XF86DRI
#ifndef ExaOffscreenMarkUsed
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b62bda0..c1748b3 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -449,7 +449,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
mmsize = size;
/* EXA area is fixed. */
- if (pI830->useEXA) {
+ if (pI830->accel == ACCEL_EXA) {
mmsize -= ROUND_TO_PAGE(3 * pScrn->displayWidth * pI830->cpp *
pScrn->virtualY);
}
@@ -1022,7 +1022,7 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
- if (pI830->noAccel || pI830->memory_manager || pI830->LpRing->mem != NULL)
+ if (pI830->accel == ACCEL_NONE || pI830->memory_manager || pI830->LpRing->mem != NULL)
return TRUE;
/* We don't have any mechanism in the DRM yet to alert it that we've moved
@@ -1167,7 +1167,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
minspace = pitch * pScrn->virtualY;
avail = pScrn->videoRam * 1024;
- if (!pI830->useEXA) {
+ if (pI830->accel == ACCEL_XAA) {
maxCacheLines = (avail - minspace) / pitch;
/* This shouldn't happen. */
if (maxCacheLines < 0) {
@@ -1198,7 +1198,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
"Allocating %d scanlines for pixmap cache\n",
cacheLines);
} else {
- /* For EXA, we have a separate allocation for the linear allocator
+ /* For non-XAA, we have a separate allocation for the linear allocator
* which also does the pixmap cache.
*/
cacheLines = 0;
@@ -1213,7 +1213,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
* acceleration operations (non-XY COLOR_BLT) can't be done to tiled
* buffers.
*/
- if (!pI830->useEXA && IS_I965G(pI830))
+ if (pI830->accel <= ACCEL_XAA && IS_I965G(pI830))
tiling = FALSE;
else
tiling = pI830->tiling;
@@ -1412,7 +1412,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
}
/* even in XAA, 965G needs state mem buffer for rendering */
- if (IS_I965G(pI830) && !pI830->noAccel &&
+ if (IS_I965G(pI830) && pI830->accel != ACCEL_NONE &&
pI830->gen4_render_state_mem == NULL)
{
pI830->gen4_render_state_mem =
@@ -1450,7 +1450,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
return FALSE;
#ifdef I830_USE_EXA
- if (pI830->useEXA) {
+ if (pI830->accel == ACCEL_EXA) {
if (pI830->exa_offscreen == NULL) {
/* Default EXA to having 3 screens worth of offscreen memory space
* (for pixmaps).
@@ -1478,7 +1478,7 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
}
#endif /* I830_USE_EXA */
- if (!pI830->noAccel && !pI830->useEXA) {
+ if (pI830->accel == ACCEL_XAA) {
/* The lifetime fixed offset of xaa scratch is probably not required,
* but we do some setup using it at XAAInit() time. And XAA may not
* end up being supported with GEM anyway.
diff --git a/src/i830_video.c b/src/i830_video.c
index 486f670..1719835 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2460,13 +2460,13 @@ I830PutImage(ScrnInfoPtr pScrn,
}
#ifdef I830_USE_EXA
- if (pPriv->textured && pI830->useEXA) {
+ if (pPriv->textured && pI830->accel == ACCEL_EXA) {
/* Force the pixmap into framebuffer so we can draw to it. */
exaMoveInPixmap(pPixmap);
}
#endif
- if (pPriv->textured && !pI830->useEXA &&
+ if (pPriv->textured && pI830->accel <= ACCEL_XAA &&
(((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) ||
((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase +
pI830->FbMapSize))) {
diff --git a/uxa/Makefile.am b/uxa/Makefile.am
new file mode 100644
index 0000000..641b414
--- /dev/null
+++ b/uxa/Makefile.am
@@ -0,0 +1,20 @@
+noinst_LTLIBRARIES = libuxa.la
+
+# Override these since UXA doesn't need them and the needed files aren't
+# built (in hw/xfree86/os-support/solaris) until after UXA is built
+SOLARIS_ASM_CFLAGS=""
+
+INCLUDES = \
+ $(XORG_INCS)
+
+AM_CFLAGS = $(WARN_CFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS)
+
+libuxa_la_SOURCES = \
+ uxa.c \
+ uxa.h \
+ uxa-accel.c \
+ uxa-glyphs.c \
+ uxa-render.c \
+ uxa-priv.h \
+ uxa-unaccel.c
+
diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c
new file mode 100644
index 0000000..7c7b3e9
--- /dev/null
+++ b/uxa/uxa-accel.c
@@ -0,0 +1,1038 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric at anholt.net>
+ * Michel Dänzer <michel at tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "uxa-priv.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "uxa.h"
+
+static void
+uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
+ BoxPtr pextent, pbox;
+ int nbox;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1;
+ int partX1, partX2;
+ int off_x, off_y;
+
+ if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
+ !(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) ||
+ !(*uxa_screen->info->PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+ uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+
+ pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (n--)
+ {
+ fullX1 = ppt->x;
+ fullY1 = ppt->y;
+ fullX2 = fullX1 + (int) *pwidth;
+ ppt++;
+ pwidth++;
+
+ if (fullY1 < extentY1 || extentY2 <= fullY1)
+ continue;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullX1 >= fullX2)
+ continue;
+
+ nbox = REGION_NUM_RECTS (pClip);
+ if (nbox == 1)
+ {
+ (*uxa_screen->info->Solid) (pPixmap,
+ fullX1 + off_x, fullY1 + off_y,
+ fullX2 + off_x, fullY1 + 1 + off_y);
+ }
+ else
+ {
+ pbox = REGION_RECTS(pClip);
+ while(nbox--)
+ {
+ if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ if (partX2 > partX1) {
+ (*uxa_screen->info->Solid) (pPixmap,
+ partX1 + off_x, fullY1 + off_y,
+ partX2 + off_x, fullY1 + 1 + off_y);
+ }
+ }
+ pbox++;
+ }
+ }
+ }
+ (*uxa_screen->info->DoneSolid) (pPixmap);
+ uxa_mark_sync(pScreen);
+}
+
+static Bool
+uxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int format, char *bits, int src_stride)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+ PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
+ RegionPtr pClip;
+ BoxPtr pbox;
+ int nbox;
+ int xoff, yoff;
+ int bpp = pDrawable->bitsPerPixel;
+ Bool access_prepared = FALSE;
+
+ /* Don't bother with under 8bpp, XYPixmaps. */
+ if (format != ZPixmap || bpp < 8)
+ return FALSE;
+
+ /* Only accelerate copies: no rop or planemask. */
+ if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
+ return FALSE;
+
+ if (uxa_screen->swappedOut)
+ return FALSE;
+
+ pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+ if (!pPix || !uxa_screen->info->UploadToScreen)
+ return FALSE;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ pClip = fbGetCompositeClip(pGC);
+ for (nbox = REGION_NUM_RECTS(pClip),
+ pbox = REGION_RECTS(pClip);
+ nbox--;
+ pbox++)
+ {
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + w;
+ int y2 = y + h;
+ char *src;
+ Bool ok;
+
+ if (x1 < pbox->x1)
+ x1 = pbox->x1;
+ if (y1 < pbox->y1)
+ y1 = pbox->y1;
+ if (x2 > pbox->x2)
+ x2 = pbox->x2;
+ if (y2 > pbox->y2)
+ y2 = pbox->y2;
+ if (x1 >= x2 || y1 >= y2)
+ continue;
+
+ src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
+ ok = uxa_screen->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
+ x2 - x1, y2 - y1, src, src_stride);
+ /* If we fail to accelerate the upload, fall back to using unaccelerated
+ * fb calls.
+ */
+ if (!ok) {
+ FbStip *dst;
+ FbStride dst_stride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ if (!access_prepared) {
+ uxa_prepare_access(pDrawable, UXA_PREPARE_DEST);
+
+ access_prepared = TRUE;
+ }
+
+ fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
+ dstXoff, dstYoff);
+
+ fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
+ src_stride / sizeof(FbStip),
+ (x1 - x) * dstBpp,
+ dst + (y1 + dstYoff) * dst_stride,
+ dst_stride,
+ (x1 + dstXoff) * dstBpp,
+ (x2 - x1) * dstBpp,
+ y2 - y1,
+ GXcopy, FB_ALLONES, dstBpp);
+ }
+ }
+
+ if (access_prepared)
+ uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+ else
+ uxa_mark_sync(pDrawable->pScreen);
+
+ return TRUE;
+}
+
+#ifdef MITSHM
+
+static Bool
+uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ unsigned int format, int w, int h, int sx, int sy, int sw,
+ int sh, int dx, int dy, char *data)
+{
+ int src_stride = PixmapBytePad(w, depth);
+
+ if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
+ sy * src_stride + sx * BitsPerPixel(depth) / 8,
+ src_stride))
+ return TRUE;
+
+ if (format == ZPixmap)
+ {
+ PixmapPtr pPixmap;
+
+ pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
+ BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
+ if (!pPixmap)
+ return FALSE;
+
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+
+ fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
+ uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+
+ FreeScratchPixmapHeader(pPixmap);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
+ * inform any interested parties of the damage incurred to the drawable.
+ *
+ * We also need to set the pending damage to ensure correct migration in all
+ * cases.
+ */
+void
+uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
+ int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+ char *data)
+{
+ if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
+ dx, dy, data)) {
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
+ data);
+ uxa_finish_access(pDrawable, UXA_PREPARE_DEST);
+ }
+}
+
+ShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image };
+
+#endif
+
+static void
+uxa_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+#ifdef MITSHM
+ if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y,
+ bits))
+#else
+ if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
+ PixmapBytePad(w, pDrawable->depth)))
+#endif
+ uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+}
+
+static Bool inline
+uxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+ PixmapPtr pSrcPixmap, pDstPixmap;
+ int src_off_x, src_off_y, dst_off_x, dst_off_y;
+ int dirsetup;
+
+ /* Need to get both pixmaps to call the driver routines */
+ pSrcPixmap = uxa_get_offscreen_pixmap (pSrcDrawable, &src_off_x, &src_off_y);
+ pDstPixmap = uxa_get_offscreen_pixmap (pDstDrawable, &dst_off_x, &dst_off_y);
+ if (!pSrcPixmap || !pDstPixmap)
+ return FALSE;
+
+ /*
+ * Now the case of a chip that only supports xdir = ydir = 1 or
+ * xdir = ydir = -1, but we have xdir != ydir.
+ */
+ dirsetup = 0; /* No direction set up yet. */
+ for (; nbox; pbox++, nbox--) {
+ if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+ /* Do a xdir = ydir = -1 blit instead. */
+ if (dirsetup != -1) {
+ if (dirsetup != 0)
+ uxa_screen->info->DoneCopy(pDstPixmap);
+ dirsetup = -1;
+ if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ -1, -1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ (*uxa_screen->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+ /* Do a xdir = ydir = 1 blit instead. */
+ if (dirsetup != 1) {
+ if (dirsetup != 0)
+ uxa_screen->info->DoneCopy(pDstPixmap);
+ dirsetup = 1;
+ if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ 1, 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ (*uxa_screen->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ } else if (dx >= 0) {
+ /*
+ * xdir = 1, ydir = -1.
+ * Perform line-by-line xdir = ydir = 1 blits, going up.
+ */
+ int i;
+ if (dirsetup != 1) {
+ if (dirsetup != 0)
+ uxa_screen->info->DoneCopy(pDstPixmap);
+ dirsetup = 1;
+ if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ 1, 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
+ (*uxa_screen->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy + i,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1 + i,
+ pbox->x2 - pbox->x1, 1);
+ } else {
+ /*
+ * xdir = -1, ydir = 1.
+ * Perform line-by-line xdir = ydir = -1 blits, going down.
+ */
+ int i;
+ if (dirsetup != -1) {
+ if (dirsetup != 0)
+ uxa_screen->info->DoneCopy(pDstPixmap);
+ dirsetup = -1;
+ if (!(*uxa_screen->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ -1, -1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ for (i = 0; i < pbox->y2 - pbox->y1; i++)
+ (*uxa_screen->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy + i,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1 + i,
+ pbox->x2 - pbox->x1, 1);
+ }
+ }
+ if (dirsetup != 0)
+ uxa_screen->info->DoneCopy(pDstPixmap);
+ uxa_mark_sync(pDstDrawable->pScreen);
+ return TRUE;
+}
+
+void
+uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+ int src_off_x, src_off_y;
+ int dst_off_x, dst_off_y;
+ PixmapPtr pSrcPixmap, pDstPixmap;
+
+ pSrcPixmap = uxa_get_drawable_pixmap (pSrcDrawable);
+ pDstPixmap = uxa_get_drawable_pixmap (pDstDrawable);
+
+ uxa_get_drawable_deltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
+ uxa_get_drawable_deltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
+
+ /* Mixed directions must be handled specially if the card is lame */
+ if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) &&
+ reverse != upsidedown) {
+ if (uxa_copy_n_to_n_two_dir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+ dx, dy))
+ return;
+ goto fallback;
+ }
+
+ if (!uxa_pixmap_is_offscreen(pSrcPixmap) ||
+ !uxa_pixmap_is_offscreen(pDstPixmap) ||
+ !(*uxa_screen->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ upsidedown ? -1 : 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES)) {
+ goto fallback;
+ }
+
+ while (nbox--)
+ {
+ (*uxa_screen->info->Copy) (pDstPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ (*uxa_screen->info->DoneCopy) (pDstPixmap);
+ uxa_mark_sync (pDstDrawable->pScreen);
+
+ return;
+
+fallback:
+ UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
+ uxa_drawable_location(pSrcDrawable),
+ uxa_drawable_location(pDstDrawable)));
+ uxa_prepare_access (pDstDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (pSrcDrawable, UXA_PREPARE_SRC);
+ fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
+ upsidedown, bitplane, closure);
+ uxa_finish_access (pSrcDrawable, UXA_PREPARE_SRC);
+ uxa_finish_access (pDstDrawable, UXA_PREPARE_DEST);
+}
+
+RegionPtr
+uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
+
+ if (uxa_screen->swappedOut) {
+ return uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+ }
+
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, uxa_copy_n_to_n, 0, NULL);
+}
+
+static void
+uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ int i;
+ xRectangle *prect;
+
+ /* If we can't reuse the current GC as is, don't bother accelerating the
+ * points.
+ */
+ if (pGC->fillStyle != FillSolid) {
+ uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = xalloc(sizeof(xRectangle) * npt);
+ for (i = 0; i < npt; i++) {
+ prect[i].x = ppt[i].x;
+ prect[i].y = ppt[i].y;
+ if (i > 0 && mode == CoordModePrevious) {
+ prect[i].x += prect[i - 1].x;
+ prect[i].y += prect[i - 1].y;
+ }
+ prect[i].width = 1;
+ prect[i].height = 1;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
+ xfree(prect);
+}
+
+/**
+ * uxa_poly_lines() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ xRectangle *prect;
+ int x1, x2, y1, y2;
+ int i;
+
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+ pGC->fillStyle != FillSolid) {
+ uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = xalloc(sizeof(xRectangle) * (npt - 1));
+ x1 = ppt[0].x;
+ y1 = ppt[0].y;
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < npt - 1; i++) {
+ if (mode == CoordModePrevious) {
+ x2 = x1 + ppt[i + 1].x;
+ y2 = y1 + ppt[i + 1].y;
+ } else {
+ x2 = ppt[i + 1].x;
+ y2 = ppt[i + 1].y;
+ }
+
+ if (x1 != x2 && y1 != y2) {
+ xfree(prect);
+ uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ if (x1 < x2) {
+ prect[i].x = x1;
+ prect[i].width = x2 - x1 + 1;
+ } else {
+ prect[i].x = x2;
+ prect[i].width = x1 - x2 + 1;
+ }
+ if (y1 < y2) {
+ prect[i].y = y1;
+ prect[i].height = y2 - y1 + 1;
+ } else {
+ prect[i].y = y2;
+ prect[i].height = y1 - y2 + 1;
+ }
+
+ x1 = x2;
+ y1 = y2;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
+ xfree(prect);
+}
+
+/**
+ * uxa_poly_segment() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+uxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
+ xSegment *pSeg)
+{
+ xRectangle *prect;
+ int i;
+
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+ pGC->fillStyle != FillSolid)
+ {
+ uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
+ uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+ }
+
+ prect = xalloc(sizeof(xRectangle) * nseg);
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 < pSeg[i].x2) {
+ prect[i].x = pSeg[i].x1;
+ prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
+ } else {
+ prect[i].x = pSeg[i].x2;
+ prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
+ }
+ if (pSeg[i].y1 < pSeg[i].y2) {
+ prect[i].y = pSeg[i].y1;
+ prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
+ } else {
+ prect[i].y = pSeg[i].y2;
+ prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
+ }
+
+ /* don't paint last pixel */
+ if (pGC->capStyle == CapNotLast) {
+ if (prect[i].width == 1)
+ prect[i].height--;
+ else
+ prect[i].width--;
+ }
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
+ xfree(prect);
+}
+
+static Bool uxa_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion,
+ Pixel pixel, CARD32 planemask, CARD32 alu);
+
+static void
+uxa_poly_fill_rect(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nrect,
+ xRectangle *prect)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ register BoxPtr pbox;
+ BoxPtr pextent;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1, fullY2;
+ int partX1, partX2, partY1, partY2;
+ int xoff, yoff;
+ int xorg, yorg;
+ int n;
+ RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
+
+ /* Compute intersection of rects and clip region */
+ REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
+ REGION_INTERSECT(pScreen, pReg, pClip, pReg);
+
+ if (!REGION_NUM_RECTS(pReg))
+ goto out;
+
+ uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+
+ if (uxa_screen->swappedOut)
+ goto fallback;
+
+ /* For ROPs where overlaps don't matter, convert rectangles to region and
+ * call uxa_fill_region_{solid,tiled}.
+ */
+ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
+ (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
+ pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
+ pGC->alu == GXset)) {
+ if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
+ uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
+ pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
+ pGC->alu)) ||
+ (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
+ uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
+ pGC->planemask, pGC->alu))) {
+ goto out;
+ }
+ }
+
+ if (pGC->fillStyle != FillSolid &&
+ !(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
+ {
+ goto fallback;
+ }
+
+ if (!uxa_pixmap_is_offscreen (pPixmap) ||
+ !(*uxa_screen->info->PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+fallback:
+ uxa_check_poly_fill_rect (pDrawable, pGC, nrect, prect);
+ goto out;
+ }
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (nrect--)
+ {
+ fullX1 = prect->x + xorg;
+ fullY1 = prect->y + yorg;
+ fullX2 = fullX1 + (int) prect->width;
+ fullY2 = fullY1 + (int) prect->height;
+ prect++;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullY1 < extentY1)
+ fullY1 = extentY1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullY2 > extentY2)
+ fullY2 = extentY2;
+
+ if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
+ continue;
+ n = REGION_NUM_RECTS (pClip);
+ if (n == 1)
+ {
+ (*uxa_screen->info->Solid) (pPixmap,
+ fullX1 + xoff, fullY1 + yoff,
+ fullX2 + xoff, fullY2 + yoff);
+ }
+ else
+ {
+ pbox = REGION_RECTS(pClip);
+ /*
+ * clip the rectangle to each box in the clip region
+ * this is logically equivalent to calling Intersect(),
+ * but rectangles may overlap each other here.
+ */
+ while(n--)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partY1 = pbox->y1;
+ if (partY1 < fullY1)
+ partY1 = fullY1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ partY2 = pbox->y2;
+ if (partY2 > fullY2)
+ partY2 = fullY2;
+
+ pbox++;
+
+ if (partX1 < partX2 && partY1 < partY2) {
+ (*uxa_screen->info->Solid) (pPixmap,
+ partX1 + xoff, partY1 + yoff,
+ partX2 + xoff, partY2 + yoff);
+ }
+ }
+ }
+ }
+ (*uxa_screen->info->DoneSolid) (pPixmap);
+ uxa_mark_sync(pDrawable->pScreen);
+
+out:
+ REGION_UNINIT(pScreen, pReg);
+ REGION_DESTROY(pScreen, pReg);
+}
+
+const GCOps uxa_ops = {
+ uxa_fill_spans,
+ uxa_check_set_spans,
+ uxa_put_image,
+ uxa_copy_area,
+ uxa_check_copy_plane,
+ uxa_poly_point,
+ uxa_poly_lines,
+ uxa_poly_segment,
+ miPolyRectangle,
+ uxa_check_poly_arc,
+ miFillPolygon,
+ uxa_poly_fill_rect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ uxa_check_image_glyph_blt,
+ uxa_check_poly_glyph_blt,
+ uxa_check_push_pixels,
+};
+
+void
+uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ RegionRec rgnDst;
+ int dx, dy;
+ PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+#ifdef COMPOSITE
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+ fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ NULL,
+ &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+static Bool
+uxa_fill_region_solid (DrawablePtr pDrawable,
+ RegionPtr pRegion,
+ Pixel pixel,
+ CARD32 planemask,
+ CARD32 alu)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+ PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
+ int xoff, yoff;
+ Bool ret = FALSE;
+
+ uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+ if (uxa_pixmap_is_offscreen (pPixmap) &&
+ (*uxa_screen->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+ {
+ int nbox;
+ BoxPtr pBox;
+
+ nbox = REGION_NUM_RECTS (pRegion);
+ pBox = REGION_RECTS (pRegion);
+
+ while (nbox--)
+ {
+ (*uxa_screen->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ pBox->y2);
+ pBox++;
+ }
+ (*uxa_screen->info->DoneSolid) (pPixmap);
+ uxa_mark_sync(pDrawable->pScreen);
+
+ ret = TRUE;
+ }
+
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+
+ return ret;
+}
+
+/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
+ * Based on fbFillRegionTiled(), fbTile().
+ */
+Bool
+uxa_fill_region_tiled (DrawablePtr pDrawable,
+ RegionPtr pRegion,
+ PixmapPtr pTile,
+ DDXPointPtr pPatOrg,
+ CARD32 planemask,
+ CARD32 alu)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+ PixmapPtr pPixmap;
+ int xoff, yoff;
+ int tileWidth, tileHeight;
+ int nbox = REGION_NUM_RECTS (pRegion);
+ BoxPtr pBox = REGION_RECTS (pRegion);
+ Bool ret = FALSE;
+
+ tileWidth = pTile->drawable.width;
+ tileHeight = pTile->drawable.height;
+
+ /* If we're filling with a solid color, grab it out and go to
+ * FillRegionSolid, saving numerous copies.
+ */
+ if (tileWidth == 1 && tileHeight == 1)
+ return uxa_fill_region_solid(pDrawable, pRegion,
+ uxa_get_pixmap_first_pixel (pTile), planemask,
+ alu);
+
+ pPixmap = uxa_get_drawable_pixmap (pDrawable);
+ uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+ pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+ if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
+ goto out;
+
+ if ((*uxa_screen->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+ {
+ while (nbox--)
+ {
+ int height = pBox->y2 - pBox->y1;
+ int dstY = pBox->y1;
+ int tileY;
+
+ modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
+
+ while (height > 0) {
+ int width = pBox->x2 - pBox->x1;
+ int dstX = pBox->x1;
+ int tileX;
+ int h = tileHeight - tileY;
+
+ if (h > height)
+ h = height;
+ height -= h;
+
+ modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
+ tileX);
+
+ while (width > 0) {
+ int w = tileWidth - tileX;
+ if (w > width)
+ w = width;
+ width -= w;
+
+ (*uxa_screen->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
+ w, h);
+ dstX += w;
+ tileX = 0;
+ }
+ dstY += h;
+ tileY = 0;
+ }
+ pBox++;
+ }
+ (*uxa_screen->info->DoneCopy) (pPixmap);
+ uxa_mark_sync(pDrawable->pScreen);
+
+ ret = TRUE;
+ }
+
+out:
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+
+ return ret;
+}
+
+
+/**
+ * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
+ *
+ * This is probably the only case we actually care about. The rest fall through
+ * to migration and fbGetImage, which hopefully will result in migration pushing
+ * the pixmap out of framebuffer.
+ */
+void
+uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
+ BoxRec Box;
+ PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
+ int xoff, yoff;
+ Bool ok;
+
+ uxa_get_drawable_deltas (pDrawable, pPix, &xoff, &yoff);
+
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
+
+ if (uxa_screen->swappedOut)
+ goto fallback;
+
+ pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+
+ if (pPix == NULL || uxa_screen->info->DownloadFromScreen == NULL)
+ goto fallback;
+
+ /* Only cover the ZPixmap, solid copy case. */
+ if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask))
+ goto fallback;
+
+ /* Only try to handle the 8bpp and up cases, since we don't want to think
+ * about <8bpp.
+ */
+ if (pDrawable->bitsPerPixel < 8)
+ goto fallback;
+
+ ok = uxa_screen->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+ pDrawable->y + y + yoff, w, h, d,
+ PixmapBytePad(w, pDrawable->depth));
+ if (ok) {
+ uxa_wait_sync(pDrawable->pScreen);
+ goto out;
+ }
+
+fallback:
+ UXA_FALLBACK(("from %p (%c)\n", pDrawable,
+ uxa_drawable_location(pDrawable)));
+
+ uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+ fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
+ uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+
+out:
+ return;
+}
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c
new file mode 100644
index 0000000..3c44640
--- /dev/null
+++ b/uxa/uxa-glyphs.c
@@ -0,0 +1,880 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ * Partly based on code Copyright © 2000 SuSE, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor <otaylor at fishsoup.net>
+ * Based on code by: Keith Packard
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "uxa-priv.h"
+
+#include "mipict.h"
+
+#if DEBUG_GLYPH_CACHE
+#define DBG_GLYPH_CACHE(a) ErrorF a
+#else
+#define DBG_GLYPH_CACHE(a)
+#endif
+
+/* Width of the pixmaps we use for the caches; this should be less than
+ * max texture size of the driver; this may need to actually come from
+ * the driver.
+ */
+#define CACHE_PICTURE_WIDTH 1024
+
+/* Maximum number of glyphs we buffer on the stack before flushing
+ * rendering to the mask or destination surface.
+ */
+#define GLYPH_BUFFER_SIZE 256
+
+typedef struct {
+ PicturePtr source;
+ uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE];
+ int count;
+} uxa_glyph_buffer_t;
+
+typedef enum {
+ UXA_GLYPH_SUCCESS, /* Glyph added to render buffer */
+ UXA_GLYPH_FAIL, /* out of memory, etc */
+ UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */
+} uxa_glyph_cache_result_t;
+
+void
+uxa_glyphs_init(ScreenPtr pScreen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ int i = 0;
+
+ memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
+
+ uxa_screen->glyphCaches[i].format = PICT_a8;
+ uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
+ i++;
+ uxa_screen->glyphCaches[i].format = PICT_a8;
+ uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
+ i++;
+ uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
+ uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 16;
+ i++;
+ uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
+ uxa_screen->glyphCaches[i].glyphWidth = uxa_screen->glyphCaches[i].glyphHeight = 32;
+ i++;
+
+ assert(i == UXA_NUM_GLYPH_CACHES);
+
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_screen->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth;
+ uxa_screen->glyphCaches[i].size = 256;
+ uxa_screen->glyphCaches[i].hashSize = 557;
+ }
+}
+
+static void
+uxa_unrealize_glyph_caches(ScreenPtr pScreen,
+ unsigned int format)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ int i;
+
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+
+ if (cache->format != format)
+ continue;
+
+ if (cache->picture) {
+ FreePicture ((pointer) cache->picture, (XID) 0);
+ cache->picture = NULL;
+ }
+
+ if (cache->hashEntries) {
+ xfree(cache->hashEntries);
+ cache->hashEntries = NULL;
+ }
+
+ if (cache->glyphs) {
+ xfree(cache->glyphs);
+ cache->glyphs = NULL;
+ }
+ cache->glyphCount = 0;
+ }
+}
+
+/* All caches for a single format share a single pixmap for glyph storage,
+ * allowing mixing glyphs of different sizes without paying a penalty
+ * for switching between source pixmaps. (Note that for a size of font
+ * right at the border between two sizes, we might be switching for almost
+ * every glyph.)
+ *
+ * This function allocates the storage pixmap, and then fills in the
+ * rest of the allocated structures for all caches with the given format.
+ */
+static Bool
+uxa_realize_glyph_caches(ScreenPtr pScreen,
+ unsigned int format)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ int depth = PIXMAN_FORMAT_DEPTH(format);
+ PictFormatPtr pPictFormat;
+ PixmapPtr pPixmap;
+ PicturePtr pPicture;
+ int height;
+ int i;
+ int error;
+
+ pPictFormat = PictureMatchFormat(pScreen, depth, format);
+ if (!pPictFormat)
+ return FALSE;
+
+ /* Compute the total vertical size needed for the format */
+
+ height = 0;
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+ int rows;
+
+ if (cache->format != format)
+ continue;
+
+ cache->yOffset = height;
+
+ rows = (cache->size + cache->columns - 1) / cache->columns;
+ height += rows * cache->glyphHeight;
+ }
+
+ /* Now allocate the pixmap and picture */
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen,
+ CACHE_PICTURE_WIDTH,
+ height, depth, 0);
+ if (!pPixmap)
+ return FALSE;
+
+ pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
+ 0, 0, serverClient, &error);
+
+ (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
+
+ if (!pPicture)
+ return FALSE;
+
+ /* And store the picture in all the caches for the format */
+
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+ int j;
+
+ if (cache->format != format)
+ continue;
+
+ cache->picture = pPicture;
+ cache->picture->refcnt++;
+ cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
+ cache->glyphs = xalloc(sizeof(uxa_cached_glyph_t) * cache->size);
+ cache->glyphCount = 0;
+
+ if (!cache->hashEntries || !cache->glyphs)
+ goto bail;
+
+ for (j = 0; j < cache->hashSize; j++)
+ cache->hashEntries[j] = -1;
+
+ cache->evictionPosition = rand() % cache->size;
+ }
+
+ /* Each cache references the picture individually */
+ FreePicture ((pointer) pPicture, (XID) 0);
+ return TRUE;
+
+bail:
+ uxa_unrealize_glyph_caches(pScreen, format);
+ return FALSE;
+}
+
+void
+uxa_glyphs_fini (ScreenPtr pScreen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ int i;
+
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+
+ if (cache->picture)
+ uxa_unrealize_glyph_caches(pScreen, cache->format);
+ }
+}
+
+static int
+uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t *cache, GlyphPtr pGlyph)
+{
+ int slot;
+
+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
+
+ while (TRUE) { /* hash table can never be full */
+ int entryPos = cache->hashEntries[slot];
+ if (entryPos == -1)
+ return -1;
+
+ if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
+ return entryPos;
+ }
+
+ slot--;
+ if (slot < 0)
+ slot = cache->hashSize - 1;
+ }
+}
+
+static void
+uxa_glyph_cache_hash_insert(uxa_glyph_cache_t *cache,
+ GlyphPtr pGlyph,
+ int pos)
+{
+ int slot;
+
+ memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
+
+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
+
+ while (TRUE) { /* hash table can never be full */
+ if (cache->hashEntries[slot] == -1) {
+ cache->hashEntries[slot] = pos;
+ return;
+ }
+
+ slot--;
+ if (slot < 0)
+ slot = cache->hashSize - 1;
+ }
+}
+
+static void
+uxa_glyph_cache_hash_remove(uxa_glyph_cache_t *cache,
+ int pos)
+{
+ int slot;
+ int emptiedSlot = -1;
+
+ slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
+
+ while (TRUE) { /* hash table can never be full */
+ int entryPos = cache->hashEntries[slot];
+
+ if (entryPos == -1)
+ return;
+
+ if (entryPos == pos) {
+ cache->hashEntries[slot] = -1;
+ emptiedSlot = slot;
+ } else if (emptiedSlot != -1) {
+ /* See if we can move this entry into the emptied slot, we can't
+ * do that if if entry would have hashed between the current position
+ * and the emptied slot. (taking wrapping into account). Bad positions
+ * are:
+ *
+ * | XXXXXXXXXX |
+ * i j
+ *
+ * |XXX XXXX|
+ * j i
+ *
+ * i - slot, j - emptiedSlot
+ *
+ * (Knuth 6.4R)
+ */
+
+ int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
+
+ if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
+ (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot))))
+ {
+ cache->hashEntries[emptiedSlot] = entryPos;
+ cache->hashEntries[slot] = -1;
+ emptiedSlot = slot;
+ }
+ }
+
+ slot--;
+ if (slot < 0)
+ slot = cache->hashSize - 1;
+ }
+}
+
+#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
+#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
+
+/* The most efficient thing to way to upload the glyph to the screen
+ * is to use the UploadToScreen() driver hook; this allows us to
+ * pipeline glyph uploads and to avoid creating offscreen pixmaps for
+ * glyphs that we'll never use again.
+ */
+static Bool
+uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
+ uxa_glyph_cache_t *cache,
+ int pos,
+ GlyphPtr pGlyph)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
+ PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
+ PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
+ int cacheXoff, cacheYoff;
+
+ if (!uxa_screen->info->UploadToScreen || uxa_screen->swappedOut)
+ return FALSE;
+
+ /* If the glyph pixmap is already uploaded, no point in doing
+ * things this way */
+ if (uxa_pixmap_is_offscreen(pGlyphPixmap))
+ return FALSE;
+
+ /* UploadToScreen only works if bpp match */
+ if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
+ return FALSE;
+
+ pCachePixmap = uxa_get_offscreen_pixmap ((DrawablePtr)pCachePixmap, &cacheXoff, &cacheYoff);
+ if (!pCachePixmap)
+ return FALSE;
+
+ if (!uxa_screen->info->UploadToScreen(pCachePixmap,
+ CACHE_X(pos) + cacheXoff,
+ CACHE_Y(pos) + cacheYoff,
+ pGlyph->info.width,
+ pGlyph->info.height,
+ (char *)pGlyphPixmap->devPrivate.ptr,
+ pGlyphPixmap->devKind))
+ return FALSE;
+
+ return TRUE;
+}
+
+static uxa_glyph_cache_result_t
+uxa_glyph_cache_buffer_glyph(ScreenPtr pScreen,
+ uxa_glyph_cache_t *cache,
+ uxa_glyph_buffer_t *buffer,
+ GlyphPtr pGlyph,
+ int xGlyph,
+ int yGlyph)
+{
+ uxa_composite_rect_t *rect;
+ int pos;
+
+ if (buffer->source && buffer->source != cache->picture)
+ return UXA_GLYPH_NEED_FLUSH;
+
+ if (!cache->picture) {
+ if (!uxa_realize_glyph_caches(pScreen, cache->format))
+ return UXA_GLYPH_FAIL;
+ }
+
+ DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
+ cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB",
+ (long)*(CARD32 *) pGlyph->sha1));
+
+ pos = uxa_glyph_cache_hash_lookup(cache, pGlyph);
+ if (pos != -1) {
+ DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
+ } else {
+ if (cache->glyphCount < cache->size) {
+ /* Space remaining; we fill from the start */
+ pos = cache->glyphCount;
+ cache->glyphCount++;
+ DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
+
+ uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
+
+ } else {
+ /* Need to evict an entry. We have to see if any glyphs
+ * already in the output buffer were at this position in
+ * the cache
+ */
+
+ pos = cache->evictionPosition;
+ DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
+ if (buffer->count) {
+ int x, y;
+ int i;
+
+ x = CACHE_X(pos);
+ y = CACHE_Y(pos);
+
+ for (i = 0; i < buffer->count; i++) {
+ if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
+ DBG_GLYPH_CACHE((" must flush buffer\n"));
+ return UXA_GLYPH_NEED_FLUSH;
+ }
+ }
+ }
+
+ /* OK, we're all set, swap in the new glyph */
+ uxa_glyph_cache_hash_remove(cache, pos);
+ uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
+
+ /* And pick a new eviction position */
+ cache->evictionPosition = rand() % cache->size;
+ }
+
+ /* Now actually upload the glyph into the cache picture; if
+ * we can't do it with UploadToScreen (because the glyph is
+ * offscreen, etc), we fall back to CompositePicture.
+ */
+ if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) {
+ CompositePicture (PictOpSrc,
+ GlyphPicture(pGlyph)[pScreen->myNum],
+ None,
+ cache->picture,
+ 0, 0,
+ 0, 0,
+ CACHE_X(pos),
+ CACHE_Y(pos),
+ pGlyph->info.width,
+ pGlyph->info.height);
+ }
+
+ }
+
+
+ buffer->source = cache->picture;
+
+ rect = &buffer->rects[buffer->count];
+ rect->xSrc = CACHE_X(pos);
+ rect->ySrc = CACHE_Y(pos);
+ rect->xDst = xGlyph - pGlyph->info.x;
+ rect->yDst = yGlyph - pGlyph->info.y;
+ rect->width = pGlyph->info.width;
+ rect->height = pGlyph->info.height;
+
+ buffer->count++;
+
+ return UXA_GLYPH_SUCCESS;
+}
+
+#undef CACHE_X
+#undef CACHE_Y
+
+static uxa_glyph_cache_result_t
+uxa_buffer_glyph(ScreenPtr pScreen,
+ uxa_glyph_buffer_t *buffer,
+ GlyphPtr pGlyph,
+ int xGlyph,
+ int yGlyph)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
+ int width = pGlyph->info.width;
+ int height = pGlyph->info.height;
+ uxa_composite_rect_t *rect;
+ PicturePtr source;
+ int i;
+
+ if (buffer->count == GLYPH_BUFFER_SIZE)
+ return UXA_GLYPH_NEED_FLUSH;
+
+ if (PICT_FORMAT_BPP(format) == 1)
+ format = PICT_a8;
+
+ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
+
+ if (format == cache->format &&
+ width <= cache->glyphWidth &&
+ height <= cache->glyphHeight) {
+ uxa_glyph_cache_result_t result = uxa_glyph_cache_buffer_glyph(pScreen, &uxa_screen->glyphCaches[i],
+ buffer,
+ pGlyph, xGlyph, yGlyph);
+ switch (result) {
+ case UXA_GLYPH_FAIL:
+ break;
+ case UXA_GLYPH_SUCCESS:
+ case UXA_GLYPH_NEED_FLUSH:
+ return result;
+ }
+ }
+ }
+
+ /* Couldn't find the glyph in the cache, use the glyph picture directly */
+
+ source = GlyphPicture(pGlyph)[pScreen->myNum];
+ if (buffer->source && buffer->source != source)
+ return UXA_GLYPH_NEED_FLUSH;
+
+ buffer->source = source;
+
+ rect = &buffer->rects[buffer->count];
+ rect->xSrc = 0;
+ rect->ySrc = 0;
+ rect->xDst = xGlyph - pGlyph->info.x;
+ rect->yDst = yGlyph - pGlyph->info.y;
+ rect->width = pGlyph->info.width;
+ rect->height = pGlyph->info.height;
+
+ buffer->count++;
+
+ return UXA_GLYPH_SUCCESS;
+}
+
+static void
+uxa_glyphs_to_mask(PicturePtr pMask,
+ uxa_glyph_buffer_t *buffer)
+{
+ uxa_composite_rects(PictOpAdd, buffer->source, pMask,
+ buffer->count, buffer->rects);
+
+ buffer->count = 0;
+ buffer->source = NULL;
+}
+
+static void
+uxa_glyphs_to_dst(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ uxa_glyph_buffer_t *buffer,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xDst,
+ INT16 yDst)
+{
+ int i;
+
+ for (i = 0; i < buffer->count; i++) {
+ uxa_composite_rect_t *rect = &buffer->rects[i];
+
+ CompositePicture (op,
+ pSrc,
+ buffer->source,
+ pDst,
+ xSrc + rect->xDst - xDst,
+ ySrc + rect->yDst - yDst,
+ rect->xSrc,
+ rect->ySrc,
+ rect->xDst,
+ rect->yDst,
+ rect->width,
+ rect->height);
+ }
+
+ buffer->count = 0;
+ buffer->source = NULL;
+}
+
+/* Cut and paste from render/glyph.c - probably should export it instead */
+static void
+uxa_glyph_extents (int nlist,
+ GlyphListPtr list,
+ GlyphPtr *glyphs,
+ BoxPtr extents)
+{
+ int x1, x2, y1, y2;
+ int n;
+ GlyphPtr glyph;
+ int x, y;
+
+ x = 0;
+ y = 0;
+ extents->x1 = MAXSHORT;
+ extents->x2 = MINSHORT;
+ extents->y1 = MAXSHORT;
+ extents->y2 = MINSHORT;
+ while (nlist--)
+ {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ list++;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ x1 = x - glyph->info.x;
+ if (x1 < MINSHORT)
+ x1 = MINSHORT;
+ y1 = y - glyph->info.y;
+ if (y1 < MINSHORT)
+ y1 = MINSHORT;
+ x2 = x1 + glyph->info.width;
+ if (x2 > MAXSHORT)
+ x2 = MAXSHORT;
+ y2 = y1 + glyph->info.height;
+ if (y2 > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 < extents->x1)
+ extents->x1 = x1;
+ if (x2 > extents->x2)
+ extents->x2 = x2;
+ if (y1 < extents->y1)
+ extents->y1 = y1;
+ if (y2 > extents->y2)
+ extents->y2 = y2;
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ }
+}
+
+/**
+ * Returns TRUE if the glyphs in the lists intersect. Only checks based on
+ * bounding box, which appears to be good enough to catch most cases at least.
+ */
+static Bool
+uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ int x1, x2, y1, y2;
+ int n;
+ GlyphPtr glyph;
+ int x, y;
+ BoxRec extents;
+ Bool first = TRUE;
+
+ x = 0;
+ y = 0;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ list++;
+ while (n--) {
+ glyph = *glyphs++;
+
+ if (glyph->info.width == 0 || glyph->info.height == 0) {
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ continue;
+ }
+
+ x1 = x - glyph->info.x;
+ if (x1 < MINSHORT)
+ x1 = MINSHORT;
+ y1 = y - glyph->info.y;
+ if (y1 < MINSHORT)
+ y1 = MINSHORT;
+ x2 = x1 + glyph->info.width;
+ if (x2 > MAXSHORT)
+ x2 = MAXSHORT;
+ y2 = y1 + glyph->info.height;
+ if (y2 > MAXSHORT)
+ y2 = MAXSHORT;
+
+ if (first) {
+ extents.x1 = x1;
+ extents.y1 = y1;
+ extents.x2 = x2;
+ extents.y2 = y2;
+ first = FALSE;
+ } else {
+ if (x1 < extents.x2 && x2 > extents.x1 &&
+ y1 < extents.y2 && y2 > extents.y1)
+ {
+ return TRUE;
+ }
+
+ if (x1 < extents.x1)
+ extents.x1 = x1;
+ if (x2 > extents.x2)
+ extents.x2 = x2;
+ if (y1 < extents.y1)
+ extents.y1 = y1;
+ if (y2 > extents.y2)
+ extents.y2 = y2;
+ }
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ }
+
+ return FALSE;
+}
+
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
+void
+uxa_glyphs (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlist,
+ GlyphListPtr list,
+ GlyphPtr *glyphs)
+{
+ PicturePtr pPicture;
+ PixmapPtr pMaskPixmap = 0;
+ PicturePtr pMask;
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ int width = 0, height = 0;
+ int x, y;
+ int xDst = list->xOff, yDst = list->yOff;
+ int n;
+ GlyphPtr glyph;
+ int error;
+ BoxRec extents = {0, 0, 0, 0};
+ CARD32 component_alpha;
+ uxa_glyph_buffer_t buffer;
+
+ /* If we don't have a mask format but all the glyphs have the same format
+ * and don't intersect, use the glyph format as mask format for the full
+ * benefits of the glyph cache.
+ */
+ if (!maskFormat) {
+ Bool sameFormat = TRUE;
+ int i;
+
+ maskFormat = list[0].format;
+
+ for (i = 0; i < nlist; i++) {
+ if (maskFormat->format != list[i].format->format) {
+ sameFormat = FALSE;
+ break;
+ }
+ }
+
+ if (!sameFormat || (maskFormat->depth != 1 &&
+ uxa_glyphs_intersect(nlist, list, glyphs))) {
+ maskFormat = NULL;
+ }
+ }
+
+ if (maskFormat)
+ {
+ GCPtr pGC;
+ xRectangle rect;
+
+ uxa_glyph_extents (nlist, list, glyphs, &extents);
+
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+
+ if (maskFormat->depth == 1) {
+ PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
+
+ if (a8Format)
+ maskFormat = a8Format;
+ }
+
+ pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+ maskFormat->depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pMaskPixmap)
+ return;
+ component_alpha = NeedsComponent(maskFormat->format);
+ pMask = CreatePicture (0, &pMaskPixmap->drawable,
+ maskFormat, CPComponentAlpha, &component_alpha,
+ serverClient, &error);
+ if (!pMask)
+ {
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ return;
+ }
+ pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
+ ValidateGC (&pMaskPixmap->drawable, pGC);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
+ FreeScratchGC (pGC);
+ x = -extents.x1;
+ y = -extents.y1;
+ }
+ else
+ {
+ pMask = pDst;
+ x = 0;
+ y = 0;
+ }
+ buffer.count = 0;
+ buffer.source = NULL;
+ while (nlist--)
+ {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ pPicture = GlyphPicture (glyph)[pScreen->myNum];
+
+ if (glyph->info.width > 0 && glyph->info.height > 0 &&
+ uxa_buffer_glyph(pScreen, &buffer, glyph, x, y) == UXA_GLYPH_NEED_FLUSH)
+ {
+ if (maskFormat)
+ uxa_glyphs_to_mask(pMask, &buffer);
+ else
+ uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
+ xSrc, ySrc, xDst, yDst);
+
+ uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+ }
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+
+ if (maskFormat)
+ uxa_glyphs_to_mask(pMask, &buffer);
+ else
+ uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
+ xSrc, ySrc, xDst, yDst);
+
+ if (maskFormat)
+ {
+ x = extents.x1;
+ y = extents.y1;
+ CompositePicture (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc + x - xDst,
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+ FreePicture ((pointer) pMask, (XID) 0);
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ }
+}
diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h
new file mode 100644
index 0000000..acc82bb
--- /dev/null
+++ b/uxa/uxa-priv.h
@@ -0,0 +1,444 @@
+/*
+ *
+ * Copyright © 2000,2008 Keith Packard
+ * 2005 Zack Rusin, Trolltech
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef UXAPRIV_H
+#define UXAPRIV_H
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#else
+#include <xorg-server.h>
+#endif
+
+#include "uxa.h"
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#ifdef MITSHM
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#endif
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "mi.h"
+#include "dix.h"
+#include "fb.h"
+#include "fboverlay.h"
+#ifdef RENDER
+//#include "fbpict.h"
+#include "glyphstr.h"
+#endif
+#include "damage.h"
+
+#define DEBUG_TRACE_FALL 0
+#define DEBUG_MIGRATE 0
+#define DEBUG_PIXMAP 0
+#define DEBUG_OFFSCREEN 0
+#define DEBUG_GLYPH_CACHE 0
+
+#if DEBUG_TRACE_FALL
+#define UXA_FALLBACK(x) \
+do { \
+ ErrorF("UXA fallback at %s: ", __FUNCTION__); \
+ ErrorF x; \
+} while (0)
+
+char
+uxa_drawable_location(DrawablePtr pDrawable);
+#else
+#define UXA_FALLBACK(x)
+#endif
+
+#if DEBUG_PIXMAP
+#define DBG_PIXMAP(a) ErrorF a
+#else
+#define DBG_PIXMAP(a)
+#endif
+
+typedef struct {
+ unsigned char sha1[20];
+} uxa_cached_glyph_t;
+
+typedef struct {
+ /* The identity of the cache, statically configured at initialization */
+ unsigned int format;
+ int glyphWidth;
+ int glyphHeight;
+
+ int size; /* Size of cache; eventually this should be dynamically determined */
+
+ /* Hash table mapping from glyph sha1 to position in the glyph; we use
+ * open addressing with a hash table size determined based on size and large
+ * enough so that we always have a good amount of free space, so we can
+ * use linear probing. (Linear probing is preferrable to double hashing
+ * here because it allows us to easily remove entries.)
+ */
+ int *hashEntries;
+ int hashSize;
+
+ uxa_cached_glyph_t *glyphs;
+ int glyphCount; /* Current number of glyphs */
+
+ PicturePtr picture; /* Where the glyphs of the cache are stored */
+ int yOffset; /* y location within the picture where the cache starts */
+ int columns; /* Number of columns the glyphs are layed out in */
+ int evictionPosition; /* Next random position to evict a glyph */
+} uxa_glyph_cache_t;
+
+#define UXA_NUM_GLYPH_CACHES 4
+
+typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
+typedef struct {
+ uxa_driver_t *info;
+ CreateGCProcPtr SavedCreateGC;
+ CloseScreenProcPtr SavedCloseScreen;
+ GetImageProcPtr SavedGetImage;
+ GetSpansProcPtr SavedGetSpans;
+ CreatePixmapProcPtr SavedCreatePixmap;
+ DestroyPixmapProcPtr SavedDestroyPixmap;
+ CopyWindowProcPtr SavedCopyWindow;
+ ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
+ BitmapToRegionProcPtr SavedBitmapToRegion;
+#ifdef RENDER
+ CompositeProcPtr SavedComposite;
+ TrianglesProcPtr SavedTriangles;
+ GlyphsProcPtr SavedGlyphs;
+ TrapezoidsProcPtr SavedTrapezoids;
+ AddTrapsProcPtr SavedAddTraps;
+#endif
+
+ Bool swappedOut;
+ unsigned disableFbCount;
+ unsigned offScreenCounter;
+
+ uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES];
+} uxa_screen_t;
+
+/*
+ * This is the only completely portable way to
+ * compute this info.
+ */
+#ifndef BitsPerPixel
+#define BitsPerPixel(d) (\
+ PixmapWidthPaddingInfo[d].notPower2 ? \
+ (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
+ ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
+ (PixmapWidthPaddingInfo[d].padRoundUp+1)))
+#endif
+
+extern DevPrivateKey uxa_screen_key;
+#define uxa_get_screen(s) ((uxa_screen_t *)dixLookupPrivate(&(s)->devPrivates, uxa_screen_key))
+
+/** Align an offset to an arbitrary alignment */
+#define UXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
+ (((offset) + (align) - 1) % (align)))
+/** Align an offset to a power-of-two alignment */
+#define UXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
+
+typedef struct {
+ INT16 xSrc;
+ INT16 ySrc;
+ INT16 xDst;
+ INT16 yDst;
+ INT16 width;
+ INT16 height;
+} uxa_composite_rect_t;
+
+/**
+ * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
+ * to set EXA options or hook in screen functions to handle using EXA as the AA.
+ */
+void exaDDXDriverInit (ScreenPtr pScreen);
+
+void
+uxa_prepare_access_window(WindowPtr pWin);
+
+void
+uxa_finish_access_window(WindowPtr pWin);
+
+/* uxa-unaccel.c */
+void
+uxa_prepare_access_gc(GCPtr pGC);
+
+void
+uxa_finish_access_gc(GCPtr pGC);
+
+void
+uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
+ DDXPointPtr ppt, int *pwidth, int fSorted);
+
+void
+uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
+
+void
+uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *bits);
+
+RegionPtr
+uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty);
+
+RegionPtr
+uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane);
+
+void
+uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit);
+
+void
+uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt);
+
+void
+uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit);
+
+void
+uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *pArcs);
+
+void
+uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrect, xRectangle *prect);
+
+void
+uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+
+void
+uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+
+void
+uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable,
+ int w, int h, int x, int y);
+
+void
+uxa_check_get_spans (DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ char *pdstStart);
+
+void
+uxa_check_add_traps (PicturePtr pPicture,
+ INT16 x_off,
+ INT16 y_off,
+ int ntrap,
+ xTrap *traps);
+
+/* uxa-accel.c */
+
+static _X_INLINE Bool
+uxa_gc_reads_destination(DrawablePtr pDrawable, unsigned long planemask,
+ unsigned int fillStyle, unsigned char alu)
+{
+ return ((alu != GXcopy && alu != GXclear &&alu != GXset &&
+ alu != GXcopyInverted) || fillStyle == FillStippled ||
+ !UXA_PM_IS_SOLID(pDrawable, planemask));
+}
+
+void
+uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+Bool
+uxa_fill_region_tiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
+ DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
+
+void
+uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
+ int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+ char *data);
+
+void
+uxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d);
+
+extern const GCOps uxa_ops;
+
+#ifdef MITSHM
+extern ShmFuncs uxa_shm_funcs;
+
+/* XXX these come from shmint.h, which isn't exported by the server */
+void
+ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
+
+void
+ShmSetPixmapFormat(ScreenPtr pScreen, int format);
+
+void
+fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
+
+#endif
+
+#ifdef RENDER
+
+/* XXX these are in fbpict.h, which is not installed */
+void
+fbComposite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+void
+fbAddTraps (PicturePtr pPicture,
+ INT16 xOff,
+ INT16 yOff,
+ int ntrap,
+ xTrap *traps);
+
+void
+uxa_check_composite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+#endif
+
+/* uxa.c */
+void
+uxa_prepare_access(DrawablePtr pDrawable, int index);
+
+void
+uxa_finish_access(DrawablePtr pDrawable, int index);
+
+void
+uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
+ int *xp, int *yp);
+
+Bool
+uxa_drawable_is_offscreen (DrawablePtr pDrawable);
+
+Bool
+uxa_pixmap_is_offscreen(PixmapPtr p);
+
+PixmapPtr
+uxa_get_offscreen_pixmap (DrawablePtr pDrawable, int *xp, int *yp);
+
+PixmapPtr
+uxa_get_drawable_pixmap(DrawablePtr pDrawable);
+
+RegionPtr
+uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+void
+uxa_copy_n_to_n (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure);
+
+/* uxa_render.c */
+Bool
+uxa_op_reads_destination (CARD8 op);
+
+void
+uxa_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+void
+uxa_composite_rects(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ int nrect,
+ uxa_composite_rect_t *rects);
+
+void
+uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps);
+
+void
+uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris);
+
+/* uxa_glyph.c */
+void
+uxa_glyphs_init(ScreenPtr pScreen);
+
+void
+uxa_glyphs_fini (ScreenPtr pScreen);
+
+void
+uxa_glyphs (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlist,
+ GlyphListPtr list,
+ GlyphPtr *glyphs);
+
+#endif /* UXAPRIV_H */
diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
new file mode 100644
index 0000000..38e6088
--- /dev/null
+++ b/uxa/uxa-render.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "uxa-priv.h"
+
+#ifdef RENDER
+#include "mipict.h"
+
+#if DEBUG_TRACE_FALL
+static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, int n)
+{
+ char format[20];
+ char size[20];
+ char loc;
+ int temp;
+
+ if (!pict) {
+ snprintf(string, n, "None");
+ return;
+ }
+
+ switch (pict->format)
+ {
+ case PICT_a8r8g8b8:
+ snprintf(format, 20, "ARGB8888");
+ break;
+ case PICT_x8r8g8b8:
+ snprintf(format, 20, "XRGB8888");
+ break;
+ case PICT_r5g6b5:
+ snprintf(format, 20, "RGB565 ");
+ break;
+ case PICT_x1r5g5b5:
+ snprintf(format, 20, "RGB555 ");
+ break;
+ case PICT_a8:
+ snprintf(format, 20, "A8 ");
+ break;
+ case PICT_a1:
+ snprintf(format, 20, "A1 ");
+ break;
+ default:
+ snprintf(format, 20, "0x%x", (int)pict->format);
+ break;
+ }
+
+ loc = uxa_get_drawable_pixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+
+ snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+ pict->pDrawable->height, pict->repeat ?
+ " R" : "");
+
+ snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
+}
+
+static void
+uxa_print_composite_fallback(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst)
+{
+ char sop[20];
+ char srcdesc[40], maskdesc[40], dstdesc[40];
+
+ switch(op)
+ {
+ case PictOpSrc:
+ sprintf(sop, "Src");
+ break;
+ case PictOpOver:
+ sprintf(sop, "Over");
+ break;
+ default:
+ sprintf(sop, "0x%x", (int)op);
+ break;
+ }
+
+ uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
+ uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
+ uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
+
+ ErrorF("Composite fallback: op %s, \n"
+ " src %s, \n"
+ " mask %s, \n"
+ " dst %s, \n",
+ sop, srcdesc, maskdesc, dstdesc);
+}
+#endif /* DEBUG_TRACE_FALL */
+
+Bool
+uxa_op_reads_destination (CARD8 op)
+{
+ /* FALSE (does not read destination) is the list of ops in the protocol
+ * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
+ * That's just Clear and Src. ReduceCompositeOp() will already have
+ * converted con/disjoint clear/src to Clear or Src.
+ */
+ switch (op) {
+ case PictOpClear:
+ case PictOpSrc:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+
+static Bool
+uxa_get_pixel_from_rgba(CARD32 *pixel,
+ CARD16 red,
+ CARD16 green,
+ CARD16 blue,
+ CARD16 alpha,
+ CARD32 format)
+{
+ int rbits, bbits, gbits, abits;
+ int rshift, bshift, gshift, ashift;
+
+ *pixel = 0;
+
+ if (!PICT_FORMAT_COLOR(format))
+ return FALSE;
+
+ rbits = PICT_FORMAT_R(format);
+ gbits = PICT_FORMAT_G(format);
+ bbits = PICT_FORMAT_B(format);
+ abits = PICT_FORMAT_A(format);
+
+ if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
+ bshift = 0;
+ gshift = bbits;
+ rshift = gshift + gbits;
+ ashift = rshift + rbits;
+ } else { /* PICT_TYPE_ABGR */
+ rshift = 0;
+ gshift = rbits;
+ bshift = gshift + gbits;
+ ashift = bshift + bbits;
+ }
+
+ *pixel |= ( blue >> (16 - bbits)) << bshift;
+ *pixel |= ( red >> (16 - rbits)) << rshift;
+ *pixel |= (green >> (16 - gbits)) << gshift;
+ *pixel |= (alpha >> (16 - abits)) << ashift;
+
+ return TRUE;
+}
+
+static Bool
+uxa_get_rgba_from_pixel(CARD32 pixel,
+ CARD16 *red,
+ CARD16 *green,
+ CARD16 *blue,
+ CARD16 *alpha,
+ CARD32 format)
+{
+ int rbits, bbits, gbits, abits;
+ int rshift, bshift, gshift, ashift;
+
+ if (!PICT_FORMAT_COLOR(format))
+ return FALSE;
+
+ rbits = PICT_FORMAT_R(format);
+ gbits = PICT_FORMAT_G(format);
+ bbits = PICT_FORMAT_B(format);
+ abits = PICT_FORMAT_A(format);
+
+ if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
+ bshift = 0;
+ gshift = bbits;
+ rshift = gshift + gbits;
+ ashift = rshift + rbits;
+ } else { /* PICT_TYPE_ABGR */
+ rshift = 0;
+ gshift = rbits;
+ bshift = gshift + gbits;
+ ashift = bshift + bbits;
+ }
+
+ *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
+ while (rbits < 16) {
+ *red |= *red >> rbits;
+ rbits <<= 1;
+ }
+
+ *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
+ while (gbits < 16) {
+ *green |= *green >> gbits;
+ gbits <<= 1;
+ }
+
+ *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
+ while (bbits < 16) {
+ *blue |= *blue >> bbits;
+ bbits <<= 1;
+ }
+
+ if (abits) {
+ *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
+ while (abits < 16) {
+ *alpha |= *alpha >> abits;
+ abits <<= 1;
+ }
+ } else
+ *alpha = 0xffff;
+
+ return TRUE;
+}
+
+static int
+uxa_try_driver_solid_fill(PicturePtr pSrc,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+ int dst_off_x, dst_off_y;
+ PixmapPtr pSrcPix, pDstPix;
+ CARD32 pixel;
+ CARD16 red, green, blue, alpha;
+
+ pDstPix = uxa_get_drawable_pixmap (pDst->pDrawable);
+ pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+
+ if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
+ xSrc, ySrc, 0, 0, xDst, yDst,
+ width, height))
+ return 1;
+
+ uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+
+ REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
+
+ pixel = uxa_get_pixmap_first_pixel (pSrcPix);
+
+ if (!uxa_pixmap_is_offscreen(pDstPix)) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return 0;
+ }
+
+ if (!uxa_get_rgba_from_pixel(pixel, &red, &green, &blue, &alpha,
+ pSrc->format))
+ {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return -1;
+ }
+
+ if (!uxa_get_pixel_from_rgba(&pixel, red, green, blue, alpha,
+ pDst->format))
+ {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return -1;
+ }
+
+ if (!(*uxa_screen->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
+ {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return -1;
+ }
+
+ nbox = REGION_NUM_RECTS(®ion);
+ pbox = REGION_RECTS(®ion);
+
+ while (nbox--)
+ {
+ (*uxa_screen->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+ pbox++;
+ }
+
+ (*uxa_screen->info->DoneSolid) (pDstPix);
+ uxa_mark_sync(pDst->pDrawable->pScreen);
+
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return 1;
+}
+
+static int
+uxa_try_driver_composite_rects(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ int nrect,
+ uxa_composite_rect_t *rects)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ int src_off_x, src_off_y, dst_off_x, dst_off_y;
+ PixmapPtr pSrcPix, pDstPix;
+ struct _Pixmap scratch;
+
+ if (!uxa_screen->info->PrepareComposite)
+ return -1;
+
+ pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
+
+ pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+
+ if (uxa_screen->info->CheckComposite &&
+ !(*uxa_screen->info->CheckComposite) (op, pSrc, NULL, pDst))
+ {
+ return -1;
+ }
+
+ uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+
+ pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!uxa_pixmap_is_offscreen(pDstPix))
+ return 0;
+
+ if (!pSrcPix && uxa_screen->info->UploadToScratch)
+ {
+ pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+ if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
+ pSrcPix = &scratch;
+ }
+
+ if (!pSrcPix)
+ return 0;
+
+ if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
+ NULL, pDstPix))
+ return -1;
+
+ while (nrect--)
+ {
+ INT16 xDst = rects->xDst + pDst->pDrawable->x;
+ INT16 yDst = rects->yDst + pDst->pDrawable->y;
+ INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
+ INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
+
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+
+ if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
+ xSrc, ySrc, 0, 0, xDst, yDst,
+ rects->width, rects->height))
+ goto next_rect;
+
+ REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
+
+ nbox = REGION_NUM_RECTS(®ion);
+ pbox = REGION_RECTS(®ion);
+
+ xSrc = xSrc + src_off_x - xDst - dst_off_x;
+ ySrc = ySrc + src_off_y - yDst - dst_off_y;
+
+ while (nbox--)
+ {
+ (*uxa_screen->info->Composite) (pDstPix,
+ pbox->x1 + xSrc,
+ pbox->y1 + ySrc,
+ 0, 0,
+ pbox->x1,
+ pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ next_rect:
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+
+ rects++;
+ }
+
+ (*uxa_screen->info->DoneComposite) (pDstPix);
+ uxa_mark_sync(pDst->pDrawable->pScreen);
+
+ return 1;
+}
+
+/**
+ * Copy a number of rectangles from source to destination in a single
+ * operation. This is specialized for building a glyph mask: we don'y
+ * have a mask argument because we don't need it for that, and we
+ * don't have he special-case fallbacks found in uxa_composite() - if the
+ * driver can support it, we use the driver functionality, otherwise we
+ * fallback straight to software.
+ */
+void
+uxa_composite_rects(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ int nrect,
+ uxa_composite_rect_t *rects)
+{
+ int n;
+ uxa_composite_rect_t *r;
+
+ /************************************************************/
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
+
+ if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
+ n = nrect;
+ r = rects;
+ while (n--) {
+ uxa_check_composite (op, pSrc, NULL, pDst,
+ r->xSrc, r->ySrc,
+ 0, 0,
+ r->xDst, r->yDst,
+ r->width, r->height);
+ r++;
+ }
+ }
+
+ /************************************************************/
+
+}
+
+static int
+uxa_try_driver_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+ int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
+ PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
+ struct _Pixmap scratch;
+
+ pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable);
+ pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (pMask)
+ pMaskPix = uxa_get_drawable_pixmap(pMask->pDrawable);
+
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+
+ if (pMask) {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ }
+
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+
+ if (uxa_screen->info->CheckComposite &&
+ !(*uxa_screen->info->CheckComposite) (op, pSrc, pMask, pDst))
+ {
+ return -1;
+ }
+
+ if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height))
+ return 1;
+
+ uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
+
+ REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
+
+ pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (pMask)
+ pMaskPix = uxa_get_offscreen_pixmap (pMask->pDrawable, &mask_off_x,
+ &mask_off_y);
+
+ if (!uxa_pixmap_is_offscreen(pDstPix)) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return 0;
+ }
+
+ if (!pSrcPix && (!pMask || pMaskPix) && uxa_screen->info->UploadToScratch) {
+ pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable);
+ if ((*uxa_screen->info->UploadToScratch) (pSrcPix, &scratch))
+ pSrcPix = &scratch;
+ } else if (pSrcPix && pMask && !pMaskPix && uxa_screen->info->UploadToScratch) {
+ pMaskPix = uxa_get_drawable_pixmap (pMask->pDrawable);
+ if ((*uxa_screen->info->UploadToScratch) (pMaskPix, &scratch))
+ pMaskPix = &scratch;
+ }
+
+ if (!pSrcPix || (pMask && !pMaskPix)) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return 0;
+ }
+
+ if (!(*uxa_screen->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
+ pMaskPix, pDstPix))
+ {
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return -1;
+ }
+
+ nbox = REGION_NUM_RECTS(®ion);
+ pbox = REGION_RECTS(®ion);
+
+ xMask = xMask + mask_off_x - xDst - dst_off_x;
+ yMask = yMask + mask_off_y - yDst - dst_off_y;
+
+ xSrc = xSrc + src_off_x - xDst - dst_off_x;
+ ySrc = ySrc + src_off_y - yDst - dst_off_y;
+
+ while (nbox--)
+ {
+ (*uxa_screen->info->Composite) (pDstPix,
+ pbox->x1 + xSrc,
+ pbox->y1 + ySrc,
+ pbox->x1 + xMask,
+ pbox->y1 + yMask,
+ pbox->x1,
+ pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+ (*uxa_screen->info->DoneComposite) (pDstPix);
+ uxa_mark_sync(pDst->pDrawable->pScreen);
+
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ return 1;
+}
+
+/**
+ * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of
+ * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
+ * alpha and limited 1-tmu cards.
+ *
+ * From http://anholt.livejournal.com/32058.html:
+ *
+ * The trouble is that component-alpha rendering requires two different sources
+ * for blending: one for the source value to the blender, which is the
+ * per-channel multiplication of source and mask, and one for the source alpha
+ * for multiplying with the destination channels, which is the multiplication
+ * of the source channels by the mask alpha. So the equation for Over is:
+ *
+ * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
+ *
+ * But we can do some simpler operations, right? How about PictOpOutReverse,
+ * which has a source factor of 0 and dest factor of (1 - source alpha). We
+ * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
+ * blenders pretty easily. So we can do a component-alpha OutReverse, which
+ * gets us:
+ *
+ * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
+ *
+ * OK. And if an op doesn't use the source alpha value for the destination
+ * factor, then we can do the channel multiplication in the texture blenders
+ * to get the source value, and ignore the source alpha that we wouldn't use.
+ * We've supported this in the Radeon driver for a long time. An example would
+ * be PictOpAdd, which does:
+ *
+ * dst.A = src.A * mask.A + dst.A
+ * dst.R = src.R * mask.R + dst.R
+ * dst.G = src.G * mask.G + dst.G
+ * dst.B = src.B * mask.B + dst.B
+ *
+ * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
+ * after it, we get:
+ *
+ * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
+ * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
+ * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
+ * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
+ */
+
+static int
+uxa_try_magic_two_pass_composite_helper(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+
+ assert(op == PictOpOver);
+
+ if (uxa_screen->info->CheckComposite &&
+ (!(*uxa_screen->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
+ pDst) ||
+ !(*uxa_screen->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))
+ {
+ return -1;
+ }
+
+ /* Now, we think we should be able to accelerate this operation. First,
+ * composite the destination to be the destination times the source alpha
+ * factors.
+ */
+ uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+
+ /* Then, add in the source value times the destination alpha factors (1.0).
+ */
+ uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+
+ return 1;
+}
+
+void
+uxa_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ int ret = -1;
+ Bool saveSrcRepeat = pSrc->repeat;
+ Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
+ RegionRec region;
+
+ /* We currently don't support acceleration of gradients, or other pictures
+ * with a NULL pDrawable.
+ */
+ if (uxa_screen->swappedOut ||
+ pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
+ {
+ goto fallback;
+ }
+
+ /* Remove repeat in source if useless */
+ if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
+ (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
+ (ySrc + height) <= pSrc->pDrawable->height)
+ pSrc->repeat = 0;
+
+ if (!pMask)
+ {
+ if ((op == PictOpSrc &&
+ ((pSrc->format == pDst->format) ||
+ (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
+ (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
+ (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
+ pSrc->format == pDst->format &&
+ (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
+ {
+ if (pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat)
+ {
+ ret = uxa_try_driver_solid_fill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
+ else if (pSrc->pDrawable != NULL &&
+ !pSrc->repeat &&
+ !pSrc->transform)
+ {
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+
+ if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst,
+ yDst, width, height))
+ goto done;
+
+
+ uxa_copy_n_to_n (pSrc->pDrawable, pDst->pDrawable, NULL,
+ REGION_RECTS(®ion), REGION_NUM_RECTS(®ion),
+ xSrc - xDst, ySrc - yDst,
+ FALSE, FALSE, 0, NULL);
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+ goto done;
+ }
+ else if (pSrc->pDrawable != NULL &&
+ pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
+ !pSrc->transform &&
+ pSrc->repeatType == RepeatNormal)
+ {
+ DDXPointRec patOrg;
+
+ /* Let's see if the driver can do the repeat in one go */
+ if (uxa_screen->info->PrepareComposite && !pSrc->alphaMap &&
+ !pDst->alphaMap)
+ {
+ ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc,
+ ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
+
+ /* Now see if we can use uxa_fill_region_tiled() */
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+
+ if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc,
+ ySrc, xMask, yMask, xDst, yDst,
+ width, height))
+ goto done;
+
+ /* pattern origin is the point in the destination drawable
+ * corresponding to (0,0) in the source */
+ patOrg.x = xDst - xSrc;
+ patOrg.y = yDst - ySrc;
+
+ ret = uxa_fill_region_tiled(pDst->pDrawable, ®ion,
+ (PixmapPtr)pSrc->pDrawable,
+ &patOrg, FB_ALLONES, GXcopy);
+
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
+
+ if (ret)
+ goto done;
+ }
+ }
+ }
+
+ /* Remove repeat in mask if useless */
+ if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
+ (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
+ (yMask + height) <= pMask->pDrawable->height)
+ pMask->repeat = 0;
+
+ if (uxa_screen->info->PrepareComposite &&
+ !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
+ {
+ Bool isSrcSolid;
+
+ ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
+ yMask, xDst, yDst, width, height);
+ if (ret == 1)
+ goto done;
+
+ /* For generic masks and solid src pictures, mach64 can do Over in two
+ * passes, similar to the component-alpha case.
+ */
+ isSrcSolid = pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat;
+
+ /* If we couldn't do the Composite in a single pass, and it was a
+ * component-alpha Over, see if we can do it in two passes with
+ * an OutReverse and then an Add.
+ */
+ if (ret == -1 && op == PictOpOver && pMask &&
+ (pMask->componentAlpha || isSrcSolid)) {
+ ret = uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst,
+ xSrc, ySrc,
+ xMask, yMask, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
+ }
+
+fallback:
+#if DEBUG_TRACE_FALL
+ uxa_print_composite_fallback (op, pSrc, pMask, pDst);
+#endif
+
+ uxa_check_composite (op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+
+done:
+ pSrc->repeat = saveSrcRepeat;
+ if (pMask)
+ pMask->repeat = saveMaskRepeat;
+}
+#endif
+
+/**
+ * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead
+ * of PolyFillRect to initialize the pixmap after creating it, to prevent
+ * the pixmap from being migrated.
+ *
+ * See the comments about uxa_trapezoids and uxa_triangles.
+ */
+static PicturePtr
+uxa_create_alpha_picture (ScreenPtr pScreen,
+ PicturePtr pDst,
+ PictFormatPtr pPictFormat,
+ CARD16 width,
+ CARD16 height)
+{
+ PixmapPtr pPixmap;
+ PicturePtr pPicture;
+ GCPtr pGC;
+ int error;
+ xRectangle rect;
+
+ if (width > 32767 || height > 32767)
+ return 0;
+
+ if (!pPictFormat)
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+ if (!pPictFormat)
+ return 0;
+ }
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+ pPictFormat->depth, 0);
+ if (!pPixmap)
+ return 0;
+ pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+ if (!pGC)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ return 0;
+ }
+ ValidateGC (&pPixmap->drawable, pGC);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ uxa_check_poly_fill_rect (&pPixmap->drawable, pGC, 1, &rect);
+ FreeScratchGC (pGC);
+ pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
+ 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ return pPicture;
+}
+
+/**
+ * uxa_trapezoids is essentially a copy of miTrapezoids that uses
+ * uxa_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to RasterizeTrapezoid won't be accelerated however, which
+ * forces the pixmap to be moved out again.
+ *
+ * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
+ * to initialize the contents.
+ */
+void
+uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ BoxRec bounds;
+ Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
+
+ if (maskFormat || direct) {
+ miTrapezoidBounds (ntrap, traps, &bounds);
+
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+ }
+
+ /*
+ * Check for solid alpha add
+ */
+ if (direct)
+ {
+ DrawablePtr pDraw = pDst->pDrawable;
+ PixmapPtr pixmap = uxa_get_drawable_pixmap (pDraw);
+ int xoff, yoff;
+
+ uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff);
+
+ xoff += pDraw->x;
+ yoff += pDraw->y;
+
+ uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+
+ uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+ }
+ else if (maskFormat)
+ {
+ PicturePtr pPicture;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+
+ xDst = traps[0].left.p1.x >> 16;
+ yDst = traps[0].left.p1.y >> 16;
+
+ pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ if (!pPicture)
+ return;
+
+ uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pPicture, traps,
+ -bounds.x1, -bounds.y1);
+ uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture (op, pSrc, pPicture, pDst,
+ xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ FreePicture (pPicture, 0);
+ }
+ else
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+ for (; ntrap; ntrap--, traps++)
+ uxa_trapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
+ }
+}
+
+/**
+ * uxa_triangles is essentially a copy of miTriangles that uses
+ * uxa_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to AddTriangles won't be accelerated however, which forces the pixmap
+ * to be moved out again.
+ *
+ * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect
+ * to initialize the contents.
+ */
+void
+uxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ BoxRec bounds;
+ Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc);
+
+ if (maskFormat || direct) {
+ miTriangleBounds (ntri, tris, &bounds);
+
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+ }
+
+ /*
+ * Check for solid alpha add
+ */
+ if (direct)
+ {
+ DrawablePtr pDraw = pDst->pDrawable;
+ uxa_prepare_access(pDraw, UXA_PREPARE_DEST);
+ (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
+ uxa_finish_access(pDraw, UXA_PREPARE_DEST);
+ }
+ else if (maskFormat)
+ {
+ PicturePtr pPicture;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+
+ xDst = tris[0].p1.x >> 16;
+ yDst = tris[0].p1.y >> 16;
+
+ pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ if (!pPicture)
+ return;
+
+ uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
+ uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture (op, pSrc, pPicture, pDst,
+ xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+ bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
+ FreePicture (pPicture, 0);
+ }
+ else
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+
+ for (; ntri; ntri--, tris++)
+ uxa_triangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
+ }
+}
diff --git a/uxa/uxa-unaccel.c b/uxa/uxa-unaccel.c
new file mode 100644
index 0000000..2719420
--- /dev/null
+++ b/uxa/uxa-unaccel.c
@@ -0,0 +1,370 @@
+/*
+ *
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "uxa-priv.h"
+
+#ifdef RENDER
+#include "mipict.h"
+#endif
+
+/*
+ * These functions wrap the low-level fb rendering functions and
+ * synchronize framebuffer/accelerated drawing by stalling until
+ * the accelerator is idle
+ */
+
+/**
+ * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
+ * current fill style.
+ *
+ * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
+ * 1bpp and never in fb, so we don't worry about them.
+ * We should worry about them for completeness sake and going forward.
+ */
+void
+uxa_prepare_access_gc(GCPtr pGC)
+{
+ if (pGC->stipple)
+ uxa_prepare_access(&pGC->stipple->drawable, UXA_PREPARE_MASK);
+ if (pGC->fillStyle == FillTiled)
+ uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+/**
+ * Finishes access to the tile in the GC, if used.
+ */
+void
+uxa_finish_access_gc(GCPtr pGC)
+{
+ if (pGC->fillStyle == FillTiled)
+ uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_MASK);
+ if (pGC->stipple)
+ uxa_finish_access(&pGC->stipple->drawable, UXA_PREPARE_SRC);
+}
+
+#if DEBUG_TRACE_FALL
+char
+uxa_drawable_location(DrawablePtr pDrawable)
+{
+ return uxa_drawable_is_offscreen(pDrawable) ? 's' : 'm';
+}
+#endif /* DEBUG_TRACE_FALL */
+
+void
+uxa_check_fill_spans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_set_spans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *bits)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+RegionPtr
+uxa_check_copy_area (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ RegionPtr ret;
+
+ UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+ uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
+ uxa_prepare_access (pDst, UXA_PREPARE_DEST);
+ uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+ ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
+ uxa_finish_access (pSrc, UXA_PREPARE_SRC);
+ uxa_finish_access (pDst, UXA_PREPARE_DEST);
+
+ return ret;
+}
+
+RegionPtr
+uxa_check_copy_plane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane)
+{
+ RegionPtr ret;
+
+ UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+ uxa_drawable_location(pSrc), uxa_drawable_location(pDst)));
+ uxa_prepare_access (pDst, UXA_PREPARE_DEST);
+ uxa_prepare_access (pSrc, UXA_PREPARE_SRC);
+ ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
+ bitPlane);
+ uxa_finish_access (pSrc, UXA_PREPARE_SRC);
+ uxa_finish_access (pDst, UXA_PREPARE_DEST);
+
+ return ret;
+}
+
+void
+uxa_check_poly_point (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_poly_lines (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ UXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
+ pDrawable, uxa_drawable_location(pDrawable),
+ pGC->lineWidth, mode, npt));
+
+ if (pGC->lineWidth == 0) {
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbPolyLine (pDrawable, pGC, mode, npt, ppt);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolyLine (pDrawable, pGC, mode, npt, ppt);
+}
+
+void
+uxa_check_poly_segment (DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit)
+{
+ UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
+ uxa_drawable_location(pDrawable), pGC->lineWidth, nsegInit));
+ if (pGC->lineWidth == 0) {
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
+}
+
+void
+uxa_check_poly_arc (DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *pArcs)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+
+ /* Disable this as fbPolyArc can call miZeroPolyArc which in turn
+ * can call accelerated functions, that as yet, haven't been notified
+ * with uxa_finish_access().
+ */
+#if 0
+ if (pGC->lineWidth == 0)
+ {
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbPolyArc (pDrawable, pGC, narcs, pArcs);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+ return;
+ }
+#endif
+ miPolyArc (pDrawable, pGC, narcs, pArcs);
+}
+
+void
+uxa_check_poly_fill_rect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrect, xRectangle *prect)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbPolyFillRect (pDrawable, pGC, nrect, prect);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_image_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ UXA_FALLBACK(("to %p (%c)\n", pDrawable,
+ uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_poly_glyph_blt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
+ uxa_drawable_location(pDrawable), pGC->fillStyle, pGC->alu));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access_gc (pGC);
+ fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_push_pixels (GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable,
+ int w, int h, int x, int y)
+{
+ UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
+ uxa_drawable_location(&pBitmap->drawable),
+ uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_DEST);
+ uxa_prepare_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+ uxa_prepare_access_gc (pGC);
+ fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
+ uxa_finish_access_gc (pGC);
+ uxa_finish_access (&pBitmap->drawable, UXA_PREPARE_SRC);
+ uxa_finish_access (pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_get_spans (DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ char *pdstStart)
+{
+ UXA_FALLBACK(("from %p (%c)\n", pDrawable, uxa_drawable_location(pDrawable)));
+ uxa_prepare_access (pDrawable, UXA_PREPARE_SRC);
+ fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ uxa_finish_access (pDrawable, UXA_PREPARE_SRC);
+}
+
+void
+uxa_check_composite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ UXA_FALLBACK(("from picts %p/%p to pict %p\n",
+ pSrc, pMask, pDst));
+
+ uxa_prepare_access (pDst->pDrawable, UXA_PREPARE_DEST);
+ if (pSrc->pDrawable != NULL)
+ uxa_prepare_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+ if (pMask && pMask->pDrawable != NULL)
+ uxa_prepare_access (pMask->pDrawable, UXA_PREPARE_MASK);
+ fbComposite (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+ if (pMask && pMask->pDrawable != NULL)
+ uxa_finish_access (pMask->pDrawable, UXA_PREPARE_MASK);
+ if (pSrc->pDrawable != NULL)
+ uxa_finish_access (pSrc->pDrawable, UXA_PREPARE_SRC);
+ uxa_finish_access (pDst->pDrawable, UXA_PREPARE_DEST);
+}
+
+void
+uxa_check_add_traps (PicturePtr pPicture,
+ INT16 x_off,
+ INT16 y_off,
+ int ntrap,
+ xTrap *traps)
+{
+ UXA_FALLBACK(("to pict %p (%c)\n",
+ uxa_drawable_location(pPicture->pDrawable)));
+ uxa_prepare_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+ fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
+ uxa_finish_access(pPicture->pDrawable, UXA_PREPARE_DEST);
+}
+
+/**
+ * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
+ * that happen to be 1x1. Pixmap must be at least 8bpp.
+ *
+ * XXX This really belongs in fb, so it can be aware of tiling and etc.
+ */
+CARD32
+uxa_get_pixmap_first_pixel (PixmapPtr pPixmap)
+{
+ CARD32 pixel;
+ void *fb;
+
+ uxa_prepare_access (&pPixmap->drawable, UXA_PREPARE_SRC);
+ fb = pPixmap->devPrivate.ptr;
+
+ switch (pPixmap->drawable.bitsPerPixel) {
+ case 32:
+ pixel = *(CARD32 *)fb;
+ break;
+ case 16:
+ pixel = *(CARD16 *)fb;
+ break;
+ default:
+ pixel = *(CARD8 *)fb;
+ break;
+ }
+ uxa_finish_access(&pPixmap->drawable, UXA_PREPARE_SRC);
+
+ return pixel;
+}
diff --git a/uxa/uxa.c b/uxa/uxa.c
new file mode 100644
index 0000000..9745f8b
--- /dev/null
+++ b/uxa/uxa.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/** @file
+ * This file covers the initialization and teardown of UXA, and has various
+ * functions not responsible for performing rendering, pixmap migration, or
+ * memory management.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "uxa-priv.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "uxa.h"
+
+DevPrivateKey uxa_screen_key = &uxa_screen_key;
+
+/**
+ * uxa_get_drawable_pixmap() 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
+ * uxa_get_drawable_pixmap() on the drawable.
+ */
+PixmapPtr
+uxa_get_drawable_pixmap(DrawablePtr pDrawable)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
+ else
+ return (PixmapPtr) pDrawable;
+}
+
+/**
+ * Sets the offsets to add to coordinates to make them address the same bits in
+ * the backing drawable. These coordinates are nonzero only for redirected
+ * windows.
+ */
+void
+uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
+ int *xp, int *yp)
+{
+#ifdef COMPOSITE
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ *xp = -pPixmap->screen_x;
+ *yp = -pPixmap->screen_y;
+ return;
+ }
+#endif
+
+ *xp = 0;
+ *yp = 0;
+}
+
+/**
+ * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
+ * memory, meaning that acceleration could probably be done to it, and that it
+ * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * with the CPU.
+ *
+ * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
+ * deal with moving pixmaps in and out of system memory), UXA will give drivers
+ * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
+ *
+ * @return TRUE if the given drawable is in framebuffer memory.
+ */
+Bool
+uxa_pixmap_is_offscreen(PixmapPtr p)
+{
+ ScreenPtr pScreen = p->drawable.pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+
+ if (uxa_screen->info->PixmapIsOffscreen)
+ return uxa_screen->info->PixmapIsOffscreen(p);
+
+ return FALSE;
+}
+
+/**
+ * uxa_drawable_is_offscreen() is a convenience wrapper for uxa_pixmap_is_offscreen().
+ */
+Bool
+uxa_drawable_is_offscreen (DrawablePtr pDrawable)
+{
+ return uxa_pixmap_is_offscreen (uxa_get_drawable_pixmap (pDrawable));
+}
+
+/**
+ * Returns the pixmap which backs a drawable, and the offsets to add to
+ * coordinates to make them address the same bits in the backing drawable.
+ */
+PixmapPtr
+uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp)
+{
+ PixmapPtr pixmap = uxa_get_drawable_pixmap (drawable);
+
+ uxa_get_drawable_deltas (drawable, pixmap, xp, yp);
+
+ if (uxa_pixmap_is_offscreen (pixmap))
+ return pixmap;
+ else
+ return NULL;
+}
+
+
+
+/**
+ * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
+ *
+ * It deals with waiting for synchronization with the card, determining if
+ * PrepareAccess() is necessary, and working around PrepareAccess() failure.
+ */
+void
+uxa_prepare_access(DrawablePtr pDrawable, int index)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
+ Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
+
+ if (!offscreen)
+ return;
+
+ /* XXX should be pPixmap eventually */
+ uxa_wait_sync (pScreen);
+
+ if (uxa_screen->info->PrepareAccess)
+ (*uxa_screen->info->PrepareAccess) (pPixmap, index);
+}
+
+/**
+ * uxa_finish_access() is UXA's wrapper for the driver's FinishAccess() handler.
+ *
+ * It deals with calling the driver's FinishAccess() only if necessary.
+ */
+void
+uxa_finish_access(DrawablePtr pDrawable, int index)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable);
+
+ if (uxa_screen->info->FinishAccess == NULL)
+ return;
+
+ if (!uxa_pixmap_is_offscreen (pPixmap))
+ return;
+
+ (*uxa_screen->info->FinishAccess) (pPixmap, index);
+}
+
+/**
+ * uxa_validate_gc() sets the ops to UXA's implementations, which may be
+ * accelerated or may sync the card and fall back to fb.
+ */
+static void
+uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
+ * Preempt fbValidateGC by doing its work and masking the change out, so
+ * that we can do the Prepare/FinishAccess.
+ */
+#ifdef FB_24_32BIT
+ if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
+ (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
+ fbGetRotatedPixmap(pGC) = 0;
+ }
+
+ if (pGC->fillStyle == FillTiled) {
+ PixmapPtr pOldTile, pNewTile;
+
+ pOldTile = pGC->tile.pixmap;
+ if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
+ {
+ pNewTile = fbGetRotatedPixmap(pGC);
+ if (!pNewTile ||
+ pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
+ {
+ if (pNewTile)
+ (*pGC->pScreen->DestroyPixmap) (pNewTile);
+ /* fb24_32ReformatTile will do direct access of a newly-
+ * allocated pixmap. This isn't a problem yet, since we don't
+ * put pixmaps in FB until at least one accelerated UXA op.
+ */
+ uxa_prepare_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+ pNewTile = fb24_32ReformatTile (pOldTile,
+ pDrawable->bitsPerPixel);
+ uxa_finish_access(&pOldTile->drawable, UXA_PREPARE_SRC);
+ }
+ if (pNewTile)
+ {
+ fbGetRotatedPixmap(pGC) = pOldTile;
+ pGC->tile.pixmap = pNewTile;
+ changes |= GCTile;
+ }
+ }
+ }
+#endif
+ if (changes & GCTile) {
+ if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
+ pDrawable->bitsPerPixel))
+ {
+ uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+ fbPadPixmap (pGC->tile.pixmap);
+ uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_PREPARE_SRC);
+ }
+ /* Mask out the GCTile change notification, now that we've done FB's
+ * job for it.
+ */
+ changes &= ~GCTile;
+ }
+
+ uxa_prepare_access_gc(pGC);
+ fbValidateGC (pGC, changes, pDrawable);
+ uxa_finish_access_gc(pGC);
+
+ pGC->ops = (GCOps *) &uxa_ops;
+}
+
+static GCFuncs uxaGCFuncs = {
+ uxa_validate_gc,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+/**
+ * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
+ * uxa_validate_gc() will get called.
+ */
+static int
+uxa_create_gc (GCPtr pGC)
+{
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ pGC->funcs = &uxaGCFuncs;
+
+ return TRUE;
+}
+
+void
+uxa_prepare_access_window(WindowPtr pWin)
+{
+ if (pWin->backgroundState == BackgroundPixmap)
+ uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+
+ if (pWin->borderIsPixel == FALSE)
+ uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+void
+uxa_finish_access_window(WindowPtr pWin)
+{
+ if (pWin->backgroundState == BackgroundPixmap)
+ uxa_finish_access(&pWin->background.pixmap->drawable, UXA_PREPARE_SRC);
+
+ if (pWin->borderIsPixel == FALSE)
+ uxa_finish_access(&pWin->border.pixmap->drawable, UXA_PREPARE_SRC);
+}
+
+static Bool
+uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
+{
+ Bool ret;
+
+ uxa_prepare_access_window(pWin);
+ ret = fbChangeWindowAttributes(pWin, mask);
+ uxa_finish_access_window(pWin);
+ return ret;
+}
+
+static RegionPtr
+uxa_bitmap_to_region(PixmapPtr pPix)
+{
+ RegionPtr ret;
+ uxa_prepare_access(&pPix->drawable, UXA_PREPARE_SRC);
+ ret = fbPixmapToRegion(pPix);
+ uxa_finish_access(&pPix->drawable, UXA_PREPARE_SRC);
+ return ret;
+}
+
+/**
+ * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
+ * screen private, before calling down to the next CloseSccreen.
+ */
+static Bool
+uxa_close_screen(int i, ScreenPtr pScreen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ uxa_glyphs_fini(pScreen);
+
+ pScreen->CreateGC = uxa_screen->SavedCreateGC;
+ pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
+ pScreen->GetImage = uxa_screen->SavedGetImage;
+ pScreen->GetSpans = uxa_screen->SavedGetSpans;
+ pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
+ pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
+ pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
+ pScreen->ChangeWindowAttributes = uxa_screen->SavedChangeWindowAttributes;
+ pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = uxa_screen->SavedComposite;
+ ps->Glyphs = uxa_screen->SavedGlyphs;
+ ps->Trapezoids = uxa_screen->SavedTrapezoids;
+ ps->AddTraps = uxa_screen->SavedAddTraps;
+ ps->Triangles = uxa_screen->SavedTriangles;
+ }
+#endif
+
+ xfree (uxa_screen);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+/**
+ * This function allocates a driver structure for UXA drivers to fill in. By
+ * having UXA allocate the structure, the driver structure can be extended
+ * without breaking ABI between UXA and the drivers. The driver's
+ * responsibility is to check beforehand that the UXA 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
+ */
+uxa_driver_t *
+uxa_driver_alloc(void)
+{
+ return xcalloc(1, sizeof(uxa_driver_t));
+}
+
+/**
+ * @param pScreen screen being initialized
+ * @param pScreenInfo UXA driver record
+ *
+ * uxa_driver_init sets up UXA given a driver record filled in by the driver.
+ * pScreenInfo should have been allocated by uxa_driver_alloc(). See the
+ * comments in _UxaDriver for what must be filled in and what is optional.
+ *
+ * @return TRUE if UXA was successfully initialized.
+ */
+Bool
+uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver)
+{
+ uxa_screen_t *uxa_screen;
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
+
+ if (!uxa_driver)
+ return FALSE;
+
+ if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
+ uxa_driver->uxa_minor > UXA_VERSION_MINOR)
+ {
+ LogMessage(X_ERROR, "UXA(%d): driver's UXA version requirements "
+ "(%d.%d) are incompatible with UXA version (%d.%d)\n",
+ screen->myNum,
+ uxa_driver->uxa_major, uxa_driver->uxa_minor,
+ UXA_VERSION_MAJOR, UXA_VERSION_MINOR);
+ return FALSE;
+ }
+
+ if (!uxa_driver->PrepareSolid) {
+ LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareSolid must be "
+ "non-NULL\n", screen->myNum);
+ return FALSE;
+ }
+
+ if (!uxa_driver->PrepareCopy) {
+ LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::PrepareCopy must be "
+ "non-NULL\n", screen->myNum);
+ return FALSE;
+ }
+
+ if (!uxa_driver->WaitMarker) {
+ LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::WaitMarker must be "
+ "non-NULL\n", screen->myNum);
+ return FALSE;
+ }
+
+ /* If the driver doesn't set any max pitch values, we'll just assume
+ * that there's a limitation by pixels, and that it's the same as
+ * maxX.
+ *
+ * We want maxPitchPixels or maxPitchBytes to be set so we can check
+ * pixmaps against the max pitch in uxaCreatePixmap() -- it matters
+ * whether a pixmap is rejected because of its pitch or
+ * because of its width.
+ */
+ if (!uxa_driver->maxPitchPixels && !uxa_driver->maxPitchBytes)
+ {
+ uxa_driver->maxPitchPixels = uxa_driver->maxX;
+ }
+
+#ifdef RENDER
+ ps = GetPictureScreenIfSet(screen);
+#endif
+
+ uxa_screen = xcalloc (sizeof (uxa_screen_t), 1);
+
+ if (!uxa_screen) {
+ LogMessage(X_WARNING, "UXA(%d): Failed to allocate screen private\n",
+ screen->myNum);
+ return FALSE;
+ }
+
+ uxa_screen->info = uxa_driver;
+
+ dixSetPrivate(&screen->devPrivates, uxa_screen_key, uxa_screen);
+
+// exaDDXDriverInit(screen);
+
+ /*
+ * Replace various fb screen functions
+ */
+ uxa_screen->SavedCloseScreen = screen->CloseScreen;
+ screen->CloseScreen = uxa_close_screen;
+
+ uxa_screen->SavedCreateGC = screen->CreateGC;
+ screen->CreateGC = uxa_create_gc;
+
+ uxa_screen->SavedGetImage = screen->GetImage;
+ screen->GetImage = uxa_get_image;
+
+ uxa_screen->SavedGetSpans = screen->GetSpans;
+ screen->GetSpans = uxa_check_get_spans;
+
+ uxa_screen->SavedCopyWindow = screen->CopyWindow;
+ screen->CopyWindow = uxa_copy_window;
+
+ uxa_screen->SavedChangeWindowAttributes = screen->ChangeWindowAttributes;
+ screen->ChangeWindowAttributes = uxa_change_window_attributes;
+
+ uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
+ screen->BitmapToRegion = uxa_bitmap_to_region;
+
+#ifdef RENDER
+ if (ps) {
+ uxa_screen->SavedComposite = ps->Composite;
+ ps->Composite = uxa_composite;
+
+ uxa_screen->SavedGlyphs = ps->Glyphs;
+ ps->Glyphs = uxa_glyphs;
+
+ uxa_screen->SavedTriangles = ps->Triangles;
+ ps->Triangles = uxa_triangles;
+
+ uxa_screen->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = uxa_trapezoids;
+
+ uxa_screen->SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = uxa_check_add_traps;
+ }
+#endif
+
+#ifdef MITSHM
+ /* Re-register with the MI funcs, which don't allow shared pixmaps.
+ * Shared pixmaps are almost always a performance loss for us, but this
+ * still allows for SHM PutImage.
+ */
+ ShmRegisterFuncs(screen, &uxa_shm_funcs);
+#endif
+
+ uxa_glyphs_init(screen);
+
+ LogMessage(X_INFO, "UXA(%d): Driver registered support for the following"
+ " operations:\n", screen->myNum);
+ assert(uxa_driver->PrepareSolid != NULL);
+ LogMessage(X_INFO, " Solid\n");
+ assert(uxa_driver->PrepareCopy != NULL);
+ LogMessage(X_INFO, " Copy\n");
+ if (uxa_driver->PrepareComposite != NULL) {
+ LogMessage(X_INFO, " Composite (RENDER acceleration)\n");
+ }
+ if (uxa_driver->UploadToScreen != NULL) {
+ LogMessage(X_INFO, " UploadToScreen\n");
+ }
+ if (uxa_driver->DownloadFromScreen != NULL) {
+ LogMessage(X_INFO, " DownloadFromScreen\n");
+ }
+
+ return TRUE;
+}
+
+/**
+ * uxa_driver_fini tears down UXA on a given screen.
+ *
+ * @param pScreen screen being torn down.
+ */
+void
+uxa_driver_fini (ScreenPtr pScreen)
+{
+ /*right now does nothing*/
+}
+
+/**
+ * uxa_mark_sync() should be called after any asynchronous drawing by the hardware.
+ *
+ * @param pScreen screen which drawing occurred on
+ *
+ * uxa_mark_sync() 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 uxa_mark_sync(ScreenPtr pScreen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+
+ uxa_screen->info->needsSync = TRUE;
+ if (uxa_screen->info->MarkSync != NULL) {
+ uxa_screen->info->lastMarker = (*uxa_screen->info->MarkSync)(pScreen);
+ }
+}
+
+/**
+ * uxa_wait_sync() 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 uxa_wait_sync(ScreenPtr pScreen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+
+ if (uxa_screen->info->needsSync && !uxa_screen->swappedOut) {
+ (*uxa_screen->info->WaitMarker)(pScreen, uxa_screen->info->lastMarker);
+ uxa_screen->info->needsSync = FALSE;
+ }
+}
diff --git a/uxa/uxa.h b/uxa/uxa.h
new file mode 100644
index 0000000..57e84f3
--- /dev/null
+++ b/uxa/uxa.h
@@ -0,0 +1,671 @@
+/*
+ * Copyright © 2000, 2008 Keith Packard
+ * 2004 Eric Anholt
+ * 2005 Zack Rusin
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Copyright holders make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/** @file
+ * UXA - the unified memory acceleration architecture.
+ *
+ * This is the header containing the public API of UXA for uxa drivers.
+ */
+
+#ifndef UXA_H
+#define UXA_H
+
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "picturestr.h"
+#include "fb.h"
+
+#define UXA_VERSION_MAJOR 1
+#define UXA_VERSION_MINOR 0
+#define UXA_VERSION_RELEASE 0
+
+/**
+ * The UxaDriver structure is allocated through uxa_driver_alloc(), and then
+ * fllled in by drivers.
+ */
+typedef struct _UxaDriver {
+ /**
+ * uxa_major and uxa_minor should be set by the driver to the version of
+ * UXA which the driver was compiled for (or configures itself at runtime
+ * to support). This allows UXA to extend the structure for new features
+ * without breaking ABI for drivers compiled against older versions.
+ */
+ int uxa_major, uxa_minor;
+
+ /**
+ * The flags field is bitfield of boolean values controlling UXA's behavior.
+ *
+ * The flags include UXA_TWO_BITBLT_DIRECTIONS.
+ */
+ int flags;
+
+ /** @{ */
+ /**
+ * 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 */
+ Bool needsSync;
+ int lastMarker;
+
+ /** @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 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 series of consecutive
+ * Solid() calls following a successful PrepareSolid(). This allows drivers
+ * to finish up emitting drawing commands that were buffered, or clean up
+ * state from PrepareSolid().
+ *
+ * This call is required if PrepareSolid() ever succeeds.
+ */
+ void (*DoneSolid) (PixmapPtr pPixmap);
+ /** @} */
+
+ /** @name Copy
+ * @{
+ */
+ /**
+ * PrepareCopy() sets up the driver for doing a copy within video
+ * 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
+ * #UXA_TWO_BITBLT_DIRECTIONS, and UXA 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,
+ int dx,
+ 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 uxaGetPixmapOffset() and uxa_get_pixmap_pitch().
+ *
+ * This call is required if PrepareCopy ever succeeds.
+ */
+ void (*Copy) (PixmapPtr pDstPixmap,
+ int srcX,
+ int srcY,
+ int dstX,
+ 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 series of consecutive
+ * Copy() calls following a successful PrepareCopy(). This allows drivers
+ * to finish up emitting drawing commands that were buffered, or clean up
+ * state from PrepareCopy().
+ *
+ * This call is required if PrepareCopy() ever succeeds.
+ */
+ void (*DoneCopy) (PixmapPtr pDstPixmap);
+ /** @} */
+
+ /** @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 offsets and pitches 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 operation
+ * 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 #UXA_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 PrepareComposite() 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,
+ PicturePtr pDstPicture,
+ 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,
+ int maskX,
+ int maskY,
+ int dstX,
+ 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 series of consecutive
+ * Composite() calls following a successful PrepareComposite(). This allows
+ * drivers to finish up emitting drawing commands that were buffered, or
+ * clean up state from PrepareComposite().
+ *
+ * This call is required if PrepareComposite() ever succeeds.
+ */
+ void (*DoneComposite) (PixmapPtr pDst);
+ /** @} */
+
+ /**
+ * 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 uxa_mark_sync(). This is in contrast to most other acceleration
+ * calls in UXA.
+ *
+ * UploadToScreen() can aid in pixmap migration, but is most important for
+ * the performance of uxa_glyphs() (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 UXA 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,
+ int y,
+ int w,
+ 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 uxa_glyphs() 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 UXA.
+ */
+ Bool (*UploadToScratch) (PixmapPtr pSrc,
+ PixmapPtr pDst);
+
+ /**
+ * DownloadFromScreen() loads a rectangle of data from pSrc into 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, UXA leaves it up to the driver to call
+ * uxa_mark_sync() if DownloadFromScreen() was asynchronous. This is in
+ * contrast to most other acceleration calls in UXA.
+ *
+ * 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 UXA should fall back to doing the download in software.
+ *
+ * DownloadFromScreen() is not required, but is highly recommended.
+ */
+ Bool (*DownloadFromScreen)(PixmapPtr pSrc,
+ int x, int y,
+ int w, int h,
+ char *dst, int dst_pitch);
+
+ /**
+ * MarkSync() requests that the driver mark a synchronization point,
+ * returning an driver-defined 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
+ * UXA.
+ *
+ * Note that drivers should call uxa_mark_sync() when they have done some
+ * acceleration, rather than their own MarkSync() handler, as otherwise UXA
+ * will be unaware of the driver's acceleration and not sync to it during
+ * fallbacks.
+ *
+ * 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.
+ *
+ * Note that drivers should call uxa_wait_sync() to wait for all acceleration
+ * to finish, as otherwise UXA will be unaware of the driver having
+ * synchronized, resulting in excessive WaitMarker() calls.
+ *
+ * WaitMarker() is required of all drivers.
+ */
+ void (*WaitMarker) (ScreenPtr pScreen, int marker);
+
+ /** @{ */
+ /**
+ * 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 #UXA_PREPARE_DEST, #UXA_PREPARE_SRC, or
+ * #UXA_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 uxample when doing
+ * a copy within the same pixmap (so it gets PrepareAccess as()
+ * #UXA_PREPARE_DEST and then as #UXA_PREPARE_SRC).
+ *
+ * PrepareAccess() may fail. An uxample might be the case of hardware that
+ * can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
+ * fails, UXA will migrate the pixmap to system memory.
+ * DownloadFromScreen() must be implemented and must not fail if a driver
+ * wishes to fail in PrepareAccess(). PrepareAccess() must not fail when
+ * pPix is the visible screen, because the visible screen can not be
+ * migrated.
+ *
+ * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
+ * drawing.
+ * @return FALSE if PrepareAccess() is unsuccessful and UXA should use
+ * DownloadFromScreen() to migate the pixmap out.
+ */
+ 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);
+
+ /**
+ * PixmapIsOffscreen() is an optional driver replacement to
+ * uxa_pixmap_is_offscreen(). Set to NULL if you want the standard behaviour
+ * of uxa_pixmap_is_offscreen().
+ *
+ * @param pPix the pixmap
+ * @return TRUE if the given drawable is in framebuffer memory.
+ *
+ * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
+ * memory, meaning that acceleration could probably be done to it, and that it
+ * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * with the CPU.
+ *
+ *
+ */
+ Bool (*PixmapIsOffscreen)(PixmapPtr pPix);
+
+ /** @name PrepareAccess() and FinishAccess() indices
+ * @{
+ */
+ /**
+ * UXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
+ * read from.
+ */
+ #define UXA_PREPARE_DEST 0
+ /**
+ * UXA_PREPARE_SRC is the index for a pixmap that may be read from
+ */
+ #define UXA_PREPARE_SRC 1
+ /**
+ * UXA_PREPARE_SRC is the index for a second pixmap that may be read
+ * from.
+ */
+ #define UXA_PREPARE_MASK 2
+ /** @} */
+
+ /**
+ * maxPitchPixels controls the pitch limitation for rendering from
+ * the card.
+ * The driver should never receive a request for rendering a pixmap
+ * that has a pitch (in pixels) beyond maxPitchPixels.
+ *
+ * Setting this field is optional -- if your hardware doesn't have
+ * a pitch limitation in pixels, don't set this. If neither this value
+ * nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
+ * If set, it must not be smaller than maxX.
+ *
+ * @sa maxPitchBytes
+ */
+ int maxPitchPixels;
+
+ /**
+ * maxPitchBytes controls the pitch limitation for rendering from
+ * the card.
+ * The driver should never receive a request for rendering a pixmap
+ * that has a pitch (in bytes) beyond maxPitchBytes.
+ *
+ * Setting this field is optional -- if your hardware doesn't have
+ * a pitch limitation in bytes, don't set this.
+ * If set, it must not be smaller than maxX * 4.
+ * There's no default value for maxPitchBytes.
+ *
+ * @sa maxPitchPixels
+ */
+ int maxPitchBytes;
+
+ /** @} */
+} uxa_driver_t;
+
+/** @name UXA driver flags
+ * @{
+ */
+/**
+ * UXA_TWO_BITBLT_DIRECTIONS indicates to UXA that the driver can only
+ * support copies that are (left-to-right, top-to-bottom) or
+ * (right-to-left, bottom-to-top).
+ */
+#define UXA_TWO_BITBLT_DIRECTIONS (1 << 2)
+
+/** @} */
+
+uxa_driver_t *
+uxa_driver_alloc(void);
+
+Bool
+uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver);
+
+void
+uxa_driver_fini(ScreenPtr pScreen);
+
+void
+uxa_mark_sync(ScreenPtr pScreen);
+
+void
+uxa_wait_sync(ScreenPtr pScreen);
+
+void
+uxaEnableDisableFBAccess (int index, Bool enable);
+
+CARD32
+uxa_get_pixmap_first_pixel (PixmapPtr pPixmap);
+
+/**
+ * Returns TRUE if the given planemask covers all the significant bits in the
+ * pixel values for pDrawable.
+ */
+#define UXA_PM_IS_SOLID(_pDrawable, _pm) \
+ (((_pm) & FbFullMask((_pDrawable)->depth)) == \
+ FbFullMask((_pDrawable)->depth))
+
+#endif /* UXA_H */
More information about the xorg-commit
mailing list