22#include <freerdp/config.h> 
   23#include <winpr/assert.h> 
   24#include <winpr/cast.h> 
   26#include <freerdp/types.h> 
   27#include <freerdp/primitives.h> 
   28#include <freerdp/codec/color.h> 
   30#include "prim_internal.h" 
   31#include "prim_colors.h" 
   34#define MINMAX(_v_, _l_, _h_) ((_v_) < (_l_) ? (_l_) : ((_v_) > (_h_) ? (_h_) : (_v_))) 
   46static const INT32 ycbcr_constants[][4] = { { 1, 1, 0, 2 },
 
   54                                          { 359, 183, 88, 453 },
 
   55                                          { 718, 366, 176, 906 },
 
   56                                          { 1436, 732, 352, 1812 },
 
   57                                          { 2872, 1463, 704, 3625 },
 
   58                                          { 5745, 2926, 1408, 7250 },
 
   59                                          { 11489, 5852, 2816, 14499 },
 
   60                                          { 22979, 11705, 5632, 28998 },
 
   61                                          { 45958, 23409, 11263, 57996 },
 
   62                                          { 91916, 46819, 22527, 115992 },
 
   63                                          { 183832, 93638, 45053, 231985 },
 
   64                                          { 367664, 187276, 90107, 463970 },
 
   65                                          { 735327, 374552, 180214, 927940 },
 
   66                                          { 1470654, 749104, 360427, 1855880 },
 
   67                                          { 2941308, 1498207, 720854, 3711760 },
 
   68                                          { 5882616, 2996415, 1441708, 7423520 },
 
   69                                          { 11765232, 5992830, 2883416, 14847039 },
 
   70                                          { 23530465, 11985660, 5766832, 29694078 },
 
   71                                          { 47060930, 23971320, 11533665, 59388157 },
 
   72                                          { 94121859, 47942640, 23067330, 118776314 },
 
   73                                          { 188243719, 95885279, 46134660, 237552628 },
 
   74                                          { 376487438, 191770558, 92269319, 475105256 },
 
   75                                          { 752974876, 383541116, 184538639, 950210512 },
 
   76                                          { 1505949752, 767082233, 369077277, 1900421023 } };
 
   78static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(
const INT16* WINPR_RESTRICT pSrc[3],
 
   79                                                      UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
 
   80                                                      UINT32 dstStep, UINT32 DstFormat,
 
   84  const INT16* pY = pSrc[0];
 
   85  const INT16* pCb = pSrc[1];
 
   86  const INT16* pCr = pSrc[2];
 
   87  const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
 
   88  const size_t dstPad = (dstStep - (roi->width * 4));
 
   89  const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
 
   91  for (UINT32 y = 0; y < roi->height; y++)
 
   93    for (UINT32 x = 0; x < roi->width; x++)
 
   95      const INT32 divisor = 16;
 
   96      const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
 
   97      const INT32 Cb = (*pCb++);
 
   98      const INT32 Cr = (*pCr++);
 
  100      const INT32 CrR = WINPR_ASSERTING_INT_CAST(
 
  101          int32_t, Cr* ycbcr_constants[divisor][0]); 
 
  102      const INT32 CrG = WINPR_ASSERTING_INT_CAST(
 
  103          int32_t, Cr* ycbcr_constants[divisor][1]); 
 
  104      const INT32 CbG = WINPR_ASSERTING_INT_CAST(
 
  105          int32_t, Cb* ycbcr_constants[divisor][2]); 
 
  106      const INT32 CbB = WINPR_ASSERTING_INT_CAST(
 
  107          int32_t, Cb* ycbcr_constants[divisor][3]); 
 
  108      const INT16 R = WINPR_ASSERTING_INT_CAST(int16_t, ((CrR + Y) >> divisor) >> 5);
 
  109      const INT16 G = WINPR_ASSERTING_INT_CAST(int16_t, ((Y - CbG - CrG) >> divisor) >> 5);
 
  110      const INT16 B = WINPR_ASSERTING_INT_CAST(int16_t, ((CbB + Y) >> divisor) >> 5);
 
  111      pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
 
  120  return PRIMITIVES_SUCCESS;
 
  123static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(
const INT16* WINPR_RESTRICT pSrc[3],
 
  124                                                         UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
 
  125                                                         UINT32 dstStep, UINT32 DstFormat,
 
  129  const INT16* pY = pSrc[0];
 
  130  const INT16* pCb = pSrc[1];
 
  131  const INT16* pCr = pSrc[2];
 
  132  const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
 
  133  const size_t dstPad = (dstStep - (roi->width * 4));
 
  134  const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
 
  135  const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
 
  137  for (UINT32 y = 0; y < roi->height; y++)
 
  139    for (UINT32 x = 0; x < roi->width; x++)
 
  141      const INT32 divisor = 16;
 
  142      const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
 
  143      const INT32 Cb = (*pCb++);
 
  144      const INT32 Cr = (*pCr++);
 
  145      const INT32 CrR = Cr * ycbcr_constants[divisor][0];
 
  146      const INT32 CrG = Cr * ycbcr_constants[divisor][1];
 
  147      const INT32 CbG = Cb * ycbcr_constants[divisor][2];
 
  148      const INT32 CbB = Cb * ycbcr_constants[divisor][3];
 
  149      const INT32 R = (CrR + Y) >> (divisor + 5);
 
  150      const INT32 G = (Y - CbG - CrG) >> (divisor + 5);
 
  151      const INT32 B = (CbB + Y) >> (divisor + 5);
 
  152      pRGB = writePixel(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
 
  161  return PRIMITIVES_SUCCESS;
 
  164static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(
const INT16* WINPR_RESTRICT pSrc[3],
 
  165                                                 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
 
  166                                                 UINT32 dstStep, UINT32 DstFormat,
 
  171    case PIXEL_FORMAT_BGRA32:
 
  172    case PIXEL_FORMAT_BGRX32:
 
  173      return general_yCbCrToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat,
 
  177      return general_yCbCrToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
 
  185general_yCbCrToRGB_16s16s_P3P3(
const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
 
  186                               INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
 
  200  const INT16* yptr = pSrc[0];
 
  201  const INT16* cbptr = pSrc[1];
 
  202  const INT16* crptr = pSrc[2];
 
  203  INT16* rptr = pDst[0];
 
  204  INT16* gptr = pDst[1];
 
  205  INT16* bptr = pDst[2];
 
  206  UINT32 srcbump = (WINPR_ASSERTING_INT_CAST(uint32_t, srcStep) - (roi->width * 
sizeof(UINT16))) /
 
  208  UINT32 dstbump = (WINPR_ASSERTING_INT_CAST(uint32_t, dstStep) - (roi->width * 
sizeof(UINT16))) /
 
  211  for (UINT32 y = 0; y < roi->height; y++)
 
  213    for (UINT32 x = 0; x < roi->width; ++x)
 
  218      INT32 cy = (INT32)(*yptr++);
 
  219      INT32 cb = (INT32)(*cbptr++);
 
  220      INT32 cr = (INT32)(*crptr++);
 
  244      cy = (INT32)((UINT32)(cy + 4096) << 16);
 
  246      r = 1LL * cy + 1LL * cr * ycbcr_constants[16][0];
 
  247      g = 1LL * cy - 1LL * cb * ycbcr_constants[16][1] - 1LL * cr * ycbcr_constants[16][2];
 
  248      b = 1LL * cy + 1LL * cb * ycbcr_constants[16][3];
 
  249      *rptr++ = CLIP(r >> 21);
 
  250      *gptr++ = CLIP(g >> 21);
 
  251      *bptr++ = CLIP(b >> 21);
 
  262  return PRIMITIVES_SUCCESS;
 
  267general_RGBToYCbCr_16s16s_P3P3(
const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
 
  268                               INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
 
  281  const INT16* rptr = pSrc[0];
 
  282  const INT16* gptr = pSrc[1];
 
  283  const INT16* bptr = pSrc[2];
 
  284  INT16* yptr = pDst[0];
 
  285  INT16* cbptr = pDst[1];
 
  286  INT16* crptr = pDst[2];
 
  287  UINT32 srcbump = (WINPR_ASSERTING_INT_CAST(uint32_t, srcStep) - (roi->width * 
sizeof(UINT16))) /
 
  289  UINT32 dstbump = (WINPR_ASSERTING_INT_CAST(uint32_t, dstStep) - (roi->width * 
sizeof(UINT16))) /
 
  292  for (UINT32 y = 0; y < roi->height; y++)
 
  294    for (UINT32 x = 0; x < roi->width; ++x)
 
  299      INT32 r = (INT32)(*rptr++);
 
  300      INT32 g = (INT32)(*gptr++);
 
  301      INT32 b = (INT32)(*bptr++);
 
  314      INT32 cy = (r * 9798 + g * 19235 + b * 3735) >> 10;
 
  315      INT32 cb = (r * -5535 + g * -10868 + b * 16403) >> 10;
 
  316      INT32 cr = (r * 16377 + g * -13714 + b * -2663) >> 10;
 
  317      *yptr++ = (INT16)MINMAX(cy - 4096, -4096, 4095);
 
  318      *cbptr++ = (INT16)MINMAX(cb, -4096, 4095);
 
  319      *crptr++ = (INT16)MINMAX(cr, -4096, 4095);
 
  330  return PRIMITIVES_SUCCESS;
 
  333static inline void writeScanlineGeneric(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
 
  334                                        const INT16* r, 
const INT16* g, 
const INT16* b, DWORD width)
 
  336  fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
 
  338  for (UINT32 x = 0; x < width; x++)
 
  340    const INT16 pr = *r++;
 
  341    const INT16 pg = *g++;
 
  342    const INT16 pb = *b++;
 
  345        writePixel(dst, formatSize, DstFormat, WINPR_ASSERTING_INT_CAST(UINT8, pr),
 
  346                   WINPR_ASSERTING_INT_CAST(UINT8, pg), WINPR_ASSERTING_INT_CAST(UINT8, pb), 0);
 
  350static inline void writeScanlineRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  351                                    const INT16* g, 
const INT16* b, DWORD width)
 
  353  WINPR_UNUSED(formatSize);
 
  354  WINPR_UNUSED(DstFormat);
 
  356  for (UINT32 x = 0; x < width; x++)
 
  358    const BYTE R = CLIP(*r++);
 
  359    const BYTE G = CLIP(*g++);
 
  360    const BYTE B = CLIP(*b++);
 
  367static inline void writeScanlineBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  368                                    const INT16* g, 
const INT16* b, DWORD width)
 
  370  WINPR_UNUSED(formatSize);
 
  371  WINPR_UNUSED(DstFormat);
 
  373  for (UINT32 x = 0; x < width; x++)
 
  375    const BYTE R = CLIP(*r++);
 
  376    const BYTE G = CLIP(*g++);
 
  377    const BYTE B = CLIP(*b++);
 
  384static inline void writeScanlineBGRX(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  385                                     const INT16* g, 
const INT16* b, DWORD width)
 
  387  WINPR_UNUSED(formatSize);
 
  388  WINPR_UNUSED(DstFormat);
 
  390  for (UINT32 x = 0; x < width; x++)
 
  392    const BYTE R = CLIP(*r++);
 
  393    const BYTE G = CLIP(*g++);
 
  394    const BYTE B = CLIP(*b++);
 
  402static inline void writeScanlineRGBX(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  403                                     const INT16* g, 
const INT16* b, DWORD width)
 
  405  WINPR_UNUSED(formatSize);
 
  406  WINPR_UNUSED(DstFormat);
 
  408  for (UINT32 x = 0; x < width; x++)
 
  410    const BYTE R = CLIP(*r++);
 
  411    const BYTE G = CLIP(*g++);
 
  412    const BYTE B = CLIP(*b++);
 
  420static inline void writeScanlineXBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  421                                     const INT16* g, 
const INT16* b, DWORD width)
 
  423  WINPR_UNUSED(formatSize);
 
  424  WINPR_UNUSED(DstFormat);
 
  426  for (UINT32 x = 0; x < width; x++)
 
  428    const BYTE R = CLIP(*r++);
 
  429    const BYTE G = CLIP(*g++);
 
  430    const BYTE B = CLIP(*b++);
 
  438static inline void writeScanlineXRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, 
const INT16* r,
 
  439                                     const INT16* g, 
const INT16* b, DWORD width)
 
  441  WINPR_UNUSED(formatSize);
 
  442  WINPR_UNUSED(DstFormat);
 
  444  for (UINT32 x = 0; x < width; x++)
 
  446    const BYTE R = CLIP(*r++);
 
  447    const BYTE G = CLIP(*g++);
 
  448    const BYTE B = CLIP(*b++);
 
  456typedef void (*fkt_writeScanline)(BYTE*, DWORD, UINT32, 
const INT16*, 
const INT16*, 
const INT16*,
 
  459static inline fkt_writeScanline getScanlineWriteFunction(DWORD format)
 
  463    case PIXEL_FORMAT_ARGB32:
 
  464    case PIXEL_FORMAT_XRGB32:
 
  465      return writeScanlineXRGB;
 
  467    case PIXEL_FORMAT_ABGR32:
 
  468    case PIXEL_FORMAT_XBGR32:
 
  469      return writeScanlineXBGR;
 
  471    case PIXEL_FORMAT_RGBA32:
 
  472    case PIXEL_FORMAT_RGBX32:
 
  473      return writeScanlineRGBX;
 
  475    case PIXEL_FORMAT_BGRA32:
 
  476    case PIXEL_FORMAT_BGRX32:
 
  477      return writeScanlineBGRX;
 
  479    case PIXEL_FORMAT_BGR24:
 
  480      return writeScanlineBGR;
 
  482    case PIXEL_FORMAT_RGB24:
 
  483      return writeScanlineRGB;
 
  486      return writeScanlineGeneric;
 
  491static pstatus_t general_RGBToRGB_16s8u_P3AC4R_general(
 
  492    const INT16* WINPR_RESTRICT pSrc[3], 
 
  494    BYTE* WINPR_RESTRICT pDst,           
 
  496    UINT32 DstFormat, 
const prim_size_t* WINPR_RESTRICT roi) 
 
  498  const INT16* r = pSrc[0];
 
  499  const INT16* g = pSrc[1];
 
  500  const INT16* b = pSrc[2];
 
  501  const DWORD srcAdd = srcStep / 
sizeof(INT16);
 
  502  fkt_writeScanline writeScanline = getScanlineWriteFunction(DstFormat);
 
  503  const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
 
  505  for (UINT32 y = 0; y < roi->height; ++y)
 
  507    (*writeScanline)(pDst, formatSize, DstFormat, r, g, b, roi->width);
 
  514  return PRIMITIVES_SUCCESS;
 
  517static pstatus_t general_RGBToRGB_16s8u_P3AC4R_BGRX(
 
  518    const INT16* WINPR_RESTRICT pSrc[3], 
 
  520    BYTE* WINPR_RESTRICT pDst,           
 
  522    UINT32 DstFormat, 
const prim_size_t* WINPR_RESTRICT roi) 
 
  524  const INT16* r = pSrc[0];
 
  525  const INT16* g = pSrc[1];
 
  526  const INT16* b = pSrc[2];
 
  527  const DWORD srcAdd = srcStep / 
sizeof(INT16);
 
  528  const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
 
  530  for (UINT32 y = 0; y < roi->height; ++y)
 
  532    writeScanlineBGRX(pDst, formatSize, DstFormat, r, g, b, roi->width);
 
  539  return PRIMITIVES_SUCCESS;
 
  543general_RGBToRGB_16s8u_P3AC4R(
const INT16* WINPR_RESTRICT pSrc[3], 
 
  545                              BYTE* WINPR_RESTRICT pDst, 
 
  552    case PIXEL_FORMAT_BGRA32:
 
  553    case PIXEL_FORMAT_BGRX32:
 
  554      return general_RGBToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
 
  557      return general_RGBToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
 
  562void primitives_init_colors(
primitives_t* WINPR_RESTRICT prims)
 
  564  prims->yCbCrToRGB_16s8u_P3AC4R = general_yCbCrToRGB_16s8u_P3AC4R;
 
  565  prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
 
  566  prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
 
  567  prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;
 
  571void primitives_init_colors_opt(
primitives_t* WINPR_RESTRICT prims)
 
  573  primitives_init_colors(prims);
 
  574  primitives_init_colors_sse2(prims);
 
  575  primitives_init_colors_neon(prims);