xfreerdp-server: start work on XShm

This commit is contained in:
Marc-André Moreau 2012-01-09 22:08:25 -05:00
parent 20cacf5f29
commit c3186a9281
5 changed files with 193 additions and 17 deletions

49
cmake/FindXShm.cmake Normal file
View File

@ -0,0 +1,49 @@
# - Find XSHM
# Find the XSHM libraries
#
# This module defines the following variables:
# XSHM_FOUND - true if XSHM_INCLUDE_DIR & XSHM_LIBRARY are found
# XSHM_LIBRARIES - Set when XSHM_LIBRARY is found
# XSHM_INCLUDE_DIRS - Set when XSHM_INCLUDE_DIR is found
#
# XSHM_INCLUDE_DIR - where to find XShm.h, etc.
# XSHM_LIBRARY - the XSHM library
#
#=============================================================================
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# 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.
#=============================================================================
find_path(XSHM_INCLUDE_DIR NAMES XShm.h
PATH_SUFFIXES X11/extensions
DOC "The XShm include directory"
)
find_library(XSHM_LIBRARY NAMES Xext
DOC "The XShm library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XSHM DEFAULT_MSG XSHM_LIBRARY XSHM_INCLUDE_DIR)
if(XSHM_FOUND)
set( XSHM_LIBRARIES ${XSHM_LIBRARY} )
set( XSHM_INCLUDE_DIRS ${XSHM_INCLUDE_DIR} )
endif()
mark_as_advanced(XSHM_INCLUDE_DIR XSHM_LIBRARY)

View File

@ -24,6 +24,12 @@ add_executable(xfreerdp-server
xf_encode.c
xfreerdp.c)
find_suggested_package(XShm)
if(XSHM_FOUND)
add_definitions(-DWITH_XSHM)
include_directories(${XSHM_INCLUDE_DIRS})
endif()
find_suggested_package(Xext)
if(XEXT_FOUND)
add_definitions(-DWITH_XEXT)

View File

@ -27,7 +27,22 @@ XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height)
xfInfo* xfi = xfp->info;
pthread_mutex_lock(&(xfp->mutex));
image = XGetImage(xfi->display, RootWindow(xfi->display, xfi->number), x, y, width, height, AllPlanes, ZPixmap);
if (xfi->use_xshm)
{
XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap,
xfi->xdamage_gc, x, y, width, height, x, y);
XSync(xfi->display, False);
image = xfi->fb_image;
}
else
{
image = XGetImage(xfi->display, xfi->root_window,
x, y, width, height, AllPlanes, ZPixmap);
}
pthread_mutex_unlock(&(xfp->mutex));
return image;

View File

