20 #include <freerdp/config.h>
22 #include <freerdp/types.h>
23 #include <freerdp/primitives.h>
24 #include <freerdp/codec/color.h>
26 #include "prim_internal.h"
27 #include "prim_colors.h"
30 #define MINMAX(_v_, _l_, _h_) ((_v_) < (_l_) ? (_l_) : ((_v_) > (_h_) ? (_h_) : (_v_)))
33 static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(
const INT16* WINPR_RESTRICT pSrc[3],
34 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
35 UINT32 dstStep, UINT32 DstFormat,
39 const INT16* pY = pSrc[0];
40 const INT16* pCb = pSrc[1];
41 const INT16* pCr = pSrc[2];
42 const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
43 const size_t dstPad = (dstStep - (roi->width * 4));
44 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
46 for (UINT32 y = 0; y < roi->height; y++)
48 for (UINT32 x = 0; x < roi->width; x++)
53 const INT32 divisor = 16;
54 const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
55 const INT32 Cb = (*pCb++);
56 const INT32 Cr = (*pCr++);
57 const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL;
58 const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL;
59 const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL;
60 const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL;
61 R = ((INT16)((CrR + Y) >> divisor) >> 5);
62 G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5);
63 B = ((INT16)((CbB + Y) >> divisor) >> 5);
64 pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
73 return PRIMITIVES_SUCCESS;
76 static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(
const INT16* WINPR_RESTRICT pSrc[3],
77 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
78 UINT32 dstStep, UINT32 DstFormat,
82 const INT16* pY = pSrc[0];
83 const INT16* pCb = pSrc[1];
84 const INT16* pCr = pSrc[2];
85 const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
86 const size_t dstPad = (dstStep - (roi->width * 4));
87 const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
88 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
90 for (UINT32 y = 0; y < roi->height; y++)
92 for (UINT32 x = 0; x < roi->width; x++)
94 const INT32 divisor = 16;
95 const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
96 const INT32 Cb = (*pCb++);
97 const INT32 Cr = (*pCr++);
98 const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL;
99 const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL;
100 const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL;
101 const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL;
102 const INT64 R = (CrR + Y) >> (divisor + 5);
103 const INT64 G = (Y - CbG - CrG) >> (divisor + 5);
104 const INT64 B = (CbB + Y) >> (divisor + 5);
105 pRGB = writePixel(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
114 return PRIMITIVES_SUCCESS;
117 static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(
const INT16* WINPR_RESTRICT pSrc[3],
118 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
119 UINT32 dstStep, UINT32 DstFormat,
124 case PIXEL_FORMAT_BGRA32:
125 case PIXEL_FORMAT_BGRX32:
126 return general_yCbCrToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat,
130 return general_yCbCrToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
138 general_yCbCrToRGB_16s16s_P3P3(
const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
139 INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
153 const INT16* yptr = pSrc[0];
154 const INT16* cbptr = pSrc[1];
155 const INT16* crptr = pSrc[2];
156 INT16* rptr = pDst[0];
157 INT16* gptr = pDst[1];
158 INT16* bptr = pDst[2];
159 UINT32 srcbump = (srcStep - (roi->width *
sizeof(UINT16))) /
sizeof(UINT16);
160 UINT32 dstbump = (dstStep - (roi->width *
sizeof(UINT16))) /
sizeof(UINT16);
162 for (UINT32 y = 0; y < roi->height; y++)
164 for (UINT32 x = 0; x < roi->width; ++x)
169 INT32 cy = (INT32)(*yptr++);
170 INT32 cb = (INT32)(*cbptr++);
171 INT32 cr = (INT32)(*crptr++);
195 cy = (INT32)((UINT32)(cy + 4096) << 16);
196 r = cy + cr * 91947LL;
197 g = cy - cb * 22544LL - cr * 46792LL;
198 b = cy + cb * 115998LL;
199 *rptr++ = CLIP(r >> 21);
200 *gptr++ = CLIP(g >> 21);
201 *bptr++ = CLIP(b >> 21);
212 return PRIMITIVES_SUCCESS;
217 general_RGBToYCbCr_16s16s_P3P3(
const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
218 INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
231 const INT16* rptr = pSrc[0];
232 const INT16* gptr = pSrc[1];
233 const INT16* bptr = pSrc[2];
234 INT16* yptr = pDst[0];
235 INT16* cbptr = pDst[1];
236 INT16* crptr = pDst[2];
237 UINT32 srcbump = (srcStep - (roi->width *
sizeof(UINT16))) /
sizeof(UINT16);
238 UINT32 dstbump = (dstStep - (roi->width *
sizeof(UINT16))) /
sizeof(UINT16);
240 for (UINT32 y = 0; y < roi->height; y++)
242 for (UINT32 x = 0; x < roi->width; ++x)
247 INT32 r = (INT32)(*rptr++);
248 INT32 g = (INT32)(*gptr++);
249 INT32 b = (INT32)(*bptr++);
262 INT32 cy = (r * 9798 + g * 19235 + b * 3735) >> 10;
263 INT32 cb = (r * -5535 + g * -10868 + b * 16403) >> 10;
264 INT32 cr = (r * 16377 + g * -13714 + b * -2663) >> 10;
265 *yptr++ = (INT16)MINMAX(cy - 4096, -4096, 4095);
266 *cbptr++ = (INT16)MINMAX(cb, -4096, 4095);
267 *crptr++ = (INT16)MINMAX(cr, -4096, 4095);
278 return PRIMITIVES_SUCCESS;
281 static INLINE
void writeScanlineGeneric(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
282 const INT16* r,
const INT16* g,
const INT16* b, DWORD width)
284 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
286 for (UINT32 x = 0; x < width; x++)
287 dst = writePixel(dst, formatSize, DstFormat, *r++, *g++, *b++, 0);
290 static INLINE
void writeScanlineRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
291 const INT16* g,
const INT16* b, DWORD width)
293 WINPR_UNUSED(formatSize);
294 WINPR_UNUSED(DstFormat);
296 for (UINT32 x = 0; x < width; x++)
298 const BYTE R = CLIP(*r++);
299 const BYTE G = CLIP(*g++);
300 const BYTE B = CLIP(*b++);
307 static INLINE
void writeScanlineBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
308 const INT16* g,
const INT16* b, DWORD width)
310 WINPR_UNUSED(formatSize);
311 WINPR_UNUSED(DstFormat);
313 for (UINT32 x = 0; x < width; x++)
315 const BYTE R = CLIP(*r++);
316 const BYTE G = CLIP(*g++);
317 const BYTE B = CLIP(*b++);
324 static INLINE
void writeScanlineBGRX(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
325 const INT16* g,
const INT16* b, DWORD width)
327 WINPR_UNUSED(formatSize);
328 WINPR_UNUSED(DstFormat);
330 for (UINT32 x = 0; x < width; x++)
332 const BYTE R = CLIP(*r++);
333 const BYTE G = CLIP(*g++);
334 const BYTE B = CLIP(*b++);
342 static INLINE
void writeScanlineRGBX(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
343 const INT16* g,
const INT16* b, DWORD width)
345 WINPR_UNUSED(formatSize);
346 WINPR_UNUSED(DstFormat);
348 for (UINT32 x = 0; x < width; x++)
350 const BYTE R = CLIP(*r++);
351 const BYTE G = CLIP(*g++);
352 const BYTE B = CLIP(*b++);
360 static INLINE
void writeScanlineXBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
361 const INT16* g,
const INT16* b, DWORD width)
363 WINPR_UNUSED(formatSize);
364 WINPR_UNUSED(DstFormat);
366 for (UINT32 x = 0; x < width; x++)
368 const BYTE R = CLIP(*r++);
369 const BYTE G = CLIP(*g++);
370 const BYTE B = CLIP(*b++);
378 static INLINE
void writeScanlineXRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
const INT16* r,
379 const INT16* g,
const INT16* b, DWORD width)
381 WINPR_UNUSED(formatSize);
382 WINPR_UNUSED(DstFormat);
384 for (UINT32 x = 0; x < width; x++)
386 const BYTE R = CLIP(*r++);
387 const BYTE G = CLIP(*g++);
388 const BYTE B = CLIP(*b++);
396 typedef void (*fkt_writeScanline)(BYTE*, DWORD, UINT32,
const INT16*,
const INT16*,
const INT16*,
399 static INLINE fkt_writeScanline getScanlineWriteFunction(DWORD format)
403 case PIXEL_FORMAT_ARGB32:
404 case PIXEL_FORMAT_XRGB32:
405 return writeScanlineXRGB;
407 case PIXEL_FORMAT_ABGR32:
408 case PIXEL_FORMAT_XBGR32:
409 return writeScanlineXBGR;
411 case PIXEL_FORMAT_RGBA32:
412 case PIXEL_FORMAT_RGBX32:
413 return writeScanlineRGBX;
415 case PIXEL_FORMAT_BGRA32:
416 case PIXEL_FORMAT_BGRX32:
417 return writeScanlineBGRX;
419 case PIXEL_FORMAT_BGR24:
420 return writeScanlineBGR;
422 case PIXEL_FORMAT_RGB24:
423 return writeScanlineRGB;
426 return writeScanlineGeneric;
431 static pstatus_t general_RGBToRGB_16s8u_P3AC4R_general(
432 const INT16* WINPR_RESTRICT pSrc[3],
434 BYTE* WINPR_RESTRICT pDst,
436 UINT32 DstFormat,
const prim_size_t* WINPR_RESTRICT roi)
438 const INT16* r = pSrc[0];
439 const INT16* g = pSrc[1];
440 const INT16* b = pSrc[2];
441 const DWORD srcAdd = srcStep /
sizeof(INT16);
442 fkt_writeScanline writeScanline = getScanlineWriteFunction(DstFormat);
443 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
445 for (UINT32 y = 0; y < roi->height; ++y)
447 (*writeScanline)(pDst, formatSize, DstFormat, r, g, b, roi->width);
454 return PRIMITIVES_SUCCESS;
457 static pstatus_t general_RGBToRGB_16s8u_P3AC4R_BGRX(
458 const INT16* WINPR_RESTRICT pSrc[3],
460 BYTE* WINPR_RESTRICT pDst,
462 UINT32 DstFormat,
const prim_size_t* WINPR_RESTRICT roi)
464 const INT16* r = pSrc[0];
465 const INT16* g = pSrc[1];
466 const INT16* b = pSrc[2];
467 const DWORD srcAdd = srcStep /
sizeof(INT16);
468 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
470 for (UINT32 y = 0; y < roi->height; ++y)
472 writeScanlineBGRX(pDst, formatSize, DstFormat, r, g, b, roi->width);
479 return PRIMITIVES_SUCCESS;
483 general_RGBToRGB_16s8u_P3AC4R(
const INT16* WINPR_RESTRICT pSrc[3],
485 BYTE* WINPR_RESTRICT pDst,
492 case PIXEL_FORMAT_BGRA32:
493 case PIXEL_FORMAT_BGRX32:
494 return general_RGBToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
497 return general_RGBToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
502 void primitives_init_colors(
primitives_t* WINPR_RESTRICT prims)
504 prims->yCbCrToRGB_16s8u_P3AC4R = general_yCbCrToRGB_16s8u_P3AC4R;
505 prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
506 prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
507 prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;
511 void primitives_init_colors_opt(
primitives_t* WINPR_RESTRICT prims)
513 primitives_init_colors_sse2(prims);
514 primitives_init_colors_neon(prims);