libfreerdp-codec: add BGR support to egfx

This commit is contained in:
Marc-André Moreau 2014-09-16 16:55:47 -04:00
parent b25258e8c6
commit 1837c34e6e
9 changed files with 200 additions and 41 deletions

View File

@ -27,6 +27,8 @@
#define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1
#define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2
#define FREERDP_PIXEL_FORMAT_IS_ABGR(_format) (FREERDP_PIXEL_FORMAT_TYPE(_format) == FREERDP_PIXEL_FORMAT_TYPE_ABGR)
#define FREERDP_PIXEL_FLIP_NONE 0
#define FREERDP_PIXEL_FLIP_VERTICAL 1
#define FREERDP_PIXEL_FLIP_HORIZONTAL 2

View File

@ -283,6 +283,8 @@ struct _PROGRESSIVE_CONTEXT
{
BOOL Compressor;
BOOL invert;
wLog* log;
wBufferPool* bufferPool;

View File

@ -31,6 +31,7 @@ struct gdi_gfx_surface
BOOL alpha;
BYTE* data;
int scanline;
UINT32 format;
};
typedef struct gdi_gfx_surface gdiGfxSurface;
@ -42,6 +43,7 @@ struct gdi_gfx_cache_entry
BOOL alpha;
BYTE* data;
int scanline;
UINT32 format;
};
typedef struct gdi_gfx_cache_entry gdiGfxCacheEntry;

View File

