diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 8f4207734..b93962b0e 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -90,7 +90,6 @@ struct rdp_shadow_client CRITICAL_SECTION lock; REGION16 invalidRegion; rdpShadowServer* server; - rdpShadowSurface* lobby; rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; @@ -112,6 +111,7 @@ struct rdp_shadow_server wArrayList* clients; rdpShadowScreen* screen; rdpShadowSurface* surface; + rdpShadowSurface* lobby; rdpShadowCapture* capture; rdpShadowSubsystem* subsystem; @@ -282,6 +282,8 @@ FREERDP_API int shadow_client_boardcast_quit(rdpShadowServer* server, int nExitC FREERDP_API int shadow_encoder_preferred_fps(rdpShadowEncoder* encoder); FREERDP_API UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder); +FREERDP_API BOOL shadow_screen_resize(rdpShadowScreen* screen); + #ifdef __cplusplus } #endif diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 230ae4609..1cd97662c 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -51,6 +51,8 @@ #define TAG SERVER_TAG("shadow.x11") +int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors); + #ifdef WITH_PAM #include @@ -273,12 +275,6 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U x += surface->x; y += surface->y; - if (server->shareSubRect) - { - x += server->subRect.left; - y += server->subRect.top; - } - XTestGrabControl(subsystem->display, True); if (flags & PTR_FLAGS_WHEEL) @@ -332,12 +328,6 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 x += surface->x; y += surface->y; - if (server->shareSubRect) - { - x += server->subRect.left; - y += server->subRect.top; - } - XTestGrabControl(subsystem->display, True); XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); @@ -495,6 +485,13 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) y = root_y; } + /* Convert to offset based on current surface */ + if (surface) + { + x -= surface->x; + y -= surface->y; + } + if ((x != subsystem->pointerX) || (y != subsystem->pointerY)) { subsystem->pointerX = x; @@ -572,8 +569,8 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) nWidth = subsystem->cursorWidth; nHeight = subsystem->cursorHeight; - nXDst = subsystem->pointerX - surface->x - subsystem->cursorHotX; - nYDst = subsystem->pointerY - surface->y - subsystem->cursorHotY; + nXDst = subsystem->pointerX - subsystem->cursorHotX; + nYDst = subsystem->pointerY - subsystem->cursorHotY; if (nXDst >= surface->width) return 1; @@ -659,6 +656,51 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) return 1; } +BOOL x11_shadow_check_resize(x11ShadowSubsystem* subsystem) +{ + MONITOR_DEF* virtualScreen; + XWindowAttributes attr; + XGetWindowAttributes(subsystem->display, subsystem->root_window, &attr); + + if (attr.width != subsystem->width || attr.height != subsystem->height) + { + /* Screen size changed. Refresh monitor definitions and trigger screen resize */ + subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16); + + shadow_screen_resize(subsystem->server->screen); + + subsystem->width = attr.width; + subsystem->height = attr.height; + + virtualScreen = &(subsystem->virtualScreen); + virtualScreen->left = 0; + virtualScreen->top = 0; + virtualScreen->right = subsystem->width; + virtualScreen->bottom = subsystem->height; + virtualScreen->flags = 1; + + return TRUE; + } + + return FALSE; +} + +static int x11_shadow_error_handler_for_capture(Display * display, XErrorEvent * event) +{ + char msg[256]; + XGetErrorText(display, event->error_code, (char *) &msg, sizeof(msg)); + WLog_ERR(TAG, "X11 error: %s Error code: %x, request code: %x, minor code: %x", + msg, event->error_code, event->request_code, event->minor_code); + + /* Ignore BAD MATCH error during image capture. Abort in other case */ + if (event->error_code != BadMatch) + { + abort(); + } + + return 0; +} + int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int count; @@ -692,6 +734,12 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) 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; @@ -707,10 +755,22 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) 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); @@ -757,6 +817,12 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) XDestroyImage(image); return 1; + +fail_capture: + XSetErrorHandler(NULL); + XSync(subsystem->display, False); + XUnlockDisplay(subsystem->display); + return 0; } int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message) @@ -866,6 +932,7 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { + x11_shadow_check_resize(subsystem); x11_shadow_screen_grab(subsystem); x11_shadow_query_cursor(subsystem, FALSE); @@ -1127,6 +1194,8 @@ int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) } #endif + XCloseDisplay(display); + if (numMonitors < 1) { index = 0; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 694289985..98b973230 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -150,12 +150,6 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client) MessageQueue_Clear(client->MsgQueue); MessageQueue_Free(client->MsgQueue); - if (client->lobby) - { - shadow_surface_free(client->lobby); - client->lobby = NULL; - } - if (client->encoder) { shadow_encoder_free(client->encoder); @@ -188,6 +182,19 @@ BOOL shadow_client_capabilities(freerdp_peer* peer) return TRUE; } +static INLINE void shadow_client_calc_desktop_size(rdpShadowServer* server, int* pWidth, int* pHeight) +{ + RECTANGLE_16 viewport = {0, 0, server->screen->width, server->screen->height}; + + if (server->shareSubRect) + { + rectangles_intersection(&viewport, &(server->subRect), &viewport); + } + + (*pWidth) = viewport.right - viewport.left; + (*pHeight) = viewport.bottom - viewport.top; +} + BOOL shadow_client_post_connect(freerdp_peer* peer) { int authStatus; @@ -203,17 +210,7 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) server = client->server; subsystem = server->subsystem; - if (!server->shareSubRect) - { - width = server->screen->width; - height = server->screen->height; - } - else - { - width = server->subRect.right - server->subRect.left; - height = server->subRect.bottom - server->subRect.top; - } - + shadow_client_calc_desktop_size(server, &width, &height); settings->DesktopWidth = width; settings->DesktopHeight = height; @@ -232,13 +229,11 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) invalidRect.left = 0; invalidRect.top = 0; - invalidRect.right = width; - invalidRect.bottom = height; + invalidRect.right = server->screen->width; + invalidRect.bottom = server->screen->height; region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect); - shadow_client_init_lobby(client); - authStatus = -1; if (settings->Username && settings->Password) @@ -270,6 +265,30 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) return TRUE; } +/* Convert rects in sub rect coordinate to client/surface coordinate */ +static INLINE void shadow_client_convert_rects(rdpShadowClient* client, + RECTANGLE_16* dst, RECTANGLE_16* src, UINT32 numRects) +{ + if (client->server->shareSubRect) + { + int i = 0; + UINT16 offsetX = client->server->subRect.left; + UINT16 offsetY = client->server->subRect.top; + + for (i = 0; i < numRects; i++) + { + dst[i].left = src[i].left + offsetX; + dst[i].right = src[i].right + offsetX; + dst[i].top = src[i].top + offsetY; + dst[i].bottom = src[i].bottom + offsetY; + } + } + else + { + CopyMemory(dst, src, numRects * sizeof(RECTANGLE_16)); + } +} + BOOL shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas) { wMessage message = { 0 }; @@ -294,7 +313,7 @@ BOOL shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_1 return FALSE; } - CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16)); + shadow_client_convert_rects(client, wParam->rects, areas, wParam->numRects); } message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID; @@ -319,7 +338,7 @@ BOOL shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGL wParam->allow = (UINT32) allow; if (area) - CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16)); + shadow_client_convert_rects(client, &(wParam->rect), area, 1); message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID; message.wParam = (void*) wParam; @@ -445,7 +464,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s rect.height = nHeight; if (!(messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData, - surface->width, surface->height, nSrcStep, &numMessages, + settings->DesktopWidth, settings->DesktopHeight, nSrcStep, &numMessages, settings->MultifragMaxRequestSize))) { return 0; @@ -455,12 +474,12 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s cmd.destLeft = 0; cmd.destTop = 0; - cmd.destRight = surface->width; - cmd.destBottom = surface->height; + cmd.destRight = settings->DesktopWidth; + cmd.destBottom = settings->DesktopHeight; cmd.bpp = 32; - cmd.width = surface->width; - cmd.height = surface->height; + cmd.width = settings->DesktopWidth; + cmd.height = settings->DesktopHeight; cmd.skipCompression = TRUE; if (numMessages > 0) @@ -569,6 +588,21 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* nSrcStep = surface->scanline; SrcFormat = PIXEL_FORMAT_RGB32; + if (server->shareSubRect) + { + int subX, subY; + int subWidth, subHeight; + + subX = server->subRect.left; + subY = server->subRect.top; + subWidth = server->subRect.right - server->subRect.left; + subHeight = server->subRect.bottom - server->subRect.top; + + nXSrc -= subX; + nYSrc -= subY; + pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)]; + } + if ((nXSrc % 4) != 0) { nWidth += (nXSrc % 4); @@ -747,7 +781,7 @@ int shadow_client_send_surface_update(rdpShadowClient* client) server = client->server; encoder = client->encoder; - surface = client->inLobby ? client->lobby : server->surface; + surface = client->inLobby ? server->lobby : server->surface; EnterCriticalSection(&(client->lock)); @@ -915,6 +949,12 @@ int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* m pointerPosition.xPos = msg->xPos; pointerPosition.yPos = msg->yPos; + if (client->server->shareSubRect) + { + pointerPosition.xPos -= client->server->subRect.left; + pointerPosition.yPos -= client->server->subRect.top; + } + if (client->activated) { if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY)) @@ -1060,15 +1100,44 @@ void* shadow_client_thread(rdpShadowClient* client) int index; int numRects = 0; const RECTANGLE_16* rects; + int width, height; - rects = region16_rects(&(subsystem->invalidRegion), &numRects); - - for (index = 0; index < numRects; index++) + /* Check resize */ + shadow_client_calc_desktop_size(server, &width, &height); + if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height) { - region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]); - } + /* Screen size changed, do resize */ + settings->DesktopWidth = width; + settings->DesktopHeight = height; - shadow_client_send_surface_update(client); + /** + * 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); + } } /* diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index 17ae041bf..1f3edff22 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -224,6 +224,9 @@ int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder) int shadow_encoder_init(rdpShadowEncoder* encoder) { + encoder->width = encoder->server->screen->width; + encoder->height = encoder->server->screen->height; + encoder->maxTileWidth = 64; encoder->maxTileHeight = 64; @@ -401,9 +404,6 @@ rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client) encoder->fps = 16; encoder->maxFps = 32; - encoder->width = server->screen->width; - encoder->height = server->screen->height; - if (shadow_encoder_init(encoder) < 0) { free (encoder); diff --git a/server/shadow/shadow_input.c b/server/shadow/shadow_input.c index 45ad38db6..e12878965 100644 --- a/server/shadow/shadow_input.c +++ b/server/shadow/shadow_input.c @@ -72,6 +72,12 @@ BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; + if (client->server->shareSubRect) + { + x += client->server->subRect.left; + y += client->server->subRect.top; + } + if (!(flags & PTR_FLAGS_WHEEL)) { client->pointerX = x; @@ -102,6 +108,12 @@ BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; + if (client->server->shareSubRect) + { + x += client->server->subRect.left; + y += client->server->subRect.top; + } + client->pointerX = x; client->pointerY = y; diff --git a/server/shadow/shadow_lobby.c b/server/shadow/shadow_lobby.c index 0c4a8d6e3..267772786 100644 --- a/server/shadow/shadow_lobby.c +++ b/server/shadow/shadow_lobby.c @@ -26,31 +26,44 @@ #include "shadow_lobby.h" -int shadow_client_init_lobby(rdpShadowClient* client) +BOOL shadow_client_init_lobby(rdpShadowServer* server) { int width; int height; rdtkEngine* engine; rdtkSurface* surface; RECTANGLE_16 invalidRect; - rdpShadowSurface* lobby; - rdpContext* context = (rdpContext*) client; - rdpSettings* settings = context->settings; + rdpShadowSurface* lobby = server->lobby; - width = settings->DesktopWidth; - height = settings->DesktopHeight; + if (!lobby) + return FALSE; - lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height); + if (!(engine = rdtk_engine_new())) + { + return FALSE; + } - if (!client->lobby) - return -1; + if (!(surface = rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline))) + { + rdtk_engine_free(engine); + return FALSE; + } - engine = rdtk_engine_new(); + invalidRect.left = 0; + invalidRect.top = 0; + invalidRect.right = lobby->width; + invalidRect.bottom = lobby->height; + if (server->shareSubRect) + { + /* If we have shared sub rect setting, only fill shared rect */ + rectangles_intersection(&invalidRect, &(server->subRect), &invalidRect); + } - surface = rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline); + width = invalidRect.right - invalidRect.left; + height = invalidRect.bottom - invalidRect.top; + rdtk_surface_fill(surface, invalidRect.left, invalidRect.top, width, height, 0x3BB9FF); - rdtk_surface_fill(surface, 0, 0, width, height, 0x3BB9FF); - //rdtk_label_draw(surface, 16, 16, 128, 32, NULL, "label", 0, 0); + rdtk_label_draw(surface, invalidRect.left, invalidRect.top, width, height, NULL, "Welcome", 0, 0); //rdtk_button_draw(surface, 16, 64, 128, 32, NULL, "button"); //rdtk_text_field_draw(surface, 16, 128, 128, 32, NULL, "text field"); @@ -58,12 +71,7 @@ int shadow_client_init_lobby(rdpShadowClient* client) rdtk_engine_free(engine); - invalidRect.left = 0; - invalidRect.top = 0; - invalidRect.right = width; - invalidRect.bottom = height; - region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect); - return 1; + return TRUE; } diff --git a/server/shadow/shadow_lobby.h b/server/shadow/shadow_lobby.h index 3c9313045..c3aa68156 100644 --- a/server/shadow/shadow_lobby.h +++ b/server/shadow/shadow_lobby.h @@ -30,7 +30,7 @@ extern "C" { #endif -int shadow_client_init_lobby(rdpShadowClient* client); +BOOL shadow_client_init_lobby(rdpShadowServer* server); #ifdef __cplusplus } diff --git a/server/shadow/shadow_screen.c b/server/shadow/shadow_screen.c index ff767b274..94086bb73 100644 --- a/server/shadow/shadow_screen.c +++ b/server/shadow/shadow_screen.c @@ -23,6 +23,7 @@ #include "shadow_surface.h" #include "shadow_screen.h" +#include "shadow_lobby.h" rdpShadowScreen* shadow_screen_new(rdpShadowServer* server) { @@ -30,35 +31,27 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server) int width, height; rdpShadowScreen* screen; rdpShadowSubsystem* subsystem; + MONITOR_DEF* primary; screen = (rdpShadowScreen*) calloc(1, sizeof(rdpShadowScreen)); if (!screen) - return NULL; + goto out_error; screen->server = server; subsystem = server->subsystem; if (!InitializeCriticalSectionAndSpinCount(&(screen->lock), 4000)) - return NULL; + goto out_free; region16_init(&(screen->invalidRegion)); - if (server->shareSubRect) { - x = server->subRect.left; - y = server->subRect.top; - width = server->subRect.right - server->subRect.left; - height = server->subRect.bottom - server->subRect.top; - } else { - MONITOR_DEF* primary; + primary = &(subsystem->monitors[subsystem->selectedMonitor]); - primary = &(subsystem->monitors[subsystem->selectedMonitor]); - - x = primary->left; - y = primary->top; - width = primary->right - primary->left; - height = primary->bottom - primary->top; - } + x = primary->left; + y = primary->top; + width = primary->right - primary->left; + height = primary->bottom - primary->top; screen->width = width; screen->height = height; @@ -66,11 +59,31 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server) screen->primary = shadow_surface_new(server, x, y, width, height); if (!screen->primary) - return NULL; + goto out_free_region; server->surface = screen->primary; + screen->lobby = shadow_surface_new(server, x, y, width, height); + + if (!screen->lobby) + goto out_free_primary; + + server->lobby = screen->lobby; + + shadow_client_init_lobby(server); + return screen; + +out_free_primary: + shadow_surface_free(screen->primary); + server->surface = screen->primary = NULL; +out_free_region: + region16_uninit(&(screen->invalidRegion)); + DeleteCriticalSection(&(screen->lock)); +out_free: + free(screen); +out_error: + return NULL; } void shadow_screen_free(rdpShadowScreen* screen) @@ -88,6 +101,45 @@ void shadow_screen_free(rdpShadowScreen* screen) screen->primary = NULL; } + if (screen->lobby) + { + shadow_surface_free(screen->lobby); + screen->lobby = NULL; + } + free(screen); } +BOOL shadow_screen_resize(rdpShadowScreen* screen) +{ + int x, y; + int width, height; + MONITOR_DEF* primary; + rdpShadowSubsystem* subsystem; + + if (!screen) + return FALSE; + + subsystem = screen->server->subsystem; + primary = &(subsystem->monitors[subsystem->selectedMonitor]); + + x = primary->left; + y = primary->top; + width = primary->right - primary->left; + height = primary->bottom - primary->top; + + if (shadow_surface_resize(screen->primary, x, y, width, height) + && shadow_surface_resize(screen->lobby, x, y, width, height)) + { + if ((width != screen->width) || (height != screen->height)) + { + /* screen size is changed. Store new size and reinit lobby */ + screen->width = width; + screen->height = height; + shadow_client_init_lobby(screen->server); + } + return TRUE; + } + + return FALSE; +} diff --git a/server/shadow/shadow_screen.h b/server/shadow/shadow_screen.h index 2b305e336..806d40fa7 100644 --- a/server/shadow/shadow_screen.h +++ b/server/shadow/shadow_screen.h @@ -35,6 +35,7 @@ struct rdp_shadow_screen REGION16 invalidRegion; rdpShadowSurface* primary; + rdpShadowSurface* lobby; }; #ifdef __cplusplus diff --git a/server/shadow/shadow_surface.c b/server/shadow/shadow_surface.c index 4c13662e7..d01e4ab76 100644 --- a/server/shadow/shadow_surface.c +++ b/server/shadow/shadow_surface.c @@ -41,16 +41,13 @@ rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int surface->height = height; surface->scanline = (surface->width + (surface->width % 4)) * 4; - surface->data = (BYTE*) malloc(surface->scanline * surface->height); - + surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); if (!surface->data) { free (surface); return NULL; } - ZeroMemory(surface->data, surface->scanline * surface->height); - if (!InitializeCriticalSectionAndSpinCount(&(surface->lock), 4000)) { free (surface->data); @@ -76,3 +73,35 @@ void shadow_surface_free(rdpShadowSurface* surface) free(surface); } + +BOOL shadow_surface_resize(rdpShadowSurface *surface, int x, int y, int width, int height) +{ + BYTE* buffer = NULL; + int scanline = (width + (width % 4)) * 4; + + if (!surface) + return FALSE; + + if ((width == surface->width) && (height == surface->height)) + { + /* We don't need to reset frame buffer, just update left top */ + surface->x = x; + surface->y = y; + return TRUE; + } + + buffer = (BYTE*) realloc(surface->data, scanline * height); + if (buffer) + { + surface->x = x; + surface->y = y; + surface->width = width; + surface->height = height; + surface->scanline = scanline; + surface->data = buffer; + + return TRUE; + } + + return FALSE; +} diff --git a/server/shadow/shadow_surface.h b/server/shadow/shadow_surface.h index 2f6bc8300..eeae82220 100644 --- a/server/shadow/shadow_surface.h +++ b/server/shadow/shadow_surface.h @@ -45,6 +45,7 @@ extern "C" { rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int width, int height); void shadow_surface_free(rdpShadowSurface* surface); +BOOL shadow_surface_resize(rdpShadowSurface *surface, int x, int y, int width, int height); #ifdef __cplusplus }