diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 95bd78a02..392e7c4b2 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -109,20 +109,6 @@ wfInfo* wf_info_init() { _tprintf(_T("CreateMutex error: %d\n"), GetLastError()); } - - wfi->encodeMutex = CreateMutex(NULL, FALSE, NULL); - - if (wfi->encodeMutex == NULL) - { - _tprintf(_T("CreateMutex error: %d\n"), GetLastError()); - } - - wfi->can_send_mutex = CreateMutex(NULL, FALSE, NULL); - - if (wfi->can_send_mutex == NULL) - { - _tprintf(_T("CreateMutex error: %d\n"), GetLastError()); - } } return wfi; @@ -138,53 +124,31 @@ wfInfo* wf_info_get_instance() void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context) { - DWORD dRes; - - dRes = WaitForSingleObject(wfi->mutex, INFINITE); - - switch (dRes) + if (wf_info_lock(wfi) > 0) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: + if (wfi->subscribers < 1) + { + context->info = wfi; + wf_check_disp_devices(wfi); + wf_disp_device_set_attach_mode(wfi, 1); + wf_update_mirror_drv(wfi, 0); + wf_map_mirror_mem(wfi); - if (wfi->subscribers < 1) - { - /* only the first peer needs to call this. */ + wfi->rfx_context = rfx_context_new(); + wfi->rfx_context->mode = RLGR3; + wfi->rfx_context->width = wfi->width; + wfi->rfx_context->height = wfi->height; - context->info = wfi; - wf_check_disp_devices(context->info); - wf_disp_device_set_attach_mode(context->info, 1); - wf_update_mirror_drv(context->info, 0); - wf_map_mirror_mem(context->info); + rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); + wfi->s = stream_new(65536); + } - context->rfx_context = rfx_context_new(); - context->rfx_context->mode = RLGR3; - context->rfx_context->width = context->info->width; - context->rfx_context->height = context->info->height; + wfi->subscribers++; - rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); - context->s = stream_new(65536); - - context->info->primary_buffer = (BYTE*) malloc((context->info->width) * (context->info->height) * 4); - - ReleaseMutex(wfi->encodeMutex); - } - ++wfi->subscribers; - - if (!ReleaseMutex(wfi->mutex)) - { - _tprintf(_T("Error releasing mutex\n")); - } - - break; - - default: - _tprintf(_T("Error waiting for mutex: %d\n"), dRes); - break; + wf_info_unlock(wfi); } } - /** * TODO: i think i can replace all the context->info here with info * in fact it may not even care about subscribers @@ -192,46 +156,26 @@ void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context) void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context) { - DWORD dRes; - - WaitForSingleObject(wfi->mutex, INFINITE); - - if (context && (wfi->subscribers == 1)) + if (wf_info_lock(wfi) > 0) { - dRes = WaitForSingleObject(wfi->encodeMutex, INFINITE); - - switch (dRes) + if (context && (wfi->subscribers == 1)) { - /* The thread got ownership of the mutex */ - - case WAIT_OBJECT_0: - --wfi->subscribers; - /* only the last peer needs to call this */ - wf_mirror_cleanup(context->info); - wf_disp_device_set_attach_mode(context->info, FALSE); - wf_update_mirror_drv(context->info, 1); + wfi->subscribers--; + /* only the last peer needs to call this */ + wf_mirror_cleanup(context->info); + wf_disp_device_set_attach_mode(context->info, FALSE); + wf_update_mirror_drv(context->info, 1); - stream_free(context->s); - rfx_context_free(context->rfx_context); - - free(context->info->primary_buffer); - break; - - /** - * The thread got ownership of an abandoned mutex - * The database is in an indeterminate state - */ - default: - printf("wf_info_subscriber_release: Something else happened!!! dRes = %d\n", dRes); - break; + stream_free(wfi->s); + rfx_context_free(wfi->rfx_context); + } + else + { + wfi->subscribers--; } - } - else - { - --wfi->subscribers; - } - ReleaseMutex(wfi->mutex); + wf_info_unlock(wfi); + } /** * Note: if we released the last subscriber, @@ -255,11 +199,6 @@ BOOL wf_info_have_updates(wfInfo* wfi) return TRUE; } -void wf_info_updated(wfInfo* wfi) -{ - wfi->lastUpdate = wfi->nextUpdate; -} - void wf_info_update_changes(wfInfo* wfi) { GETCHANGESBUF* buf; @@ -275,53 +214,31 @@ void wf_info_find_invalid_region(wfInfo* wfi) buf = (GETCHANGESBUF*) wfi->changeBuffer; - if (wfi->enc_data == FALSE) - { - wfi->invalid_x1 = wfi->width - 1; - wfi->invalid_x2 = 0; - wfi->invalid_y1 = wfi->height - 1; - wfi->invalid_y2 = 0; - } - for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF) { - wfi->invalid_x1 = min(wfi->invalid_x1, buf->buffer->pointrect[i].rect.left); - wfi->invalid_x2 = max(wfi->invalid_x2, buf->buffer->pointrect[i].rect.right); - wfi->invalid_y1 = min(wfi->invalid_y1, buf->buffer->pointrect[i].rect.top); - wfi->invalid_y2 = max(wfi->invalid_y2, buf->buffer->pointrect[i].rect.bottom); + UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect); } - if (wfi->invalid_x1 < 0) - wfi->invalid_x1 = 0; + if (wfi->invalid.left < 0) + wfi->invalid.left = 0; - if (wfi->invalid_y1 < 0) - wfi->invalid_y1 = 0; + if (wfi->invalid.top < 0) + wfi->invalid.top = 0; - if (wfi->invalid_x2 >= wfi->width) - wfi->invalid_x2 = wfi->width - 1; + if (wfi->invalid.right >= wfi->width) + wfi->invalid.right = wfi->width - 1; - if (wfi->invalid_y2 >= wfi->height) - wfi->invalid_y2 = wfi->height - 1; + if (wfi->invalid.bottom >= wfi->height) + wfi->invalid.bottom = wfi->height - 1; } void wf_info_clear_invalid_region(wfInfo* wfi) { - WaitForSingleObject(wfi->mutex, INFINITE); - wfi->lastUpdate = wfi->nextUpdate; - - wfi->invalid_x1 = wfi->width - 1; - wfi->invalid_x2 = 0; - wfi->invalid_y1 = wfi->height - 1; - wfi->invalid_y2 = 0; - - ReleaseMutex(wfi->mutex); + SetRectEmpty(&wfi->invalid); } BOOL wf_info_have_invalid_region(wfInfo* wfi) { - if ((wfi->invalid_x1 >= wfi->invalid_x2) || (wfi->invalid_y1 >= wfi->invalid_y2)) - return FALSE; - - return TRUE; + return IsRectEmpty(&wfi->invalid); } diff --git a/server/Windows/wf_info.h b/server/Windows/wf_info.h index b67051ce1..43138138d 100644 --- a/server/Windows/wf_info.h +++ b/server/Windows/wf_info.h @@ -20,11 +20,14 @@ #ifndef WF_INFO_H #define WF_INFO_H +#include + struct wf_peer_context; typedef struct wf_peer_context wfPeerContext; struct wf_info { + STREAM* s; HDC driverDC; BOOL activated; void* changeBuffer; @@ -36,22 +39,12 @@ struct wf_info int width; int bitsPerPix; + RECT invalid; HANDLE mutex; - HANDLE encodeMutex; - HANDLE can_send_mutex; - + BOOL updatePending; + RFX_CONTEXT* rfx_context; unsigned long lastUpdate; unsigned long nextUpdate; - - long invalid_x1; - long invalid_y1; - - long invalid_x2; - long invalid_y2; - - BOOL enc_data; - - BYTE* primary_buffer; }; typedef struct wf_info wfInfo; @@ -65,7 +58,6 @@ void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context); BOOL wf_info_has_subscribers(wfInfo* wfi); BOOL wf_info_have_updates(wfInfo* wfi); -void wf_info_updated(wfInfo* wfi); void wf_info_update_changes(wfInfo* wfi); void wf_info_find_invalid_region(wfInfo* wfi); void wf_info_clear_invalid_region(wfInfo* wfi); diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 3745e241c..a82bd8bc1 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -67,18 +67,21 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam) { beg = GetTickCount(); - wf_info_lock(wfi); - - if (wf_info_has_subscribers(wfi)) + if (wf_info_lock(wfi) > 0) { - wf_info_update_changes(wfi); + if (wf_info_has_subscribers(wfi)) + { + wf_info_update_changes(wfi); - if (wf_info_have_updates(wfi)) - wf_rfx_encode(client); + if (wf_info_have_updates(wfi)) + { + wf_rfx_encode(client); + } + } + + wf_info_unlock(wfi); } - wf_info_unlock(wfi); - end = GetTickCount(); diff = end - beg; @@ -97,7 +100,6 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam) void wf_rfx_encode(freerdp_peer* client) { - int dRes; STREAM* s; wfInfo* wfi; long offset; @@ -108,101 +110,51 @@ void wf_rfx_encode(freerdp_peer* client) GETCHANGESBUF* buf; SURFACE_BITS_COMMAND* cmd; -#ifdef WITH_DOUBLE_BUFFERING - uint16 i; - int scanline; - BYTE* srcp; - BYTE* dstp; -#endif + wfp = (wfPeerContext*) client->context; + wfi = wfp->info; if (client->activated == FALSE) return; - wfp = (wfPeerContext*) client->context; - wfi = wfp->info; + if (wfp->activated == FALSE) + return; - dRes = WaitForSingleObject(wfi->encodeMutex, INFINITE); + wf_info_find_invalid_region(wfi); - switch (dRes) - { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: + update = client->update; + cmd = &update->surface_bits_command; + buf = (GETCHANGESBUF*) wfi->changeBuffer; - wf_info_find_invalid_region(wfi); + width = (wfi->invalid.right - wfi->invalid.left) + 1; + height = (wfi->invalid.bottom - wfi->invalid.top) + 1; - if ((wfp->activated == false) || - (wf_info_has_subscribers(wfi) == false) || - !wf_info_have_invalid_region(wfi) || - (wfi->enc_data == true) ) - { - ReleaseMutex(wfi->encodeMutex); - break; - } + stream_clear(wfi->s); + stream_set_pos(wfi->s, 0); + s = wfi->s; - update = client->update; - cmd = &update->surface_bits_command; - buf = (GETCHANGESBUF*) wfi->changeBuffer; + rect.x = 0; + rect.y = 0; + rect.width = (uint16) width; + rect.height = (uint16) height; - width = (wfi->invalid_x2 - wfi->invalid_x1) + 1; - height = (wfi->invalid_y2 - wfi->invalid_y1) + 1; + offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4); - stream_clear(wfp->s); - stream_set_pos(wfp->s, 0); - s = wfp->s; - - rect.x = 0; - rect.y = 0; - rect.width = (uint16) width; - rect.height = (uint16) height; - -#ifndef WITH_DOUBLE_BUFFERING - offset = (4 * wfi->invalid_x1) + (wfi->invalid_y1 * wfi->width * 4); + rfx_compose_message(wfi->rfx_context, s, &rect, 1, + ((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4); - - rfx_compose_message(wfp->rfx_context, s, &rect, 1, - ((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4); -#else - scanline = (wfi->width * 4); - offset = (wfi->invalid_y1 * scanline) + (wfi->invalid_x1 * 4); - srcp = (BYTE*) buf->Userbuffer + offset; - dstp = (BYTE*) wfi->primary_buffer + offset; + cmd->destLeft = wfi->invalid.left; + cmd->destTop = wfi->invalid.top; + cmd->destRight = wfi->invalid.left + width; + cmd->destBottom = wfi->invalid.top + height; - for (i = 0; i < height; i++) - { - memcpy(dstp, srcp, width * 4); - dstp += scanline; - srcp += scanline; - } - - rfx_compose_message(wfp->rfx_context, s, &rect, 1, - wfi->primary_buffer + offset, width, height, wfi->width * 4); -#endif - - cmd->destLeft = wfi->invalid_x1; - cmd->destTop = wfi->invalid_y1; - cmd->destRight = wfi->invalid_x1 + width; - cmd->destBottom = wfi->invalid_y1 + height; - - cmd->bpp = 32; - cmd->codecID = client->settings->rfx_codec_id; - cmd->width = width; - cmd->height = height; - cmd->bitmapDataLength = stream_get_length(s); - cmd->bitmapData = stream_get_head(s); - - wfi->enc_data = true; - ReleaseMutex(wfi->encodeMutex); - break; - - case WAIT_TIMEOUT: - - ReleaseMutex(wfi->encodeMutex); - break; - - default: - break; - } + cmd->bpp = 32; + cmd->codecID = client->settings->rfx_codec_id; + cmd->width = width; + cmd->height = height; + cmd->bitmapDataLength = stream_get_length(s); + cmd->bitmapData = stream_get_head(s); + wfi->updatePending = TRUE; } void wf_peer_init(freerdp_peer* client) @@ -293,43 +245,22 @@ void wf_peer_synchronize_event(rdpInput* input, uint32 flags) void wf_peer_send_changes(freerdp_peer* client) { - int dRes; wfInfo* wfi; wfPeerContext* context = (wfPeerContext*) client->context; wfi = context->info; - /* are we currently encoding? */ - dRes = WaitForSingleObject(wfi->encodeMutex, 0); - - switch (dRes) + if (wf_info_lock(wfi) > 0) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: + if (wfi->updatePending) + { + wfi->lastUpdate = wfi->nextUpdate; - if (wf_info_try_lock(wfi, 100) != -1) - { - if ((!wf_info_have_updates(wfi) || !wf_info_have_invalid_region(wfi) || (wfi->enc_data == FALSE))) - { - wf_info_unlock(wfi); - ReleaseMutex(wfi->encodeMutex); - break; - } + client->update->SurfaceBits(client->update->context, &client->update->surface_bits_command); - wf_info_updated(wfi); + wfi->updatePending = FALSE; + } - client->update->SurfaceBits(client->update->context, &client->update->surface_bits_command); - - wfi->enc_data = FALSE; - wf_info_unlock(wfi); - ReleaseMutex(wfi->encodeMutex); - } - break; - - case WAIT_TIMEOUT: - break; - - default: - break; + wf_info_unlock(wfi); } } diff --git a/server/Windows/wfreerdp.c b/server/Windows/wfreerdp.c index 99ecfbe2c..f6a20c940 100644 --- a/server/Windows/wfreerdp.c +++ b/server/Windows/wfreerdp.c @@ -92,7 +92,7 @@ static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) } #ifndef WITH_WIN8 - if(client->activated) + if (client->activated) wf_peer_send_changes(client); #endif } @@ -136,6 +136,7 @@ static void wf_server_main_loop(freerdp_listener* instance) printf("Failed to check FreeRDP file descriptor\n"); break; } + Sleep(20); } diff --git a/server/Windows/wfreerdp.h b/server/Windows/wfreerdp.h index dce836d8b..169933001 100644 --- a/server/Windows/wfreerdp.h +++ b/server/Windows/wfreerdp.h @@ -21,20 +21,17 @@ #define WFREERDP_H //#define WITH_WIN8 1 -//#define WITH_DOUBLE_BUFFERING 1 #include -#include + #include "wf_info.h" struct wf_peer_context { rdpContext _p; - STREAM* s; wfInfo* info; boolean activated; - RFX_CONTEXT* rfx_context; }; typedef struct wf_peer_context wfPeerContext;