@ -140,6 +140,10 @@ typedef pstatus_t (*__yCbCrToRGB_16s8u_P3AC4R_t)(
const INT16* pSrc[3], INT32 srcStep,
BYTE* pDst, INT32 dstStep,
const prim_size_t* roi);
typedef pstatus_t (*__yCbCrToBGR_16s8u_P3AC4R_t)(
const INT16* pSrc[3], INT32 srcStep,
BYTE* pDst, INT32 dstStep,
const prim_size_t* roi);
typedef pstatus_t (*__yCbCrToRGB_16s16s_P3P3_t)(
const INT16 *pSrc[3], INT32 srcStep,
INT16 *pDst[3], INT32 dstStep,
@ -208,6 +212,7 @@ typedef struct
__sign_16s_t sign_16s;
/* Color conversions */
__yCbCrToRGB_16s8u_P3AC4R_t yCbCrToRGB_16s8u_P3AC4R;
__yCbCrToBGR_16s8u_P3AC4R_t yCbCrToBGR_16s8u_P3AC4R;
__yCbCrToRGB_16s16s_P3P3_t yCbCrToRGB_16s16s_P3P3;
__RGBToYCbCr_16s16s_P3P3_t RGBToYCbCr_16s16s_P3P3;
__RGBToRGB_16s8u_P3AC4R_t RGBToRGB_16s8u_P3AC4R;

View File

@ -57,6 +57,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
{
UINT32 i;
BOOL invert;
UINT32 x, y;
UINT32 count;
UINT32 color;
@ -95,6 +96,8 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
if ((nWidth > 0xFFFF) || (nHeight > 0xFFFF))
return -1004;
invert = FREERDP_PIXEL_FORMAT_IS_ABGR(DstFormat) ? TRUE : FALSE;
glyphFlags = pSrcData[0];
seqNumber = pSrcData[1];
offset += 2;
@ -195,7 +198,11 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
if ((residualByteCount - suboffset) < 4)
return -1015;
color = RGB32(residualData[suboffset + 2], residualData[suboffset + 1], residualData[suboffset + 0]);
if (!invert)
color = RGB32(residualData[suboffset + 2], residualData[suboffset + 1], residualData[suboffset + 0]);
else
color = BGR32(residualData[suboffset + 2], residualData[suboffset + 1], residualData[suboffset + 0]);
suboffset += 3;
runLengthFactor = (UINT32) residualData[suboffset];
@ -288,7 +295,11 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
yEnd = *((UINT16*) &bandsData[suboffset + 6]);
suboffset += 8;
colorBkg = RGB32(bandsData[suboffset + 2], bandsData[suboffset + 1], bandsData[suboffset + 0]);
if (!invert)
colorBkg = RGB32(bandsData[suboffset + 2], bandsData[suboffset + 1], bandsData[suboffset + 0]);
else
colorBkg = BGR32(bandsData[suboffset + 2], bandsData[suboffset + 1], bandsData[suboffset + 0]);
suboffset += 3;
if (xEnd < xStart)
@ -376,11 +387,23 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
pDstPixel32 = vBarShortEntry->pixels;
for (y = 0; y < vBarShortPixelCount; y++)
if (!invert)
{
*pDstPixel32 = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
for (y = 0; y < vBarShortPixelCount; y++)
{
*pDstPixel32 = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
}
}
else
{
for (y = 0; y < vBarShortPixelCount; y++)
{
*pDstPixel32 = BGR32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
}
}
suboffset += (vBarShortPixelCount * 3);
@ -561,15 +584,32 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
pSrcPixel8 = bitmapData;
for (y = 0; y < height; y++)
if (!invert)
{
pDstPixel32 = (UINT32*) &pDstData[((nYDstRel + y) * nDstStep) + (nXDstRel * 4)];
for (x = 0; x < width; x++)
for (y = 0; y < height; y++)
{
*pDstPixel32 = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
pDstPixel32 = (UINT32*) &pDstData[((nYDstRel + y) * nDstStep) + (nXDstRel * 4)];
for (x = 0; x < width; x++)
{
*pDstPixel32 = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
}
}
}
else
{
for (y = 0; y < height; y++)
{
pDstPixel32 = (UINT32*) &pDstData[((nYDstRel + y) * nDstStep) + (nXDstRel * 4)];
for (x = 0; x < width; x++)
{
*pDstPixel32 = BGR32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
pDstPixel32++;
}
}
}
}
@ -582,11 +622,33 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
pSrcPixel8 = clear->nsc->BitmapData;
pDstPixel8 = &pDstData[(nYDstRel * nDstStep) + (nXDstRel * 4)];
for (y = 0; y < height; y++)
if (!invert)
{
CopyMemory(pDstPixel8, pSrcPixel8, nSrcStep);
pSrcPixel8 += nSrcStep;
pDstPixel8 += nDstStep;
for (y = 0; y < height; y++)
{
CopyMemory(pDstPixel8, pSrcPixel8, nSrcStep);
pSrcPixel8 += nSrcStep;
pDstPixel8 += nDstStep;
}
}
else
{
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
pDstPixel8[0] = pSrcPixel8[2];
pDstPixel8[1] = pSrcPixel8[1];
pDstPixel8[2] = pSrcPixel8[0];
pDstPixel8[3] = 0xFF;
pSrcPixel8 += 4;
pDstPixel8 += 4;
}
pSrcPixel8 += (nSrcStep - (width * 4));
pDstPixel8 += (nDstStep - (width * 4));
}
}
}
else if (subcodecId == 2) /* CLEARCODEC_SUBCODEC_RLEX */
@ -606,10 +668,21 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
if (paletteCount > 127)
return -1047;
for (i = 0; i < paletteCount; i++)
if (!invert)
{
palette[i] = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
for (i = 0; i < paletteCount; i++)
{
palette[i] = RGB32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
}
}
else
{
for (i = 0; i < paletteCount; i++)
{
palette[i] = BGR32(pSrcPixel8[2], pSrcPixel8[1], pSrcPixel8[0]);
pSrcPixel8 += 3;
}
}
pixelIndex = 0;

View File

@ -1446,7 +1446,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
pDstPixel[0] = pSrcPixel[2];
pDstPixel[1] = pSrcPixel[1];
pDstPixel[2] = pSrcPixel[0];
pDstPixel[4] = 0xFF;
pDstPixel[3] = 0xFF;
pSrcPixel += 4;
pDstPixel += 4;
@ -1468,7 +1468,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
pDstPixel[0] = pSrcPixel[2];
pDstPixel[1] = pSrcPixel[1];
pDstPixel[2] = pSrcPixel[0];
pDstPixel[4] = 0xFF;
pDstPixel[3] = 0xFF;
pSrcPixel += 4;
pDstPixel += 4;

