diff options
Diffstat (limited to 'xorg-server/hw/xgl/xglsync.c')
-rw-r--r-- | xorg-server/hw/xgl/xglsync.c | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/xorg-server/hw/xgl/xglsync.c b/xorg-server/hw/xgl/xglsync.c new file mode 100644 index 000000000..6b5c00b57 --- /dev/null +++ b/xorg-server/hw/xgl/xglsync.c @@ -0,0 +1,453 @@ +/* + * Copyright © 2004 David Reveman + * + * 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 + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN 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: David Reveman <davidr@novell.com> + */ + +#include "xgl.h" + +Bool +xglSyncBits (DrawablePtr pDrawable, + BoxPtr pExtents) +{ + RegionRec region; + BoxRec box; + + XGL_DRAWABLE_PIXMAP (pDrawable); + XGL_PIXMAP_PRIV (pPixmap); + + if (pPixmapPriv->allBits) + return xglMapPixmapBits (pPixmap); + + if (pPixmapPriv->target == xglPixmapTargetIn && pExtents) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pPixmap->drawable.width; + box.y2 = pPixmap->drawable.height; + if (pExtents->x1 > box.x1) + box.x1 = pExtents->x1; + if (pExtents->y1 > box.y1) + box.y1 = pExtents->y1; + if (pExtents->x2 < box.x2) + box.x2 = pExtents->x2; + if (pExtents->y2 < box.y2) + box.y2 = pExtents->y2; + + if (box.x2 <= box.x1 || box.y2 <= box.y1) + return xglMapPixmapBits (pPixmap); + + if (REGION_NOTEMPTY (pDrawable->pScreen, &pPixmapPriv->bitRegion)) + { + switch (RECT_IN_REGION (pDrawable->pScreen, + &pPixmapPriv->bitRegion, + &box)) { + case rgnIN: + REGION_INIT (pDrawable->pScreen, ®ion, NullBox, 0); + break; + case rgnOUT: + REGION_INIT (pDrawable->pScreen, ®ion, &box, 1); + REGION_UNION (pDrawable->pScreen, + &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion, + ®ion); + break; + case rgnPART: + REGION_INIT (pDrawable->pScreen, ®ion, &box, 1); + REGION_SUBTRACT (pDrawable->pScreen, ®ion, ®ion, + &pPixmapPriv->bitRegion); + REGION_UNION (pDrawable->pScreen, + &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion, + ®ion); + break; + } + } + else + { + REGION_INIT (pDrawable->pScreen, ®ion, &box, 1); + REGION_SUBTRACT (pDrawable->pScreen, &pPixmapPriv->bitRegion, + ®ion, &pPixmapPriv->bitRegion); + } + + if (REGION_NUM_RECTS (&pPixmapPriv->bitRegion) == 1) + { + BoxPtr pBox; + + pBox = REGION_RECTS (&pPixmapPriv->bitRegion); + + if (pBox->x1 <= 0 && + pBox->y1 <= 0 && + pBox->x2 >= pPixmap->drawable.width && + pBox->y2 >= pPixmap->drawable.height) + pPixmapPriv->allBits = TRUE; + } + } + else + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pPixmap->drawable.width; + box.y2 = pPixmap->drawable.height; + + REGION_INIT (pDrawable->pScreen, ®ion, &box, 1); + REGION_SUBTRACT (pDrawable->pScreen, ®ion, ®ion, + &pPixmapPriv->bitRegion); + + pPixmapPriv->allBits = TRUE; + } + + if (!pPixmapPriv->buffer) + if (!xglAllocatePixmapBits (pPixmap, XGL_PIXMAP_USAGE_HINT_DEFAULT)) + return FALSE; + + if (REGION_NOTEMPTY (pDrawable->pScreen, ®ion) && pPixmapPriv->surface) + { + glitz_pixel_format_t format; + BoxPtr pBox; + BoxPtr pExt; + int nBox; + + if (!xglSyncSurface (pDrawable)) + FatalError (XGL_SW_FAILURE_STRING); + + xglUnmapPixmapBits (pPixmap); + + pBox = REGION_RECTS (®ion); + nBox = REGION_NUM_RECTS (®ion); + pExt = REGION_EXTENTS (pDrawable->pScreen, ®ion); + + format.fourcc = GLITZ_FOURCC_RGB; + format.masks = pPixmapPriv->pVisual->pPixel->masks; + format.xoffset = pExt->x1; + + if (pPixmapPriv->stride < 0) + { + format.skip_lines = pPixmap->drawable.height - pExt->y2; + format.bytes_per_line = -pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + } + else + { + format.skip_lines = pExt->y1; + format.bytes_per_line = pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; + } + + glitz_surface_set_clip_region (pPixmapPriv->surface, + 0, 0, (glitz_box_t *) pBox, nBox); + + glitz_get_pixels (pPixmapPriv->surface, + pExt->x1, + pExt->y1, + pExt->x2 - pExt->x1, + pExt->y2 - pExt->y1, + &format, + pPixmapPriv->buffer); + + glitz_surface_set_clip_region (pPixmapPriv->surface, 0, 0, NULL, 0); + } + + REGION_UNINIT (pDrawable->pScreen, ®ion); + + if (pPixmapPriv->allBits) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pPixmap->drawable.width; + box.y2 = pPixmap->drawable.height; + + REGION_UNINIT (pDrawable->pScreen, &pPixmapPriv->bitRegion); + REGION_INIT (pDrawable->pScreen, &pPixmapPriv->bitRegion, &box, 1); + } + + return xglMapPixmapBits (pPixmap); +} + +void +xglSyncDamageBoxBits (DrawablePtr pDrawable) +{ + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + if (!xglSyncBits (pDrawable, &pPixmapPriv->damageBox)) + FatalError (XGL_SW_FAILURE_STRING); +} + +Bool +xglSyncSurface (DrawablePtr pDrawable) +{ + RegionPtr pRegion; + + XGL_DRAWABLE_PIXMAP (pDrawable); + XGL_PIXMAP_PRIV (pPixmap); + + if (!pPixmapPriv->surface) + { + if (!xglCreatePixmapSurface (pPixmap)) + return FALSE; + } + + pRegion = DamageRegion (pPixmapPriv->pDamage); + + if (REGION_NOTEMPTY (pDrawable->pScreen, pRegion)) + { + glitz_pixel_format_t format; + BoxPtr pBox; + BoxPtr pExt; + int nBox; + + xglUnmapPixmapBits (pPixmap); + + nBox = REGION_NUM_RECTS (pRegion); + pBox = REGION_RECTS (pRegion); + pExt = REGION_EXTENTS (pDrawable->pScreen, pRegion); + + format.fourcc = pPixmapPriv->pVisual->format.surface->color.fourcc; + format.masks = pPixmapPriv->pVisual->pPixel->masks; + format.xoffset = pExt->x1; + + if (pPixmapPriv->stride < 0) + { + format.skip_lines = pPixmap->drawable.height - pExt->y2; + format.bytes_per_line = -pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + } + else + { + format.skip_lines = pExt->y1; + format.bytes_per_line = pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; + } + + glitz_surface_set_clip_region (pPixmapPriv->surface, + 0, 0, (glitz_box_t *) pBox, nBox); + + glitz_set_pixels (pPixmapPriv->surface, + pExt->x1, + pExt->y1, + pExt->x2 - pExt->x1, + pExt->y2 - pExt->y1, + &format, + pPixmapPriv->buffer); + + glitz_surface_set_clip_region (pPixmapPriv->surface, 0, 0, NULL, 0); + + REGION_EMPTY (pDrawable->pScreen, pRegion); + } + + return TRUE; +} + +Bool +xglPrepareTarget (DrawablePtr pDrawable) +{ + XGL_DRAWABLE_PIXMAP (pDrawable); + XGL_PIXMAP_PRIV (pPixmap); + + switch (pPixmapPriv->target) { + case xglPixmapTargetNo: + break; + case xglPixmapTargetOut: + if (xglSyncSurface (pDrawable)) + { + glitz_drawable_format_t *format; + + XGL_SCREEN_PRIV (pDrawable->pScreen); + + if (!pPixmapPriv->drawable) + { + unsigned int width, height; + + format = pPixmapPriv->pVisual->format.drawable; + width = pPixmap->drawable.width; + height = pPixmap->drawable.height; + + if (pPixmapPriv->pVisual->pbuffer) + { + pPixmapPriv->drawable = + glitz_create_pbuffer_drawable (pScreenPriv->drawable, + format, width, height); + } + else + { + pPixmapPriv->drawable = + glitz_create_drawable (pScreenPriv->drawable, + format, width, height); + } + } + + if (pPixmapPriv->drawable) + { + glitz_surface_attach (pPixmapPriv->surface, + pPixmapPriv->drawable, + GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); + + pPixmapPriv->target = xglPixmapTargetIn; + + return TRUE; + } + } + pPixmapPriv->target = xglPixmapTargetNo; + break; + case xglPixmapTargetIn: + if (xglSyncSurface (pDrawable)) + return TRUE; + break; + } + + return FALSE; +} + +void +xglAddSurfaceDamage (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + glitz_surface_t *surface; + int xOff, yOff; + + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + pPixmapPriv->damageBox = miEmptyBox; + + XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); + + if (xOff || yOff) + REGION_TRANSLATE (pDrawable->pScreen, pRegion, xOff, yOff); + + if (pPixmapPriv->pDamage) + { + RegionPtr pDamageRegion; + + pDamageRegion = DamageRegion (pPixmapPriv->pDamage); + + REGION_UNION (pDrawable->pScreen, + pDamageRegion, pDamageRegion, + pRegion); + } + + REGION_UNION (pDrawable->pScreen, + &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion, + pRegion); + + if (xOff || yOff) + REGION_TRANSLATE (pDrawable->pScreen, pRegion, -xOff, -yOff); +} + +void +xglAddCurrentSurfaceDamage (DrawablePtr pDrawable) +{ + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + if (BOX_NOTEMPTY (&pPixmapPriv->damageBox)) + { + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, &pPixmapPriv->damageBox, 1); + + if (pPixmapPriv->pDamage) + { + RegionPtr pDamageRegion; + + pDamageRegion = DamageRegion (pPixmapPriv->pDamage); + + REGION_UNION (pDrawable->pScreen, + pDamageRegion, pDamageRegion, + ®ion); + } + + REGION_UNION (pDrawable->pScreen, + &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion, + ®ion); + + REGION_UNINIT (pDrawable->pScreen, ®ion); + + pPixmapPriv->damageBox = miEmptyBox; + } +} + +void +xglAddBitDamage (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + if (REGION_NOTEMPTY (pDrawable->pScreen, &pPixmapPriv->bitRegion)) + { + BoxPtr pBox; + BoxPtr pExt, pBitExt; + int nBox; + + pBox = REGION_RECTS (pRegion); + pExt = REGION_EXTENTS (pDrawable->pScreen, pRegion); + nBox = REGION_NUM_RECTS (pRegion); + + pBitExt = REGION_EXTENTS (pDrawable->pScreen, &pPixmapPriv->bitRegion); + + if (pExt->x1 < pBitExt->x2 && + pExt->y1 < pBitExt->y2 && + pExt->x2 > pBitExt->x1 && + pExt->y2 > pBitExt->y1) + { + while (nBox--) + { + if (pBox->x1 < pBitExt->x2 && + pBox->y1 < pBitExt->y2 && + pBox->x2 > pBitExt->x1 && + pBox->y2 > pBitExt->y1) + { + REGION_UNINIT (pDrawable->pScreen, + &pPixmapPriv->bitRegion); + REGION_INIT (pDrawable->pScreen, &pPixmapPriv->bitRegion, + NullBox, 0); + pPixmapPriv->allBits = FALSE; + return; + } + + pBox++; + } + } + } +} + +void +xglAddCurrentBitDamage (DrawablePtr pDrawable) +{ + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + if (REGION_NOTEMPTY (pDrawable->pScreen, &pPixmapPriv->bitRegion)) + { + BoxPtr pBitExt; + + pBitExt = REGION_EXTENTS (pDrawable->pScreen, &pPixmapPriv->bitRegion); + + if (pPixmapPriv->damageBox.x1 < pBitExt->x2 && + pPixmapPriv->damageBox.y1 < pBitExt->y2 && + pPixmapPriv->damageBox.x2 > pBitExt->x1 && + pPixmapPriv->damageBox.y2 > pBitExt->y1) + { + REGION_UNINIT (pDrawable->pScreen, &pPixmapPriv->bitRegion); + REGION_INIT (pDrawable->pScreen, &pPixmapPriv->bitRegion, + NullBox, 0); + pPixmapPriv->allBits = FALSE; + } + } + + pPixmapPriv->damageBox = miEmptyBox; +} |