TLIBAPI TBOOL region_subregion(struct RectPool *pool, struct Region *dregion, struct Region *sregion) { TBOOL success = TTRUE; struct TNode *next, *node = sregion->rg_Rects.rl_List.tlh_Head; for (; success && (next = node->tln_Succ); node = next) { struct RectNode *rn = (struct RectNode *) node; success = region_subrect(pool, dregion, rn->rn_Rect); } /* note: if unsucessful, dregion is of no use anymore */ return success; }
LOCAL void rfb_flush_clients(struct rfb_Display *mod, TBOOL also_external) { TAPTR TExecBase = mod->rfb_ExecBase; struct RectPool *pool = &mod->rfb_RectPool; /* flush windows to buffer */ /* screen mask: */ struct Rect s; REGION_RECT_SET(&s, 0, 0, mod->rfb_Width - 1, mod->rfb_Height - 1); struct Region S; if (region_init(pool, &S, s.r)) { struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct rfb_Window *v = (struct rfb_Window *) node; if (v->rfbw_Flags & RFBWFL_DIRTY) { struct Region *R = &v->rfbw_DirtyRegion; TINT sx = v->rfbw_ScreenRect.r[0]; TINT sy = v->rfbw_ScreenRect.r[1]; region_shift(R, sx, sy); region_andregion(pool, R, &S); struct TNode *rnext, *rnode = R->rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (rnext = rnode->tln_Succ); rnode = rnext) { struct RectNode *r = (struct RectNode *) rnode; TINT x0 = r->rn_Rect[0]; TINT y0 = r->rn_Rect[1]; TINT x1 = r->rn_Rect[2]; TINT y1 = r->rn_Rect[3]; pixconv_convert(&v->rfbw_PixBuf, &mod->rfb_PixBuf, x0, y0, x1, y1, x0 - sx, y0 - sy, TFALSE, TFALSE); region_orrect(pool, &mod->rfb_DirtyRegion, r->rn_Rect, TTRUE); mod->rfb_Flags |= RFBFL_DIRTY; } region_free(pool, R); v->rfbw_Flags &= ~RFBWFL_DIRTY; } /* subtract this window from screenmask: */ region_subrect(pool, &S, v->rfbw_ScreenRect.r); } region_free(pool, &S); } /* flush buffer to device(s) */ if (mod->rfb_Flags & RFBFL_DIRTY) { struct Region *D = &mod->rfb_DirtyRegion; struct TNode *next, *node; #if defined(ENABLE_VNCSERVER) if (also_external && mod->rfb_VNCTask) rfb_vnc_flush(mod, D); #endif /* flush to sub pixbuf: */ if (mod->rfb_Flags & RFBFL_BUFFER_DEVICE) { node = D->rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *r = (struct RectNode *) node; TINT x0 = r->rn_Rect[0]; TINT y0 = r->rn_Rect[1]; TINT x1 = r->rn_Rect[2]; TINT y1 = r->rn_Rect[3]; pixconv_convert(&mod->rfb_PixBuf, &mod->rfb_DevBuf, x0, y0, x1, y1, x0, y0, TFALSE, TFALSE); } } /* flush to sub device: */ if (mod->rfb_RndDevice) { TTAGITEM tags[2]; tags[0].tti_Tag = TVisual_PixelFormat; tags[0].tti_Value = mod->rfb_PixBuf.tpb_Format; tags[1].tti_Tag = TTAG_DONE; /* NOTE: do multiple flushes asynchronously? */ struct TVRequest *req = mod->rfb_RndRequest; req->tvr_Req.io_Command = TVCMD_DRAWBUFFER; req->tvr_Op.DrawBuffer.Window = mod->rfb_RndInstance; req->tvr_Op.DrawBuffer.Tags = tags; req->tvr_Op.DrawBuffer.TotWidth = mod->rfb_Width; node = D->rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *r = (struct RectNode *) node; TINT x0 = r->rn_Rect[0]; TINT y0 = r->rn_Rect[1]; TINT x1 = r->rn_Rect[2]; TINT y1 = r->rn_Rect[3]; req->tvr_Op.DrawBuffer.RRect[0] = x0; req->tvr_Op.DrawBuffer.RRect[1] = y0; req->tvr_Op.DrawBuffer.RRect[2] = x1 - x0 + 1; req->tvr_Op.DrawBuffer.RRect[3] = y1 - y0 + 1; req->tvr_Op.DrawBuffer.Buf = TVPB_GETADDRESS(&mod->rfb_PixBuf, x0, y0); TDoIO(&req->tvr_Req); } req->tvr_Req.io_Command = TVCMD_FLUSH; req->tvr_Op.Flush.Window = mod->rfb_RndInstance; req->tvr_Op.Flush.Rect[0] = 0; req->tvr_Op.Flush.Rect[1] = 0; req->tvr_Op.Flush.Rect[2] = -1; req->tvr_Op.Flush.Rect[3] = -1; TDoIO(&req->tvr_Req); } region_free(&mod->rfb_RectPool, D); mod->rfb_Flags &= ~RFBFL_DIRTY; } }
LOCAL TBOOL rfb_damage(struct rfb_Display *mod, TINT drect[], struct rfb_Window *v) { TAPTR TExecBase = TGetExecBase(mod); struct RectPool *pool = &mod->rfb_RectPool; struct Region A, B; if (!region_init(pool, &A, drect)) return TFALSE; TDBPRINTF(TDB_TRACE, ("incoming damage: %d %d %d %d\n", drect[0], drect[1], drect[2], drect[3])); /* traverse window stack; refresh B where A and B overlap ; A = A - B */ struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; TBOOL success = TTRUE; TBOOL below = TFALSE; TLock(mod->rfb_InstanceLock); for (; success && !region_isempty(pool, &A) && (next = node->tln_Succ); node = next) { struct rfb_Window *bv = (struct rfb_Window *) node; if (v && !below) { if (bv == v) below = TTRUE; else /* above: subtract current from rect to be damaged: */ success = region_subrect(pool, &A, bv->rfbw_ScreenRect.r); continue; } success = TFALSE; if (region_init(pool, &B, bv->rfbw_ScreenRect.r)) { if (region_andregion(pool, &B, &A)) { region_shift(&B, bv->rfbw_WinRect.r[0] - bv->rfbw_ScreenRect.r[0], bv->rfbw_WinRect.r[1] - bv->rfbw_ScreenRect.r[1]); struct TNode *next, *node = B.rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *r = (struct RectNode *) node; if (bv->rfbw_Flags & RFBWFL_BACKBUFFER) { rfb_markdirty(mod, bv, r->rn_Rect); } else if (bv->rfbw_InputMask & TITYPE_REFRESH) { TIMSG *imsg; if (rfb_getimsg(mod, bv, &imsg, TITYPE_REFRESH)) { TDBPRINTF(TDB_TRACE, ("send refresh %d %d %d %d\n", r->rn_Rect[0], r->rn_Rect[1], r->rn_Rect[2], r->rn_Rect[3])); imsg->timsg_X = r->rn_Rect[0]; imsg->timsg_Y = r->rn_Rect[1]; imsg->timsg_Width = r->rn_Rect[2] - r->rn_Rect[0] + 1; imsg->timsg_Height = r->rn_Rect[3] - r->rn_Rect[1] + 1; imsg->timsg_X -= bv->rfbw_ScreenRect.r[0]; imsg->timsg_Y -= bv->rfbw_ScreenRect.r[1]; TPutMsg(bv->rfbw_IMsgPort, TNULL, imsg); } } } success = TTRUE; } region_free(pool, &B); } if (success) success = region_subrect(pool, &A, bv->rfbw_ScreenRect.r); } TUnlock(mod->rfb_InstanceLock); region_free(pool, &A); return success; }