4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifndef OVERLAYFRAME_H
23 #define OVERLAYFRAME_H
25 #include "loadbalance.h"
26 #include "overlayframe.inc"
42 #define STD_ALPHA(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx)
43 #define STD_BLEND(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx)
49 // NORMAL [Sa + Da * (1 - Sa), Sc * Sa + Dc * (1 - Sa)])
50 #define ALPHA_NORMAL(mx, Sa, Da) (Sa + (Da * (mx - Sa)) / mx)
51 #define COLOR_NORMAL(mx, Sc, Sa, Dc, Da) ((Sc * Sa + Dc * (mx - Sa)) / mx)
52 #define CHROMA_NORMAL COLOR_NORMAL
54 // ADDITION [(Sa + Da), (Sc + Dc)]
55 #define ALPHA_ADDITION(mx, Sa, Da) (Sa + Da)
56 #define COLOR_ADDITION(mx, Sc, Sa, Dc, Da) (Sc + Dc)
57 #define CHROMA_ADDITION COLOR_ADDITION
59 // SUBTRACT [(Sa - Da), (Sc - Dc)]
60 #define ALPHA_SUBTRACT(mx, Sa, Da) (Sa - Da)
61 #define COLOR_SUBTRACT(mx, Sc, Sa, Dc, Da) (Sc - Dc)
62 #define CHROMA_SUBTRACT COLOR_SUBTRACT
64 // MULTIPLY [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + Sc * Dc]
65 #define ALPHA_MULTIPLY STD_ALPHA
66 #define COLOR_MULTIPLY(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
68 #define CHROMA_MULTIPLY COLOR_MULTIPLY
70 // DIVIDE [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + Sc / Dc]
71 #define ALPHA_DIVIDE STD_ALPHA
72 #define COLOR_DIVIDE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
73 (Dc > ZERO ? (Sc * mx) / Dc : ZERO))
74 #define CHROMA_DIVIDE COLOR_DIVIDE
76 // REPLACE [Sa, Sc] (fade = 1)
77 #define ALPHA_REPLACE(mx, Sa, Da) Sa
78 #define COLOR_REPLACE(mx, Sc, Sa, Dc, Da) Sc
79 #define CHROMA_REPLACE COLOR_REPLACE
81 // MAX [max(Sa, Da), MAX(Sc, Dc)]
82 #define ALPHA_MAX(mx, Sa, Da) (Sa > Da ? Sa : Da)
83 #define COLOR_MAX(mx, Sc, Sa, Dc, Da) (Sc > Dc ? Sc : Dc)
84 #define CHROMA_MAX(mx, Sc, Sa, Dc, Da) (mabs(Sc) > mabs(Dc) ? Sc : Dc)
86 // MIN [min(Sa, Da), MIN(Sc, Dc)]
87 #define ALPHA_MIN(mx, Sa, Da) (Sa < Da ? Sa : Da)
88 #define COLOR_MIN(mx, Sc, Sa, Dc, Da) (Sc < Dc ? Sc : Dc)
89 #define CHROMA_MIN(mx, Sc, Sa, Dc, Da) (mabs(Sc) < mabs(Dc) ? Sc : Dc)
91 // DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc*Da, Dc*Sa)]
92 #define ALPHA_DARKEN STD_ALPHA
93 #define COLOR_DARKEN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
94 mmin(Sc * Da, Dc * Sa) / mx)
95 #define CHROMA_DARKEN(mx, Sc, Sa, Dc, Da) (CHROMA_XOR(mx,Sc,Sa,Dc,Da) + \
96 (mabs(Sc * Da) < mabs(Dc * Sa) ? Sc * Da : Dc * Sa) / mx)
98 // LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc*Da, Dc*Sa)]
99 #define ALPHA_LIGHTEN STD_ALPHA
100 #define COLOR_LIGHTEN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
101 mmax(Sc * Da, Dc * Sa) / mx)
102 #define CHROMA_LIGHTEN(mx, Sc, Sa, Dc, Da) (CHROMA_XOR(mx,Sc,Sa,Dc,Da) + \
103 (mabs(Sc * Da) > mabs(Dc * Sa) ? Sc * Da : Dc * Sa) / mx)
106 #define ALPHA_DST(mx, Sa, Da) Da
107 #define COLOR_DST(mx, Sc, Sa, Dc, Da) Dc
108 #define CHROMA_DST COLOR_DST
110 // DST_ATOP [Sa, Sc * (1 - Da) + Dc * Sa]
111 #define ALPHA_DST_ATOP(mx, Sa, Da) Sa
112 #define COLOR_DST_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * Sa) / mx)
113 #define CHROMA_DST_ATOP COLOR_DST_ATOP
115 // DST_IN [Da * Sa, Dc * Sa]
116 #define ALPHA_DST_IN(mx, Sa, Da) ((Da * Sa) / mx)
117 #define COLOR_DST_IN(mx, Sc, Sa, Dc, Da) ((Dc * Sa) / mx)
118 #define CHROMA_DST_IN COLOR_DST_IN
120 // DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)]
121 #define ALPHA_DST_OUT(mx, Sa, Da) (Da * (mx - Sa) / mx)
122 #define COLOR_DST_OUT(mx, Sc, Sa, Dc, Da) (Dc * (mx - Sa) / mx)
123 #define CHROMA_DST_OUT COLOR_DST_OUT
125 // DST_OVER [Sa + Da - Sa*Da, Sc * (1 - Da) + Dc]
126 #define ALPHA_DST_OVER STD_ALPHA
127 #define COLOR_DST_OVER(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da)/ mx + Dc)
128 #define CHROMA_DST_OVER COLOR_DST_OVER
131 #define ALPHA_SRC(mx, Sa, Da) Sa
132 #define COLOR_SRC(mx, Sc, Sa, Dc, Da) Sc
133 #define CHROMA_SRC COLOR_SRC
135 // SRC_ATOP [Da, Sc * Da + Dc * (1 - Sa)]
136 #define ALPHA_SRC_ATOP(mx, Sa, Da) Da
137 #define COLOR_SRC_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * Da + Dc * (mx - Sa)) / mx)
138 #define CHROMA_SRC_ATOP COLOR_SRC_ATOP
140 // SRC_IN [Sa * Da, Sc * Da]
141 #define ALPHA_SRC_IN(mx, Sa, Da) ((Sa * Da) / mx)
142 #define COLOR_SRC_IN(mx, Sc, Sa, Dc, Da) (Sc * Da / mx)
143 #define CHROMA_SRC_IN COLOR_SRC_IN
145 // SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)]
146 #define ALPHA_SRC_OUT(mx, Sa, Da) (Sa * (mx - Da) / mx)
147 #define COLOR_SRC_OUT(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da) / mx)
148 #define CHROMA_SRC_OUT COLOR_SRC_OUT
150 // SRC_OVER [Sa + Da - Sa*Da, Sc + (1 - Sa) * Dc]
151 #define ALPHA_SRC_OVER STD_ALPHA
152 #define COLOR_SRC_OVER(mx, Sc, Sa, Dc, Da) (Sc + Dc * (mx - Sa) / mx)
153 #define CHROMA_SRC_OVER COLOR_SRC_OVER
155 // AND [Sa * Da, Sc * Dc]
156 #define ALPHA_AND(mx, Sa, Da) ((Sa * Da) / mx)
157 #define COLOR_AND(mx, Sc, Sa, Dc, Da) ((Sc * Dc) / mx)
158 #define CHROMA_AND COLOR_AND
160 // OR [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
161 #define ALPHA_OR(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx)
162 #define COLOR_OR(mx, Sc, Sa, Dc, Da) (Sc + Dc - (Sc * Dc) / mx)
163 #define CHROMA_OR COLOR_OR
165 // XOR [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
166 #define ALPHA_XOR(mx, Sa, Da) (Sa + Da - (TWO * Sa * Da / mx))
167 #define COLOR_XOR(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx)
168 #define CHROMA_XOR COLOR_XOR
171 //https://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html
172 // OVERLAY [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
173 // 2*Dc < Da ? 2*Sc*Dc : Sa*Da - 2*(Da-Dc)*(Sa-Sc) ]
174 #define ALPHA_OVERLAY STD_ALPHA
175 #define COLOR_OVERLAY(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
177 (TWO * Sc * Dc) : (Sa * Da - TWO * (Da - Dc) * (Sa - Sc))) / mx)
178 #define CHROMA_OVERLAY COLOR_OVERLAY
180 // SCREEN [Sa + Da - Sa * Da, Sc + Dc - (Sc * Dc)] (same as OR)
181 #define ALPHA_SCREEN STD_ALPHA
182 #define COLOR_SCREEN(mx, Sc, Sa, Dc, Da) (Sc + Dc - (Sc * Dc) / mx)
183 #define CHROMA_SCREEN COLOR_SCREEN
185 // BURN [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
186 // Sc <= 0 || Sc*Da + Dc*Sa <= Sa*Da ? 0 : (Sc*Da + Dc*Sa - Sa*Da)*Sa/Sc]
187 #define ALPHA_BURN STD_ALPHA
188 #define COLOR_BURN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
189 ((Sc <= ZERO || Sc * Da + Dc * Sa <= Sa * Da) ? ZERO : \
190 (Sa * ((Sc * Da + Dc * Sa - Sa * Da) / Sc) / mx)))
191 #define CHROMA_BURN COLOR_BURN
193 // DODGE [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
194 // Sa <= Sc || Sc*Da + Dc*Sa >= Sa*Da) ? Sa*Da : Dc*Sa / (1 - Sc/Sa)]
195 #define ALPHA_DODGE STD_ALPHA
196 #define COLOR_DODGE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
197 ((Sa <= Sc || Sc * Da + Dc * Sa >= Sa * Da) ? (Sa * Da) : \
198 (Sa * ((Dc * Sa) / (Sa - Sc))) / mx))
199 #define CHROMA_DODGE COLOR_DODGE
201 // HARDLIGHT [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
202 // 2*Sc < Sa ? 2*Sc*Dc : Sa*Da - 2*(Da - Dc)*(Sa - Sc)]
203 #define ALPHA_HARDLIGHT STD_ALPHA
204 #define COLOR_HARDLIGHT(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
206 (TWO * Sc * Dc) : (Sa * Da - TWO * (Da - Dc) * (Sa - Sc))) / mx)
207 #define CHROMA_HARDLIGHT COLOR_HARDLIGHT
209 // SOFTLIGHT [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
210 // Da > 0 ? (Dc*Sa + 2*Sc*(Da - Dc))/Da : 0]
211 #define ALPHA_SOFTLIGHT STD_ALPHA
212 #define COLOR_SOFTLIGHT(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
214 (Dc * ((Dc*Sa + TWO * Sc * (Da - Dc)) / Da) / mx) : ZERO))
215 #define CHROMA_SOFTLIGHT COLOR_SOFTLIGHT
217 // DIFFERENCE [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) +
218 // abs(Sc * Da - Dc * Sa)]
219 #define ALPHA_DIFFERENCE STD_ALPHA
220 #define COLOR_DIFFERENCE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \
221 (mabs(Sc * Da - Dc * Sa) / mx))
222 #define CHROMA_DIFFERENCE COLOR_DIFFERENCE
224 static inline int mabs(int32_t v) { return abs(v); }
225 static inline int mabs(int64_t v) { return llabs(v); }
226 static inline float mabs(float v) { return fabsf(v); }
227 static inline int mmin(int32_t a, int32_t b) { return a < b ? a : b; }
228 static inline int mmin(int64_t a, int64_t b) { return a < b ? a : b; }
229 static inline float mmin(float a, float b) { return a < b ? a : b; }
230 static inline int mmax(int32_t a, int32_t b) { return a > b ? a : b; }
231 static inline int mmax(int64_t a, int64_t b) { return a > b ? a : b; }
232 static inline float mmax(float a, float b) { return a > b ? a : b; }
234 static inline int32_t aclip(int32_t v, int mx) {
235 return v < 0 ? 0 : v > mx ? mx : v;
237 static inline int64_t aclip(int64_t v, int mx) {
238 return v < 0 ? 0 : v > mx ? mx : v;
240 static inline float aclip(float v, float mx) {
241 return v < -FLT_MAX+1 ? -FLT_MAX : v > FLT_MAX-1 ? FLT_MAX : v;
243 static inline float aclip(float v, int mx) {
244 return v < 0 ? 0 : v > mx ? mx : v;
246 static inline int aclip(int v, float mx) {
247 return v < 0 ? 0 : v > mx ? mx : v;
249 static inline int32_t cclip(int32_t v, int mx) {
250 return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v;
252 static inline int64_t cclip(int64_t v, int mx) {
253 return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v;
255 static inline float cclip(float v, float mx) {
256 return v > (mx/=2) ? mx : v < (mx=(-mx)) ? mx : v;
258 static inline float cclip(float v, int mx) {
259 return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v;
261 static inline int cclip(int v, float mx) {
262 return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v;
265 /* number of data pts per unit x in lookup table */
266 #define TRANSFORM_SPP (4096)
267 /* bits of fraction past TRANSFORM_SPP on kernel index accumulation */
268 #define INDEX_FRACTION (8)
269 #define TRANSFORM_MIN (.5 / TRANSFORM_SPP)
271 #define ZTYP(ty) typedef ty z_##ty __attribute__ ((__unused__))
272 ZTYP(int8_t); ZTYP(uint8_t);
273 ZTYP(int16_t); ZTYP(uint16_t);
274 ZTYP(int32_t); ZTYP(uint32_t);
275 ZTYP(int64_t); ZTYP(uint64_t);
276 ZTYP(float); ZTYP(double);
278 #define ALPHA3_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \
279 typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \
280 typ inp2 = (typ)inp[2] - iofs, inp3 = mx; \
281 typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \
282 typ out2 = (typ)out[2] - oofs, out3 = mx; \
283 r = COLOR_##FN(mx, inp0, inp3, out0, out3); \
285 g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \
286 b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \
289 g = COLOR_##FN(mx, inp1, inp3, out1, out3); \
290 b = COLOR_##FN(mx, inp2, inp3, out2, out3); \
293 #define ALPHA4_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \
294 typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \
295 typ inp2 = (typ)inp[2] - iofs, inp3 = inp[3]; \
296 typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \
297 typ out2 = (typ)out[2] - oofs, out3 = out[3]; \
298 r = COLOR_##FN(mx, inp0, inp3, out0, out3); \
300 g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \
301 b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \
304 g = COLOR_##FN(mx, inp1, inp3, out1, out3); \
305 b = COLOR_##FN(mx, inp2, inp3, out2, out3); \
307 a = ALPHA_##FN(mx, inp3, out3)
309 #define ALPHA_STORE(out, ofs, mx) \
314 #define ALPHA3_STORE(out, ofs, mx) \
316 g = ofs ? cclip(g, mx) : aclip(g, mx); \
317 b = ofs ? cclip(b, mx) : aclip(b, mx); \
319 r = (r * opcty + out0 * trnsp) / mx; \
320 g = (g * opcty + out1 * trnsp) / mx; \
321 b = (b * opcty + out2 * trnsp) / mx; \
323 ALPHA_STORE(out, ofs, mx)
325 #define ALPHA4_STORE(out, ofs, mx) \
327 g = ofs ? cclip(g, mx) : aclip(g, mx); \
328 b = ofs ? cclip(b, mx) : aclip(b, mx); \
330 r = (r * opcty + out0 * trnsp) / mx; \
331 g = (g * opcty + out1 * trnsp) / mx; \
332 b = (b * opcty + out2 * trnsp) / mx; \
333 a = (a * opcty + out3 * trnsp) / mx; \
335 ALPHA_STORE(out, ofs, mx); \
336 out[3] = aclip(a, mx)
338 #define BLEND_SWITCH(FN) \
340 case TRANSFER_NORMAL: FN(NORMAL); \
341 case TRANSFER_ADDITION: FN(ADDITION); \
342 case TRANSFER_SUBTRACT: FN(SUBTRACT); \
343 case TRANSFER_MULTIPLY: FN(MULTIPLY); \
344 case TRANSFER_DIVIDE: FN(DIVIDE); \
345 case TRANSFER_REPLACE: FN(REPLACE); \
346 case TRANSFER_MAX: FN(MAX); \
347 case TRANSFER_MIN: FN(MIN); \
348 case TRANSFER_DARKEN: FN(DARKEN); \
349 case TRANSFER_LIGHTEN: FN(LIGHTEN); \
350 case TRANSFER_DST: FN(DST); \
351 case TRANSFER_DST_ATOP: FN(DST_ATOP); \
352 case TRANSFER_DST_IN: FN(DST_IN); \
353 case TRANSFER_DST_OUT: FN(DST_OUT); \
354 case TRANSFER_DST_OVER: FN(DST_OVER); \
355 case TRANSFER_SRC: FN(SRC); \
356 case TRANSFER_SRC_ATOP: FN(SRC_ATOP); \
357 case TRANSFER_SRC_IN: FN(SRC_IN); \
358 case TRANSFER_SRC_OUT: FN(SRC_OUT); \
359 case TRANSFER_SRC_OVER: FN(SRC_OVER); \
360 case TRANSFER_AND: FN(AND); \
361 case TRANSFER_OR: FN(OR); \
362 case TRANSFER_XOR: FN(XOR); \
363 case TRANSFER_OVERLAY: FN(OVERLAY); \
364 case TRANSFER_SCREEN: FN(SCREEN); \
365 case TRANSFER_BURN: FN(BURN); \
366 case TRANSFER_DODGE: FN(DODGE); \
367 case TRANSFER_HARDLIGHT: FN(HARDLIGHT); \
368 case TRANSFER_SOFTLIGHT: FN(SOFTLIGHT); \
369 case TRANSFER_DIFFERENCE: FN(DIFFERENCE); \
375 OverlayKernel(int interpolation_type);
386 class DirectPackage : public LoadPackage
391 int out_row1, out_row2;
396 class NNPackage : public LoadPackage
401 int out_row1, out_row2;
406 class SamplePackage : public LoadPackage
411 int out_col1, out_col2;
415 class DirectUnit : public LoadClient
418 DirectUnit(DirectEngine *server);
421 void process_package(LoadPackage *package);
422 DirectEngine *engine;
426 VFrame *output, *input;
442 class NNUnit : public LoadClient
445 NNUnit(NNEngine *server);
448 void process_package(LoadPackage *package);
453 VFrame *output, *input;
470 class SampleUnit : public LoadClient
473 SampleUnit(SampleEngine *server);
476 void process_package(LoadPackage *package);
477 SampleEngine *engine;
480 VFrame *voutput, *vinput;
484 int i1i, i2i, o1i, o2i, oh, kd;
485 float i1f, i2f, o1f, o2f, *k;
486 int *lookup_sx0, *lookup_sx1, *lookup_sk;
502 class DirectEngine : public LoadServer
505 DirectEngine(int cpus);
508 void init_packages();
509 LoadClient* new_client();
510 LoadPackage* new_package();
524 class NNEngine : public LoadServer
530 void init_packages();
531 LoadClient* new_client();
532 LoadPackage* new_package();
553 class SampleEngine : public LoadServer
556 SampleEngine(int cpus);
559 void init_packages();
560 LoadClient* new_client();
561 LoadPackage* new_package();
565 OverlayKernel *kernel;
589 OverlayFrame(int cpus = 1);
590 virtual ~OverlayFrame();
592 int overlay(VFrame *output,
604 int interpolation_type);
606 DirectEngine *direct_engine;
608 SampleEngine *sample_engine;
612 OverlayKernel *kernel[4];