123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- /*
- * upscale.h image upscaling
- *
- * This file contains upscalers for picodrive.
- *
- * scaler types:
- * nn: nearest neighbour
- * snn: "smoothed" nearest neighbour (see below)
- * bln: n-level-bilinear with n quantized weights
- * quantization: 0: a<1/(2*n), 1/n: 1/(2*n)<=a<3/(2*n), etc
- * currently n=2, n=4 are implemented (there's n=8 mixing, but no filters)
- * [NB this has been brought to my attn, which is probably the same as bl2:
- * https://www.drdobbs.com/image-scaling-with-bresenham/184405045?pgno=1]
- *
- * "smoothed" nearest neighbour: uses the average of the source pixels if no
- * source pixel covers more than 65% of the result pixel. It definitely
- * looks better than nearest neighbour and is still quite fast. It creates
- * a sharper look than a bilinear filter, at the price of some visible jags
- * on diagonal edges.
- *
- * example scaling modes:
- * 256x_Y_ -> 320x_Y_, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (NTSC 7% aspect err)
- * 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (PAL 7% aspect err)
- * 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (PAL 7% etc etc...)
- * 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3
- *
- *
- * (C) 2021 kub <derkub@gmail.com>
- *
- * This work is licensed under the terms of any of these licenses
- * (at your option):
- * - GNU GPL, version 2 or later.
- * - MAME license.
- * See COPYING file in the top-level directory.
- */
- #include <pico/pico_types.h>
- /* LSB of all colors in 1 or 2 pixels */
- #if defined(USE_BGR555)
- #define PXLSB 0x04210421
- #else
- #define PXLSB 0x08210821
- #endif
- /* RGB565 pixel mixing, see https://www.compuphase.com/graphic/scale3.htm and
- http://blargg.8bitalley.com/info/rgb_mixing.html */
- /* 2-level mixing. NB blargg version isn't 2-pixel-at-once safe for RGB565 */
- //#define p_05(d,p1,p2) d=(((p1)+(p2) + ( ((p1)^(p2))&PXLSB))>>1) // round up
- //#define p_05(d,p1,p2) d=(((p1)+(p2) - ( ((p1)^(p2))&PXLSB))>>1) // round down
- #define p_05(d,p1,p2) d=(((p1)&(p2)) + ((((p1)^(p2))&~PXLSB)>>1))
- /* 4-level mixing, 2 times slower */
- // 1/4*p1 + 3/4*p2 = 1/2*(1/2*(p1+p2) + p2)
- #define p_025(d,p1,p2) p_05(t, p1, p2); p_05( d, t, p2)
- #define p_075(d,p1,p2) p_025(d,p2,p1)
- /* 8-level mixing, 3 times slower */
- // 1/8*p1 + 7/8*p2 = 1/2*(1/2*(1/2*(p1+p2) + p2) + p2)
- #define p_0125(d,p1,p2) p_05(t, p1, p2); p_05( u, t, p2); p_05( d, u, p2)
- // 3/8*p1 + 5/8*p2 = 1/2*(1/2*(1/2*(p1+p2) + p2) + 1/2*(p1+p2))
- #define p_0375(d,p1,p2) p_05(t, p1, p2); p_05( u, t, p2); p_05( d, u, t)
- #define p_0625(d,p1,p2) p_0375(d,p2,p1)
- #define p_0875(d,p1,p2) p_0125(d,p2,p1)
- /* pixel transforms */
- #define f_pal(v) pal[v] // convert CLUT index -> RGB565
- #define f_nop(v) (v) // source already in dest format (CLUT/RGB)
- #define f_or(v) (v|pal) // CLUT, add palette selection
- /*
- scalers h:
- 256->320: - (4:5) (256x224/240 -> 320x224/240)
- 256->299: - (6:7) (256x224 -> 299x224, alt?)
- 160->320: - (1:2) 2x (160x144 -> 320x240, GG)
- 160->288: - (5:9) (160x144 -> 288x216, GG alt?)
- */
- /* scale 4:5 */
- #define h_upscale_nn_4_5(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- di[0] = f(si[0]); \
- di[1] = f(si[1]); \
- di[2] = f(si[1]); \
- di[3] = f(si[2]); \
- di[4] = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- // reverse version for overlapping buffers
- #define rh_upscale_nn_4_5(di,ds,si,ss,w,f) do { \
- int i; \
- di += w/4*5; \
- si += w; \
- for (i = w/4; i > 0; i--, si -= 4, di -= 5) { \
- di[-1] = f(si[-1]); \
- di[-2] = f(si[-2]); \
- di[-3] = f(si[-3]); \
- di[-4] = f(si[-3]); \
- di[-5] = f(si[-4]); \
- } \
- di += ds; \
- si += ss; \
- } while (0)
- #define h_upscale_snn_4_5(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- di[0] = f(si[0]); \
- di[1] = f(si[1]); \
- p_05(di[2], f(si[1]),f(si[2])); \
- di[3] = f(si[2]); \
- di[4] = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bln_4_5(di,ds,si,ss,w,f) do { \
- int i; u16 t; \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- di[0] = f(si[0]); \
- p_025(di[1], f(si[0]),f(si[1])); \
- p_05 (di[2], f(si[1]),f(si[2])); \
- p_075(di[3], f(si[2]),f(si[3])); \
- di[4] = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl2_4_5(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- di[0] = f(si[0]); \
- p_05(di[1], f(si[0]),f(si[1])); \
- p_05(di[2], f(si[1]),f(si[2])); \
- di[3] = f(si[2]); \
- di[4] = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl4_4_5(di,ds,si,ss,w,f) do { \
- int i; u16 t, p = f(si[0]); \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- p_025(di[0], p, f(si[0])); \
- p_05 (di[1], f(si[0]),f(si[1])); \
- p_05 (di[2], f(si[1]),f(si[2])); \
- p_075(di[3], f(si[2]),f(si[3])); \
- di[4] = p = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl8_4_5(di,ds,si,ss,w,f) do { \
- int i; u16 t, u, p = f(si[0]); \
- for (i = w/4; i > 0; i--, si += 4, di += 5) { \
- p_025 (di[0], p, f(si[0])); \
- p_0375(di[1], f(si[0]),f(si[1])); \
- p_0625(di[2], f(si[1]),f(si[2])); \
- p_075 (di[3], f(si[2]),f(si[3])); \
- di[4] = p = f(si[3]); \
- } \
- di += ds - w/4*5; \
- si += ss - w; \
- } while (0)
- /* scale 6:7 */
- #define h_upscale_nn_6_7(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/6; i > 0; i--, si += 6, di += 7) { \
- di[0] = f(si[0]); \
- di[1] = f(si[1]); \
- di[2] = f(si[2]); \
- di[3] = f(si[2]); \
- di[4] = f(si[3]); \
- di[5] = f(si[4]); \
- di[6] = f(si[5]); \
- } \
- di += ds - w/6*7; \
- si += ss - w; \
- } while (0)
- // reverse version for overlapping buffers
- #define rh_upscale_nn_6_7(di,ds,si,ss,w,f) do { \
- int i; \
- di += w/6*7; \
- si += w; \
- for (i = w/6; i > 0; i--, si -= 6, di -= 7) { \
- di[-1] = f(si[-1]); \
- di[-2] = f(si[-2]); \
- di[-3] = f(si[-3]); \
- di[-4] = f(si[-4]); \
- di[-5] = f(si[-4]); \
- di[-6] = f(si[-5]); \
- di[-7] = f(si[-6]); \
- } \
- di += ds; \
- si += ss; \
- } while (0)
- #define h_upscale_snn_6_7(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/6; i > 0; i--, si += 6, di += 7) { \
- di[0] = f(si[0]); \
- di[1] = f(si[1]); \
- di[2] = f(si[2]); \
- p_05(di[3], f(si[2]),f(si[3])); \
- di[4] = f(si[3]); \
- di[5] = f(si[4]); \
- di[6] = f(si[5]); \
- } \
- di += ds - w/6*7; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl2_6_7(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/6; i > 0; i--, si += 6, di += 7) { \
- di[0] = f(si[0]); \
- p_05(di[1], f(si[0]),f(si[1])); \
- p_05(di[2], f(si[1]),f(si[2])); \
- p_05(di[3], f(si[2]),f(si[3])); \
- p_05(di[4], f(si[3]),f(si[4])); \
- di[5] = f(si[4]); \
- di[6] = f(si[5]); \
- } \
- di += ds - w/6*7; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl4_6_7(di,ds,si,ss,w,f) do { \
- int i; u16 t p = f(si[0]); \
- for (i = w/6; i > 0; i--, si += 6, di += 7) { \
- p_025(di[0], p, f(si[0])); \
- p_025(di[1], f(si[0]),f(si[1])); \
- p_05 (di[2], f(si[1]),f(si[2])); \
- p_05 (di[3], f(si[2]),f(si[3])); \
- p_075(di[4], f(si[3]),f(si[4])); \
- p_075(di[5], f(si[4]),f(si[5])); \
- di[6] = p = f(si[5]); \
- } \
- di += ds - w/6*7; \
- si += ss - w; \
- } while (0)
- /* scale 5:9 */
- #define h_upscale_nn_5_9(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/5; i > 0; i--, si += 5, di += 9) { \
- di[0] = f(si[0]); \
- di[1] = f(si[0]); \
- di[2] = f(si[1]); \
- di[3] = f(si[1]); \
- di[4] = f(si[2]); \
- di[5] = f(si[3]); \
- di[6] = f(si[3]); \
- di[7] = f(si[4]); \
- di[8] = f(si[4]); \
- } \
- di += ds - w/5*9; \
- si += ss - w; \
- } while (0)
- #define h_upscale_snn_5_9(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/5; i > 0; i--, si += 5, di += 9) { \
- di[0] = f(si[0]); \
- di[1] = f(si[0]); \
- di[2] = f(si[1]); \
- p_05(di[3], f(si[1]),f(si[2])); \
- di[4] = f(si[2]); \
- p_05(di[5], f(si[2]),f(si[3])); \
- di[6] = f(si[3]); \
- di[7] = f(si[4]); \
- di[8] = f(si[4]); \
- } \
- di += ds - w/5*9; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl2_5_9(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/5; i > 0; i--, si += 5, di += 9) { \
- di[0] = f(si[0]); \
- p_05(di[1], f(si[0]),f(si[1])); \
- di[2] = f(si[1]); \
- p_05(di[3], f(si[1]),f(si[2])); \
- di[4] = f(si[2]); \
- p_05(di[5], f(si[2]),f(si[3])); \
- di[6] = f(si[3]); \
- p_05(di[7], f(si[3]),f(si[4])); \
- di[8] = f(si[4]); \
- } \
- di += ds - w/5*9; \
- si += ss - w; \
- } while (0)
- #define h_upscale_bl4_5_9(di,ds,si,ss,w,f) do { \
- int i; u16 t, p = f(si[0]); \
- for (i = w/5; i > 0; i--, si += 5, di += 9) { \
- p_05 (di[0], p, f(si[0])); \
- di[1] = f(si[0]); \
- p_025(di[2], f(si[0]),f(si[1])); \
- p_075(di[3], f(si[1]),f(si[2])); \
- p_025(di[4], f(si[1]),f(si[2])); \
- p_075(di[5], f(si[2]),f(si[3])); \
- di[6] = f(si[3]); \
- p_05 (di[7], f(si[3]),f(si[4])); \
- di[8] = p = f(si[4]); \
- } \
- di += ds - w/5*9; \
- si += ss - w; \
- } while (0)
- /* scale 1:2 integer scale */
- #define h_upscale_nn_1_2(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/2; i > 0; i--, si += 2, di += 4) { \
- di[0] = f(si[0]); \
- di[1] = f(si[0]); \
- di[2] = f(si[1]); \
- di[3] = f(si[1]); \
- } \
- di += ds - w*2; \
- si += ss - w; \
- } while (0)
- // reverse version for overlapping buffers
- #define rh_upscale_nn_1_2(di,ds,si,ss,w,f) do { \
- int i; \
- di += w*2; \
- si += w; \
- for (i = w/2; i > 0; i--, si -= 2, di -= 4) { \
- di[-1] = f(si[-1]); \
- di[-2] = f(si[-1]); \
- di[-3] = f(si[-2]); \
- di[-4] = f(si[-2]); \
- } \
- di += ds; \
- si += ss; \
- } while (0)
- #define h_upscale_bl2_1_2(di,ds,si,ss,w,f) do { \
- int i; uint p = f(si[0]); \
- for (i = w/2; i > 0; i--, si += 2, di += 4) { \
- p_05 (di[0], p, f(si[0])); \
- di[1] = f(si[0]); \
- p_05 (di[2], f(si[0]),f(si[1])); \
- di[3] = p = f(si[1]); \
- } \
- di += ds - w*2; \
- si += ss - w; \
- } while (0)
- /* scale 1:1, copy */
- #define h_copy(di,ds,si,ss,w,f) do { \
- int i; \
- for (i = w/4; i > 0; i--, si += 4, di += 4) { \
- di[0] = f(si[0]); \
- di[1] = f(si[1]); \
- di[2] = f(si[2]); \
- di[3] = f(si[3]); \
- } \
- di += ds - w; \
- si += ss - w; \
- } while (0)
- /*
- scalers v:
- 224->240: - (14:15) (256/320x224 -> 320x240)
- 224->238: - (16:17) (256/320x224 -> 320x238 alt?)
- 144->240: - (3:5) (160x144 -> 320x240, GG)
- 144->216: - (2:3) (160x144 -> 288x216, GG alt?)
- */
- #define v_mix(di,li,ri,w,p_mix,f) do { \
- int i; u32 t, u; (void)t, (void)u; \
- for (i = 0; i < w; i += 4) { \
- p_mix((di)[i ], f((li)[i ]),f((ri)[i ])); \
- p_mix((di)[i+1], f((li)[i+1]),f((ri)[i+1])); \
- p_mix((di)[i+2], f((li)[i+2]),f((ri)[i+2])); \
- p_mix((di)[i+3], f((li)[i+3]),f((ri)[i+3])); \
- } \
- } while (0)
- #define v_copy(di,ri,w,f) do { \
- int i; \
- for (i = 0; i < w; i += 4) { \
- (di)[i ] = f((ri)[i ]); \
- (di)[i+1] = f((ri)[i+1]); \
- (di)[i+2] = f((ri)[i+2]); \
- (di)[i+3] = f((ri)[i+3]); \
- } \
- } while (0)
- /* scale 14:15 */
- #define v_upscale_nn_14_15(di,ds,w,l) do { \
- if (++l == 7) { \
- di += ds; \
- } else if (l >= 14) { \
- l = 0; \
- di -= 7*ds; \
- v_copy(&di[0], &di[-ds], w, f_nop); \
- di += 7*ds; \
- } \
- } while (0)
- #define v_upscale_snn_14_15(di,ds,w,l) do { \
- if (++l == 7) { \
- di += ds; \
- } else if (l >= 14) { \
- l = 0; \
- di -= 7*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- v_mix(&di[-ds], &di[-2*ds], &di[-ds], w, p_05, f_nop); \
- v_mix(&di[ ds], &di[ ds], &di[ 2*ds], w, p_05, f_nop); \
- di += 7*ds; \
- } \
- } while (0)
- #define v_upscale_bl2_14_15(di,ds,w,l) do { \
- if (++l == 3) { \
- di += ds; \
- } else if (l >= 14) { \
- int j; \
- l = 0; \
- di -= 11*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- for (j = 0; j < 7; j++) { \
- di += ds; \
- v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
- } \
- di += 4*ds; \
- } \
- } while (0)
- #define v_upscale_bl4_14_15(di,ds,w,l) do { \
- if (++l == 1) { \
- di += ds; \
- } else if (l >= 14) { \
- int j; \
- l = 0; \
- di -= 13*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_025, f_nop); \
- di += ds; \
- for (j = 0; j < 3; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_025, f_nop); \
- di += ds; \
- } \
- for (j = 0; j < 4; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
- di += ds; \
- } \
- for (j = 0; j < 4; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_075, f_nop); \
- di += ds; \
- } \
- di += 1*ds; \
- } \
- } while (0)
- /* scale 16:17 */
- #define v_upscale_nn_16_17(di,ds,w,l) do { \
- if (++l == 8) { \
- di += ds; \
- } else if (l >= 16) { \
- l = 0; \
- di -= 8*ds; \
- v_copy(&di[0], &di[-ds], w, f_nop); \
- di += 8*ds; \
- } \
- } while (0)
- #define v_upscale_snn_16_17(di,ds,w,l) do { \
- if (++l == 8) { \
- di += ds; \
- } else if (l >= 16) { \
- l = 0; \
- di -= 8*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- v_mix(&di[-ds], &di[-2*ds], &di[-ds], w, p_05, f_nop); \
- v_mix(&di[ ds], &di[ ds], &di[ 2*ds], w, p_05, f_nop); \
- di += 8*ds; \
- } \
- } while (0)
- #define v_upscale_bl2_16_17(di,ds,w,l) do { \
- if (++l == 4) { \
- di += ds; \
- } else if (l >= 16) { \
- int j; \
- l = 0; \
- di -= 12*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- for (j = 0; j < 7; j++) { \
- di += ds; \
- v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
- } \
- di += 5*ds; \
- } \
- } while (0)
- #define v_upscale_bl4_16_17(di,ds,w,l) do { \
- if (++l == 2) { \
- di += ds; \
- } else if (l >= 16) { \
- int j; \
- l = 0; \
- di -= 14*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_025, f_nop); \
- di += ds; \
- for (j = 0; j < 3; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_025, f_nop); \
- di += ds; \
- } \
- for (j = 0; j < 4; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_05, f_nop); \
- di += ds; \
- } \
- for (j = 0; j < 4; j++) { \
- v_mix(&di[0], &di[0], &di[ds], w, p_075, f_nop); \
- di += ds; \
- } \
- di += 2*ds; \
- } \
- } while (0)
- /* scale 3:5 */
- #define v_upscale_nn_3_5(di,ds,w,l) do { \
- if (++l < 3) { \
- di += ds; \
- } else { \
- int j; \
- l = 0; \
- di -= 3*ds; \
- for (j = 0; j < 2; j++) { \
- v_copy(&di[0], &di[-ds], w, f_nop); \
- di += 2*ds; \
- } \
- di -= ds; \
- } \
- } while (0)
- #define v_upscale_snn_3_5(di,ds,w,l) do { \
- if (++l < 3) { \
- di += ds; \
- } else { \
- int j; \
- l = 0; \
- di -= 3*ds; \
- for (j = 0; j < 2; j++) { \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- di += 2*ds; \
- } \
- di -= ds; \
- } \
- } while (0)
- /* scale 2:3 */
- #define v_upscale_nn_2_3(di,ds,w,l) do { \
- if (++l < 2) { \
- di += ds; \
- } else { \
- int j; \
- l = 0; \
- di -= 2*ds; \
- v_copy(&di[0], &di[-ds], w, f_nop); \
- di += 2*ds; \
- } \
- } while (0)
- #define v_upscale_snn_2_3(di,ds,w,l) do { \
- if (++l < 2) { \
- di += ds; \
- } else { \
- int j; \
- l = 0; \
- di -= 2*ds; \
- v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
- di += 2*ds; \
- } \
- } while (0)
- /* exponentially smoothing (for LCD ghosting): y[n] = x[n]*a + y[n-1]*(1-a) */
- #define PXLSBn (PXLSB*15) // using 4 LSBs of each subpixel for subtracting
- // NB implement rounding to x[n] by adding 1 to counter round down if y[n] is
- // smaller than x[n]: use some of the lower bits to implement subtraction on
- // subpixels, with an additional bit to detect borrow, then add the borrow.
- // It's doing the increment wrongly in a lot of cases, which doesn't matter
- // much since it will converge to x[n] in a few frames anyway if x[n] is static
- #define p_05_round(d,p1,p2) \
- p_05(u, p1, p2); \
- t=(u|~PXLSBn)-(p1&PXLSBn); d = u+(~(t>>4)&PXLSB)
- // Unfortunately this won't work for p_025, where adding 1 isn't enough and
- // adding 2 would be too much, so offer only p_075 here
- #define p_075_round(d,p1,p2) \
- p_075(u, p1, p2); \
- t=(u|~PXLSBn)-(p1&PXLSBn); d = u+(~(t>>4)&PXLSB)
- // this is essentially v_mix and v_copy combined
- #define v_blend(di,ri,w,p_mix) do { \
- int i; u32 t, u; (void)t, (void)u; \
- for (i = 0; i < w; i += 4) { \
- p_mix((ri)[i ], (di)[i ],(ri)[i ]); (di)[i ] = (ri)[i ]; \
- p_mix((ri)[i+1], (di)[i+1],(ri)[i+1]); (di)[i+1] = (ri)[i+1]; \
- p_mix((ri)[i+2], (di)[i+2],(ri)[i+2]); (di)[i+2] = (ri)[i+2]; \
- p_mix((ri)[i+3], (di)[i+3],(ri)[i+3]); (di)[i+3] = (ri)[i+3]; \
- } \
- } while (0)
- /* X x Y -> X*5/4 x Y, for X 256->320 */
- void upscale_rgb_nn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_snn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl4_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- /* X x Y -> X x Y*17/16, for Y 224->238 or 192->204 (SMS) */
- void upscale_rgb_nn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_snn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl4_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- /* X x Y -> X*5/4 x Y*17/16 */
- void upscale_rgb_nn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_snn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl4_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- /* X x Y -> X*2/1 x Y, e.g. for X 160->320 (GG) */
- void upscale_rgb_nn_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- /* X x Y -> X x Y*5/3, e.g. for Y 144->240 (GG) */
- void upscale_rgb_nn_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl4_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- /* X x Y -> X*2/1 x Y*5/3 (GG) */
- void upscale_rgb_nn_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl2_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
- void upscale_rgb_bl4_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal);
|