View File

@ -812,8 +812,10 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG
progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], pSign[1], diff); /* Cb */
progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], pSign[2], diff); /* Cr */
prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2,
tile->data, 64 * 4, &roi_64x64);
if (!progressive->invert)
prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64);
else
prims->yCbCrToBGR_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64);
BufferPool_Return(progressive->bufferPool, pBuffer);
@ -1231,8 +1233,10 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR
if (status < 0)
return -1;
prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2,
tile->data, 64 * 4, &roi_64x64);
if (!progressive->invert)
prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64);
else
prims->yCbCrToBGR_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64);
BufferPool_Return(progressive->bufferPool, pBuffer);
@ -1543,6 +1547,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN
RFX_COMPONENT_CODEC_QUANT* quantVal;
RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal;
progressive->invert = FREERDP_PIXEL_FORMAT_IS_ABGR(DstFormat) ? TRUE : FALSE;
surface = (PROGRESSIVE_SURFACE_CONTEXT*) progressive_get_surface_data(progressive, surfaceId);
if (!surface)

View File

@ -82,8 +82,8 @@ int gdi_OutputUpdate(rdpGdi* gdi)
update->BeginPaint(gdi->context);
freerdp_image_copy(pDstData, PIXEL_FORMAT_XRGB32, nDstStep, nXDst, nYDst, nWidth, nHeight,
surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, nXSrc, nYSrc);
freerdp_image_copy(pDstData, gdi->format, nDstStep, nXDst, nYDst, nWidth, nHeight,
surface->data, surface->format, surface->scanline, nXSrc, nYSrc);
gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, nWidth, nHeight);
@ -141,7 +141,7 @@ int gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* context, R
if (!surface)
return -1;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top,
freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top,
cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0);
invalidRect.left = cmd->left;
@ -220,7 +220,7 @@ int gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* context, RDPGF
nWidth = updateRects[j].right - updateRects[j].left;
nHeight = updateRects[j].bottom - updateRects[j].top;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_copy(surface->data, surface->format, surface->scanline,
nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0);
@ -255,7 +255,7 @@ int gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* context, RDP
DstData = surface->data;
status = clear_decompress(gdi->codecs->clear, cmd->data, cmd->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
if (status < 0)
{
@ -468,7 +468,7 @@ int gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* context, RD
nXSrc = nXDst - (cmd->left + tile->x);
nYSrc = nYDst - (cmd->top + tile->y);
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
freerdp_image_copy(surface->data, surface->format,
surface->scanline, nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc);
@ -534,6 +534,7 @@ int gdi_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODI
int gdi_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
{
gdiGfxSurface* surface;
rdpGdi* gdi = (rdpGdi*) context->custom;
surface = (gdiGfxSurface*) calloc(1, sizeof(gdiGfxSurface));
@ -545,6 +546,8 @@ int gdi_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* c
surface->height = (UINT32) createSurface->height;
surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE;
surface->format = (!gdi->abgr) ? PIXEL_FORMAT_XRGB32 : PIXEL_FORMAT_XBGR32;
surface->scanline = (surface->width + (surface->width % 4)) * 4;
surface->data = (BYTE*) calloc(1, surface->scanline * surface->height);
@ -558,7 +561,7 @@ int gdi_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* c
int gdi_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
{
gdiGfxSurface* surface = NULL;
gdiGfxSurface* surface;
rdpGdi* gdi = (rdpGdi*) context->custom;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId);
@ -598,7 +601,10 @@ int gdi_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill
r = solidFill->fillPixel.R;
a = solidFill->fillPixel.XA;
color = ARGB32(a, r, g, b);
if (!gdi->abgr)
color = ARGB32(a, r, g, b);
else
color = ABGR32(a, r, g, b);
for (index = 0; index < solidFill->fillRectCount; index++)
{
@ -612,7 +618,7 @@ int gdi_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill
invalidRect.right = rect->right;
invalidRect.bottom = rect->bottom;
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_fill(surface->data, surface->format, surface->scanline,
rect->left, rect->top, nWidth, nHeight, color);
region16_union_rect(&(gdi->invalidRegion), &(gdi->invalidRegion), &invalidRect);
@ -655,8 +661,8 @@ int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE
{
destPt = &surfaceToSurface->destPts[index];
freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32,
freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format,
surfaceSrc->scanline, rectSrc->left, rectSrc->top);
invalidRect.left = destPt->x;
@ -678,6 +684,7 @@ int gdi_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU
RDPGFX_RECT16* rect;
gdiGfxSurface* surface;
gdiGfxCacheEntry* cacheEntry;
rdpGdi* gdi = (rdpGdi*) context->custom;
rect = &(surfaceToCache->rectSrc);
@ -695,15 +702,17 @@ int gdi_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU
cacheEntry->height = (UINT32) (rect->bottom - rect->top);
cacheEntry->alpha = surface->alpha;
cacheEntry->format = (!gdi->abgr) ? PIXEL_FORMAT_XRGB32 : PIXEL_FORMAT_XBGR32;
cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4;
cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height);
if (!cacheEntry->data)
return -1;
freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline,
freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height, surface->data,
PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top);
surface->format, surface->scanline, rect->left, rect->top);
context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry);
@ -729,9 +738,9 @@ int gdi_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU
{
destPt = &cacheToSurface->destPts[index];
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_copy(surface->data, surface->format, surface->scanline,
destPt->x, destPt->y, cacheEntry->width, cacheEntry->height,
cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0);
cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0);
invalidRect.left = destPt->x;
invalidRect.top = destPt->y;

