void miWindowExposures(WindowPtr pWin, RegionPtr prgn) { RegionPtr exposures = prgn; if (prgn && !RegionNil(prgn)) { RegionRec expRec; int clientInterested = (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask; if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) { /* * If we have LOTS of rectangles, we decide to take the extents * and force an exposure on that. This should require much less * work overall, on both client and server. This is cheating, but * isn't prohibited by the protocol ("spontaneous combustion" :-). */ BoxRec box = *RegionExtents(prgn); exposures = &expRec; RegionInit(exposures, &box, 1); RegionReset(prgn, &box); /* miPaintWindow doesn't clip, so we have to */ RegionIntersect(prgn, prgn, &pWin->clipList); } pWin->drawable.pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND); if (clientInterested) miSendExposures(pWin, exposures, pWin->drawable.x, pWin->drawable.y); if (exposures == &expRec) RegionUninit(exposures); RegionEmpty(prgn); } }
int ProcXFixesFetchRegion (ClientPtr client) { RegionPtr pRegion; xXFixesFetchRegionReply *reply; xRectangle *pRect; BoxPtr pExtent; BoxPtr pBox; int i, nBox; REQUEST(xXFixesFetchRegionReq); REQUEST_SIZE_MATCH(xXFixesFetchRegionReq); VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess); pExtent = RegionExtents(pRegion); pBox = RegionRects (pRegion); nBox = RegionNumRects (pRegion); reply = malloc(sizeof (xXFixesFetchRegionReply) + nBox * sizeof (xRectangle)); if (!reply) return BadAlloc; reply->type = X_Reply; reply->sequenceNumber = client->sequence; reply->length = nBox << 1; reply->x = pExtent->x1; reply->y = pExtent->y1; reply->width = pExtent->x2 - pExtent->x1; reply->height = pExtent->y2 - pExtent->y1; pRect = (xRectangle *) (reply + 1); for (i = 0; i < nBox; i++) { pRect[i].x = pBox[i].x1; pRect[i].y = pBox[i].y1; pRect[i].width = pBox[i].x2 - pBox[i].x1; pRect[i].height = pBox[i].y2 - pBox[i].y1; } if (client->swapped) { int n; swaps (&reply->sequenceNumber, n); swapl (&reply->length, n); swaps (&reply->x, n); swaps (&reply->y, n); swaps (&reply->width, n); swaps (&reply->height, n); SwapShorts ((INT16 *) pRect, nBox * 4); } (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) + nBox * sizeof (xRectangle), (char *) reply); free(reply); return Success; }
static Bool localResizeOffscreenLinear(FBLinearPtr resize, int length) { FBManagerPtr offman; FBLinearLinkPtr pLink; ScreenPtr pScreen = resize->pScreen; offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey); pLink = offman->LinearAreas; if (!pLink) return FALSE; while (&(pLink->linear) != resize) { pLink = pLink->next; if (!pLink) return FALSE; } /* This could actually be alot smarter and try to move allocations from XY to linear when available. For now if it was XY, we keep it XY */ if (pLink->area) { /* really an XY area */ BoxPtr extents; int pitch, w, h; extents = RegionExtents(offman->InitialBoxes); pitch = extents->x2 - extents->x1; if (length < pitch) { /* special case */ w = length; h = 1; } else { w = pitch; h = (length + pitch - 1) / pitch; } if (localResizeOffscreenArea(pLink->area, w, h)) { resize->size = h * w; resize->offset = (pitch * pLink->area->box.y1) + pLink->area->box.x1; return TRUE; } } else { /* TODO!!!! resize the linear area */ } return FALSE; }
RegionPtr XFixesRegionCopy(RegionPtr pRegion) { RegionPtr pNew = RegionCreate(RegionExtents(pRegion), RegionNumRects(pRegion)); if (!pNew) return 0; if (!RegionCopy(pNew, pRegion)) { RegionDestroy(pNew); return 0; } return pNew; }
int ProcXFixesRegionExtents (ClientPtr client) { RegionPtr pSource, pDestination; REQUEST(xXFixesRegionExtentsReq); REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq); VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); RegionReset(pDestination, RegionExtents(pSource)); return Success; }
static int ephyrPutVideo(KdScreenInfo * a_info, DrawablePtr a_drawable, short a_vid_x, short a_vid_y, short a_drw_x, short a_drw_y, short a_vid_w, short a_vid_h, short a_drw_w, short a_drw_h, RegionPtr a_clipping_region, pointer a_port_priv) { EphyrPortPriv *port_priv = a_port_priv; BoxRec clipped_area, dst_box; int result = BadImplementation; int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0; EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, BadValue); EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue); EPHYR_LOG("enter\n"); dst_box.x1 = a_drw_x; dst_box.x2 = a_drw_x + a_drw_w; dst_box.y1 = a_drw_y; dst_box.y2 = a_drw_y + a_drw_h; if (!DoSimpleClip(&dst_box, RegionExtents(a_clipping_region), &clipped_area)) { EPHYR_LOG_ERROR("failed to simple clip\n"); goto out; } drw_x = clipped_area.x1; drw_y = clipped_area.y1; drw_w = clipped_area.x2 - clipped_area.x1; drw_h = clipped_area.y2 - clipped_area.y1; if (!ephyrHostXVPutVideo(a_info->pScreen->myNum, port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { EPHYR_LOG_ERROR("ephyrHostXVPutVideo() failed\n"); goto out; } result = Success; out: EPHYR_LOG("leave\n"); return result; }
static Bool localQueryLargestOffscreenLinear(ScreenPtr pScreen, int *size, int gran, int priority) { FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey); FBLinearLinkPtr pLink; FBLinearLinkPtr pLinkRet; *size = 0; pLink = offman->LinearAreas; if (pLink && !pLink->area) { pLinkRet = pLink; while (pLink) { if (pLink->free) { if (pLink->linear.size > pLinkRet->linear.size) pLinkRet = pLink; } pLink = pLink->next; } if (pLinkRet->free) { *size = pLinkRet->linear.size; return TRUE; } } else { int w, h; if (localQueryLargestOffscreenArea(pScreen, &w, &h, gran, FAVOR_WIDTH_THEN_AREA, priority)) { FBManagerPtr offman; BoxPtr extents; offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey); extents = RegionExtents(offman->InitialBoxes); if ((extents->x2 - extents->x1) == w) *size = w * h; return TRUE; } } return FALSE; }
FBAreaPtr xf86AllocateLinearOffscreenArea(ScreenPtr pScreen, int length, int gran, MoveAreaCallbackProcPtr moveCB, RemoveAreaCallbackProcPtr removeCB, void *privData) { FBManagerFuncsPtr funcs; FBManagerPtr offman; BoxPtr extents; int w, h; if (xf86FBManagerKey == NULL) return NULL; if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBManagerKey))) return NULL; offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey); extents = RegionExtents(offman->InitialBoxes); w = extents->x2 - extents->x1; if (gran > 1) { if (gran > w) return NULL; if (w % gran) length += gran - 1; } if (length <= w) { /* special case */ h = 1; w = length; } else { h = (length + w - 1) / w; } return (*funcs->AllocateOffscreenArea) (pScreen, w, h, gran, moveCB, removeCB, privData); }
static void DamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure) { DamageExtPtr pDamageExt = closure; switch (pDamageExt->level) { case DamageReportRawRegion: case DamageReportDeltaRegion: DamageExtNotify (pDamageExt, RegionRects(pRegion), RegionNumRects(pRegion)); break; case DamageReportBoundingBox: DamageExtNotify (pDamageExt, RegionExtents(pRegion), 1); break; case DamageReportNonEmpty: DamageExtNotify (pDamageExt, NullBox, 0); break; case DamageReportNone: break; } }
static bool fbGlyphIn(GCPtr gc, int x, int y, int width, int height) { BoxRec box; BoxPtr extents = RegionExtents(gc->pCompositeClip); /* * Check extents by hand to avoid 16 bit overflows */ if (x < (int) extents->x1 || (int) extents->x2 < x + width) return FALSE; if (y < (int) extents->y1 || (int) extents->y2 < y + height) return FALSE; box.x1 = x; box.x2 = x + width; box.y1 = y; box.y2 = y + height; return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN; }
Bool fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height) { BoxRec box; BoxPtr pExtents = RegionExtents(pRegion); /* * Check extents by hand to avoid 16 bit overflows */ if (x < (int) pExtents->x1) return FALSE; if ((int) pExtents->x2 < x + width) return FALSE; if (y < (int) pExtents->y1) return FALSE; if ((int) pExtents->y2 < y + height) return FALSE; box.x1 = x; box.x2 = x + width; box.y1 = y; box.y2 = y + height; return RegionContainsRect(pRegion, &box) == rgnIN; }
static void winShadowUpdateGDI (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); DWORD dwBox = RegionNumRects (damage); BoxPtr pBox = RegionRects (damage); int x, y, w, h; HRGN hrgnTemp = NULL, hrgnCombined = NULL; #ifdef XWIN_UPDATESTATS static DWORD s_dwNonUnitRegions = 0; static DWORD s_dwTotalUpdates = 0; static DWORD s_dwTotalBoxes = 0; #endif BoxPtr pBoxExtents = RegionExtents(damage); /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; #ifdef XWIN_UPDATESTATS ++s_dwTotalUpdates; s_dwTotalBoxes += dwBox; if (dwBox != 1) { ++s_dwNonUnitRegions; ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox); } if ((s_dwTotalUpdates % 100) == 0) ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d " "nu: %d tu: %d\n", (s_dwNonUnitRegions * 100) / s_dwTotalUpdates, s_dwTotalBoxes / s_dwTotalUpdates, s_dwNonUnitRegions, s_dwTotalUpdates); #endif /* XWIN_UPDATESTATS */ /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (!pScreenInfo->fMultiWindow && (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes)) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* * Calculate x offset, y offset, width, and height for * current damage box */ x = pBox->x1; y = pBox->y1; w = pBox->x2 - pBox->x1; h = pBox->y2 - pBox->y1; BitBlt (pScreenPriv->hdcScreen, x, y, w, h, pScreenPriv->hdcShadow, x, y, SRCCOPY); /* Get a pointer to the next box */ ++pBox; } } else if (!pScreenInfo->fMultiWindow) { /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; /* * Blit the shadow buffer to the screen, * constrained to the clipping region. */ BitBlt (pScreenPriv->hdcScreen, pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2 - pBoxExtents->x1, pBoxExtents->y2 - pBoxExtents->y1, pScreenPriv->hdcShadow, pBoxExtents->x1, pBoxExtents->y1, SRCCOPY); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } #ifdef XWIN_MULTIWINDOW /* Redraw all multiwindow windows */ if (pScreenInfo->fMultiWindow) EnumThreadWindows (g_dwCurrentThreadID, winRedrawDamagedWindowShadowGDI, (LPARAM)pBoxExtents); #endif }
static Bool _glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure, Bool fallback) { PixmapPtr dst_pixmap, src_pixmap; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; BoxPtr extent; RegionRec region; int src_x_off, src_y_off, dst_x_off, dst_y_off; Bool ok = FALSE; int force_clip = 0; if (nbox == 0) return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); glamor_priv = glamor_get_screen_private(dst->pScreen); DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", box[0].x1, box[0].y1, box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, dx, dy, src_pixmap, dst_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) goto fall_back; if (gc) { if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fall_back; dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { glamor_put_dispatch(glamor_priv); goto fail_noregion; } glamor_put_dispatch(glamor_priv); } if (!src_pixmap_priv) { glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); } glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); RegionInitBoxes(®ion, box, nbox); extent = RegionExtents(®ion); if (!glamor_check_fbo_size(glamor_priv, extent->x2 - extent->x1, extent->y2 - extent->y1) && (src_pixmap_priv->type == GLAMOR_MEMORY || (src_pixmap_priv == dst_pixmap_priv))) { force_clip = 1; } if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { glamor_pixmap_clipped_regions *clipped_dst_regions; int n_dst_region, i, j; PixmapPtr temp_source_pixmap; glamor_pixmap_private *temp_source_priv = NULL; RegionTranslate(®ion, dst_x_off, dst_y_off); if (!force_clip) clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, ®ion, &n_dst_region, 0, reverse, upsidedown); else clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, &n_dst_region, glamor_priv->max_fbo_size, glamor_priv->max_fbo_size, reverse, upsidedown); for(i = 0; i < n_dst_region; i++) { int n_src_region; glamor_pixmap_clipped_regions *clipped_src_regions; BoxPtr current_boxes; int n_current_boxes; SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx); temp_source_pixmap = NULL; if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionTranslate(clipped_dst_regions[i].region, -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, &n_src_region, 0, reverse, upsidedown); DEBUGF("Source is large pixmap.\n"); for (j = 0; j < n_src_region; j++) { if (src_pixmap_priv != dst_pixmap_priv) SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); else if (src_pixmap_priv == dst_pixmap_priv && clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx) { /* source and the dest are the same, but need different block_idx. * we create a empty pixmap and fill the required source fbo and box to * it. It's a little hacky, but avoid extra copy. */ temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0, src->depth, 0); if (!temp_source_pixmap) { ok = FALSE; goto fail; } src->pScreen->ModifyPixmapHeader(temp_source_pixmap, src_pixmap->drawable.width, src_pixmap->drawable.height, 0, 0, src_pixmap->devKind, NULL); temp_source_priv = glamor_get_pixmap_private(temp_source_pixmap); *temp_source_priv = *src_pixmap_priv; temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.pixmap = temp_source_pixmap; } assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); RegionTranslate(clipped_src_regions[j].region, -src_x_off - dx, -src_y_off - dy); current_boxes = RegionRects(clipped_src_regions[j].region); n_current_boxes = RegionNumRects(clipped_src_regions[j].region); DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx, clipped_src_regions[j].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); if (!temp_source_pixmap) ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); else { ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->base.fbo = NULL; glamor_destroy_pixmap(temp_source_pixmap); temp_source_pixmap = NULL; } RegionDestroy(clipped_src_regions[j].region); if (!ok) { assert(0); goto fail; } } if (n_src_region == 0) ok = TRUE; free(clipped_src_regions); } else { RegionTranslate(clipped_dst_regions[i].region, - dst_x_off, - dst_y_off); current_boxes = RegionRects(clipped_dst_regions[i].region); n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); DEBUGF("dest pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); } RegionDestroy(clipped_dst_regions[i].region); } if (n_dst_region == 0) ok = TRUE; free(clipped_dst_regions); } else { ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } fail: RegionUninit(®ion); fail_noregion: dispatch = glamor_get_dispatch(glamor_priv); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); if (ok) return TRUE; fall_back: if (!fallback && glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) goto done; if (src_pixmap_priv->type == GLAMOR_DRM_ONLY || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { LogMessage(X_WARNING, "Access a DRM only pixmap is not allowed within glamor.\n"); return TRUE; } glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO) && glamor_prepare_access_gc(gc)) { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } glamor_finish_access_gc(gc); glamor_finish_access(src); glamor_finish_access(dst); ok = TRUE; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); return ok; }
RegionPtr rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; RegionRec reg1; int num_clips; int cd; int j; int can_do_screen_blt; int got_id; int dirty_type; int post_process; int reset_surface; struct image_data id; BoxRec box; BoxPtr pbox; PixmapPtr pSrcPixmap; PixmapPtr pDstPixmap; rdpPixmapRec *pSrcPriv; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; WindowPtr pDstWnd; WindowPtr pSrcWnd; LLOGLN(10, ("rdpCopyArea: x %d y %d w %d h %d", dstx, dsty, w, h)); if (pSrc->type == DRAWABLE_WINDOW) { pSrcWnd = (WindowPtr)pSrc; if (pSrcWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { return rdpCopyAreaWndToWnd(pSrcWnd, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 1")); } } } } if (pSrc->type == DRAWABLE_PIXMAP) { pSrcPixmap = (PixmapPtr)pSrc; pSrcPriv = GETPIXPRIV(pSrcPixmap); if (xrdp_is_os(pSrcPixmap, pSrcPriv)) { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); rdpup_check_dirty(pSrcPixmap, pSrcPriv); return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { if (g_can_do_pix_to_pix) { rdpup_check_dirty(pSrcPixmap, pSrcPriv); rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 4")); } } } else { LLOGLN(10, ("rdpCopyArea: 2")); } } /* do original call */ rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLL; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { LLOGLN(10, ("rdpCopyArea: 3")); } } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return rv; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, 1); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_end_update(); } } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1); RegionUninit(&box_reg); } else if (got_id) { rdpup_begin_update(); box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); rdpup_end_update(); } } } RegionUninit(&clip_reg); if (reset_surface) { rdpup_switch_os_surface(-1); } return rv; }
static FBLinearPtr localAllocateOffscreenLinear(ScreenPtr pScreen, int length, int gran, MoveLinearCallbackProcPtr moveCB, RemoveLinearCallbackProcPtr removeCB, void *privData) { FBManagerPtr offman; FBLinearLinkPtr link; FBAreaPtr area; FBLinearPtr linear = NULL; BoxPtr extents; int w, h, pitch; offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey); /* Try to allocate from linear memory first...... */ DebugF("ALLOCATING LINEAR\n"); if ((linear = AllocateLinear(offman, length, gran, privData))) return linear; DebugF("NOPE, ALLOCATING AREA\n"); if (!(link = malloc(sizeof(FBLinearLink)))) return NULL; /* No linear available, so try and pinch some from the XY areas */ extents = RegionExtents(offman->InitialBoxes); pitch = extents->x2 - extents->x1; if (gran > 1) { if (gran > pitch) { /* we can't match the specified alignment with XY allocations */ free(link); return NULL; } if (pitch % gran) { /* pitch and granularity aren't a perfect match, let's allocate * a bit more so we can align later on */ length += gran - 1; } } if (length < pitch) { /* special case */ w = length; h = 1; } else { w = pitch; h = (length + pitch - 1) / pitch; } if ((area = localAllocateOffscreenArea(pScreen, w, h, gran, moveCB ? LinearMoveCBWrapper : NULL, removeCB ? LinearRemoveCBWrapper : NULL, privData))) { link->area = area; link->free = 0; link->next = offman->LinearAreas; offman->LinearAreas = link; linear = &(link->linear); linear->pScreen = pScreen; linear->size = h * w; linear->offset = (pitch * area->box.y1) + area->box.x1; if (gran > 1) linear->offset = ((linear->offset + gran - 1) / gran) * gran; linear->granularity = gran; linear->MoveLinearCallback = moveCB; linear->RemoveLinearCallback = removeCB; linear->devPrivate.ptr = privData; } else free(link); DumpDebug(offman->LinearAreas); return linear; }
RegionPtr rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; int cd; int num_clips; int j; int post_process; BoxRec box; BoxPtr pbox; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; LLOGLN(10, ("rdpCopyPlane:")); /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); post_process = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr) pDst; pDstPriv = GETPIXPRIV(pDstPixmap); } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr) pDst; if (pDstWnd->viewable) { post_process = 1; } } } if (!post_process) return rv; RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { rdp_send_area_update(pDst->x + dstx, pDst->y + dsty, w, h); } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdp_send_area_update(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdp_send_area_update(pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); } } RegionUninit(&clip_reg); return rv; }
Bool miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin) { BoxPtr box; WindowPtr pChild, pLast; Bool anyMarked = FALSE; MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; /* single layered systems are easy */ if (ppLayerWin) *ppLayerWin = pWin; if (pWin == pFirst) { /* Blindly mark pWin and all of its inferiors. This is a slight * overkill if there are mapped windows that outside pWin's border, * but it's better than wasting time on RectIn checks. */ pChild = pWin; while (1) { if (pChild->viewable) { if (RegionBroken(&pChild->winSize)) SetWinSize(pChild); if (RegionBroken(&pChild->borderSize)) SetBorderSize(pChild); (*MarkWindow) (pChild); if (pChild->firstChild) { pChild = pChild->firstChild; continue; } } while (!pChild->nextSib && (pChild != pWin)) pChild = pChild->parent; if (pChild == pWin) break; pChild = pChild->nextSib; } anyMarked = TRUE; pFirst = pFirst->nextSib; } if ((pChild = pFirst)) { box = RegionExtents(&pWin->borderSize); pLast = pChild->parent->lastChild; while (1) { if (pChild->viewable) { if (RegionBroken(&pChild->winSize)) SetWinSize(pChild); if (RegionBroken(&pChild->borderSize)) SetBorderSize(pChild); if (RegionContainsRect(&pChild->borderSize, box)) { (*MarkWindow) (pChild); anyMarked = TRUE; if (pChild->firstChild) { pChild = pChild->firstChild; continue; } } } while (!pChild->nextSib && (pChild != pLast)) pChild = pChild->parent; if (pChild == pLast) break; pChild = pChild->nextSib; } } if (anyMarked) (*MarkWindow) (pWin->parent); return anyMarked; }
RegionPtr miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { RegionPtr prgnSrcClip; /* drawable-relative source clip */ RegionRec rgnSrcRec; RegionPtr prgnDstClip; /* drawable-relative dest clip */ RegionRec rgnDstRec; BoxRec srcBox; /* unclipped source */ RegionRec rgnExposed; /* exposed region, calculated source- relative, made dst relative to intersect with visible parts of dest and send events to client, and then screen relative to paint the window background */ WindowPtr pSrcWin; BoxRec expBox = { 0, }; Bool extents; /* avoid work if we can */ if (!pGC->graphicsExposures && pDstDrawable->type == DRAWABLE_PIXMAP) return NULL; srcBox.x1 = srcx; srcBox.y1 = srcy; srcBox.x2 = srcx + width; srcBox.y2 = srcy + height; if (pSrcDrawable->type != DRAWABLE_PIXMAP) { BoxRec TsrcBox; TsrcBox.x1 = srcx + pSrcDrawable->x; TsrcBox.y1 = srcy + pSrcDrawable->y; TsrcBox.x2 = TsrcBox.x1 + width; TsrcBox.y2 = TsrcBox.y1 + height; pSrcWin = (WindowPtr) pSrcDrawable; if (pGC->subWindowMode == IncludeInferiors) { prgnSrcClip = NotClippedByChildren(pSrcWin); if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) { RegionDestroy(prgnSrcClip); return NULL; } } else { if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN) return NULL; prgnSrcClip = &rgnSrcRec; RegionNull(prgnSrcClip); RegionCopy(prgnSrcClip, &pSrcWin->clipList); } RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y); } else { BoxRec box; if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && (srcBox.x2 <= pSrcDrawable->width) && (srcBox.y2 <= pSrcDrawable->height)) return NULL; box.x1 = 0; box.y1 = 0; box.x2 = pSrcDrawable->width; box.y2 = pSrcDrawable->height; prgnSrcClip = &rgnSrcRec; RegionInit(prgnSrcClip, &box, 1); pSrcWin = NULL; } if (pDstDrawable == pSrcDrawable) { prgnDstClip = prgnSrcClip; } else if (pDstDrawable->type != DRAWABLE_PIXMAP) { if (pGC->subWindowMode == IncludeInferiors) { prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable); } else { prgnDstClip = &rgnDstRec; RegionNull(prgnDstClip); RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList); } RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y); } else { BoxRec box; box.x1 = 0; box.y1 = 0; box.x2 = pDstDrawable->width; box.y2 = pDstDrawable->height; prgnDstClip = &rgnDstRec; RegionInit(prgnDstClip, &box, 1); } /* drawable-relative source region */ RegionInit(&rgnExposed, &srcBox, 1); /* now get the hidden parts of the source box */ RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip); /* move them over the destination */ RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy); /* intersect with visible areas of dest */ RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip); /* intersect with client clip region. */ if (pGC->clientClip) RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip); /* * If we have LOTS of rectangles, we decide to take the extents * and force an exposure on that. This should require much less * work overall, on both client and server. This is cheating, but * isn't prohibited by the protocol ("spontaneous combustion" :-) * for windows. */ extents = pGC->graphicsExposures && (RegionNumRects(&rgnExposed) > RECTLIMIT) && (pDstDrawable->type != DRAWABLE_PIXMAP); if (pSrcWin) { RegionPtr region; if (!(region = wClipShape(pSrcWin))) region = wBoundingShape(pSrcWin); /* * If you try to CopyArea the extents of a shaped window, compacting the * exposed region will undo all our work! */ if (extents && pSrcWin && region && (RegionContainsRect(region, &srcBox) != rgnIN)) extents = FALSE; } if (extents) { expBox = *RegionExtents(&rgnExposed); RegionReset(&rgnExposed, &expBox); } if ((pDstDrawable->type != DRAWABLE_PIXMAP) && (((WindowPtr) pDstDrawable)->backgroundState != None)) { WindowPtr pWin = (WindowPtr) pDstDrawable; /* make the exposed area screen-relative */ RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y); if (extents) { /* PaintWindow doesn't clip, so we have to */ RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList); } pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable, &rgnExposed, PW_BACKGROUND); if (extents) { RegionReset(&rgnExposed, &expBox); } else RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y); } if (prgnDstClip == &rgnDstRec) { RegionUninit(prgnDstClip); } else if (prgnDstClip != prgnSrcClip) { RegionDestroy(prgnDstClip); } if (prgnSrcClip == &rgnSrcRec) { RegionUninit(prgnSrcClip); } else { RegionDestroy(prgnSrcClip); } if (pGC->graphicsExposures) { /* don't look */ RegionPtr exposed = RegionCreate(NullBox, 0); *exposed = rgnExposed; return exposed; } else { RegionUninit(&rgnExposed); return NULL; } }
RegionPtr rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; int cd; int num_clips; int j; int got_id; BoxRec box; BoxPtr pbox; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpCopyPlane:")); /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); got_id = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (XRDP_IS_OS(pDstPriv)) { rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { rdpup_get_screen_image_rect(&id); got_id = 1; } } } if (!got_id) { return rv; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_end_update(); } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { rdpup_begin_update(); box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); rdpup_end_update(); } } RegionUninit(&clip_reg); return rv; }
static void cwCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; SCREEN_PROLOGUE(pScreen, CopyWindow); if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) { (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); } else { GCPtr pGC; BoxPtr pExtents; int x_off, y_off; int dx, dy; PixmapPtr pBackingPixmap; RegionPtr pClip; int src_x, src_y, dst_x, dst_y, w, h; dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; pExtents = RegionExtents(prgnSrc); pBackingPixmap = (PixmapPtr) cwGetBackingDrawable((DrawablePtr)pWin, &x_off, &y_off); src_x = pExtents->x1 - pBackingPixmap->screen_x; src_y = pExtents->y1 - pBackingPixmap->screen_y; w = pExtents->x2 - pExtents->x1; h = pExtents->y2 - pExtents->y1; dst_x = src_x - dx; dst_y = src_y - dy; /* Translate region (as required by API) */ RegionTranslate(prgnSrc, -dx, -dy); pGC = GetScratchGC(pBackingPixmap->drawable.depth, pScreen); /* * Copy region to GC as clip, aligning as dest clip */ pClip = RegionCreate(NULL, 0); RegionIntersect(pClip, &pWin->borderClip, prgnSrc); RegionTranslate(pClip, -pBackingPixmap->screen_x, -pBackingPixmap->screen_y); (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); ValidateGC(&pBackingPixmap->drawable, pGC); (*pGC->ops->CopyArea) (&pBackingPixmap->drawable, &pBackingPixmap->drawable, pGC, src_x, src_y, w, h, dst_x, dst_y); (*pGC->funcs->DestroyClip) (pGC); FreeScratchGC(pGC); } SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); }
static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { ScreenPtr pScreen = pDrawable->pScreen; ExaScreenPriv(pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); ExaPixmapPriv(pPixmap); BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; int off_x, off_y; if (pExaScr->fallback_counter || pExaScr->swappedOut || pGC->fillStyle != FillSolid || pExaPixmap->accel_blocked) { ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); return; } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = NULL; exaDoMigration(pixmaps, 1, TRUE); } if (!(pPixmap = exaGetOffscreenPixmap(pDrawable, &off_x, &off_y)) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); return; } pextent = RegionExtents(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 = RegionNumRects(pClip); if (nbox == 1) { (*pExaScr->info->Solid) (pPixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); } else { pbox = RegionRects(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) { (*pExaScr->info->Solid) (pPixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); } } pbox++; } } } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pScreen); }
static int ProcShapeQueryExtents(ClientPtr client) { REQUEST(xShapeQueryExtentsReq); WindowPtr pWin; xShapeQueryExtentsReply rep; BoxRec extents, *pExtents; int rc; RegionPtr region; REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); if (rc != Success) return rc; memset(&rep, 0, sizeof(xShapeQueryExtentsReply)); rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.boundingShaped = (wBoundingShape(pWin) != 0); rep.clipShaped = (wClipShape(pWin) != 0); if ((region = wBoundingShape(pWin))) { /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ pExtents = RegionExtents(region); extents = *pExtents; } else { extents.x1 = -wBorderWidth(pWin); extents.y1 = -wBorderWidth(pWin); extents.x2 = pWin->drawable.width + wBorderWidth(pWin); extents.y2 = pWin->drawable.height + wBorderWidth(pWin); } rep.xBoundingShape = extents.x1; rep.yBoundingShape = extents.y1; rep.widthBoundingShape = extents.x2 - extents.x1; rep.heightBoundingShape = extents.y2 - extents.y1; if ((region = wClipShape(pWin))) { /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ pExtents = RegionExtents(region); extents = *pExtents; } else { extents.x1 = 0; extents.y1 = 0; extents.x2 = pWin->drawable.width; extents.y2 = pWin->drawable.height; } rep.xClipShape = extents.x1; rep.yClipShape = extents.y1; rep.widthClipShape = extents.x2 - extents.x1; rep.heightClipShape = extents.y2 - extents.y1; if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swaps(&rep.xBoundingShape); swaps(&rep.yBoundingShape); swaps(&rep.widthBoundingShape); swaps(&rep.heightBoundingShape); swaps(&rep.xClipShape); swaps(&rep.yClipShape); swaps(&rep.widthClipShape); swaps(&rep.heightClipShape); } WriteToClient(client, sizeof(xShapeQueryExtentsReply), (char *) &rep); return Success; }
int XAAGetRectClipBoxes(GCPtr pGC, BoxPtr pboxClippedBase, int nrectFill, xRectangle *prectInit) { int Right, Bottom; BoxPtr pextent, pboxClipped = pboxClippedBase; xRectangle *prect = prectInit; RegionPtr prgnClip = pGC->pCompositeClip; if (RegionNumRects(prgnClip) == 1) { pextent = RegionRects(prgnClip); while (nrectFill--) { pboxClipped->x1 = max(pextent->x1, prect->x); pboxClipped->y1 = max(pextent->y1, prect->y); Right = (int) prect->x + (int) prect->width; pboxClipped->x2 = min(pextent->x2, Right); Bottom = (int) prect->y + (int) prect->height; pboxClipped->y2 = min(pextent->y2, Bottom); prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; } } } else { pextent = RegionExtents(prgnClip); while (nrectFill--) { int n; BoxRec box, *pbox; box.x1 = max(pextent->x1, prect->x); box.y1 = max(pextent->y1, prect->y); Right = (int) prect->x + (int) prect->width; box.x2 = min(pextent->x2, Right); Bottom = (int) prect->y + (int) prect->height; box.y2 = min(pextent->y2, Bottom); prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = RegionNumRects(prgnClip); pbox = RegionRects(prgnClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while (n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if (pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; } } } } return pboxClipped - pboxClippedBase; }
void SendShapeNotify(WindowPtr pWin, int which) { ShapeEventPtr *pHead, pShapeEvent; xShapeNotifyEvent se; BoxRec extents; RegionPtr region; BYTE shaped; int rc; rc = dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id, ShapeEventType, serverClient, DixReadAccess); if (rc != Success) return; switch (which) { case ShapeBounding: region = wBoundingShape(pWin); if (region) { extents = *RegionExtents(region); shaped = xTrue; } else { extents.x1 = -wBorderWidth(pWin); extents.y1 = -wBorderWidth(pWin); extents.x2 = pWin->drawable.width + wBorderWidth(pWin); extents.y2 = pWin->drawable.height + wBorderWidth(pWin); shaped = xFalse; } break; case ShapeClip: region = wClipShape(pWin); if (region) { extents = *RegionExtents(region); shaped = xTrue; } else { extents.x1 = 0; extents.y1 = 0; extents.x2 = pWin->drawable.width; extents.y2 = pWin->drawable.height; shaped = xFalse; } break; case ShapeInput: region = wInputShape(pWin); if (region) { extents = *RegionExtents(region); shaped = xTrue; } else { extents.x1 = -wBorderWidth(pWin); extents.y1 = -wBorderWidth(pWin); extents.x2 = pWin->drawable.width + wBorderWidth(pWin); extents.y2 = pWin->drawable.height + wBorderWidth(pWin); shaped = xFalse; } break; default: return; } for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { se.type = ShapeNotify + ShapeEventBase; se.kind = which; se.window = pWin->drawable.id; se.x = extents.x1; se.y = extents.y1; se.width = extents.x2 - extents.x1; se.height = extents.y2 - extents.y1; se.time = currentTime.milliseconds; se.shaped = shaped; WriteEventsToClient(pShapeEvent->client, 1, (xEvent *) &se); } }
void XAAClipAndRenderRects(GCPtr pGC, ClipAndRenderRectsFunc BoxFunc, int nrectFill, xRectangle *prect, int xorg, int yorg) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int Right, Bottom, MaxBoxes; BoxPtr pextent, pboxClipped, pboxClippedBase; MaxBoxes = infoRec->PreAllocSize / sizeof(BoxRec); pboxClippedBase = (BoxPtr) infoRec->PreAllocMem; pboxClipped = pboxClippedBase; if (RegionNumRects(pGC->pCompositeClip) == 1) { pextent = RegionRects(pGC->pCompositeClip); while (nrectFill--) { pboxClipped->x1 = max(pextent->x1, prect->x); pboxClipped->y1 = max(pextent->y1, prect->y); Right = (int) prect->x + (int) prect->width; pboxClipped->x2 = min(pextent->x2, Right); Bottom = (int) prect->y + (int) prect->height; pboxClipped->y2 = min(pextent->y2, Bottom); prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; if (pboxClipped >= (pboxClippedBase + MaxBoxes)) { (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg); pboxClipped = pboxClippedBase; } } } } else { pextent = RegionExtents(pGC->pCompositeClip); while (nrectFill--) { int n; BoxRec box, *pbox; box.x1 = max(pextent->x1, prect->x); box.y1 = max(pextent->y1, prect->y); Right = (int) prect->x + (int) prect->width; box.x2 = min(pextent->x2, Right); Bottom = (int) prect->y + (int) prect->height; box.y2 = min(pextent->y2, Bottom); prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = RegionNumRects(pGC->pCompositeClip); pbox = RegionRects(pGC->pCompositeClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while (n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if (pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; if (pboxClipped >= (pboxClippedBase + MaxBoxes)) { (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg); pboxClipped = pboxClippedBase; } } } } } if (pboxClipped != pboxClippedBase) (*BoxFunc) (pGC, pboxClipped - pboxClippedBase, pboxClippedBase, xorg, yorg); }
static void winShadowUpdateDD (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); HRESULT ddrval = DD_OK; RECT rcDest, rcSrc; POINT ptOrigin; DWORD dwBox = RegionNumRects (damage); BoxPtr pBox = RegionRects (damage); HRGN hrgnTemp = NULL, hrgnCombined = NULL; /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; /* Get the origin of the window in the screen coords */ ptOrigin.x = pScreenInfo->dwXOffset; ptOrigin.y = pScreenInfo->dwYOffset; MapWindowPoints (pScreenPriv->hwndScreen, HWND_DESKTOP, (LPPOINT)&ptOrigin, 1); /* Unlock the shadow surface, so we can blit */ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL); if (FAILED (ddrval)) { ErrorF ("winShadowUpdateDD - Unlock failed\n"); return; } /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* Assign damage box to source rectangle */ rcSrc.left = pBox->x1; rcSrc.top = pBox->y1; rcSrc.right = pBox->x2; rcSrc.bottom = pBox->y2; /* Calculate destination rectange */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Blit the damaged areas */ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, &rcDest, pScreenPriv->pddsShadow, &rcSrc, DDBLT_WAIT, NULL); /* Get a pointer to the next box */ ++pBox; } } else { BoxPtr pBoxExtents = RegionExtents(damage); /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; /* Calculating a bounding box for the source is easy */ rcSrc.left = pBoxExtents->x1; rcSrc.top = pBoxExtents->y1; rcSrc.right = pBoxExtents->x2; rcSrc.bottom = pBoxExtents->y2; /* Calculating a bounding box for the destination is trickier */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Our Blt should be clipped to the invalidated region */ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, &rcDest, pScreenPriv->pddsShadow, &rcSrc, DDBLT_WAIT, NULL); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } /* Relock the shadow surface */ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, NULL, pScreenPriv->pddsdShadow, DDLOCK_WAIT, NULL); if (FAILED (ddrval)) { ErrorF ("winShadowUpdateDD - Lock failed\n"); return; } /* Has our memory pointer changed? */ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface) { ErrorF ("winShadowUpdateDD - Memory location of the shadow " "surface has changed, trying to update the root window " "pixmap header to point to the new address. If you get " "this message and "PROJECT_NAME" freezes or crashes " "after this message then send a problem report and your " "%s file to " BUILDERADDR "\n", g_pszLogFile); /* Location of shadow framebuffer has changed */ pScreenInfo->pfb = pScreenPriv->pddsdShadow->lpSurface; /* Update the screen pixmap */ if (!(*pScreen->ModifyPixmapHeader)(pScreen->devPrivate, pScreen->width, pScreen->height, pScreen->rootDepth, BitsPerPixel (pScreen->rootDepth), PixmapBytePad (pScreenInfo->dwStride, pScreenInfo->dwBPP), pScreenInfo->pfb)) { ErrorF ("winShadowUpdateDD - Bits changed, could not " "notify fb.\n"); return; } } }
static void winShadowUpdateDDNL (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); HRESULT ddrval = DD_OK; RECT rcDest, rcSrc; POINT ptOrigin; DWORD dwBox = RegionNumRects (damage); BoxPtr pBox = RegionRects (damage); HRGN hrgnTemp = NULL, hrgnCombined = NULL; /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; /* Return immediately if we didn't get needed surfaces */ if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4) return; /* Get the origin of the window in the screen coords */ ptOrigin.x = pScreenInfo->dwXOffset; ptOrigin.y = pScreenInfo->dwYOffset; MapWindowPoints (pScreenPriv->hwndScreen, HWND_DESKTOP, (LPPOINT)&ptOrigin, 1); /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* Assign damage box to source rectangle */ rcSrc.left = pBox->x1; rcSrc.top = pBox->y1; rcSrc.right = pBox->x2; rcSrc.bottom = pBox->y2; /* Calculate destination rectangle */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Blit the damaged areas */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); if (FAILED (ddrval)) { static int s_iFailCount = 0; if (s_iFailCount < FAIL_MSG_MAX_BLT) { ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () " "failed: %08x\n", (unsigned int) ddrval); ++s_iFailCount; if (s_iFailCount == FAIL_MSG_MAX_BLT) { ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt " "failure message maximum (%d) reached. No " "more failure messages will be printed.\n", FAIL_MSG_MAX_BLT); } } } /* Get a pointer to the next box */ ++pBox; } } else { BoxPtr pBoxExtents = RegionExtents(damage); /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; #if CYGDEBUG winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, pBoxExtents->y2); #endif /* Calculating a bounding box for the source is easy */ rcSrc.left = pBoxExtents->x1; rcSrc.top = pBoxExtents->y1; rcSrc.right = pBoxExtents->x2; rcSrc.bottom = pBoxExtents->y2; /* Calculating a bounding box for the destination is trickier */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Our Blt should be clipped to the invalidated region */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } }
/* See Porting Layer Definition - p. 54 */ void winFillSpansNativeGDI(DrawablePtr pDrawable, GCPtr pGC, int iSpans, DDXPointPtr pPoints, int *piWidths, int fSorted) { winGCPriv(pGC); HBITMAP hbmpOrig = NULL, hbmpOrigStipple = NULL; HBITMAP hPenOrig = NULL; HBITMAP hBitmap = NULL; PixmapPtr pPixmap = NULL; winPrivPixmapPtr pPixmapPriv = NULL; PixmapPtr pStipple = NULL; winPrivPixmapPtr pStipplePriv = NULL; PixmapPtr pTile = NULL; winPrivPixmapPtr pTilePriv = NULL; HDC hdcStipple = NULL, hdcTile = NULL; HPEN hPen = NULL; int iX; int fg, bg; RegionPtr pClip = pGC->pCompositeClip; BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; HRGN hrgn = NULL, combined = NULL; nbox = RegionNumRects(pClip); pbox = RegionRects(pClip); if (!nbox) return; combined = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2); nbox--; pbox++; while (nbox--) { hrgn = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2); CombineRgn(combined, combined, hrgn, RGN_OR); DeleteObject(hrgn); hrgn = NULL; pbox++; } pextent = RegionExtents(pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; /* Branch on the type of drawable we have */ switch (pDrawable->type) { case DRAWABLE_PIXMAP: SelectClipRgn(pGCPriv->hdcMem, combined); DeleteObject(combined); combined = NULL; /* Get a pixmap pointer from the drawable pointer, and fetch privates */ pPixmap = (PixmapPtr) pDrawable; pPixmapPriv = winGetPixmapPriv(pPixmap); /* Select the drawable pixmap into memory hdc */ hbmpOrig = SelectObject(pGCPriv->hdcMem, pPixmapPriv->hBitmap); if (hbmpOrig == NULL) FatalError("winFillSpans - DRAWABLE_PIXMAP - " "SelectObject () failed on\n\tpPixmapPriv->hBitmap: " "%08x\n", (unsigned int) pPixmapPriv->hBitmap); /* Branch on the fill type */ switch (pGC->fillStyle) { case FillSolid: ROP16(pGCPriv->hdcMem, pGC->alu); if (pDrawable->depth == 1) { if (pGC->fgPixel == 0) hPenOrig = SelectObject(pGCPriv->hdcMem, GetStockObject(BLACK_PEN)); else hPenOrig = SelectObject(pGCPriv->hdcMem, GetStockObject(WHITE_PEN)); } else { fg = pGC->fgPixel; TRANSLATE_COLOR(fg); hPen = CreatePen(PS_SOLID, 0, fg); hPenOrig = SelectObject(pGCPriv->hdcMem, hPen); } while (iSpans--) { fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; MoveToEx(pGCPriv->hdcMem, fullX1, fullY1, NULL); LineTo(pGCPriv->hdcMem, fullX2, fullY1); } SetROP2(pGCPriv->hdcMem, R2_COPYPEN); /* Give back the Pen */ SelectObject(pGCPriv->hdcMem, hPenOrig); if (pDrawable->depth != 1) DeleteObject(hPen); break; case FillOpaqueStippled: pStipple = pGC->stipple; pStipplePriv = winGetPixmapPriv(pStipple); /* Create a device-dependent bitmap for the stipple */ hBitmap = CreateDIBitmap(pGCPriv->hdcMem, (BITMAPINFOHEADER *) pStipplePriv->pbmih, CBM_INIT, pStipplePriv->pbBits, (BITMAPINFO *) pStipplePriv->pbmih, DIB_RGB_COLORS); /* Create a memory DC to hold the stipple */ hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem); /* Select the stipple bitmap into the stipple DC */ hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); if (hbmpOrigStipple == NULL) FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " "SelectObject () failed on hbmpOrigStipple\n"); /* Make a temporary copy of the foreground and background colors */ bg = pGC->bgPixel; fg = pGC->fgPixel; /* Translate the depth-dependent colors to Win32 COLORREFs */ TRANSLATE_COLOR(fg); TRANSLATE_COLOR(bg); SetTextColor(pGCPriv->hdcMem, fg); SetBkColor(pGCPriv->hdcMem, bg); while (iSpans--) { int width = pStipple->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pStipple->drawable.width) > fullX2) width = fullX2 - iX; else width = pStipple->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pStipple->drawable.width) - pStipple->drawable.width)) % pStipple->drawable.width; else xoffset = 0; if (xoffset + width > pStipple->drawable.width) width = pStipple->drawable.width - xoffset; BitBlt(pGCPriv->hdcMem, iX, fullY1, width, 1, hdcStipple, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pStipple->drawable.height) - pStipple->drawable.height)) % pStipple->drawable.height, g_copyROP[pGC->alu]); } } /* Clear the stipple HDC */ SelectObject(hdcStipple, hbmpOrigStipple); DeleteDC(hdcStipple); /* Delete the device dependent stipple bitmap */ DeleteObject(hBitmap); break; case FillStippled: pStipple = pGC->stipple; pStipplePriv = winGetPixmapPriv(pStipple); /* Create a device-dependent bitmap for the stipple */ hBitmap = CreateDIBitmap(pGCPriv->hdcMem, (BITMAPINFOHEADER *) pStipplePriv->pbmih, CBM_INIT, pStipplePriv->pbBits, (BITMAPINFO *) pStipplePriv->pbmih, DIB_RGB_COLORS); /* Create a memory DC to hold the stipple */ hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem); /* Select the stipple bitmap into the stipple DC */ hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); if (hbmpOrigStipple == NULL) FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " "SelectObject () failed on hbmpOrigStipple\n"); /* Make a temporary copy of the foreground and background colors */ bg = pGC->bgPixel; fg = pGC->fgPixel; /* Translate the depth-dependent colors to Win32 COLORREFs */ TRANSLATE_COLOR(fg); TRANSLATE_COLOR(bg); /* this is fudgy, we should only invert on the last one * We need to get the black/white pixels right in the * colormap. But yeah ! it's working.. */ if (pGC->bgPixel != -1 && pGC->fgPixel != -1) { SetTextColor(pGCPriv->hdcMem, fg); SetBkColor(pGCPriv->hdcMem, bg); BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); } else if (pGC->bgPixel == -1) { SetTextColor(pGCPriv->hdcMem, fg); SetBkMode(pGCPriv->hdcMem, TRANSPARENT); BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); } else if (pGC->fgPixel == -1) { SetTextColor(pGCPriv->hdcMem, bg); SetBkMode(pGCPriv->hdcMem, TRANSPARENT); #if 0 BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); #endif } while (iSpans--) { int width = pStipple->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pStipple->drawable.width) > fullX2) width = fullX2 - iX; else width = pStipple->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pStipple->drawable.width) - pStipple->drawable.width)) % pStipple->drawable.width; else xoffset = 0; if (xoffset + width > pStipple->drawable.width) width = pStipple->drawable.width - xoffset; BitBlt(pGCPriv->hdcMem, iX, fullY1, width, 1, hdcStipple, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pStipple->drawable.height) - pStipple->drawable.height)) % pStipple->drawable.height, g_copyROP[pGC->alu]); } } /* Clear the stipple HDC */ SelectObject(hdcStipple, hbmpOrigStipple); DeleteDC(hdcStipple); /* Delete the device dependent stipple bitmap */ DeleteObject(hBitmap); /* Restore the background mode */ SetBkMode(pGCPriv->hdcMem, OPAQUE); break; case FillTiled: /* Get a pixmap pointer from the tile pointer, and fetch privates */ pTile = (PixmapPtr) pGC->tile.pixmap; pTilePriv = winGetPixmapPriv(pTile); /* Create a memory DC to hold the tile */ hdcTile = CreateCompatibleDC(pGCPriv->hdcMem); /* Select the tile into a DC */ hbmpOrig = SelectObject(hdcTile, pTilePriv->hBitmap); if (hbmpOrig == NULL) FatalError("winFillSpans - DRAWABLE_PIXMAP - FillTiled - " "SelectObject () failed on pTilePriv->hBitmap\n"); while (iSpans--) { int width = pTile->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pTile->drawable.width) > fullX2) width = fullX2 - iX; else width = pTile->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pTile->drawable.width) - pTile->drawable.width)) % pTile->drawable.width; else xoffset = 0; if (xoffset + width > pTile->drawable.width) width = pTile->drawable.width - xoffset; BitBlt(pGCPriv->hdcMem, iX, fullY1, width, 1, hdcTile, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pTile->drawable.height) - pTile->drawable.height)) % pTile->drawable.height, g_copyROP[pGC->alu]); } } /* Push the tile pixmap out of the memory HDC */ SelectObject(hdcTile, hbmpOrig); /* Delete the tile */ DeleteDC(hdcTile); break; default: ErrorF("winFillSpans - DRAWABLE_PIXMAP - Unknown fillStyle\n"); break; } /* Reset clip region */ SelectClipRgn(pGCPriv->hdcMem, NULL); /* Push the drawable pixmap out of the GC HDC */ SelectObject(pGCPriv->hdcMem, hbmpOrig); break; case DRAWABLE_WINDOW: SelectClipRgn(pGCPriv->hdc, combined); DeleteObject(combined); combined = NULL; /* Branch on fill style */ switch (pGC->fillStyle) { case FillSolid: ROP16(pGCPriv->hdc, pGC->alu); if (pDrawable->depth == 1) { if (pGC->fgPixel == 0) hPenOrig = SelectObject(pGCPriv->hdc, GetStockObject(BLACK_PEN)); else hPenOrig = SelectObject(pGCPriv->hdc, GetStockObject(WHITE_PEN)); } else { fg = pGC->fgPixel; TRANSLATE_COLOR(fg); hPen = CreatePen(PS_SOLID, 0, fg); hPenOrig = SelectObject(pGCPriv->hdc, hPen); } while (iSpans--) { fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; MoveToEx(pGCPriv->hdc, fullX1, fullY1, NULL); LineTo(pGCPriv->hdc, fullX2, fullY1); } SetROP2(pGCPriv->hdc, R2_COPYPEN); /* Give back the Brush */ SelectObject(pGCPriv->hdc, hPenOrig); if (pDrawable->depth != 1) DeleteObject(hPen); break; case FillOpaqueStippled: pStipple = pGC->stipple; pStipplePriv = winGetPixmapPriv(pStipple); /* Create a device-dependent bitmap for the stipple */ hBitmap = CreateDIBitmap(pGCPriv->hdc, (BITMAPINFOHEADER *) pStipplePriv->pbmih, CBM_INIT, pStipplePriv->pbBits, (BITMAPINFO *) pStipplePriv->pbmih, DIB_RGB_COLORS); /* Create a memory DC to hold the stipple */ hdcStipple = CreateCompatibleDC(pGCPriv->hdc); /* Select the stipple bitmap into the stipple DC */ hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); if (hbmpOrigStipple == NULL) FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " "SelectObject () failed on hbmpOrigStipple\n"); /* Make a temporary copy of the foreground and background colors */ bg = pGC->bgPixel; fg = pGC->fgPixel; /* Translate the depth-dependent colors to Win32 COLORREFs */ TRANSLATE_COLOR(fg); TRANSLATE_COLOR(bg); SetTextColor(pGCPriv->hdc, fg); SetBkColor(pGCPriv->hdc, bg); while (iSpans--) { int width = pStipple->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pStipple->drawable.width) > fullX2) width = fullX2 - iX; else width = pStipple->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pStipple->drawable.width) - pStipple->drawable.width)) % pStipple->drawable.width; else xoffset = 0; if (xoffset + width > pStipple->drawable.width) width = pStipple->drawable.width - xoffset; BitBlt(pGCPriv->hdc, iX, fullY1, width, 1, hdcStipple, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pStipple->drawable.height) - pStipple->drawable.height)) % pStipple->drawable.height, g_copyROP[pGC->alu]); } } /* Clear the stipple HDC */ SelectObject(hdcStipple, hbmpOrigStipple); DeleteDC(hdcStipple); /* Delete the device dependent stipple bitmap */ DeleteObject(hBitmap); break; case FillStippled: pStipple = pGC->stipple; pStipplePriv = winGetPixmapPriv(pStipple); /* Create a device-dependent bitmap for the stipple */ hBitmap = CreateDIBitmap(pGCPriv->hdcMem, (BITMAPINFOHEADER *) pStipplePriv->pbmih, CBM_INIT, pStipplePriv->pbBits, (BITMAPINFO *) pStipplePriv->pbmih, DIB_RGB_COLORS); /* Create a memory DC to hold the stipple */ hdcStipple = CreateCompatibleDC(pGCPriv->hdc); /* Select the stipple bitmap into the stipple DC */ hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); if (hbmpOrigStipple == NULL) FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " "SelectObject () failed on hbmpOrigStipple\n"); /* Make a temporary copy of the foreground and background colors */ bg = pGC->bgPixel; fg = pGC->fgPixel; /* Translate the depth-dependent colors to Win32 COLORREFs */ TRANSLATE_COLOR(fg); TRANSLATE_COLOR(bg); /* this is fudgy, we should only invert on the last one * We need to get the black/white pixels right in the * colormap. But yeah ! it's working.. */ if (pGC->bgPixel != -1 && pGC->fgPixel != -1) { SetTextColor(pGCPriv->hdc, fg); SetBkColor(pGCPriv->hdc, bg); BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); } else if (pGC->bgPixel == -1) { SetTextColor(pGCPriv->hdc, fg); SetBkMode(pGCPriv->hdc, TRANSPARENT); BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); } else if (pGC->fgPixel == -1) { SetTextColor(pGCPriv->hdc, bg); SetBkMode(pGCPriv->hdc, TRANSPARENT); #if 0 BitBlt(hdcStipple, 0, 0, pStipple->drawable.width, pStipple->drawable.height, hdcStipple, 0, 0, 0x330008); #endif } while (iSpans--) { int width = pStipple->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pStipple->drawable.width) > fullX2) width = fullX2 - iX; else width = pStipple->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pStipple->drawable.width) - pStipple->drawable.width)) % pStipple->drawable.width; else xoffset = 0; if (xoffset + width > pStipple->drawable.width) width = pStipple->drawable.width - xoffset; BitBlt(pGCPriv->hdc, iX, fullY1, width, 1, hdcStipple, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pStipple->drawable.height) - pStipple->drawable.height)) % pStipple->drawable.height, g_copyROP[pGC->alu]); } } /* Clear the stipple HDC */ SelectObject(hdcStipple, hbmpOrigStipple); DeleteDC(hdcStipple); /* Delete the device dependent stipple bitmap */ DeleteObject(hBitmap); /* Restore the background mode */ SetBkMode(pGCPriv->hdc, OPAQUE); break; case FillTiled: /* Get a pixmap pointer from the tile pointer, and fetch privates */ pTile = (PixmapPtr) pGC->tile.pixmap; pTilePriv = winGetPixmapPriv(pTile); /* Select the tile into a DC */ hbmpOrig = SelectObject(pGCPriv->hdcMem, pTilePriv->hBitmap); if (hbmpOrig == NULL) FatalError("winFillSpans - DRAWABLE_WINDOW - FillTiled - " "SelectObject () failed on pTilePriv->hBitmap\n"); while (iSpans--) { int width = pTile->drawable.width; fullX1 = pPoints->x; fullY1 = pPoints->y; fullX2 = fullX1 + (int) *piWidths; pPoints++; piWidths++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; for (iX = fullX1; iX < fullX2; iX += width) { int xoffset; if ((iX + pTile->drawable.width) > fullX2) width = fullX2 - iX; else width = pTile->drawable.width; if (iX == fullX1) xoffset = (fullX1 - (pDrawable->x + (pGC->patOrg.x % pTile->drawable.width) - pTile->drawable.width)) % pTile->drawable.width; else xoffset = 0; if (xoffset + width > pTile->drawable.width) width = pTile->drawable.width - xoffset; BitBlt(pGCPriv->hdc, iX, fullY1, width, 1, pGCPriv->hdcMem, xoffset, (fullY1 - (pDrawable->y + (pGC->patOrg.y % pTile->drawable.height) - pTile->drawable.height)) % pTile->drawable.height, g_copyROP[pGC->alu]); } } /* Push the tile pixmap out of the memory HDC */ SelectObject(pGCPriv->hdcMem, hbmpOrig); break; default: ErrorF("winFillSpans - DRAWABLE_WINDOW - Unknown fillStyle\n"); break; } /* Reset clip region */ SelectClipRgn(pGCPriv->hdc, NULL); break; default: ErrorF("winFillSpans - Unknown drawable type\n"); break; } }
static void exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { ExaScreenPriv(pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); ExaPixmapPriv(pPixmap); 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 = RegionFromRects(nrect, prect, CT_UNSORTED); /* Compute intersection of rects and clip region */ RegionTranslate(pReg, pDrawable->x, pDrawable->y); RegionIntersect(pReg, pClip, pReg); if (!RegionNumRects(pReg)) { goto out; } exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); if (pExaScr->fallback_counter || pExaScr->swappedOut || pExaPixmap->accel_blocked) { goto fallback; } /* For ROPs where overlaps don't matter, convert rectangles to region and * call exaFillRegion{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) && exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? pGC->fgPixel : pGC->tile.pixel, pGC->planemask, pGC->alu, pGC->clientClip != NULL)) || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, pGC->planemask, pGC->alu, pGC->clientClip != NULL))) { goto out; } } if (pGC->fillStyle != FillSolid && !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { goto fallback; } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = NULL; exaDoMigration(pixmaps, 1, TRUE); } if (!exaPixmapHasGpuCopy(pPixmap) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { fallback: ExaCheckPolyFillRect(pDrawable, pGC, nrect, prect); goto out; } xorg = pDrawable->x; yorg = pDrawable->y; pextent = RegionExtents(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 = RegionNumRects(pClip); if (n == 1) { (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); } else { pbox = RegionRects(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) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); } } } } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); out: RegionUninit(pReg); RegionDestroy(pReg); }
/** * If the pixmap is currently dirty, this copies at least the dirty area from * FB to system or vice versa. Both areas must be allocated. */ static void exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h, char *sys, int sys_pitch), int fallback_index, void (*sync) (ScreenPtr pScreen)) { PixmapPtr pPixmap = migrate->pPix; ExaPixmapPriv(pPixmap); RegionPtr damage = DamageRegion(pExaPixmap->pDamage); RegionRec CopyReg; Bool save_use_gpu_copy; int save_pitch; BoxPtr pBox; int nbox; Bool access_prepared = FALSE; Bool need_sync = FALSE; /* Damaged bits are valid in current copy but invalid in other one */ if (pExaPixmap->use_gpu_copy) { RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage); RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage); } else { RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage); RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage); } RegionEmpty(damage); /* Copy bits valid in source but not in destination */ RegionNull(&CopyReg); RegionSubtract(&CopyReg, pValidSrc, pValidDst); if (migrate->as_dst) { ExaScreenPriv(pPixmap->drawable.pScreen); /* XXX: The pending damage region will be marked as damaged after the * operation, so it should serve as an upper bound for the region that * needs to be synchronized for the operation. Unfortunately, this * causes corruption in some cases, e.g. when starting compiz. See * https://bugs.freedesktop.org/show_bug.cgi?id=12916 . */ if (pExaScr->optimize_migration) { RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); #if DEBUG_MIGRATE if (RegionNil(pending_damage)) { static Bool firsttime = TRUE; if (firsttime) { ErrorF("%s: Pending damage region empty!\n", __func__); firsttime = FALSE; } } #endif /* Try to prevent destination valid region from growing too many * rects by filling it up to the extents of the union of the * destination valid region and the pending damage region. */ if (RegionNumRects(pValidDst) > 10) { BoxRec box; BoxPtr pValidExt, pDamageExt; RegionRec closure; pValidExt = RegionExtents(pValidDst); pDamageExt = RegionExtents(pending_damage); box.x1 = min(pValidExt->x1, pDamageExt->x1); box.y1 = min(pValidExt->y1, pDamageExt->y1); box.x2 = max(pValidExt->x2, pDamageExt->x2); box.y2 = max(pValidExt->y2, pDamageExt->y2); RegionInit(&closure, &box, 0); RegionIntersect(&CopyReg, &CopyReg, &closure); } else RegionIntersect(&CopyReg, &CopyReg, pending_damage); } /* The caller may provide a region to be subtracted from the calculated * dirty region. This is to avoid migration of bits that don't * contribute to the result of the operation. */ if (migrate->pReg) RegionSubtract(&CopyReg, &CopyReg, migrate->pReg); } else { /* The caller may restrict the region to be migrated for source pixmaps * to what's relevant for the operation. */ if (migrate->pReg) RegionIntersect(&CopyReg, &CopyReg, migrate->pReg); } pBox = RegionRects(&CopyReg); nbox = RegionNumRects(&CopyReg); save_use_gpu_copy = pExaPixmap->use_gpu_copy; save_pitch = pPixmap->devKind; pExaPixmap->use_gpu_copy = TRUE; pPixmap->devKind = pExaPixmap->fb_pitch; while (nbox--) { pBox->x1 = max(pBox->x1, 0); pBox->y1 = max(pBox->y1, 0); pBox->x2 = min(pBox->x2, pPixmap->drawable.width); pBox->y2 = min(pBox->y2, pPixmap->drawable.height); if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) continue; if (!transfer || !transfer(pPixmap, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, (char *) (pExaPixmap->sys_ptr + pBox->y1 * pExaPixmap->sys_pitch + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8), pExaPixmap->sys_pitch)) { if (!access_prepared) { ExaDoPrepareAccess(pPixmap, fallback_index); access_prepared = TRUE; } if (fallback_index == EXA_PREPARE_DEST) { exaMemcpyBox(pPixmap, pBox, pExaPixmap->sys_ptr, pExaPixmap->sys_pitch, pPixmap->devPrivate.ptr, pPixmap->devKind); } else { exaMemcpyBox(pPixmap, pBox, pPixmap->devPrivate.ptr, pPixmap->devKind, pExaPixmap->sys_ptr, pExaPixmap->sys_pitch); } } else need_sync = TRUE; pBox++; } pExaPixmap->use_gpu_copy = save_use_gpu_copy; pPixmap->devKind = save_pitch; /* Try to prevent source valid region from growing too many rects by * removing parts of it which are also in the destination valid region. * Removing anything beyond that would lead to data loss. */ if (RegionNumRects(pValidSrc) > 20) RegionSubtract(pValidSrc, pValidSrc, pValidDst); /* The copied bits are now valid in destination */ RegionUnion(pValidDst, pValidDst, &CopyReg); RegionUninit(&CopyReg); if (access_prepared) exaFinishAccess(&pPixmap->drawable, fallback_index); else if (need_sync && sync) sync(pPixmap->drawable.pScreen); }