/** * Append given rectangle to the client's list of dirty regions. */ void fn_client_add_rect(AIO_SLOT *slot, FB_RECT *rect) { CL_SLOT *cl = (CL_SLOT *)slot; RegionRec add_region; BoxRec add_rect; int stored; int dx, dy; if (!cl->connected || cl->newfbsize_pending) return; /* If the framebuffer geometry has been changed, then we don't care about pending pixel updates any more, because all clients will want to update the whole framebuffer. */ if (g_screen_info.width != cl->fb_width || g_screen_info.height != cl->fb_height) { cl->newfbsize_pending = 1; REGION_EMPTY(&cl->pending_region); REGION_EMPTY(&cl->copy_region); return; } add_rect.x1 = rect->x; add_rect.y1 = rect->y; add_rect.x2 = add_rect.x1 + rect->w; add_rect.y2 = add_rect.y1 + rect->h; REGION_INIT(&add_region, &add_rect, 4); /* FIXME: Currently, CopyRect is stored in copy_region only if there were no other non-CopyRect updates pending for this client. Normally, that's ok, because VNC servers send CopyRect rectangles before non-CopyRect ones, but of course more elegant and efficient handling could be possible to implement here. */ stored = 0; if (rect->enc == RFB_ENCODING_COPYRECT && cl->enc_enable[RFB_ENCODING_COPYRECT] && !REGION_NOTEMPTY(&cl->pending_region)) { dx = rect->x - rect->src_x; dy = rect->y - rect->src_y; if (!REGION_NOTEMPTY(&cl->copy_region) || (dx == cl->copy_dx && dy == cl->copy_dy)) { REGION_UNION(&cl->copy_region, &cl->copy_region, &add_region); cl->copy_dx = dx; cl->copy_dy = dy; stored = 1; } } if (!stored) REGION_UNION(&cl->pending_region, &cl->pending_region, &add_region); REGION_UNINIT(&add_region); }
static Bool xf86RotateRedisplay(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DamagePtr damage = xf86_config->rotation_damage; RegionPtr region; if (!damage) return FALSE; xf86RotatePrepare (pScreen); region = DamageRegion(damage); if (REGION_NOTEMPTY(pScreen, region)) { int c; SourceValidateProcPtr SourceValidate; /* * SourceValidate is used by the software cursor code * to pull the cursor off of the screen when reading * bits from the frame buffer. Bypassing this function * leaves the software cursor in place */ SourceValidate = pScreen->SourceValidate; pScreen->SourceValidate = NULL; for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; if (crtc->rotation != RR_Rotate_0 && crtc->enabled) { RegionRec crtc_damage; /* compute portion of damage that overlaps crtc */ REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1); REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region); /* update damaged region */ if (REGION_NOTEMPTY(pScreen, &crtc_damage)) xf86RotateCrtcRedisplay (crtc, &crtc_damage); REGION_UNINIT (pScreen, &crtc_damage); } } pScreen->SourceValidate = SourceValidate; DamageEmpty(damage); } return TRUE; }
static void update_screen(struct omap_screen_info *omaps) { BoxPtr tmp; int i; if (region_is_null(omaps)) return; if (!omaps->block_updates) { /* Remove the video region from our active area. */ if (omaps->video_region && REGION_NOTEMPTY(omaps->screen->pScreen, omaps->video_region) && RECT_IN_REGION(omaps->screen->pScreen, omaps->video_region, &omaps->dirty_area)) { REGION_INIT(omaps->screen->pScreen, omaps->tmp_region, &omaps->dirty_area, 1); REGION_SUBTRACT(omaps->screen->pScreen, omaps->tmp_region, omaps->tmp_region, omaps->video_region); tmp = REGION_RECTS(omaps->tmp_region); for (i = 0; i < REGION_NUM_RECTS(omaps->tmp_region); i++, tmp++) push_box(omaps, tmp); REGION_EMPTY(omaps->screen->pScreen, omaps->tmp_region); } else { push_box(omaps, &omaps->dirty_area); } } reset_damage(omaps); }
static CARD32 damage_timer(OsTimerPtr timer, CARD32 time, pointer arg) { struct omap_screen_info *omaps = arg; int needUpdate = 0; RegionPtr region = NULL; #ifdef XSP xspScrPrivPtr xsp_priv = NULL; #endif #ifdef XSP if (xspScrPrivateIndex > 0) { xsp_priv = xspGetScrPriv(omaps->screen->pScreen); if (xsp_priv && xsp_priv->dsp_enabled) needUpdate = 1; } #endif if (!omaps->damage) { omaps->timer_active = 0; omaps->empty_updates = 0; return 0; } #ifdef PROFILE_ME_HARDER omaps->updates++; if (omaps->updates > (5000 / OMAP_UPDATE_TIME)) video_stats(omaps, time); #endif region = DamageRegion(omaps->damage); if (REGION_NOTEMPTY(omaps->screen->pScreen, region)) { accumulate_damage(omaps, region); DamageEmpty(omaps->damage); } if (!region_is_null(omaps)) needUpdate = 1; if (needUpdate) { omaps->empty_updates = 0; update_screen(omaps); } else { omaps->empty_updates++; } #if !defined(PROFILE_ME_HARDER) && !defined(DEBUG) /* Kill the timer if we've gone more than 500ms without an update. */ if (omaps->empty_updates >= 500 / OMAP_UPDATE_TIME) { omaps->timer_active = 0; omaps->empty_updates = 0; return 0; } else #endif { return OMAP_UPDATE_TIME; } }
static GCOps * s3MatchCommon (DrawablePtr pDraw, GCPtr pGC, FbGCPrivPtr fbPriv) { KdScreenPriv (pDraw->pScreen); if (!REGION_NOTEMPTY(pDraw->pScreen,fbGetCompositeClip(pGC))) { DRAW_DEBUG ((DEBUG_CLIP, "Empty composite clip, clipping all ops")); return &kdNoopOps; } if (pDraw->type != DRAWABLE_WINDOW) return (GCOps *) &kdAsyncPixmapGCOps; if (pGC->lineWidth != 0) return 0; if (pGC->lineStyle != LineSolid) return 0; if (pGC->fillStyle != FillSolid) return 0; if (fbPriv->and != 0) return 0; if (pGC->font) { if (TERMINALFONT(pGC->font)) return (GCOps *) &s3TEOps; else return (GCOps *) &s3NonTEOps; } return 0; }
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; }
/** * Returns TRUE if the pixmap is dirty (has been modified in its current * location compared to the other), or lacks a private for tracking * dirtiness. */ static Bool exaPixmapIsDirty (PixmapPtr pPix) { ExaPixmapPriv (pPix); return pExaPixmap == NULL || REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)); }
static void xf86RotateRedisplay(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DamagePtr damage = xf86_config->rotation_damage; RegionPtr region; if (!damage) return; xf86RotatePrepare (pScreen); region = DamageRegion(damage); if (REGION_NOTEMPTY(pScreen, region)) { int c; for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; if (crtc->rotation != RR_Rotate_0) { BoxRec box; RegionRec crtc_damage; /* compute portion of damage that overlaps crtc */ box.x1 = crtc->x; box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); box.y1 = crtc->y; box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); REGION_INIT(pScreen, &crtc_damage, &box, 1); REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region); /* update damaged region */ if (REGION_NOTEMPTY(pScreen, &crtc_damage)) xf86RotateCrtcRedisplay (crtc, &crtc_damage); REGION_UNINIT (pScreen, &crtc_damage); } } DamageEmpty(damage); } }
/** * Called when we've finished sending an RFB update to the client. */ static void wf_client_update_finished(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; log_write(LL_DEBUG, "Finished sending framebuffer update to %s", cur_slot->name); cl->update_in_progress = 0; if (cl->update_requested && (cl->newfbsize_pending || cl->new_cliprects || #if 0 REGION_NOTEMPTY(&cl->pending_region) || REGION_NOTEMPTY(&cl->copy_region))) { #else REGION_NOTEMPTY(&cl->copy_region) || vncspuWaitDirtyRects(&cl->pending_region, &cl->update_rect, cl->serial_number))) { #endif send_update(); } }
static void shadowRedisplay(ScreenPtr pScreen) { shadowBuf(pScreen); RegionPtr pRegion; if (!pBuf || !pBuf->pDamage || !pBuf->update) return; pRegion = DamageRegion(pBuf->pDamage); if (REGION_NOTEMPTY(pScreen, pRegion)) { (*pBuf->update)(pScreen, pBuf); DamageEmpty(pBuf->pDamage); } }
/** * Send the dirty rects to the given client, if an update was requested. * This is called as a callback by the fbupdate_rect_done() function after * the last rectangle has been decoded. */ void fn_client_send_rects(AIO_SLOT *slot) { CL_SLOT *cl = (CL_SLOT *)slot; AIO_SLOT *saved_slot = cur_slot; if (!cl->update_in_progress && cl->update_requested && (cl->newfbsize_pending || cl->new_cliprects || REGION_NOTEMPTY(&cl->copy_region) || vncspuGetDirtyRects(&cl->pending_region))) { cur_slot = slot; send_update(); cur_slot = saved_slot; } }
static void shadowRedisplay(ScreenPtr pScreen) { shadowBuf(pScreen); RegionPtr pRegion; if (!pBuf || !pBuf->pDamage || !pBuf->update) return; /* allow deferral of updates, to minimize overdraw, etc. */ if (!pBuf->ready_to_update(pScreen, pBuf)) return; pRegion = DamageRegion(pBuf->pDamage); if (REGION_NOTEMPTY(pScreen, pRegion)) { (*pBuf->update)(pScreen, pBuf); DamageEmpty(pBuf->pDamage); } }
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++; } } } }
/***** * miHandleValidateExposures(pWin) * starting at pWin, draw background in any windows that have exposure * regions, translate the regions, restore any backing store, * and then send any regions still exposed to the client *****/ void miHandleValidateExposures(WindowPtr pWin) { WindowPtr pChild; ValidatePtr val; ScreenPtr pScreen; WindowExposuresProcPtr WindowExposures; pScreen = pWin->drawable.pScreen; pChild = pWin; WindowExposures = pChild->drawable.pScreen->WindowExposures; while (1) { if ( (val = pChild->valdata) ) { if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); REGION_UNINIT(pScreen, &val->after.borderExposed); (*WindowExposures)(pChild, &val->after.exposed, NullRegion); REGION_UNINIT(pScreen, &val->after.exposed); xfree(val); pChild->valdata = NULL; if (pChild->firstChild) { pChild = pChild->firstChild; continue; } } while (!pChild->nextSib && (pChild != pWin)) pChild = pChild->parent; if (pChild == pWin) break; pChild = pChild->nextSib; } }
Bool saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, RegionPtr read_reg) { ScreenPtr pScreen = pix->drawable.pScreen; struct saa_screen_priv *sscreen = saa_screen(pScreen); struct saa_driver *driver = sscreen->driver; struct saa_pixmap *spix = saa_pixmap(pix); saa_access_t map_access = 0; Bool ret = TRUE; if (read_reg && REGION_NOTEMPTY(pScreen, read_reg)) ret = saa_download_from_hw(pix, read_reg); if (!ret) { LogMessage(X_ERROR, "Prepare access pixmap failed.\n"); return ret; } if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0) map_access = SAA_ACCESS_R; if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0) map_access |= SAA_ACCESS_W; if (map_access) { if (spix->auth_loc != saa_loc_override) { (void)driver->sync_for_cpu(driver, pix, map_access); spix->addr = driver->map(driver, pix, map_access); } else spix->addr = spix->override; spix->mapped_access |= map_access; } pix->devPrivate.ptr = spix->addr; return TRUE; }
static void trim_region (RegionPtr pRegion, DrawablePtr pDrawable, int subWindowMode) { RegionRec pixClip; int draw_x = 0; int draw_y = 0; #ifdef COMPOSITE int screen_x = 0, screen_y = 0; #endif /* short circuit for empty regions */ if (!REGION_NOTEMPTY(pScreen, pRegion)) return; #ifdef COMPOSITE /* * When drawing to a pixmap which is storing window contents, * the region presented is in pixmap relative coordinates which * need to be converted to screen relative coordinates */ if (pDrawable->type != DRAWABLE_WINDOW) { screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; } if (screen_x || screen_y) REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); #endif /* Clip against any children */ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)(pDrawable))->backingStore == NotUseful) { if (subWindowMode == ClipByChildren) { REGION_INTERSECT(pScreen, pRegion, pRegion, &((WindowPtr)(pDrawable))->clipList); } else if (subWindowMode == IncludeInferiors) { RegionPtr pTempRegion = NotClippedByChildren((WindowPtr)(pDrawable)); REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); REGION_DESTROY(pScreen, pTempRegion); } /* If subWindowMode is set to an invalid value, don't perform * any drawable-based clipping. */ } /* Clip against border or pixmap bounds */ if (pDrawable->type == DRAWABLE_WINDOW) { REGION_INTERSECT (pScreen, pRegion, pRegion, &((WindowPtr)(pDrawable))->borderClip); } else { BoxRec box; draw_x = pDrawable->x; draw_y = pDrawable->y; #ifdef COMPOSITE /* * Need to move everyone to screen coordinates * XXX what about off-screen pixmaps with non-zero x/y? */ if (!WindowDrawable(pDrawable->type)) { draw_x += ((PixmapPtr) pDrawable)->screen_x; draw_y += ((PixmapPtr) pDrawable)->screen_y; } #endif box.x1 = draw_x; box.y1 = draw_y; box.x2 = draw_x + pDrawable->width; box.y2 = draw_y + pDrawable->height; REGION_INIT(pScreen, &pixClip, &box, 1); REGION_INTERSECT (pScreen, pRegion, pRegion, &pixClip); REGION_UNINIT(pScreen, &pixClip); } /* * Move region to target coordinate space */ if (draw_x || draw_y) REGION_TRANSLATE (pScreen, pRegion, -draw_x, -draw_y); /* Now do something with the damage */ }
/** * Handle an incoming rfbFramebufferUpdateRequest message. * Determine the dirty regions and send pixel rect data to the client. */ static void rf_client_updatereq(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; RegionRec tmp_region; BoxRec rect; /*crDebug("Got Update request from %s", cur_slot->name);*/ #ifdef NETLOGGER if (vnc_spu.netlogger_url) { cl->serial_number++; NL_info("vncspu", "spu.fbrequest.receive", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } #endif /* the requested region of interest */ rect.x1 = buf_get_CARD16(&cur_slot->readbuf[1]); rect.y1 = buf_get_CARD16(&cur_slot->readbuf[3]); rect.x2 = rect.x1 + buf_get_CARD16(&cur_slot->readbuf[5]); rect.y2 = rect.y1 + buf_get_CARD16(&cur_slot->readbuf[7]); /* Make sure the rectangle bounds fit the framebuffer. */ if (rect.x1 > cl->fb_width) rect.x1 = cl->fb_width; if (rect.y1 > cl->fb_height) rect.y1 = cl->fb_height; if (rect.x2 > cl->fb_width) rect.x2 = cl->fb_width; if (rect.y2 > cl->fb_height) rect.y2 = cl->fb_height; cl->update_rect = rect; cl->update_requested = 1; cl->num_update_requests++; if (!cur_slot->readbuf[0]) { log_write(LL_DEBUG, "Received framebuffer update request (full) from %s", cur_slot->name); if (!cl->newfbsize_pending) { REGION_INIT(&tmp_region, &rect, 1); #if 0 /* Disabling this code prevents the region from outside the GL * window (garbage) from being sent to the viewer. */ REGION_UNION(&cl->pending_region, &cl->pending_region, &tmp_region); #endif REGION_UNION(&cl->pending_region, &cl->pending_region, &cl->copy_region); REGION_EMPTY(&cl->copy_region); REGION_UNINIT(&tmp_region); } } else { log_write(LL_DEBUG, "Received framebuffer update request from %s", cur_slot->name); } if (!cl->update_in_progress) { int k = (cl->newfbsize_pending || cl->new_cliprects || REGION_NOTEMPTY(&cl->copy_region) || vncspuWaitDirtyRects(&cl->pending_region, &cl->update_rect, cl->serial_number)); if (k) { send_update(); } } aio_setread(rf_client_msg, NULL, 1); }
static void send_update(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; BoxRec fb_rect; RegionRec fb_region, clip_region, outer_region; CARD8 msg_hdr[4] = { 0, 0, 0, 1 }; CARD8 rect_hdr[12]; int num_copy_rects, num_pending_rects, num_all_rects; int raw_bytes = 0, hextile_bytes = 0; int i, idx, rev_order; static int counter = 0; #ifdef NETLOGGER aio_set_serial_number(&cl->s, cl->serial_number); #endif counter++; vncspuLog(1, "Begin send update %d", counter); CRASSERT(vnc_spu.serverBuffer); /*crDebug("Enter send_update to %s", cur_slot->name);*/ /* check if clipping has changed since we got the pixels and update * the pending region if needed. */ if (NewClip) { /*crDebug("Getting updated cliprects");*/ vncspuGetScreenRects(&cl->pending_region); num_pending_rects = REGION_NUM_RECTS(&cl->pending_region); /*crDebug("Now, %d rects", num_pending_rects);*/ if (num_pending_rects == 0 && cl->enable_frame_sync) { /* always need to send _something_ for framesync to work */ BoxRec b; b.x1 = 0; b.y1 = 0; b.x2 = 1; b.y2 = 1; REGION_UNINIT(&cl->pending_region); REGION_INIT(&cl->pending_region, &b, 1); } NewClip = 0; } /*PrintRegion("Sending", &cl->pending_region);*/ /* Process framebuffer size change. */ if (cl->newfbsize_pending) { /* Update framebuffer size, clear newfbsize_pending flag. */ cl->fb_width = g_screen_info.width; cl->fb_height = g_screen_info.height; cl->newfbsize_pending = 0; log_write(LL_DEBUG, "Applying new framebuffer size (%dx%d) to %s", (int)cl->fb_width, (int)cl->fb_height, cur_slot->name); /* In any case, mark all the framebuffer contents as changed. */ fb_rect.x1 = 0; fb_rect.y1 = 0; fb_rect.x2 = cl->fb_width; fb_rect.y2 = cl->fb_height; REGION_INIT(&fb_region, &fb_rect, 1); REGION_COPY(&cl->pending_region, &fb_region); REGION_UNINIT(&fb_region); REGION_EMPTY(&cl->copy_region); /* If NewFBSize is supported by the client, send only NewFBSize pseudo-rectangle, pixel data will be sent in the next update. */ if (cl->enable_newfbsize) { send_newfbsize(); vncspuUnlockFrameBuffer(); return; } } else { /* Exclude CopyRect areas covered by pending_region. */ REGION_SUBTRACT(&cl->copy_region, &cl->copy_region, &cl->pending_region); } #if 00 if (cl->enable_cliprects_enc && cl->new_cliprects) { send_new_cliprects(); vncspuUnlockFrameBuffer(); cl->new_cliprects = 0; return; } #endif /* Clip regions to the rectangle requested by the client. */ REGION_INIT(&clip_region, &cl->update_rect, 1); REGION_INTERSECT(&cl->pending_region, &cl->pending_region, &clip_region); if (REGION_NOTEMPTY(&cl->copy_region)) { REGION_INTERSECT(&cl->copy_region, &cl->copy_region, &clip_region); REGION_INIT(&outer_region, NullBox, 8); REGION_COPY(&outer_region, &cl->copy_region); REGION_TRANSLATE(&clip_region, cl->copy_dx, cl->copy_dy); REGION_INTERSECT(&cl->copy_region, &cl->copy_region, &clip_region); REGION_SUBTRACT(&outer_region, &outer_region, &cl->copy_region); REGION_UNION(&cl->pending_region, &cl->pending_region, &outer_region); REGION_UNINIT(&outer_region); } REGION_UNINIT(&clip_region); /* Reduce the number of rectangles if possible. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { region_pack(&cl->pending_region, 32); } else { region_pack(&cl->pending_region, 12); } /* Compute the number of rectangles in regions. */ num_pending_rects = REGION_NUM_RECTS(&cl->pending_region); num_copy_rects = REGION_NUM_RECTS(&cl->copy_region); num_all_rects = num_pending_rects + num_copy_rects; if (num_all_rects == 0) { vncspuUnlockFrameBuffer(); return; } log_write(LL_DEBUG, "Sending framebuffer update (min %d rects) to %s", num_all_rects, cur_slot->name); /* Prepare and send FramebufferUpdate message header. */ /* FIXME: Enable Tight encoding even if LastRect is not supported. */ /* FIXME: Do not send LastRect if all the rectangles are CopyRect. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { buf_put_CARD16(&msg_hdr[2], 0xFFFF); } else { buf_put_CARD16(&msg_hdr[2], num_all_rects); } aio_write(NULL, msg_hdr, 4); /* Determine the order in which CopyRect rectangles should be sent. */ rev_order = (cl->copy_dy > 0 || (cl->copy_dy == 0 && cl->copy_dx > 0)); /* For each CopyRect rectangle: */ for (i = 0; i < num_copy_rects; i++) { FB_RECT rect; AIO_BLOCK *block; idx = (rev_order) ? num_copy_rects - i - 1 : i; rect.x = REGION_RECTS(&cl->copy_region)[idx].x1; rect.y = REGION_RECTS(&cl->copy_region)[idx].y1; rect.w = REGION_RECTS(&cl->copy_region)[idx].x2 - rect.x; rect.h = REGION_RECTS(&cl->copy_region)[idx].y2 - rect.y; rect.src_x = rect.x - cl->copy_dx; rect.src_y = rect.y - cl->copy_dy; rect.enc = RFB_ENCODING_COPYRECT; log_write(LL_DEBUG, "Sending CopyRect rectangle %dx%d at %d,%d to %s", (int)rect.w, (int)rect.h, (int)rect.x, (int)rect.y, cur_slot->name); /* Prepare the CopyRect rectangle. */ block = rfb_encode_copyrect_block(cl, &rect); /* Send the rectangle. FIXME: Check for block == NULL? */ aio_write_nocopy(NULL, block); } if (cl->enc_prefer == RFB_ENCODING_TIGHT) { /* needed for successful caching of zlib-compressed data (tight) */ rfb_reset_tight_encoder(cl); } if (num_pending_rects) { /* Lock around fb access so other thread doesn't change contents while * we're encoding. */ #ifdef NETLOGGER if (vnc_spu.netlogger_url) { NL_info("vncspu", "spu.encode.begin", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } #endif /* For each of the usual pending rectangles: */ for (i = 0; i < num_pending_rects; i++) { FB_RECT rect; AIO_BLOCK *block; /* crDebug("sending rect %d of %d: %d, %d .. %d, %d", i, num_pending_rects, REGION_RECTS(&cl->pending_region)[i].x1, REGION_RECTS(&cl->pending_region)[i].y1, REGION_RECTS(&cl->pending_region)[i].x2, REGION_RECTS(&cl->pending_region)[i].y2); */ rect.x = REGION_RECTS(&cl->pending_region)[i].x1; rect.y = REGION_RECTS(&cl->pending_region)[i].y1; rect.w = REGION_RECTS(&cl->pending_region)[i].x2 - rect.x; rect.h = REGION_RECTS(&cl->pending_region)[i].y2 - rect.y; log_write(LL_DEBUG, "Sending rectangle %dx%d at %d,%d to %s enc 0x%x", (int)rect.w, (int)rect.h, (int)rect.x, (int)rect.y, cur_slot->name, cl->enc_prefer); if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { /* Use Tight encoding */ rect.enc = RFB_ENCODING_TIGHT; /* lock to prevent glReadPixels in other thread changing data */ rfb_encode_tight(cl, &rect); continue; /* Important! */ } else if (cl->enc_prefer == RFB_ENCODING_RAW24) { rect.enc = RFB_ENCODING_RAW24; block = rfb_encode_raw24_block(cl, &rect); } else if ( cl->enc_prefer != RFB_ENCODING_RAW && cl->enc_enable[RFB_ENCODING_HEXTILE] ) { /* Use Hextile encoding */ rect.enc = RFB_ENCODING_HEXTILE; block = rfb_encode_hextile_block(cl, &rect); if (block != NULL) { hextile_bytes += block->data_size; raw_bytes += rect.w * rect.h * (cl->format.bits_pixel / 8); } } else { /* Use Raw encoding */ rect.enc = RFB_ENCODING_RAW; if (vnc_spu.half_rez) { block = rfb_encode_raw_block_halfrez(cl, &rect); } else { block = rfb_encode_raw_block(cl, &rect); } } /* Send the rectangle. FIXME: Check for block == NULL? */ aio_write_nocopy(NULL, block); } } /* if num_pending_rects */ REGION_EMPTY(&cl->pending_region); REGION_EMPTY(&cl->copy_region); /* Send LastRect marker. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { FB_RECT rect; rect.x = rect.y = rect.w = rect.h = 0; rect.enc = RFB_ENCODING_LASTRECT; put_rect_header(rect_hdr, &rect); aio_write(NULL, rect_hdr, 12); } /* Set the last block's callback function */ /* All prev blocks had NULL callbacks */ assert(cur_slot->outqueue_last); if (cur_slot->outqueue_last) { cur_slot->outqueue_last->func = wf_client_update_finished; } /* Something has been queued for sending. */ cl->update_in_progress = 1; cl->update_requested = 0; #ifdef NETLOGGER if (vnc_spu.netlogger_url) { NL_info("vncspu", "spu.encode.end", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } aio_set_serial_number(&cl->s, 0); #endif vncspuUnlockFrameBuffer(); /* encoder done with buffer */ /*crDebug("Leave send_update");*/ vncspuLog(1, "End send update %d", counter); }
void XAAOverCopyWindow( WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc ){ ScreenPtr pScreen = pWin->drawable.pScreen; XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); ScrnInfoPtr pScrn = infoRec->pScrn; DDXPointPtr ppt, pptSrc; RegionRec rgnDst; BoxPtr pbox; int i, nbox, dx, dy; WindowPtr pRoot = WindowTable[pScreen->myNum]; if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); if(pScrn->vtSema && infoRec->NeedToSync) { (*infoRec->Sync)(pScrn); infoRec->NeedToSync = FALSE; } (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAAOverCopyWindow); return; } infoRec->ScratchGC.alu = GXcopy; infoRec->ScratchGC.planemask = ~0; REGION_NULL(pScreen, &rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } SWITCH_DEPTH(8); XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); if(pWin->drawable.bitsPerPixel != 8) { SWITCH_DEPTH(pScrn->depth); XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); } DEALLOCATE_LOCAL(pptSrc); } REGION_UNINIT(pScreen, &rgnDst); if(pWin->drawable.depth == 8) { REGION_NULL(pScreen, &rgnDst); miSegregateChildren(pWin, &rgnDst, pScrn->depth); if(REGION_NOTEMPTY(pScreen, &rgnDst)) { REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrc); nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))){ pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } SWITCH_DEPTH(pScrn->depth); XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); DEALLOCATE_LOCAL(pptSrc); } } REGION_UNINIT(pScreen, &rgnDst); } }
void cfb8_16CopyWindow( WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc ){ ScreenPtr pScreen = pWin->drawable.pScreen; cfb8_16ScreenPtr pScreenPriv = CFB8_16_GET_SCREEN_PRIVATE(pWin->drawable.pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; DDXPointPtr ppt, pptSrc; RegionRec rgnDst; BoxPtr pbox; int i, nbox, dx, dy; WindowPtr pRoot = WindowTable[pScreen->myNum]; REGION_INIT(pScreen, &rgnDst, NullBox, 0); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } cfbDoBitbltCopy((DrawablePtr)pRoot, (DrawablePtr)pRoot, GXcopy, &rgnDst, pptSrc, ~0L); if(pWin->drawable.bitsPerPixel == 16) cfb16DoBitbltCopy((DrawablePtr)pScreenPriv->pix16, (DrawablePtr)pScreenPriv->pix16, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } REGION_UNINIT(pScreen, &rgnDst); if(pWin->drawable.depth == 8) { REGION_INIT(pScreen, &rgnDst, NullBox, 0); miSegregateChildren(pWin, &rgnDst, pScrn->depth); if(REGION_NOTEMPTY(pScreen, &rgnDst)) { REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrc); nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))){ pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } cfb16DoBitbltCopy((DrawablePtr)pScreenPriv->pix16, (DrawablePtr)pScreenPriv->pix16, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } } REGION_UNINIT(pScreen, &rgnDst); } }
static void rf_client_encodings_data(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; int i; int preferred_enc_set = 0; CARD32 enc; /* Reset encoding list (always enable raw encoding) */ cl->enc_enable[RFB_ENCODING_RAW] = 1; cl->enc_prefer = RFB_ENCODING_RAW; cl->compress_level = -1; cl->jpeg_quality = -1; cl->enable_lastrect = 0; cl->enable_newfbsize = 0; cl->enable_cliprects_enc = 0; cl->enable_frame_sync = 0; for (i = 1; i < NUM_ENCODINGS; i++) cl->enc_enable[i] = 0; /* Read and store encoding list supplied by the client */ for (i = 0; i < (int)cl->temp_count; i++) { enc = buf_get_CARD32(&cur_slot->readbuf[i * sizeof(CARD32)]); if (!preferred_enc_set) { if ( enc == RFB_ENCODING_RAW || enc == RFB_ENCODING_HEXTILE || enc == RFB_ENCODING_RAW24 || enc == RFB_ENCODING_TIGHT ) { cl->enc_prefer = enc; preferred_enc_set = 1; } } if (enc >= 0 && enc < NUM_ENCODINGS) { cl->enc_enable[enc] = 1; } else if (enc >= RFB_ENCODING_COMPESSLEVEL0 && enc <= RFB_ENCODING_COMPESSLEVEL9 && cl->compress_level == -1) { cl->compress_level = (int)(enc - RFB_ENCODING_COMPESSLEVEL0); log_write(LL_DETAIL, "Compression level %d requested by client %s", cl->compress_level, cur_slot->name); } else if (enc >= RFB_ENCODING_QUALITYLEVEL0 && enc <= RFB_ENCODING_QUALITYLEVEL9 && cl->jpeg_quality == -1) { cl->jpeg_quality = (int)(enc - RFB_ENCODING_QUALITYLEVEL0); log_write(LL_DETAIL, "JPEG quality level %d requested by client %s", cl->jpeg_quality, cur_slot->name); } else if (enc == RFB_ENCODING_LASTRECT) { log_write(LL_DETAIL, "Client %s supports LastRect markers", cur_slot->name); cl->enable_lastrect = 1; } else if (enc == RFB_ENCODING_NEWFBSIZE) { cl->enable_newfbsize = 1; log_write(LL_DETAIL, "Client %s supports desktop geometry changes", cur_slot->name); } else if (enc == RFB_ENCODING_CLIPRECTS) { cl->enable_cliprects_enc = 1; log_write(LL_DETAIL, "Client %s supports cliprects", cur_slot->name); } else if (enc == RFB_ENCODING_HALF_REZ) { vnc_spu.half_rez = 1; log_write(LL_DETAIL, "Client %s supports half rez", cur_slot->name); } else if (enc == RFB_ENCODING_FRAME_SYNC) { cl->enable_frame_sync = 1; vnc_spu.frame_drop = 0; /* can't drop frames if trying to sync! */ crDebug("Frame sync requested by client, disabling frame_drop"); log_write(LL_DETAIL, "Client %s supports frame sync encoding", cur_slot->name); } } if (cl->compress_level < 0) cl->compress_level = 6; /* default compression level */ /* CopyRect was pending but the client does not want it any more. */ if (!cl->enc_enable[RFB_ENCODING_COPYRECT] && REGION_NOTEMPTY(&cl->copy_region)) { REGION_UNION(&cl->pending_region, &cl->pending_region, &cl->copy_region); REGION_EMPTY(&cl->copy_region); } crDebug("In rf_client_encodings_data(), cl->enc_prefer=0x%x pixel_size=%d", cl->enc_prefer, vnc_spu.pixel_size); if (cl->enc_prefer == RFB_ENCODING_RAW24) { if (vnc_spu.pixel_size == 0 || vnc_spu.pixel_size == 24) { /* not set, or already 24bpp */ vnc_spu.pixel_size = 24; log_write(LL_DETAIL, "Using Raw24 encoding for client %s", cur_slot->name); } else if (vnc_spu.pixel_size == 32) { /* revert to regular 32bpp raw */ cl->enc_prefer = RFB_ENCODING_RAW; log_write(LL_DETAIL, "Using Raw (32) encoding for client %s", cur_slot->name); } } else { vnc_spu.pixel_size = 32; } if (cl->enc_prefer == RFB_ENCODING_TIGHT) if (cl->jpeg_quality < 0) cl->jpeg_quality = 6; /* default quality */ log_write(LL_DETAIL, "Using encoding %s (0x%x)", encoding_string(cl->enc_prefer), cl->enc_prefer); crDebug("VNC SPU: Using %s encoding (0x%x) for new client", encoding_string(cl->enc_prefer), cl->enc_prefer); if (cl->enc_prefer == RFB_ENCODING_TIGHT) { crDebug("VNC SPU: Tight jpeg quality level %d, compression level %d", cl->jpeg_quality, cl->compress_level); crDebug("VNC SPU: Force JPEG encoding: %d", opt_force_tight_jpeg); } crDebug("VNC SPU: pixel_size = %d", vnc_spu.pixel_size); aio_setread(rf_client_msg, NULL, 1); }
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 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 cfb8_32WidCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; cfb8_32WidScreenPtr pScreenPriv = CFB8_32WID_GET_SCREEN_PRIVATE(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; PixmapPtr pPixChildren; DDXPointPtr ppt, pptSrc; RegionRec rgnDst, rgnOther, rgnPixmap; BoxPtr pbox; int i, nbox, dx, dy, other_bpp; REGION_NULL(pScreen, &rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); if ((nbox = REGION_NUM_RECTS(&rgnDst)) == 0) { /* Nothing to render. */ REGION_UNINIT(pScreen, &rgnDst); return; } /* First, copy the WID plane for the whole area. */ pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)); if(pptSrc) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } pScreenPriv->WIDOps->WidCopyArea((DrawablePtr)pScreenPriv->pixWid, &rgnDst, pptSrc); DEALLOCATE_LOCAL(pptSrc); } /* Next, we copy children which have a different * bpp than pWin into a temporary pixmap. We will * toss this pixmap back onto the framebuffer before * we return. */ if (pWin->drawable.bitsPerPixel == 8) other_bpp = pScrn->bitsPerPixel; else other_bpp = 8; REGION_NULL(pScreen, &rgnOther); SegregateChildrenBpp(pWin, &rgnOther, 0, other_bpp, pWin->drawable.bitsPerPixel); pPixChildren = NULL; if (REGION_NOTEMPTY(pScreen, &rgnOther)) { REGION_INTERSECT(pScreen, &rgnOther, &rgnOther, prgnSrc); nbox = REGION_NUM_RECTS(&rgnOther); if (nbox) { int width = rgnOther.extents.x2 - rgnOther.extents.x1; int height = rgnOther.extents.y2 - rgnOther.extents.y1; int depth = (other_bpp == 8) ? 8 : pScrn->depth; if (other_bpp == 8) pPixChildren = cfbCreatePixmap(pScreen, width, height, depth); else pPixChildren = cfb32CreatePixmap(pScreen, width, height, depth); } if (nbox && pPixChildren && (pptSrc = (DDXPointPtr) ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnOther); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } REGION_NULL(pScreen, &rgnPixmap); REGION_COPY(pScreen, &rgnPixmap, &rgnOther); REGION_TRANSLATE(pScreen, &rgnPixmap, -(rgnOther.extents.x1), -(rgnOther.extents.y1)); if (other_bpp == 8) cfbDoBitbltCopy((DrawablePtr)pScreenPriv->pix8, (DrawablePtr)pPixChildren, GXcopy, &rgnPixmap, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pScreenPriv->pix32, (DrawablePtr)pPixChildren, GXcopy, &rgnPixmap, pptSrc, ~0L); REGION_UNINIT(pScreen, &rgnPixmap); DEALLOCATE_LOCAL(pptSrc); } REGION_SUBTRACT(pScreen, &rgnDst, &rgnDst, &rgnOther); } /* Now copy the parent along with all child windows using the same depth. */ nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } if (pWin->drawable.bitsPerPixel == 8) cfbDoBitbltCopy((DrawablePtr)pScreenPriv->pix8, (DrawablePtr)pScreenPriv->pix8, GXcopy, &rgnDst, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pScreenPriv->pix32, (DrawablePtr)pScreenPriv->pix32, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } REGION_UNINIT(pScreen, &rgnDst); if (pPixChildren) { nbox = REGION_NUM_RECTS(&rgnOther); pptSrc = (DDXPointPtr) ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)); if (pptSrc) { pbox = REGION_RECTS(&rgnOther); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 - rgnOther.extents.x1; ppt->y = pbox->y1 - rgnOther.extents.y1; } if (other_bpp == 8) cfbDoBitbltCopy((DrawablePtr)pPixChildren, (DrawablePtr)pScreenPriv->pix8, GXcopy, &rgnOther, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pPixChildren, (DrawablePtr)pScreenPriv->pix32, GXcopy, &rgnOther, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } if (other_bpp == 8) cfbDestroyPixmap(pPixChildren); else cfb32DestroyPixmap(pPixChildren); } REGION_UNINIT(pScreen, &rgnOther); }
/* cfbBitBltcfb == cfbCopyPlaneExpand */ RegionPtr cfbBitBlt ( register DrawablePtr pSrcDrawable, register DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, void (*doBitBlt)( DrawablePtr /*pSrc*/, DrawablePtr /*pDst*/, int /*alu*/, RegionPtr /*prgnDst*/, DDXPointPtr /*pptSrc*/, unsigned long /*planemask*/), unsigned long bitPlane) { RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ Bool freeSrcClip = FALSE; RegionPtr prgnExposed; RegionRec rgnDst; DDXPointPtr pptSrc; register DDXPointPtr ppt; register BoxPtr pbox; int i; register int dx; register int dy; xRectangle origSource; DDXPointRec origDest; int numRects; BoxRec fastBox; int fastClip = 0; /* for fast clipping with pixmap source */ int fastExpose = 0; /* for fast exposures with pixmap source */ origSource.x = srcx; origSource.y = srcy; origSource.width = width; origSource.height = height; origDest.x = dstx; origDest.y = dsty; if ((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate) { (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height); } srcx += pSrcDrawable->x; srcy += pSrcDrawable->y; /* clip the source */ if (pSrcDrawable->type == DRAWABLE_PIXMAP) { if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) { prgnSrcClip = cfbGetCompositeClip(pGC); } else { fastClip = 1; } } else { if (pGC->subWindowMode == IncludeInferiors) { /* * XFree86 DDX empties the border clip when the * VT is inactive */ if (!((WindowPtr) pSrcDrawable)->parent && REGION_NOTEMPTY (pSrcDrawable->pScreen, &((WindowPtr) pSrcDrawable)->borderClip)) { /* * special case bitblt from root window in * IncludeInferiors mode; just like from a pixmap */ fastClip = 1; } else if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) { prgnSrcClip = cfbGetCompositeClip(pGC); } else { prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); freeSrcClip = TRUE; } } else { prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; } } fastBox.x1 = srcx; fastBox.y1 = srcy; fastBox.x2 = srcx + width; fastBox.y2 = srcy + height; /* Don't create a source region if we are doing a fast clip */ if (fastClip) { fastExpose = 1; /* * clip the source; if regions extend beyond the source size, * make sure exposure events get sent */ if (fastBox.x1 < pSrcDrawable->x) { fastBox.x1 = pSrcDrawable->x; fastExpose = 0; } if (fastBox.y1 < pSrcDrawable->y) { fastBox.y1 = pSrcDrawable->y; fastExpose = 0; } if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; fastExpose = 0; } if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; fastExpose = 0; } } else { REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); } dstx += pDstDrawable->x; dsty += pDstDrawable->y; if (pDstDrawable->type == DRAWABLE_WINDOW) { if (!((WindowPtr)pDstDrawable)->realized) { if (!fastClip) REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return NULL; } } dx = srcx - dstx; dy = srcy - dsty; /* Translate and clip the dst to the destination composite clip */ if (fastClip) { RegionPtr cclip; /* Translate the region directly */ fastBox.x1 -= dx; fastBox.x2 -= dx; fastBox.y1 -= dy; fastBox.y2 -= dy; /* If the destination composite clip is one rectangle we can do the clip directly. Otherwise we have to create a full blown region and call intersect */ /* XXX because CopyPlane uses this routine for 8-to-1 bit * copies, this next line *must* also correctly fetch the * composite clip from an mfb gc */ cclip = cfbGetCompositeClip(pGC); if (REGION_NUM_RECTS(cclip) == 1) { BoxPtr pBox = REGION_RECTS(cclip); if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; /* Check to see if the region is empty */ if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { REGION_NULL(pGC->pScreen, &rgnDst); } else { REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); } } else { /* We must turn off fastClip now, since we must create a full blown region. It is intersected with the composite clip below. */ fastClip = 0; REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); } } else { REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); } if (!fastClip) { REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, cfbGetCompositeClip(pGC)); } /* Do bit blitting */ numRects = REGION_NUM_RECTS(&rgnDst); if (numRects && width && height) { if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects * sizeof(DDXPointRec)))) { REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return NULL; } pbox = REGION_RECTS(&rgnDst); ppt = pptSrc; for (i = numRects; --i >= 0; pbox++, ppt++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask); DEALLOCATE_LOCAL(pptSrc); } prgnExposed = NULL; if (pGC->fExpose) { /* Pixmap sources generate a NoExposed (we return NULL to do this) */ if (!fastExpose) prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, origSource.x, origSource.y, (int)origSource.width, (int)origSource.height, origDest.x, origDest.y, bitPlane); } REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return prgnExposed; }