@ -22,6 +22,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/select.h>
@ -42,11 +44,28 @@ extern boolean xf_pcap_dump_realtime;
void xf_xdamage_init(xfInfo* xfi)
{
Bool pixmaps;
int damage_event;
int damage_error;
int major, minor;
XGCValues values;
if (XShmQueryExtension(xfi->display) != False)
{
XShmQueryVersion(xfi->display, &major, &minor, &pixmaps);
if (pixmaps != True)
{
printf("XShmQueryVersion failed\n");
return;
}
}
else
{
printf("XShmQueryExtension failed\n");
return;
}
if (XDamageQueryExtension(xfi->display, &damage_event, &damage_error) == 0)
{
printf("XDamageQueryExtension failed\n");
@ -67,7 +86,7 @@ void xf_xdamage_init(xfInfo* xfi)
}
xfi->xdamage_notify_event = damage_event + XDamageNotify;
xfi->xdamage = XDamageCreate(xfi->display, DefaultRootWindow(xfi->display), XDamageReportDeltaRectangles);
xfi->xdamage = XDamageCreate(xfi->display, xfi->root_window, XDamageReportDeltaRectangles);
if (xfi->xdamage == None)
{
@ -88,11 +107,57 @@ void xf_xdamage_init(xfInfo* xfi)
#endif
values.subwindow_mode = IncludeInferiors;
xfi->xdamage_gc = XCreateGC(xfi->display, DefaultRootWindow(xfi->display), GCSubwindowMode, &values);
xfi->xdamage_gc = XCreateGC(xfi->display, xfi->root_window, GCSubwindowMode, &values);
}
#endif
void xf_xshm_init(xfInfo* xfi)
{
xfi->use_xshm = false;
xfi->fb_shm_info.shmid = -1;
xfi->fb_shm_info.shmaddr = (char*) -1;
xfi->fb_image = XShmCreateImage(xfi->display, xfi->visual, xfi->depth,
ZPixmap, NULL, &(xfi->fb_shm_info), xfi->width, xfi->height);
if (xfi->fb_image == NULL)
{
printf("XShmCreateImage failed\n");
return;
}
xfi->fb_shm_info.shmid = shmget(IPC_PRIVATE,
xfi->fb_image->bytes_per_line * xfi->fb_image->height, IPC_CREAT | 0600);
if (xfi->fb_shm_info.shmid == -1)
{
printf("shmget failed\n");
return;
}
xfi->fb_shm_info.readOnly = False;
xfi->fb_shm_info.shmaddr = shmat(xfi->fb_shm_info.shmid, 0, 0);
xfi->fb_image->data = xfi->fb_shm_info.shmaddr;
if (xfi->fb_shm_info.shmaddr == ((char*) -1))
{
printf("shmat failed\n");
return;
}
XShmAttach(xfi->display, &(xfi->fb_shm_info));
XSync(xfi->display, False);
shmctl(xfi->fb_shm_info.shmid, IPC_RMID, 0);
xfi->fb_pixmap = XShmCreatePixmap(xfi->display,
xfi->root_window, xfi->fb_image->data, &(xfi->fb_shm_info),
xfi->fb_image->width, xfi->fb_image->height, xfi->fb_image->depth);
//xfi->use_xshm = true;
}
xfInfo* xf_info_init()
{
int i;
@ -122,6 +187,7 @@ xfInfo* xf_info_init()
xfi->depth = DefaultDepthOfScreen(xfi->screen);
xfi->width = WidthOfScreen(xfi->screen);
xfi->height = HeightOfScreen(xfi->screen);
xfi->root_window = DefaultRootWindow(xfi->display);
pfs = XListPixmapFormats(xfi->display, &pf_count);
@ -172,11 +238,15 @@ xfInfo* xf_info_init()
xfi->clrconv->invert = 1;
xfi->clrconv->alpha = 1;
XSelectInput(xfi->display, DefaultRootWindow(xfi->display), SubstructureNotifyMask);
XSelectInput(xfi->display, xfi->root_window, SubstructureNotifyMask);
#ifdef WITH_XDAMAGE
xf_xdamage_init(xfi);
#endif
#endif
xf_xshm_init(xfi);
xfi->bytesPerPixel = (xfi->use_xshm) ? 4 : 3;
freerdp_kbd_init(xfi->display, 0);
@ -190,7 +260,11 @@ void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context)
context->rfx_context->mode = RLGR3;
context->rfx_context->width = context->info->width;
context->rfx_context->height = context->info->height;
rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_RGB);
if (context->info->use_xshm)
rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_BGRA);
else
rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_RGB);
context->s = stream_new(65536);
}
@ -299,7 +373,7 @@ void* xf_monitor_graphics(void* param)
xfp = (xfPeerContext*) client->context;
xfi = xfp->info;
xfp->capture_buffer = (uint8*) xmalloc(xfi->width * xfi->height * 3);
xfp->capture_buffer = (uint8*) xmalloc(xfi->width * xfi->height * xfi->bytesPerPixel);
pthread_detach(pthread_self());
@ -474,19 +548,40 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
image = xf_snapshot(xfp, x, y, width, height);
freerdp_image_convert((uint8*) image->data, xfp->capture_buffer, width, height, 32, 24, xfi->clrconv);
if (xfi->use_xshm)
{
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
rfx_compose_message(xfp->rfx_context, s, &rect, 1,
(uint8*) image->data, width, height, image->bytes_per_line);
rfx_compose_message(xfp->rfx_context, s, &rect, 1, xfp->capture_buffer, width, height, width * 3);
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + width;
cmd->destBottom = y + height;
}
else
{
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
freerdp_image_convert((uint8*) image->data, xfp->capture_buffer,
width, height, 32, 24, xfi->clrconv);
rfx_compose_message(xfp->rfx_context, s, &rect, 1,
xfp->capture_buffer, width, height, width * xfi->bytesPerPixel);
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + width;
cmd->destBottom = y + height;
}
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = width;
cmd->destBottom = height;
cmd->bpp = 32;
cmd->codecID = client->settings->rfx_codec_id;
cmd->width = width;

View File

@ -22,6 +22,10 @@
#include <freerdp/codec/color.h>
#ifdef WITH_XSHM
#include <X11/extensions/XShm.h>
#endif
#ifdef WITH_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
@ -46,7 +50,14 @@ struct xf_info
Visual* visual;
Display* display;
int scanline_pad;
int bytesPerPixel;
HCLRCONV clrconv;
boolean use_xshm;
XImage* fb_image;
Pixmap fb_pixmap;
Window root_window;
XShmSegmentInfo fb_shm_info;
#ifdef WITH_XDAMAGE
GC xdamage_gc;