From 83edc684223ec6af77086a7b95f06ab3ceeb4030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 18:03:25 -0400 Subject: [PATCH] xfreerdp: start integrating graphics pipeline --- client/X11/CMakeLists.txt | 2 + client/X11/xf_channels.c | 6 + client/X11/xf_channels.h | 1 + client/X11/xf_client.c | 22 ++- client/X11/xf_gdi.c | 13 +- client/X11/xf_gfx.c | 281 ++++++++++++++++++++++++++++++++++++++ client/X11/xf_gfx.h | 28 ++++ client/X11/xf_graphics.c | 6 +- client/X11/xfreerdp.h | 12 +- 9 files changed, 346 insertions(+), 25 deletions(-) create mode 100644 client/X11/xf_gfx.c create mode 100644 client/X11/xf_gfx.h diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 6cbe43a42..6c004e678 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -26,6 +26,8 @@ include_directories(${OPENSSL_INCLUDE_DIR}) set(${MODULE_PREFIX}_SRCS xf_gdi.c xf_gdi.h + xf_gfx.c + xf_gfx.h xf_rail.c xf_rail.h xf_tsmf.c diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index 24325046e..b00130c24 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -26,6 +26,8 @@ #include "xf_client.h" #include "xfreerdp.h" +#include "xf_gfx.h" + void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) { xfContext* xfc = (xfContext*) context; @@ -34,6 +36,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven { xfc->rdpei = (RdpeiClientContext*) e->pInterface; } + else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + xf_register_graphics_pipeline(xfc, (RdpgfxClientContext*) e->pInterface); + } } void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h index bb52d5e52..dd5969d62 100644 --- a/client/X11/xf_channels.h +++ b/client/X11/xf_channels.h @@ -23,6 +23,7 @@ #include #include #include +#include int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface); int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index e8d09031a..7fddd874b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -902,8 +902,6 @@ BOOL xf_post_connect(freerdp* instance) rdpChannels* channels; rdpSettings* settings; ResizeWindowEventArgs e; - RFX_CONTEXT* rfx_context = NULL; - NSC_CONTEXT* nsc_context = NULL; xfContext* xfc = (xfContext*) instance->context; cache = instance->context->cache; @@ -931,7 +929,7 @@ BOOL xf_post_connect(freerdp* instance) gdi = instance->context->gdi; xfc->primary_buffer = gdi->primary_buffer; - rfx_context = gdi->rfx_context; + xfc->rfx = gdi->rfx_context; } else { @@ -942,14 +940,12 @@ BOOL xf_post_connect(freerdp* instance) if (instance->settings->RemoteFxCodec) { - rfx_context = (void*) rfx_context_new(FALSE); - xfc->rfx_context = rfx_context; + xfc->rfx = rfx_context_new(FALSE); } if (instance->settings->NSCodec) { - nsc_context = (void*) nsc_context_new(); - xfc->nsc_context = nsc_context; + xfc->nsc = nsc_context_new(); } } @@ -1212,16 +1208,16 @@ void xf_window_free(xfContext* xfc) context->rail = NULL; } - if (xfc->rfx_context) + if (xfc->rfx) { - rfx_context_free(xfc->rfx_context); - xfc->rfx_context = NULL; + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; } - if (xfc->nsc_context) + if (xfc->nsc) { - nsc_context_free(xfc->nsc_context); - xfc->nsc_context = NULL; + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; } if (xfc->clrconv) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index be63db5c2..1ab20af06 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -990,14 +990,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits XImage* image; RFX_MESSAGE* message; xfContext* xfc = (xfContext*) context; - RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfc->rfx_context; - NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfc->nsc_context; xf_lock_x11(xfc, FALSE); if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX) { - message = rfx_process_message(rfx_context, + message = rfx_process_message(xfc->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1034,11 +1032,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } XSetClipMask(xfc->display, xfc->gc, None); - rfx_message_free(rfx_context, message); + rfx_message_free(xfc->rfx, message); } else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC) { - nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + nsc_process_message(xfc->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1047,7 +1045,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc, surface_bits_command->width * surface_bits_command->height * 4); - freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc, + freerdp_image_flip(xfc->nsc->BitmapData, xfc->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, @@ -1060,13 +1058,14 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits free(xfc->bmp_codec_nsc); xfc->bmp_codec_nsc = NULL; - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, surface_bits_command->destLeft, surface_bits_command->destTop); } + xf_gdi_surface_update_frame(xfc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c new file mode 100644 index 000000000..2a94b74d2 --- /dev/null +++ b/client/X11/xf_gfx.c @@ -0,0 +1,281 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf_gfx.h" + +int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) +{ + xfContext* xfc = (xfContext*) context->custom; + + if (xfc->rfx) + { + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; + } + + xfc->rfx = rfx_context_new(FALSE); + + xfc->rfx->width = resetGraphics->width; + xfc->rfx->height = resetGraphics->height; + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + + if (xfc->nsc) + { + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; + } + + xfc->nsc = nsc_context_new(); + + xfc->nsc->width = resetGraphics->width; + xfc->nsc->height = resetGraphics->height; + nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8); + + return 1; +} + +int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) +{ + return 1; +} + +int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) +{ + return 1; +} + +int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + BYTE* data; + UINT32 width; + UINT32 height; + XImage* image; + RDPGFX_RECT16* destRect; + + destRect = &(cmd->destRect); + + width = destRect->right - destRect->left + 1; + height = destRect->bottom - destRect->top + 1; + + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + /* Validate that the data received is large enough */ + if ((width * height * 4) <= cmd->bitmapDataLength) + { + data = (BYTE*) malloc(width * height * 4); + + freerdp_image_flip(cmd->bitmapData, data, width, height, 32); + + image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, width, height, 32, 0); + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, + destRect->left, destRect->top, width, height); + + XFree(image); + + free(data); + + if (!xfc->remote_app) + { + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, + destRect->left, destRect->top, width, height, destRect->left, destRect->top); + } + + //xf_gdi_surface_update_frame(xfc, destRect->left, destRect->top, width, height); + + XSetClipMask(xfc->display, xfc->gc, None); + } + + return 1; +} + +int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int i, tx, ty; + XImage* image; + RFX_MESSAGE* message; + RDPGFX_RECT16* destRect; + + destRect = &(cmd->destRect); + + message = rfx_process_message(xfc->rfx, cmd->bitmapData, cmd->bitmapDataLength); + + if (!message) + return -1; + + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + XSetClipRectangles(xfc->display, xfc->gc, + destRect->left, destRect->top, + (XRectangle*) message->rects, message->numRects, YXBanded); + + /* Draw the tiles to primary surface, each is 64x64. */ + for (i = 0; i < message->numTiles; i++) + { + image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, + (char*) message->tiles[i]->data, 64, 64, 32, 0); + + tx = message->tiles[i]->x + destRect->left; + ty = message->tiles[i]->y + destRect->top; + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, tx, ty, 64, 64); + XFree(image); + } + + /* Copy the updated region from backstore to the window. */ + for (i = 0; i < message->numRects; i++) + { + tx = message->rects[i].x + destRect->left; + ty = message->rects[i].y + destRect->top; + + if (!xfc->remote_app) + { + XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, tx, ty, message->rects[i].width, message->rects[i].height, tx, ty); + } + } + + XSetClipMask(xfc->display, xfc->gc, None); + rfx_message_free(xfc->rfx, message); + + return 1; +} + +int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status = 1; + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_SurfaceCommand: context: %p xfc: %p cmd: %p\n", context, xfc, cmd); + + switch (cmd->codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + status = xf_SurfaceCommand_Uncompressed(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CAVIDEO: + status = xf_SurfaceCommand_RemoteFX(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CLEARCODEC: + break; + + case RDPGFX_CODECID_PLANAR: + break; + + case RDPGFX_CODECID_H264: + break; + + case RDPGFX_CODECID_ALPHA: + break; + + case RDPGFX_CODECID_CAPROGRESSIVE: + break; + + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + break; + } + + return 1; +} + +int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) +{ + return 1; +} + +int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) +{ + return 1; +} + +int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) +{ + return 1; +} + +int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) +{ + return 1; +} + +int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) +{ + return 1; +} + +int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) +{ + return 1; +} + +int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) +{ + return 1; +} + +int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply) +{ + return 1; +} + +int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) +{ + return 1; +} + +int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) +{ + return 1; +} + +int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow) +{ + return 1; +} + +void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) +{ + printf("RegisterGraphicsPipeline\n"); + + xfc->gfx = gfx; + gfx->custom = (void*) xfc; + + gfx->ResetGraphics = xf_ResetGraphics; + gfx->StartFrame = xf_StartFrame; + gfx->EndFrame = xf_EndFrame; + gfx->SurfaceCommand = xf_SurfaceCommand; + gfx->DeleteEncodingContext = xf_DeleteEncodingContext; + gfx->CreateSurface = xf_CreateSurface; + gfx->DeleteSurface = xf_DeleteSurface; + gfx->SolidFill = xf_SolidFill; + gfx->SurfaceToSurface = xf_SurfaceToSurface; + gfx->SurfaceToCache = xf_SurfaceToCache; + gfx->CacheToSurface = xf_CacheToSurface; + gfx->CacheImportReply = xf_CacheImportReply; + gfx->EvictCacheEntry = xf_EvictCacheEntry; + gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput; + gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow; +} diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h new file mode 100644 index 000000000..01a61b9db --- /dev/null +++ b/client/X11/xf_gfx.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __XF_GRAPHICS_PIPELINE_H +#define __XF_GRAPHICS_PIPELINE_H + +#include "xf_client.h" +#include "xfreerdp.h" + +void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); + +#endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 2c281d33d..fa24d967c 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -145,8 +145,8 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, break; case RDP_CODEC_ID_REMOTEFX: - rfx_context_set_pixel_format(xfc->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); - msg = rfx_process_message(xfc->rfx_context, data, length); + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + msg = rfx_process_message(xfc->rfx, data, length); if (msg == NULL) { @@ -166,7 +166,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, src++; } } - rfx_message_free(xfc->rfx_context, msg); + rfx_message_free(xfc->rfx, msg); } break; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index aa01ae905..4150d0727 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -28,6 +28,13 @@ typedef struct xf_context xfContext; #include "xf_monitor.h" #include "xf_channels.h" +#include +#include +#include +#include +#include +#include + struct xf_WorkArea { UINT32 x; @@ -137,8 +144,8 @@ struct xf_context VIRTUAL_SCREEN vscreen; BYTE* bmp_codec_none; BYTE* bmp_codec_nsc; - void* rfx_context; - void* nsc_context; + RFX_CONTEXT* rfx; + NSC_CONTEXT* nsc; void* xv_context; void* clipboard_context; @@ -168,6 +175,7 @@ struct xf_context /* Channels */ RdpeiClientContext* rdpei; + RdpgfxClientContext* gfx; }; void xf_create_window(xfContext* xfc);