mirror of https://github.com/FreeRDP/FreeRDP
Added image scaling api for software drawing.
For future GFX channel functions an image scaling function is required. This moves the implementation from wayland client to core library and adds support for the much faster SWScale library.
This commit is contained in:
parent
ef104ed897
commit
6a8755a763
|
@ -37,16 +37,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
wlf_channels.h
|
||||
)
|
||||
|
||||
find_package(Cairo)
|
||||
|
||||
list (APPEND ${MODULE_PREFIX}_LIBS freerdp-client freerdp uwac)
|
||||
if (CAIRO_FOUND)
|
||||
add_definitions(-DCAIRO_FOUND=1)
|
||||
include_directories(${CAIRO_INCLUDE_DIR})
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS ${CAIRO_LIBRARY})
|
||||
else(CAIRO_FOUND)
|
||||
message(WARNING "libcairo not detected, compiling without wayland smart scaling support!")
|
||||
endif(CAIRO_FOUND)
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
#include <linux/input.h>
|
||||
|
||||
#include <uwac/uwac.h>
|
||||
#if defined(CAIRO_FOUND)
|
||||
#include <cairo.h>
|
||||
#endif
|
||||
|
||||
#include "wlfreerdp.h"
|
||||
#include "wlf_input.h"
|
||||
|
@ -623,44 +620,8 @@ BOOL wlf_copy_image(const void* src, size_t srcStride, size_t srcWidth, size_t s
|
|||
|
||||
if (scale)
|
||||
{
|
||||
#if defined(CAIRO_FOUND)
|
||||
const double sx = (double)dstWidth / (double)srcWidth;
|
||||
const double sy = (double)dstHeight / (double)srcHeight;
|
||||
cairo_t* cairo_context;
|
||||
cairo_surface_t* csrc, *cdst;
|
||||
|
||||
if ((srcWidth > INT_MAX) || (srcHeight > INT_MAX) || (srcStride > INT_MAX))
|
||||
return FALSE;
|
||||
|
||||
if ((dstWidth > INT_MAX) || (dstHeight > INT_MAX) || (dstStride > INT_MAX))
|
||||
return FALSE;
|
||||
|
||||
csrc = cairo_image_surface_create_for_data((void*)src, CAIRO_FORMAT_ARGB32, (int)srcWidth,
|
||||
(int)srcHeight, (int)srcStride);
|
||||
cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (int)dstWidth,
|
||||
(int)dstHeight, (int)dstStride);
|
||||
|
||||
if (!csrc || !cdst)
|
||||
goto fail;
|
||||
|
||||
cairo_context = cairo_create(cdst);
|
||||
|
||||
if (!cairo_context)
|
||||
goto fail2;
|
||||
|
||||
cairo_scale(cairo_context, sx, sy);
|
||||
cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface(cairo_context, csrc, 0, 0);
|
||||
cairo_paint(cairo_context);
|
||||
rc = TRUE;
|
||||
fail2:
|
||||
cairo_destroy(cairo_context);
|
||||
fail:
|
||||
cairo_surface_destroy(csrc);
|
||||
cairo_surface_destroy(cdst);
|
||||
#else
|
||||
WLog_WARN(TAG, "SmartScaling requested but compiled without libcairo support!");
|
||||
#endif
|
||||
return freerdp_image_scale(dst, PIXEL_FORMAT_BGRA32, dstStride, 0, 0, dstWidth, dstHeight,
|
||||
src, PIXEL_FORMAT_BGRA32, srcStride, 0, 0, srcWidth, srcHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -698,8 +659,6 @@ BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fro
|
|||
if (!context->settings->SmartSizing)
|
||||
return TRUE;
|
||||
|
||||
/* If libcairo is not compiled, smart scaling is ignored. */
|
||||
#if defined(CAIRO_FOUND)
|
||||
gdi = context->gdi;
|
||||
|
||||
if (UwacWindowGetDrawingBufferGeometry(wlf->window, &geometry, NULL) != UWAC_SUCCESS)
|
||||
|
@ -719,6 +678,5 @@ BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fro
|
|||
*py /= sy;
|
||||
}
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -145,11 +145,14 @@ endif(WITH_FFMPEG)
|
|||
|
||||
option(USE_VERSION_FROM_GIT_TAG "Extract FreeRDP version from git tag." OFF)
|
||||
|
||||
if(ANDROID)
|
||||
include(ConfigOptionsAndroid)
|
||||
option(WITH_CAIRO "Use CAIRO image library for screen resizing" OFF)
|
||||
option(WITH_SWSCALE "Use SWScale image library for screen resizing" OFF)
|
||||
|
||||
if (ANDROID)
|
||||
include(ConfigOptionsAndroid)
|
||||
endif(ANDROID)
|
||||
|
||||
if(IOS)
|
||||
include(ConfigOptionsiOS)
|
||||
if (IOS)
|
||||
include(ConfigOptionsiOS)
|
||||
endif(IOS)
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
include(FindPkgConfig)
|
||||
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(SWScale swscale)
|
||||
endif()
|
||||
|
||||
find_path(SWScale_INCLUDE_DIR libswscale / swscale.h PATHS $ {SWScale_INCLUDE_DIRS})
|
||||
find_library(SWScale_LIBRARY swscale PATHS $ {SWScale_LIBRARY_DIRS})
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SWScale DEFAULT_MSG SWScale_INCLUDE_DIR SWScale_LIBRARY)
|
||||
|
||||
mark_as_advanced(SWScale_INCLUDE_DIR SWScale_LIBRARY)
|
||||
|
|
@ -752,7 +752,7 @@ static INLINE BOOL WriteColor(BYTE* dst, UINT32 format, UINT32 color)
|
|||
* @return The converted pixel color in dstFormat representation
|
||||
*/
|
||||
static INLINE UINT32 FreeRDPConvertColor(UINT32 color, UINT32 srcFormat,
|
||||
UINT32 dstFormat, const gdiPalette* palette)
|
||||
UINT32 dstFormat, const gdiPalette* palette)
|
||||
{
|
||||
BYTE r = 0;
|
||||
BYTE g = 0;
|
||||
|
@ -862,6 +862,32 @@ FREERDP_API BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat,
|
|||
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
|
||||
const gdiPalette* palette, UINT32 flags);
|
||||
|
||||
/***
|
||||
*
|
||||
* @param pDstData destination buffer
|
||||
* @param DstFormat destination buffer format
|
||||
* @param nDstStep destination buffer stride (line in bytes) 0 for default
|
||||
* @param nXDst destination buffer offset x
|
||||
* @param nYDst destination buffer offset y
|
||||
* @param nDstWidth width of destination in pixels
|
||||
* @param nDstHeight height of destination in pixels
|
||||
* @param pSrcData source buffer
|
||||
* @param SrcFormat source buffer format
|
||||
* @param nSrcStep source buffer stride (line in bytes) 0 for default
|
||||
* @param nXSrc source buffer x offset in pixels
|
||||
* @param nYSrc source buffer y offset in pixels
|
||||
* @param nSrcWidth width of source in pixels
|
||||
* @param nSrcHeight height of source in pixels
|
||||
*
|
||||
* @return TRUE if success, FALSE otherwise
|
||||
*/
|
||||
FREERDP_API BOOL freerdp_image_scale(BYTE* pDstData, DWORD DstFormat,
|
||||
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
|
||||
UINT32 nDstWidth, UINT32 nDstHeight,
|
||||
const BYTE* pSrcData, DWORD SrcFormat,
|
||||
UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight);
|
||||
|
||||
/***
|
||||
*
|
||||
* @param pDstData destionation buffer
|
||||
|
|
|
@ -79,6 +79,28 @@ macro (freerdp_definition_add)
|
|||
set (LIBFREERDP_DEFINITIONS ${LIBFREERDP_DEFINITIONS} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
if (WITH_SWSCALE)
|
||||
find_package(SWScale REQUIRED)
|
||||
endif(WITH_SWSCALE)
|
||||
if (WITH_CAIRO)
|
||||
find_package(Cairo REQUIRED)
|
||||
endif(WITH_CAIRO)
|
||||
|
||||
if (SWScale_FOUND)
|
||||
add_definitions(-DSWSCALE_FOUND=1)
|
||||
include_directories(${SWScale_INCLUDE_DIR})
|
||||
freerdp_library_add(${SWScale_LIBRARY})
|
||||
else(SWScale_FOUND)
|
||||
|
||||
if (CAIRO_FOUND)
|
||||
add_definitions(-DCAIRO_FOUND=1)
|
||||
include_directories(${CAIRO_INCLUDE_DIR})
|
||||
freerdp_library_add(${CAIRO_LIBRARY})
|
||||
else(CAIRO_FOUND)
|
||||
message(WARNING "neigter swscale nor libcairo detected, compiling without image scaling support!")
|
||||
endif(CAIRO_FOUND)
|
||||
endif(SWScale_FOUND)
|
||||
|
||||
set(${MODULE_PREFIX}_SUBMODULES
|
||||
utils
|
||||
common
|
||||
|
|
|
@ -33,6 +33,14 @@
|
|||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/primitives.h>
|
||||
|
||||
#if defined(CAIRO_FOUND)
|
||||
#include <cairo.h>
|
||||
#endif
|
||||
|
||||
#if defined(SWSCALE_FOUND)
|
||||
#include <libswscale/swscale.h>
|
||||
#endif
|
||||
|
||||
#define TAG FREERDP_TAG("color")
|
||||
|
||||
BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* data)
|
||||
|
@ -570,3 +578,109 @@ BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(SWSCALE_FOUND)
|
||||
static int av_format_for_buffer(UINT32 format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXEL_FORMAT_ARGB32:
|
||||
return AV_PIX_FMT_BGRA;
|
||||
|
||||
case PIXEL_FORMAT_XRGB32:
|
||||
return AV_PIX_FMT_BGR0;
|
||||
|
||||
case PIXEL_FORMAT_BGRA32:
|
||||
return AV_PIX_FMT_RGBA;
|
||||
|
||||
case PIXEL_FORMAT_BGRX32:
|
||||
return AV_PIX_FMT_RGB0;
|
||||
|
||||
default:
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL freerdp_image_scale(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
|
||||
UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
|
||||
const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
|
||||
UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const BYTE* src = &pSrcData[nXSrc * 4 + nYSrc * nSrcStep];
|
||||
BYTE* dst = &pDstData[nXDst * 4 + nYDst * nDstStep];
|
||||
#if defined(SWSCALE_FOUND)
|
||||
{
|
||||
int res;
|
||||
struct SwsContext* resize;
|
||||
int srcFormat = av_format_for_buffer(SrcFormat);
|
||||
int dstFormat = av_format_for_buffer(DstFormat);
|
||||
const int srcStep[1] = { nSrcStep };
|
||||
const int dstStep[1] = { nDstStep };
|
||||
|
||||
if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
|
||||
return FALSE;
|
||||
|
||||
resize = sws_getContext(nSrcWidth + nXSrc, nSrcHeight + nYSrc, srcFormat,
|
||||
nDstWidth + nXDst, nDstHeight + nYDst, dstFormat,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
|
||||
if (!resize)
|
||||
goto fail;
|
||||
|
||||
res = sws_scale(resize, &pSrcData, srcStep, 0, nSrcHeight + nYSrc, &pDstData, dstStep);
|
||||
rc = (res == (nDstHeight + nYDst));
|
||||
fail:
|
||||
sws_freeContext(resize);
|
||||
}
|
||||
#elif defined(CAIRO_FOUND)
|
||||
{
|
||||
const double sx = (double)nDstWidth / (double)nSrcWidth;
|
||||
const double sy = (double)nDstHeight / (double)nSrcHeight;
|
||||
cairo_t* cairo_context;
|
||||
cairo_surface_t* csrc, *cdst;
|
||||
|
||||
if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
|
||||
return FALSE;
|
||||
|
||||
if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
|
||||
return FALSE;
|
||||
|
||||
csrc = cairo_image_surface_create_for_data((void*)src,
|
||||
CAIRO_FORMAT_ARGB32, (int)nSrcWidth, (int)nSrcHeight, (int)nSrcStep);
|
||||
cdst = cairo_image_surface_create_for_data(dst,
|
||||
CAIRO_FORMAT_ARGB32, (int)nDstWidth, (int)nDstHeight, (int)nDstStep);
|
||||
|
||||
if (!csrc || !cdst)
|
||||
goto fail;
|
||||
|
||||
cairo_context = cairo_create(cdst);
|
||||
|
||||
if (!cairo_context)
|
||||
goto fail2;
|
||||
|
||||
cairo_scale(cairo_context, sx, sy);
|
||||
cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface(cairo_context, csrc, 0, 0);
|
||||
cairo_paint(cairo_context);
|
||||
rc = TRUE;
|
||||
fail2:
|
||||
cairo_destroy(cairo_context);
|
||||
fail:
|
||||
cairo_surface_destroy(csrc);
|
||||
cairo_surface_destroy(cdst);
|
||||
}
|
||||
#else
|
||||
|
||||
if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
|
||||
{
|
||||
return freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
|
||||
pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
|
||||
NULL, FREERDP_FLIP_NONE);
|
||||
}
|
||||
|
||||
WLog_WARN(TAG, "SmartScaling requested but compiled without libcairo support!");
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue