int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) { int count; int index; xfGfxSurface* surface; UINT16* pSurfaceIds = NULL; xfContext* xfc = (xfContext*) context->custom; freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL); count = context->GetSurfaceIds(context, &pSurfaceIds); for (index = 0; index < count; index++) { surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]); if (!surface || !surface->outputMapped) continue; region16_clear(&surface->invalidRegion); } free(pSurfaceIds); xfc->graphicsReset = TRUE; return 1; }
static int test_r1_r3(void) { REGION16 region; int retCode = -1; const RECTANGLE_16* rects; UINT32 nbRects; RECTANGLE_16 r1 = { 0, 101, 200, 201}; RECTANGLE_16 r3 = {150, 151, 250, 251}; RECTANGLE_16 r1_r3[] = { { 0, 101, 200, 151}, { 0, 151, 250, 201}, {150, 201, 250, 251} }; region16_init(®ion); /* * +=============================================================== * | * |+-----+ +-----+ * || r1 | | | * || +-+------+ +-----+--------+ * || | r3 | | | * |+---+ | ====> +-----+--------+ * | | | | | * | +--------+ +--------+ */ /* R1 + R3 */ if (!region16_union_rect(®ion, ®ion, &r1)) goto out; if (!region16_union_rect(®ion, ®ion, &r3)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects)) goto out; /* R3 + R1 */ region16_clear(®ion); if (!region16_union_rect(®ion, ®ion, &r3)) goto out; if (!region16_union_rect(®ion, ®ion, &r1)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects)) goto out; retCode = 0; out: region16_uninit(®ion); return retCode; }
int gdi_OutputUpdate(rdpGdi* gdi) { int nDstStep; BYTE* pDstData; int nXDst, nYDst; int nXSrc, nYSrc; int nWidth, nHeight; gdiGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; if (!gdi->graphicsReset) return 1; pDstData = gdi->primary_buffer; nDstStep = gdi->bytesPerPixel * gdi->width; surface = (gdiGfxSurface*) gdi->gfx->GetSurfaceData(gdi->gfx, gdi->outputSurfaceId); if (!surface) return -1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = gdi->width; surfaceRect.bottom = gdi->height; region16_intersect_rect(&(gdi->invalidRegion), &(gdi->invalidRegion), &surfaceRect); if (!region16_is_empty(&(gdi->invalidRegion))) { extents = region16_extents(&(gdi->invalidRegion)); nXDst = extents->left; nYDst = extents->top; nXSrc = extents->left; nYSrc = extents->top; nWidth = extents->right - extents->left; nHeight = extents->bottom - extents->top; update->BeginPaint(gdi->context); freerdp_image_copy(pDstData, gdi->format, nDstStep, nXDst, nYDst, nWidth, nHeight, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL); gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, nWidth, nHeight); update->EndPaint(gdi->context); } region16_clear(&(gdi->invalidRegion)); return 1; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_ResetGraphics(RdpgfxClientContext* context, const RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) { UINT32 index; UINT16 count; UINT32 DesktopWidth; UINT32 DesktopHeight; gdiGfxSurface* surface; UINT16* pSurfaceIds = NULL; rdpGdi* gdi = (rdpGdi*) context->custom; rdpUpdate* update = gdi->context->update; rdpSettings* settings = gdi->context->settings; DesktopWidth = resetGraphics->width; DesktopHeight = resetGraphics->height; if ((DesktopWidth != settings->DesktopWidth) || (DesktopHeight != settings->DesktopHeight)) { settings->DesktopWidth = DesktopWidth; settings->DesktopHeight = DesktopHeight; if (update) update->DesktopResize(gdi->context); } context->GetSurfaceIds(context, &pSurfaceIds, &count); for (index = 0; index < count; index++) { surface = (gdiGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]); if (!surface || !surface->outputMapped) continue; if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL, surface->width, surface->height)) { free(pSurfaceIds); return ERROR_INTERNAL_ERROR; } region16_clear(&surface->invalidRegion); } free(pSurfaceIds); if (!freerdp_client_codecs_reset(gdi->context->codecs, FREERDP_CODEC_ALL, gdi->width, gdi->height)) return ERROR_INTERNAL_ERROR; gdi->graphicsReset = TRUE; return CHANNEL_RC_OK; }
int gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { int nDstStep; BYTE* pDstData; int nXDst, nYDst; int nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; pDstData = gdi->primary_buffer; nDstStep = gdi->bytesPerPixel * gdi->width; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!region16_is_empty(&(surface->invalidRegion))) { extents = region16_extents(&(surface->invalidRegion)); nXSrc = extents->left; nYSrc = extents->top; nXDst = surfaceX + extents->left; nYDst = surfaceY + extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; update->BeginPaint(gdi->context); freerdp_image_copy(pDstData, gdi->format, nDstStep, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL); gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); update->EndPaint(gdi->context); } region16_clear(&(surface->invalidRegion)); return 1; }
int xf_OutputUpdate(xfContext* xfc) { UINT16 width, height; xfGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; if (!xfc->graphicsReset) return 1; surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId); if (!surface) return -1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = xfc->width; surfaceRect.bottom = xfc->height; region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); if (!region16_is_empty(&(xfc->invalidRegion))) { extents = region16_extents(&(xfc->invalidRegion)); width = extents->right - extents->left; height = extents->bottom - extents->top; if (width > xfc->width) width = xfc->width; if (height > xfc->height) height = xfc->height; XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); } region16_clear(&(xfc->invalidRegion)); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, True); return 1; }
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) { xfGfxSurface* surface; surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId); surface->outputMapped = TRUE; surface->outputOriginX = surfaceToOutput->outputOriginX; surface->outputOriginY = surfaceToOutput->outputOriginY; region16_clear(&surface->invalidRegion); return 1; }
void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) { int index; int count; RECTANGLE_16 updateRect; RECTANGLE_16 windowRect; ULONG_PTR* pKeys = NULL; xfAppWindow* appWindow; const RECTANGLE_16* extents; REGION16 windowInvalidRegion; region16_init(&windowInvalidRegion); count = HashTable_GetKeys(xfc->railWindows, &pKeys); for (index = 0; index < count; index++) { appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]); if (appWindow) { windowRect.left = MAX(appWindow->x, 0); windowRect.top = MAX(appWindow->y, 0); windowRect.right = MAX(appWindow->x + appWindow->width, 0); windowRect.bottom = MAX(appWindow->y + appWindow->height, 0); region16_clear(&windowInvalidRegion); region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect); if (!region16_is_empty(&windowInvalidRegion)) { extents = region16_extents(&windowInvalidRegion); updateRect.left = extents->left - appWindow->x; updateRect.top = extents->top - appWindow->y; updateRect.right = extents->right - appWindow->x; updateRect.bottom = extents->bottom - appWindow->y; if (appWindow) { xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top, updateRect.right - updateRect.left, updateRect.bottom - updateRect.top); } } } } region16_uninit(&windowInvalidRegion); }
static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { UINT32 nXDst, nYDst; UINT32 nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* rects; UINT32 i, nbRects; rdpUpdate* update = gdi->context->update; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!(rects = region16_rects(&surface->invalidRegion, &nbRects)) || !nbRects) return CHANNEL_RC_OK; update->BeginPaint(gdi->context); for (i = 0; i < nbRects; i++) { nXSrc = rects[i].left; nYSrc = rects[i].top; nXDst = surfaceX + nXSrc; nYDst = surfaceY + nYSrc; width = rects[i].right - rects[i].left; height = rects[i].bottom - rects[i].top; if (!freerdp_image_copy(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) return CHANNEL_RC_NULL_DATA; gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); } update->EndPaint(gdi->context); region16_clear(&(surface->invalidRegion)); return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_MapSurfaceToOutput(RdpgfxClientContext* context, const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) { gdiGfxSurface* surface; surface = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; surface->outputMapped = TRUE; surface->outputOriginX = surfaceToOutput->outputOriginX; surface->outputOriginY = surfaceToOutput->outputOriginY; region16_clear(&surface->invalidRegion); return CHANNEL_RC_OK; }
static int test_basic(void) { REGION16 region; int retCode = -1; const RECTANGLE_16* rects; UINT32 nbRects; /* R1 + R2 ==> disjointed rects */ RECTANGLE_16 r1 = { 0, 101, 200, 201}; RECTANGLE_16 r2 = {150, 301, 250, 401}; RECTANGLE_16 r1_r2[] = { {0, 101, 200, 201}, {150, 301, 250, 401} }; /* r1 */ region16_init(®ion); if (!region16_union_rect(®ion, ®ion, &r1)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16))) goto out; /* r1 + r2 */ if (!region16_union_rect(®ion, ®ion, &r2)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2, nbRects)) goto out; /* clear region */ region16_clear(®ion); region16_rects(®ion, &nbRects); if (nbRects) goto out; retCode = 0; out: region16_uninit(®ion); return retCode; }
/** * Function description * Notify client for resize. The new desktop width/height * should have already been updated in rdpSettings. * * @return TRUE on success */ static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus) { rdpContext* context; rdpSettings* settings; rdpShadowServer* server; freerdp_peer* peer; server = client->server; context = (rdpContext*) client; peer = context->peer; settings = context->settings; /** * Unset client activated flag to avoid sending update message during * resize. DesktopResize will reactive the client and * shadow_client_activate would be invoked later. */ client->activated = FALSE; /* Close Gfx surfaces */ if (pStatus->gfxSurfaceCreated) { if (!shadow_client_rdpgfx_release_surface(client)) return FALSE; pStatus->gfxSurfaceCreated = FALSE; } /* Send Resize */ if (!peer->update->DesktopResize(peer->update->context)) { WLog_ERR(TAG, "DesktopResize failed"); return FALSE; } /* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */ EnterCriticalSection(&(client->lock)); region16_clear(&(client->invalidRegion)); LeaveCriticalSection(&(client->lock)); WLog_INFO(TAG, "Client from %s is resized (%dx%d@%d)", peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); return TRUE; }
void wf_rail_invalidate_region(wfContext* wfc, REGION16* invalidRegion) { int index; int count; RECT updateRect; RECTANGLE_16 windowRect; ULONG_PTR* pKeys = NULL; wfRailWindow* railWindow; const RECTANGLE_16* extents; REGION16 windowInvalidRegion; region16_init(&windowInvalidRegion); count = HashTable_GetKeys(wfc->railWindows, &pKeys); for (index = 0; index < count; index++) { railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows, (void*) pKeys[index]); if (railWindow) { windowRect.left = railWindow->x; windowRect.top = railWindow->y; windowRect.right = railWindow->x + railWindow->width; windowRect.bottom = railWindow->y + railWindow->height; region16_clear(&windowInvalidRegion); region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect); if (!region16_is_empty(&windowInvalidRegion)) { extents = region16_extents(&windowInvalidRegion); updateRect.left = extents->left - railWindow->x; updateRect.top = extents->top - railWindow->y; updateRect.right = extents->right - railWindow->x; updateRect.bottom = extents->bottom - railWindow->y; InvalidateRect(railWindow->hWnd, &updateRect, FALSE); } } } region16_uninit(&windowInvalidRegion); }
static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { UINT32 nXDst, nYDst; UINT32 nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!region16_is_empty(&(surface->invalidRegion))) { extents = region16_extents(&(surface->invalidRegion)); nXSrc = extents->left; nYSrc = extents->top; nXDst = surfaceX + extents->left; nYDst = surfaceY + extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; update->BeginPaint(gdi->context); if (!freerdp_image_copy(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) return CHANNEL_RC_NULL_DATA; gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); update->EndPaint(gdi->context); } region16_clear(&(surface->invalidRegion)); return CHANNEL_RC_OK; }
static int test_r1_r6(void) { REGION16 region; int retCode = -1; const RECTANGLE_16* rects; UINT32 nbRects; RECTANGLE_16 r1 = { 0, 101, 200, 201}; RECTANGLE_16 r6 = {150, 121, 170, 131}; region16_init(®ion); /* * +=============================================================== * | * |+--------+ +--------+ * || r1 | | | * || +--+ | | | * || |r6| | =====> | | * || +--+ | | | * || | | | * |+--------+ +--------+ * | */ region16_clear(®ion); if (!region16_union_rect(®ion, ®ion, &r1)) goto out; if (!region16_union_rect(®ion, ®ion, &r6)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 1 || !compareRectangles(rects, &r1, nbRects)) goto out; retCode = 0; out: region16_uninit(®ion); return retCode; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) { int index; UINT16 count; xfGfxSurface* surface; UINT16* pSurfaceIds = NULL; xfContext* xfc = (xfContext*) context->custom; context->GetSurfaceIds(context, &pSurfaceIds, &count); for (index = 0; index < count; index++) { surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]); if (!surface || !surface->outputMapped) continue; if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL, surface->width, surface->height)) { free(pSurfaceIds); return ERROR_INTERNAL_ERROR; } region16_clear(&surface->invalidRegion); } free(pSurfaceIds); if (!freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL, xfc->settings->DesktopWidth, xfc->settings->DesktopHeight)) return ERROR_INTERNAL_ERROR; xfc->graphicsReset = TRUE; return CHANNEL_RC_OK; }
static void UwacSubmitBufferPtr(UwacWindow* window, UwacBuffer* buffer) { UINT32 nrects, i; #ifdef HAVE_PIXMAN_REGION const pixman_box32_t* box; #else const RECTANGLE_16* box; #endif wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0); #ifdef HAVE_PIXMAN_REGION box = pixman_region32_rectangles(&buffer->damage, &nrects); for (i = 0; i < nrects; i++, box++) wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1)); #else box = region16_rects(&buffer->damage, &nrects); for (i = 0; i < nrects; i++, box++) wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top)); #endif if (window->frame_callback) wl_callback_destroy(window->frame_callback); window->frame_callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->frame_callback, &frame_listener, window); wl_surface_commit(window->surface); #ifdef HAVE_PIXMAN_REGION pixman_region32_clear(&buffer->damage); #else region16_clear(&buffer->damage); #endif }
static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) { UINT rc = ERROR_INTERNAL_ERROR; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; rdpGdi* gdi; UINT32 nbRects, x; const RECTANGLE_16* rects; gdi = xfc->context.gdi; surfaceX = surface->gdi.outputOriginX; surfaceY = surface->gdi.outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->gdi.width; surfaceRect.bottom = surface->gdi.height; XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); region16_intersect_rect(&(surface->gdi.invalidRegion), &(surface->gdi.invalidRegion), &surfaceRect); if (!(rects = region16_rects(&surface->gdi.invalidRegion, &nbRects))) return CHANNEL_RC_OK; for (x = 0; x < nbRects; x++) { const UINT32 nXSrc = rects[x].left; const UINT32 nYSrc = rects[x].top; const UINT32 width = rects[x].right - nXSrc; const UINT32 height = rects[x].bottom - nYSrc; const UINT32 nXDst = surfaceX + nXSrc; const UINT32 nYDst = surfaceY + nYSrc; if (surface->stage) { if (!freerdp_image_copy(surface->stage, gdi->dstFormat, surface->stageScanline, nXSrc, nYSrc, width, height, surface->gdi.data, surface->gdi.format, surface->gdi.scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) goto fail; } if (xfc->remote_app) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); xf_lock_x11(xfc, FALSE); xf_rail_paint(xfc, nXDst, nYDst, nXDst + width, nYDst + height); xf_unlock_x11(xfc, FALSE); } else #ifdef WITH_XRENDER if (xfc->context.settings->SmartSizing || xfc->context.settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); xf_draw_screen(xfc, nXDst, nYDst, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); } } rc = CHANNEL_RC_OK; fail: region16_clear(&surface->gdi.invalidRegion); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, False); return rc; }
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int count; int status; int x, y; int width, height; XImage* image; rdpShadowScreen* screen; rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 invalidRect; server = subsystem->server; surface = server->surface; screen = server->screen; count = ArrayList_Count(server->clients); if (count < 1) return 1; if (subsystem->use_xshm) { XLockDisplay(subsystem->display); XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); XSync(subsystem->display, False); XUnlockDisplay(subsystem->display); image = subsystem->fb_image; status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); if (status > 0) { x = invalidRect.left; y = invalidRect.top; width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x - surface->x, y - surface->y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); SetEvent(subsystem->updateEvent); EnterSynchronizationBarrier(&(subsystem->barrier), 0); DeleteSynchronizationBarrier(&(subsystem->barrier)); ResetEvent(subsystem->updateEvent); region16_clear(&(subsystem->invalidRegion)); } } else { XLockDisplay(subsystem->display); image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); XUnlockDisplay(subsystem->display); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); if (status > 0) { x = invalidRect.left; y = invalidRect.top; width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x, y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); SetEvent(subsystem->updateEvent); EnterSynchronizationBarrier(&(subsystem->barrier), 0); DeleteSynchronizationBarrier(&(subsystem->barrier)); ResetEvent(subsystem->updateEvent); region16_clear(&(subsystem->invalidRegion)); } XDestroyImage(image); } return 1; }
BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect) { REGION16_DATA *newItems; const RECTANGLE_16 *srcPtr, *endPtr, *srcExtents; RECTANGLE_16 *dstPtr; int nbRects, usedRects; RECTANGLE_16 common, newExtents; assert(src); assert(src->data); srcPtr = region16_rects(src, &nbRects); if (!nbRects) { region16_clear(dst); return TRUE; } srcExtents = region16_extents(src); if (nbRects == 1) { BOOL intersects = rectangles_intersection(srcExtents, rect, &common); region16_clear(dst); if (intersects) return region16_union_rect(dst, dst, &common); return TRUE; } newItems = allocateRegion(nbRects); if (!newItems) return FALSE; dstPtr = (RECTANGLE_16*) (&newItems[1]); usedRects = 0; ZeroMemory(&newExtents, sizeof(newExtents)); /* accumulate intersecting rectangles, the final region16_simplify_bands() will * do all the bad job to recreate correct rectangles */ for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) { if (rectangles_intersection(srcPtr, rect, &common)) { *dstPtr = common; usedRects++; dstPtr++; newExtents.top = MIN(common.top, newExtents.top); newExtents.left = MIN(common.left, newExtents.left); newExtents.bottom = MAX(common.bottom, newExtents.bottom); newExtents.right = MAX(common.right, newExtents.right); } } newItems->nbRects = usedRects; newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16)); if (dst->data->size) free(dst->data); dst->data = realloc(newItems, newItems->size); if (!dst->data) { free(newItems); return FALSE; } dst->extents = newExtents; return region16_simplify_bands(dst); }
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int count; int status; int x, y; int width, height; XImage* image; rdpShadowScreen* screen; rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 invalidRect; RECTANGLE_16 surfaceRect; const RECTANGLE_16 *extents; server = subsystem->server; surface = server->surface; screen = server->screen; count = ArrayList_Count(server->clients); if (count < 1) return 1; if ((count == 1) && subsystem->suppressOutput) return 1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; XLockDisplay(subsystem->display); if (subsystem->use_xshm) { image = subsystem->fb_image; XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); } else { image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); } XSync(subsystem->display, False); XUnlockDisplay(subsystem->display); region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); if (!region16_is_empty(&(subsystem->invalidRegion))) { extents = region16_extents(&(subsystem->invalidRegion)); x = extents->left; y = extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x, y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); //x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); SetEvent(subsystem->updateEvent); EnterSynchronizationBarrier(&(subsystem->barrier), 0); DeleteSynchronizationBarrier(&(subsystem->barrier)); if (count == 1) { rdpShadowClient* client; client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0); if (client) { subsystem->captureFrameRate = client->encoder->fps; } } ResetEvent(subsystem->updateEvent); region16_clear(&(subsystem->invalidRegion)); } if (!subsystem->use_xshm) XDestroyImage(image); return 1; }
static int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) { UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = surfaceX; surfaceRect.top = surfaceY; surfaceRect.right = surfaceX + surface->width; surfaceRect.bottom = surfaceY + surface->height; XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); if (!region16_is_empty(&surface->invalidRegion)) { extents = region16_extents(&surface->invalidRegion); width = extents->right - extents->left; height = extents->bottom - extents->top; if (width > surface->width) width = surface->width; if (height > surface->height) height = surface->height; if (surface->stage) { freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0, surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL); } #ifdef WITH_XRENDER if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height); xf_draw_screen(xfc, extents->left, extents->top, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height); } } region16_clear(&surface->invalidRegion); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, False); return 1; }
static int test_r1_r7_r8(void) { REGION16 region; int retCode = -1; const RECTANGLE_16* rects; UINT32 nbRects; RECTANGLE_16 r1 = { 0, 101, 200, 201}; RECTANGLE_16 r7 = {300, 101, 500, 201}; RECTANGLE_16 r8 = {150, 121, 400, 131}; RECTANGLE_16 r1_r7_r8[] = { { 0, 101, 200, 121}, {300, 101, 500, 121}, { 0, 121, 500, 131}, { 0, 131, 200, 201}, {300, 131, 500, 201}, }; /* * +=============================================================== * | * |+--------+ +--------+ +--------+ +--------+ * || r1 | | r7 | | | | | * || +------------+ | +--------+---+--------+ * || | r8 | | =====> | | * || +------------+ | +--------+---+--------+ * || | | | | | | | * |+--------+ +--------+ +--------+ +--------+ * | */ region16_init(®ion); if (!region16_union_rect(®ion, ®ion, &r1)) goto out; if (!region16_union_rect(®ion, ®ion, &r7)) goto out; if (!region16_union_rect(®ion, ®ion, &r8)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) goto out; region16_clear(®ion); if (!region16_union_rect(®ion, ®ion, &r1)) goto out; if (!region16_union_rect(®ion, ®ion, &r8)) goto out; if (!region16_union_rect(®ion, ®ion, &r7)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) goto out; region16_clear(®ion); if (!region16_union_rect(®ion, ®ion, &r8)) goto out; if (!region16_union_rect(®ion, ®ion, &r7)) goto out; if (!region16_union_rect(®ion, ®ion, &r1)) goto out; rects = region16_rects(®ion, &nbRects); if (!rects || nbRects != 5 || !compareRectangles(rects, r1_r7_r8, nbRects)) goto out; retCode = 0; out: region16_uninit(®ion); return retCode; }
int shadow_client_send_surface_update(rdpShadowClient* client) { int status = -1; int nXSrc, nYSrc; int nWidth, nHeight; rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowSurface* surface; rdpShadowEncoder* encoder; REGION16 invalidRegion; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; context = (rdpContext*) client; settings = context->settings; server = client->server; encoder = client->encoder; surface = client->inLobby ? server->lobby : server->surface; EnterCriticalSection(&(client->lock)); region16_init(&invalidRegion); region16_copy(&invalidRegion, &(client->invalidRegion)); region16_clear(&(client->invalidRegion)); LeaveCriticalSection(&(client->lock)); surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect); if (server->shareSubRect) { region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect)); } if (region16_is_empty(&invalidRegion)) { region16_uninit(&invalidRegion); return 1; } extents = region16_extents(&invalidRegion); nXSrc = extents->left - 0; nYSrc = extents->top - 0; nWidth = extents->right - extents->left; nHeight = extents->bottom - extents->top; //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d", // nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight); if (settings->RemoteFxCodec || settings->NSCodec) { status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight); } else { status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight); } region16_uninit(&invalidRegion); return status; }
void* shadow_client_thread(rdpShadowClient* client) { DWORD status; DWORD nCount; wMessage message; wMessage pointerPositionMsg; wMessage pointerAlphaMsg; wMessage audioVolumeMsg; HANDLE events[32]; HANDLE ClientEvent; HANDLE ChannelEvent; void* UpdateSubscriber; HANDLE UpdateEvent; freerdp_peer* peer; rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowScreen* screen; rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; wMessageQueue* MsgQueue = client->MsgQueue; server = client->server; screen = server->screen; encoder = client->encoder; subsystem = server->subsystem; context = (rdpContext*) client; peer = context->peer; settings = peer->settings; peer->Capabilities = shadow_client_capabilities; peer->PostConnect = shadow_client_post_connect; peer->Activate = shadow_client_activate; shadow_input_register_callbacks(peer->input); peer->Initialize(peer); peer->update->RefreshRect = (pRefreshRect)shadow_client_refresh_rect; peer->update->SuppressOutput = (pSuppressOutput)shadow_client_suppress_output; peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)shadow_client_surface_frame_acknowledge; if ((!client->vcm) || (!subsystem->updateEvent)) goto out; UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent); if (!UpdateSubscriber) goto out; UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber); ClientEvent = peer->GetEventHandle(peer); ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm); while (1) { nCount = 0; events[nCount++] = UpdateEvent; events[nCount++] = ClientEvent; events[nCount++] = ChannelEvent; events[nCount++] = MessageQueue_Event(MsgQueue); status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0) { if (client->activated) { int index; int numRects = 0; const RECTANGLE_16* rects; int width, height; /* Check resize */ shadow_client_calc_desktop_size(server, &width, &height); if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height) { /* Screen size changed, do resize */ settings->DesktopWidth = width; settings->DesktopHeight = height; /** * Unset client activated flag to avoid sending update message during * resize. DesktopResize will reactive the client and * shadow_client_activate would be invoked later. */ client->activated = FALSE; /* Send Resize */ peer->update->DesktopResize(peer->update->context); // update_send_desktop_resize /* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */ region16_clear(&(client->invalidRegion)); WLog_ERR(TAG, "Client from %s is resized (%dx%d@%d)", peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); } else { /* Send frame */ rects = region16_rects(&(subsystem->invalidRegion), &numRects); for (index = 0; index < numRects; index++) { region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]); } shadow_client_send_surface_update(client); } } /* * The return value of shadow_multiclient_consume is whether or not the subscriber really consumes the event. * It's not cared currently. */ (void)shadow_multiclient_consume(UpdateSubscriber); } if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0) { if (!peer->CheckFileDescriptor(peer)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } } if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm)) { WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure"); break; } } if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0) { /* Drain messages. Pointer update could be accumulated. */ pointerPositionMsg.id = 0; pointerPositionMsg.Free= NULL; pointerAlphaMsg.id = 0; pointerAlphaMsg.Free = NULL; audioVolumeMsg.id = 0; audioVolumeMsg.Free = NULL; while (MessageQueue_Peek(MsgQueue, &message, TRUE)) { if (message.id == WMQ_QUIT) { break; } switch(message.id) { case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerPositionMsg); CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerAlphaMsg); CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID: /* Abandon previous message */ shadow_client_free_queued_message(&audioVolumeMsg); CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage)); break; default: shadow_client_subsystem_process_message(client, &message); break; } } if (message.id == WMQ_QUIT) { /* Release stored message */ shadow_client_free_queued_message(&pointerPositionMsg); shadow_client_free_queued_message(&pointerAlphaMsg); shadow_client_free_queued_message(&audioVolumeMsg); break; } else { /* Process accumulated messages if needed */ if (pointerPositionMsg.id) { shadow_client_subsystem_process_message(client, &pointerPositionMsg); } if (pointerAlphaMsg.id) { shadow_client_subsystem_process_message(client, &pointerAlphaMsg); } if (audioVolumeMsg.id) { shadow_client_subsystem_process_message(client, &audioVolumeMsg); } } } } /* Free channels early because we establish channels in post connect */ shadow_client_channels_free(client); if (UpdateSubscriber) { shadow_multiclient_release_subscriber(UpdateSubscriber); UpdateSubscriber = NULL; } if (peer->connected && subsystem->ClientDisconnect) { subsystem->ClientDisconnect(subsystem, client); } out: peer->Disconnect(peer); freerdp_peer_context_free(peer); freerdp_peer_free(peer); ExitThread(0); return NULL; }
int xf_OutputUpdate(xfContext* xfc) { UINT16 width, height; xfGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; if (!xfc->graphicsReset) return 1; surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId); if (!surface) return -1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = xfc->width; surfaceRect.bottom = xfc->height; region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); if (!region16_is_empty(&(xfc->invalidRegion))) { extents = region16_extents(&(xfc->invalidRegion)); width = extents->right - extents->left; height = extents->bottom - extents->top; if (width > xfc->width) width = xfc->width; if (height > xfc->height) height = xfc->height; if (surface->stage) { freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0, surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL); } #ifdef WITH_XRENDER if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures) { XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); xf_draw_screen(xfc, extents->left, extents->top, width, height); } else #endif { XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, extents->left, extents->top, extents->left, extents->top, width, height); } } region16_clear(&(xfc->invalidRegion)); XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, True); return 1; }
int win_shadow_surface_copy(winShadowSubsystem* subsystem) { int x, y; int width; int height; int count; int status = 1; int nDstStep = 0; BYTE* pDstData = NULL; rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 surfaceRect; RECTANGLE_16 invalidRect; const RECTANGLE_16* extents; server = subsystem->server; surface = server->surface; if (ArrayList_Count(server->clients) < 1) { region16_clear(&(subsystem->invalidRegion)); return 1; } surfaceRect.left = surface->x; surfaceRect.top = surface->y; surfaceRect.right = surface->x + surface->width; surfaceRect.bottom = surface->y + surface->height; region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); if (region16_is_empty(&(subsystem->invalidRegion))) return 1; extents = region16_extents(&(subsystem->invalidRegion)); CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16)); shadow_capture_align_clip_rect(&invalidRect, &surfaceRect); x = invalidRect.left; y = invalidRect.top; width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; if (0) { x = 0; y = 0; width = surface->width; height = surface->height; } WLog_INFO(TAG, "SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d", x, y, width, height, x + width, y + height); #if defined(WITH_WDS_API) { rdpGdi* gdi; shwContext* shw; rdpContext* context; shw = subsystem->shw; context = (rdpContext*) shw; gdi = context->gdi; pDstData = gdi->primary_buffer; nDstStep = gdi->width * 4; } #elif defined(WITH_DXGI_1_2) status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height); #endif if (status <= 0) return status; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x - surface->x, y - surface->y, width, height, pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0, NULL); ArrayList_Lock(server->clients); count = ArrayList_Count(server->clients); shadow_multiclient_publish_and_wait(subsystem->updateEvent); ArrayList_Unlock(server->clients); region16_clear(&(subsystem->invalidRegion)); return 1; }
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int count; int status; int x, y; int width, height; XImage* image; rdpShadowScreen* screen; rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 invalidRect; RECTANGLE_16 surfaceRect; const RECTANGLE_16 *extents; server = subsystem->server; surface = server->surface; screen = server->screen; count = ArrayList_Count(server->clients); if (count < 1) return 1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; XLockDisplay(subsystem->display); /* * Ignore BadMatch error during image capture. The screen size may be * changed outside. We will resize to correct resolution at next frame */ XSetErrorHandler(x11_shadow_error_handler_for_capture); if (subsystem->use_xshm) { image = subsystem->fb_image; XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); } else { image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); if (!image) { /* * BadMatch error happened. The size may have been changed again. * Give up this frame and we will resize again in next frame */ goto fail_capture; } status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); } /* Restore the default error handler */ XSetErrorHandler(NULL); XSync(subsystem->display, False); XUnlockDisplay(subsystem->display); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!region16_is_empty(&(surface->invalidRegion))) { extents = region16_extents(&(surface->invalidRegion)); x = extents->left; y = extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x, y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); //x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); shadow_subsystem_frame_update((rdpShadowSubsystem *)subsystem); if (count == 1) { rdpShadowClient* client; client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0); if (client) { subsystem->captureFrameRate = shadow_encoder_preferred_fps(client->encoder); } } region16_clear(&(surface->invalidRegion)); } if (!subsystem->use_xshm) XDestroyImage(image); return 1; fail_capture: XSetErrorHandler(NULL); XSync(subsystem->display, False); XUnlockDisplay(subsystem->display); return 0; }
/** * Function description * * @return TRUE on success (or nothing need to be updated) */ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus) { BOOL ret = TRUE; int nXSrc, nYSrc; int nWidth, nHeight; rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowSurface* surface; rdpShadowEncoder* encoder; REGION16 invalidRegion; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; BYTE* pSrcData; int nSrcStep; int index; int numRects = 0; const RECTANGLE_16* rects; context = (rdpContext*) client; settings = context->settings; server = client->server; encoder = client->encoder; surface = client->inLobby ? server->lobby : server->surface; EnterCriticalSection(&(client->lock)); region16_init(&invalidRegion); region16_copy(&invalidRegion, &(client->invalidRegion)); region16_clear(&(client->invalidRegion)); LeaveCriticalSection(&(client->lock)); rects = region16_rects(&(surface->invalidRegion), &numRects); for (index = 0; index < numRects; index++) { region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]); } surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect); if (server->shareSubRect) { region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect)); } if (region16_is_empty(&invalidRegion)) { /* No image region need to be updated. Success */ goto out; } extents = region16_extents(&invalidRegion); nXSrc = extents->left; nYSrc = extents->top; nWidth = extents->right - extents->left; nHeight = extents->bottom - extents->top; pSrcData = surface->data; nSrcStep = surface->scanline; /* Move to new pSrcData / nXSrc / nYSrc according to sub rect */ if (server->shareSubRect) { int subX, subY; subX = server->subRect.left; subY = server->subRect.top; nXSrc -= subX; nYSrc -= subY; pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)]; } //WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d", // nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight); if (settings->SupportGraphicsPipeline && settings->GfxH264 && pStatus->gfxOpened) { /* GFX/h264 always full screen encoded */ nWidth = settings->DesktopWidth; nHeight = settings->DesktopHeight; /* Create primary surface if have not */ if (!pStatus->gfxSurfaceCreated) { /* Only init surface when we have h264 supported */ if (!(ret = shadow_client_rdpgfx_reset_graphic(client))) goto out; if (!(ret = shadow_client_rdpgfx_new_surface(client))) goto out; pStatus->gfxSurfaceCreated = TRUE; } ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, 0, 0, nWidth, nHeight); } else if (settings->RemoteFxCodec || settings->NSCodec) { ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth, nHeight); } else { ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth, nHeight); } out: region16_uninit(&invalidRegion); return ret; }