View File

@ -93,6 +93,65 @@ pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep,
return PRIMITIVES_SUCCESS;
}
pstatus_t general_yCbCrToBGR_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep,
BYTE* pDst, int dstStep, const prim_size_t* roi)
{
int x, y;
INT16 R, G, B;
float Y, Cb, Cr;
BYTE* pRGB = pDst;
const INT16* pY = pSrc[0];
const INT16* pCb = pSrc[1];
const INT16* pCr = pSrc[2];
int srcPad = (srcStep - (roi->width * 2)) / 2;
int dstPad = (dstStep - (roi->width * 4)) / 4;
for (y = 0; y < roi->height; y++)
{
for (x = 0; x < roi->width; x++)
{
Y = (float) (pY[0] + 4096);
Cb = (float) (pCb[0]);
Cr = (float) (pCr[0]);
R = ((INT16) (((Cr * 1.402525f) + Y + 16.0f)) >> 5);
G = ((INT16) ((Y - (Cb * 0.343730f) - (Cr * 0.714401f) + 16.0f)) >> 5);
B = ((INT16) (((Cb * 1.769905f) + Y + 16.0f)) >> 5);
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
*pRGB++ = (BYTE) R;
*pRGB++ = (BYTE) G;
*pRGB++ = (BYTE) B;
*pRGB++ = 0xFF;
pY++;
pCb++;
pCr++;
}
pY += srcPad;
pCb += srcPad;
pCr += srcPad;
pRGB += dstPad;
}
return PRIMITIVES_SUCCESS;
}
/* ------------------------------------------------------------------------- */
pstatus_t general_yCbCrToRGB_16s16s_P3P3(
@ -280,6 +339,7 @@ pstatus_t general_RGBToRGB_16s8u_P3AC4R(
void primitives_init_colors(primitives_t* prims)
{
prims->yCbCrToRGB_16s8u_P3AC4R = general_yCbCrToRGB_16s8u_P3AC4R;
prims->yCbCrToBGR_16s8u_P3AC4R = general_yCbCrToBGR_16s8u_P3AC4R;
prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;