efl
618 строк · 17.7 Кб
1#include "draw.h"2#include "draw_private.h"3#include "../rg_etc/rg_etc1.h"4
5#ifdef BUILD_NEON6#include <arm_neon.h>7#endif8
9#if DIV_USING_BITSHIFT10# define DEFINE_DIVIDER(div) const int pow2 = _pow2_geq((div) << 10); const int numerator = (1 << pow2) / (div);11# define DIVIDE(val) (((val) * numerator) >> pow2)12#else13# define DEFINE_DIVIDER(div) const int divider = (div);14# define DIVIDE(val) ((val) / divider)15#endif16
17#define CONVERT_RGB_565_TO_RGB_888(s) \18(((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \19((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \20((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))21
22#define CONVERT_A5P_TO_A8(s) \23((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7))24
25#define CONVERT_ARGB_8888_TO_A_8(s) ((s) >> 24)26
27// finds smallest power of 2 above val
28static int29_pow2_geq(int val)30{
31for (int n = 0; n < 32; n++)32if (val <= (1 << n))33return n;34
35return 32; // impossible36}
37
38static Eina_Bool39_convert_gry8_to_argb8888(void *dst, const void *src, int w, int h,40int src_stride, int dst_stride, Eina_Bool has_alpha,41Efl_Gfx_Colorspace srccs EINA_UNUSED,42Efl_Gfx_Colorspace dstcs EINA_UNUSED)43{
44const uint8_t *in = src;45uint32_t *out = dst;46int in_step, out_step, x, y;47
48if (!src_stride) src_stride = w;49if (!dst_stride) dst_stride = w * 4;50in_step = src_stride;51out_step = dst_stride / 4;52
53if (has_alpha)54{55// transparent white56for (y = 0; y < h; y++)57{58for (x = 0; x < w; x++)59{60int c = in[x];61out[x] = DRAW_ARGB_JOIN(c, c, c, c);62}63in += in_step;64out += out_step;65}66}67else68{69// opaque grayscale70for (y = 0; y < h; y++)71{72for (x = 0; x < w; x++)73{74int c = in[x];75out[x] = DRAW_ARGB_JOIN(0xFF, c, c, c);76}77in += in_step;78out += out_step;79}80}81
82return EINA_TRUE;83}
84
85static Eina_Bool86_convert_agry88_to_argb8888(void *dst, const void *src, int w, int h,87int src_stride, int dst_stride, Eina_Bool has_alpha,88Efl_Gfx_Colorspace srccs EINA_UNUSED,89Efl_Gfx_Colorspace dstcs EINA_UNUSED)90{
91const uint16_t *in = src;92uint32_t *out = dst;93int in_step, out_step, x, y;94
95if (!src_stride) src_stride = w * 2;96if (!dst_stride) dst_stride = w * 4;97in_step = src_stride / 2;98out_step = dst_stride / 4;99
100if (has_alpha)101{102for (y = 0; y < h; y++)103{104for (x = 0; x < w; x++)105{106int c = in[x] & 0xFF;107int a = in[x] >> 8;108out[x] = DRAW_ARGB_JOIN(a, c, c, c);109}110in += in_step;111out += out_step;112}113}114else115{116for (y = 0; y < h; y++)117{118for (x = 0; x < w; x++)119{120int c = in[x] & 0xFF;121out[x] = DRAW_ARGB_JOIN(0xFF, c, c, c);122}123in += in_step;124out += out_step;125}126}127
128return EINA_TRUE;129}
130
131static Eina_Bool132_convert_argb8888_to_gry8(void *dst, const void *src, int w, int h,133int src_stride, int dst_stride, Eina_Bool has_alpha,134Efl_Gfx_Colorspace srccs EINA_UNUSED,135Efl_Gfx_Colorspace dstcs EINA_UNUSED)136{
137const uint32_t *in = src;138uint8_t *out = dst;139int in_step, out_step, x, y;140#if RGBA2LUM_WEIGHTED141const int WR = 299;142const int WG = 587;143const int WB = 114;144#else145const int WR = 1;146const int WG = 1;147const int WB = 1;148#endif149DEFINE_DIVIDER(WR + WG + WB);150
151if (!src_stride) src_stride = w * 4;152if (!dst_stride) dst_stride = w;153in_step = src_stride / 4;154out_step = dst_stride;155
156if (has_alpha)157{158// copy only alpha159for (y = 0; y < h; y++)160{161for (x = 0; x < w; x++)162out[x] = A_VAL(in + x);163in += in_step;164out += out_step;165}166}167else168{169// copy only color to grayscale170for (y = 0; y < h; y++)171{172for (x = 0; x < w; x++)173out[x] = DIVIDE((R_VAL(in + x) * WR) + (G_VAL(in + x) * WG) + (B_VAL(in + x) * WB));174in += in_step;175out += out_step;176}177}178
179return EINA_TRUE;180}
181
182static Eina_Bool183_convert_argb8888_to_agry88(void *dst, const void *src, int w, int h,184int src_stride, int dst_stride, Eina_Bool has_alpha,185Efl_Gfx_Colorspace srccs EINA_UNUSED,186Efl_Gfx_Colorspace dstcs EINA_UNUSED)187{
188const uint32_t *in = src;189uint16_t *out = dst;190int in_step, out_step, x, y;191#if RGBA2LUM_WEIGHTED192const int WR = 299;193const int WG = 587;194const int WB = 114;195#else196const int WR = 1;197const int WG = 1;198const int WB = 1;199#endif200DEFINE_DIVIDER(WR + WG + WB);201
202if (!src_stride) src_stride = w * 4;203if (!dst_stride) dst_stride = w * 2;204in_step = src_stride / 4;205out_step = dst_stride / 2;206
207if (has_alpha)208{209// copy only alpha210for (y = 0; y < h; y++)211{212for (x = 0; x < w; x++)213{214int a = A_VAL(in + x);215int c = DIVIDE((R_VAL(in + x) * WR) + (G_VAL(in + x) * WG) + (B_VAL(in + x) * WB));216out[x] = (a << 8) | c;217}218in += in_step;219out += out_step;220}221}222else223{224// copy only color to grayscale225for (y = 0; y < h; y++)226{227for (x = 0; x < w; x++)228{229int c = DIVIDE((R_VAL(in + x) * WR) + (G_VAL(in + x) * WG) + (B_VAL(in + x) * WB));230out[x] = 0xFF00 | c;231}232in += in_step;233out += out_step;234}235}236
237return EINA_TRUE;238}
239
240static Eina_Bool241_convert_rgb565_a5p_to_argb8888(void *dst, const void *src, int w, int h,242int src_stride, int dst_stride, Eina_Bool has_alpha,243Efl_Gfx_Colorspace srccs EINA_UNUSED,244Efl_Gfx_Colorspace dstcs EINA_UNUSED)245{
246const uint16_t *in = src;247const uint8_t *in_alpha;248uint32_t *out = dst;249int in_step, out_step, a_step, x, y;250
251if (!src_stride) src_stride = w * 2;252if (!dst_stride) dst_stride = w * 4;253in_step = src_stride / 2;254a_step = src_stride;255out_step = dst_stride / 4;256
257// no region support (2 planes): basic safety check (can't verify h)258EINA_SAFETY_ON_FALSE_RETURN_VAL((src_stride == (w * 2)) && (dst_stride == (w * 4)), EINA_FALSE);259
260if (has_alpha)261{262in_alpha = ((uint8_t *) in) + (src_stride * h);263for (y = 0; y < h; y++)264{265for (x = 0; x < w; x++)266{267int a = CONVERT_A5P_TO_A8(in_alpha[x]);268int c = CONVERT_RGB_565_TO_RGB_888(in[x]);269out[x] = (a << 24) | c;270}271in_alpha += a_step;272in += in_step;273out += out_step;274}275}276else277{278for (y = 0; y < h; y++)279{280for (x = 0; x < w; x++)281{282int c = CONVERT_RGB_565_TO_RGB_888(in[x]);283out[x] = 0xFF000000 | c;284}285in += in_step;286out += out_step;287}288}289
290return EINA_TRUE;291}
292
293static Eina_Bool294_convert_etc2_rgb8_to_argb8888(void *dst, const void *src, int w, int h,295int src_stride, int dst_stride, Eina_Bool has_alpha,296Efl_Gfx_Colorspace srccs EINA_UNUSED,297Efl_Gfx_Colorspace dstcs EINA_UNUSED)298{
299const uint8_t *in = src;300uint32_t *out = dst;301int out_step, x, y, k;302unsigned int bgra[16];303
304EINA_SAFETY_ON_FALSE_RETURN_VAL(!(w & 3) && !(h & 3), EINA_FALSE);305EINA_SAFETY_ON_FALSE_RETURN_VAL(!has_alpha, EINA_FALSE);306
307// jumps lines 4 by 4308if (!src_stride) src_stride = w * 8 / 4;309if (!dst_stride) dst_stride = w * 4;310out_step = dst_stride / 4;311
312for (y = 0; y < h; y += 4)313{314for (x = 0; x < w; x += 4, in += 8)315{316rg_etc2_rgb8_decode_block(in, bgra);317for (k = 0; k < 4; k++)318memcpy(out + x + k * out_step, bgra + (k * 4), 16);319}320}321
322return EINA_TRUE;323}
324
325static Eina_Bool326_convert_etc2_rgba8_to_argb8888(void *dst, const void *src, int w, int h,327int src_stride, int dst_stride, Eina_Bool has_alpha,328Efl_Gfx_Colorspace srccs EINA_UNUSED,329Efl_Gfx_Colorspace dstcs EINA_UNUSED)330{
331const uint8_t *in = src;332uint32_t *out = dst;333int out_step, x, y, k;334unsigned int bgra[16];335
336EINA_SAFETY_ON_FALSE_RETURN_VAL(!(w & 3) && !(h & 3), EINA_FALSE);337EINA_SAFETY_ON_FALSE_RETURN_VAL(!has_alpha, EINA_FALSE);338
339// jumps lines 4 by 4340if (!src_stride) src_stride = w * 16 / 4;341if (!dst_stride) dst_stride = w * 4;342out_step = dst_stride / 4;343
344for (y = 0; y < h; y += 4)345{346for (x = 0; x < w; x += 4, in += 16)347{348rg_etc2_rgba8_decode_block(in, bgra);349for (k = 0; k < 4; k++)350memcpy(out + x + k * out_step, bgra + (k * 4), 16);351}352out += out_step * 4;353}354
355return EINA_TRUE;356}
357
358static Eina_Bool359_convert_etc1_alpha_to_argb8888(void *dst, const void *src, int w, int h,360int src_stride, int dst_stride, Eina_Bool has_alpha,361Efl_Gfx_Colorspace srccs EINA_UNUSED,362Efl_Gfx_Colorspace dstcs EINA_UNUSED)363{
364const uint8_t *in = src, *in_alpha;365uint32_t *out = dst;366int out_step, x, y, j, k;367unsigned int bgra[16], alpha[16];368
369EINA_SAFETY_ON_FALSE_RETURN_VAL(!(w & 3) && !(h & 3), EINA_FALSE);370EINA_SAFETY_ON_FALSE_RETURN_VAL(!has_alpha, EINA_FALSE);371
372// jumps lines 4 by 4373if (!src_stride) src_stride = w * 8 / 4;374if (!dst_stride) dst_stride = w * 4;375out_step = dst_stride / 4;376
377in_alpha = in + src_stride * h;378
379for (y = 0; y < h; y += 4)380{381for (x = 0; x < w; x += 4, in += 8, in_alpha += 8)382{383rg_etc2_rgba8_decode_block(in, bgra);384rg_etc2_rgba8_decode_block(in_alpha, alpha);385for (k = 0; k < 4; k++)386for (j = 0; j < 4; j++)387{388int a = (alpha[(k * 4) + j] & 0x00FF00) >> 8;389int c = (bgra[(k * 4) + j] & 0x00FFFFFF);390out[(k * out_step) + j] = (a << 24) | c;391}392}393out += out_step;394}395
396return EINA_TRUE;397}
398
399static Eina_Bool400_convert_generic_two_pass(void *dst, const void *src, int w, int h,401int src_stride, int dst_stride, Eina_Bool has_alpha,402Efl_Gfx_Colorspace srccs, Efl_Gfx_Colorspace dstcs)403{
404Cspace_Convert_Func to_argb = efl_draw_convert_func_get(srccs, EFL_GFX_COLORSPACE_ARGB8888, NULL);405Cspace_Convert_Func from_argb = efl_draw_convert_func_get(EFL_GFX_COLORSPACE_ARGB8888, dstcs, NULL);406uint32_t *argb;407
408EINA_SAFETY_ON_NULL_RETURN_VAL(to_argb, EINA_FALSE);409EINA_SAFETY_ON_NULL_RETURN_VAL(from_argb, EINA_FALSE);410
411argb = malloc(w * h * sizeof(uint32_t));412if (!argb) return EINA_FALSE;413
414if (!to_argb(argb, src, w, h, src_stride, 0, has_alpha, srccs, EFL_GFX_COLORSPACE_ARGB8888))415goto fail;416
417if (!from_argb(dst, argb, w, h, 0, dst_stride, has_alpha, EFL_GFX_COLORSPACE_ARGB8888, dstcs))418goto fail;419
420free(argb);421return EINA_TRUE;422
423fail:424free(argb);425return EINA_FALSE;426}
427
428Cspace_Convert_Func
429efl_draw_convert_func_get(Efl_Gfx_Colorspace srccs, Efl_Gfx_Colorspace dstcs,430Eina_Bool *region_can)431{
432Eina_Bool reg1 = EINA_FALSE, reg2 = EINA_FALSE;433Cspace_Convert_Func to_argb = NULL;434Cspace_Convert_Func from_argb = NULL;435
436EINA_SAFETY_ON_FALSE_RETURN_VAL(srccs != dstcs, NULL);437
438if ((dstcs != EFL_GFX_COLORSPACE_ARGB8888) && (srccs != EFL_GFX_COLORSPACE_ARGB8888))439{440to_argb = efl_draw_convert_func_get(srccs, EFL_GFX_COLORSPACE_ARGB8888, ®1);441from_argb = efl_draw_convert_func_get(EFL_GFX_COLORSPACE_ARGB8888, dstcs, ®2);442}443
444if (region_can) *region_can = EINA_TRUE;445
446switch (srccs)447{448case EFL_GFX_COLORSPACE_ARGB8888:449if (dstcs == EFL_GFX_COLORSPACE_GRY8)450return _convert_argb8888_to_gry8;451if (dstcs == EFL_GFX_COLORSPACE_AGRY88)452return _convert_argb8888_to_agry88;453break;454
455case EFL_GFX_COLORSPACE_GRY8:456if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)457return _convert_gry8_to_argb8888;458break;459
460case EFL_GFX_COLORSPACE_AGRY88:461if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)462return _convert_agry88_to_argb8888;463break;464
465case EFL_GFX_COLORSPACE_RGB565_A5P:466if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)467{468// we could do regions, but we would need a pointer to the alpha plane.469if (region_can) *region_can = EINA_FALSE;470return _convert_rgb565_a5p_to_argb8888;471}472break;473
474case EFL_GFX_COLORSPACE_YCBCR422P601_PL:475case EFL_GFX_COLORSPACE_YCBCR422601_PL:476case EFL_GFX_COLORSPACE_YCBCR420NV12601_PL:477case EFL_GFX_COLORSPACE_YCBCR420TM12601_PL:478case EFL_GFX_COLORSPACE_YCBCR422P709_PL:479/* FIXME */480
481case EFL_GFX_COLORSPACE_ETC1:482case EFL_GFX_COLORSPACE_RGB8_ETC2:483if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)484{485// we could do regions, but only if they are 4x4 aligned.486if (region_can) *region_can = EINA_FALSE;487return _convert_etc2_rgb8_to_argb8888;488}489break;490
491case EFL_GFX_COLORSPACE_RGBA8_ETC2_EAC:492if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)493{494// we could do regions, but only if they are 4x4 aligned.495if (region_can) *region_can = EINA_FALSE;496return _convert_etc2_rgba8_to_argb8888;497}498break;499
500case EFL_GFX_COLORSPACE_ETC1_ALPHA:501if (dstcs == EFL_GFX_COLORSPACE_ARGB8888)502{503// we could do regions, but only if they are 4x4 aligned.504if (region_can) *region_can = EINA_FALSE;505return _convert_etc1_alpha_to_argb8888;506}507break;508
509case EFL_GFX_COLORSPACE_RGB_S3TC_DXT1:510case EFL_GFX_COLORSPACE_RGBA_S3TC_DXT1:511case EFL_GFX_COLORSPACE_RGBA_S3TC_DXT2:512case EFL_GFX_COLORSPACE_RGBA_S3TC_DXT3:513case EFL_GFX_COLORSPACE_RGBA_S3TC_DXT4:514case EFL_GFX_COLORSPACE_RGBA_S3TC_DXT5:515/* FIXME: can convert to ARGB */516
517default:518break;519}520
521
522// fallback to two-pass523if (to_argb && from_argb)524{525if (region_can) *region_can = (reg1 && reg2);526return _convert_generic_two_pass;527}528
529ERR("unsupported colorspace conversion from %d to %d", srccs, dstcs);530if (region_can) *region_can = EINA_FALSE;531return NULL;532}
533
534int
535efl_draw_argb_premul(uint32_t *data, unsigned int len)536{
537uint32_t *de = data + len;538int nas = 0;539
540#ifdef BUILD_NEON541if (eina_cpu_features_get() & EINA_CPU_NEON)542{543uint8x8_t mask_0x00 = vdup_n_u8(0);544uint8x8_t mask_0x01 = vdup_n_u8(1);545uint8x8_t mask_0xff = vdup_n_u8(255);546uint8x8_t cmp;547uint64x1_t tmp;548
549while (data <= de - 8)550{551uint8x8x4_t rgba = vld4_u8((uint8_t *) data);552
553cmp = vand_u8(vorr_u8(vceq_u8(rgba.val[3], mask_0xff),554vceq_u8(rgba.val[3], mask_0x00)),555mask_0x01);556tmp = vpaddl_u32(vpaddl_u16(vpaddl_u8(cmp)));557nas += vget_lane_u32(vreinterpret_u32_u64(tmp), 0);558
559uint16x8x4_t lrgba;560lrgba.val[0] = vmovl_u8(rgba.val[0]);561lrgba.val[1] = vmovl_u8(rgba.val[1]);562lrgba.val[2] = vmovl_u8(rgba.val[2]);563lrgba.val[3] = vaddl_u8(rgba.val[3], mask_0x01);564
565rgba.val[0] = vshrn_n_u16(vmlaq_u16(lrgba.val[0], lrgba.val[0],566lrgba.val[3]), 8);567rgba.val[1] = vshrn_n_u16(vmlaq_u16(lrgba.val[1], lrgba.val[1],568lrgba.val[3]), 8);569rgba.val[2] = vshrn_n_u16(vmlaq_u16(lrgba.val[2], lrgba.val[2],570lrgba.val[3]), 8);571vst4_u8((uint8_t *) data, rgba);572data += 8;573}574}575#endif576
577while (data < de)578{579uint32_t a = 1 + (*data >> 24);580
581*data = (*data & 0xff000000) +582(((((*data) >> 8) & 0xff) * a) & 0xff00) +583(((((*data) & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);584data++;585
586if ((a == 1) || (a == 256))587nas++;588}589
590return nas;591}
592
593void
594efl_draw_argb_unpremul(uint32_t *data, unsigned int len)595{
596uint32_t *de = data + len;597uint32_t p_val = 0x00000000, p_res = 0x00000000;598
599while (data < de)600{601uint32_t a = (*data >> 24);602
603if (p_val == *data) *data = p_res;604else605{606p_val = *data;607if ((a > 0) && (a < 255))608*data = DRAW_ARGB_JOIN(a,609(R_VAL(data) * 255) / a,610(G_VAL(data) * 255) / a,611(B_VAL(data) * 255) / a);612else if (a == 0)613*data = 0x00000000;614p_res = *data;615}616data++;617}618}
619