Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2019
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / software 2D rasterizer module
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : *
25 : *
26 : */
27 :
28 : #include "rast_soft.h"
29 :
30 : static s32
31 : mul255(s32 a, s32 b)
32 : {
33 58564324 : return ((a + 1) * b) >> 8;
34 : }
35 :
36 :
37 : /*
38 : RGB part
39 : */
40 :
41 4365632 : void overmask_rgb(u32 src, u8 *dst, u32 alpha, GF_EVGSurface *surf)
42 : {
43 4365632 : s32 srca = (src >> 24) & 0xff;
44 4365632 : s32 srcr = (src >> 16) & 0xff;
45 4365632 : s32 srcg = (src >> 8) & 0xff;
46 4365632 : s32 srcb = (src) & 0xff;
47 :
48 4365632 : s32 dstr = dst[surf->idx_r] & 0xFF;
49 4365632 : s32 dstg = dst[surf->idx_g] & 0xFF;
50 4365632 : s32 dstb = dst[surf->idx_b] & 0xFF;
51 :
52 4365632 : srca = mul255(srca, alpha);
53 8731264 : dst[surf->idx_r] = mul255(srca, srcr - dstr) + dstr;
54 8731264 : dst[surf->idx_g] = mul255(srca, srcg - dstg) + dstg;
55 8731264 : dst[surf->idx_b] = mul255(srca, srcb - dstb) + dstb;
56 4365632 : }
57 :
58 6832928 : static void overmask_rgb_const_run(u32 src, u8 *dst, s32 dst_pitch_x, u32 count, GF_EVGSurface *surf)
59 : {
60 6832928 : s32 srca = (src >> 24) & 0xff;
61 6832928 : s32 srcr = (src >> 16) & 0xff;
62 6832928 : s32 srcg = (src >> 8) & 0xff;
63 6832928 : s32 srcb = (src) & 0xff;
64 :
65 25084082 : while (count) {
66 11418226 : s32 dstr = dst[surf->idx_r];
67 11418226 : s32 dstg = dst[surf->idx_g];
68 11418226 : s32 dstb = dst[surf->idx_b];
69 22836452 : dst[surf->idx_r] = (u8) mul255(srca, srcr - dstr) + dstr;
70 22836452 : dst[surf->idx_g] = (u8) mul255(srca, srcg - dstg) + dstg;
71 22836452 : dst[surf->idx_b] = (u8) mul255(srca, srcb - dstb) + dstb;
72 11418226 : dst += dst_pitch_x;
73 11418226 : count--;
74 : }
75 6832928 : }
76 :
77 3117931 : void evg_rgb_fill_single(s32 y, s32 x, u32 col, GF_EVGSurface *surf)
78 : {
79 3117931 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
80 3117931 : u8 r = GF_COL_R(col);
81 3117931 : u8 g = GF_COL_G(col);
82 3117931 : u8 b = GF_COL_B(col);
83 3117931 : dst[surf->idx_r] = r;
84 3117931 : dst[surf->idx_g] = g;
85 3117931 : dst[surf->idx_b] = b;
86 3117931 : }
87 :
88 294619 : void evg_rgb_fill_single_a(s32 y, s32 x, u8 coverage, u32 col, GF_EVGSurface *surf)
89 : {
90 294619 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
91 294619 : overmask_rgb(col, dst, coverage, surf);
92 294619 : }
93 :
94 1868607 : void evg_rgb_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
95 : {
96 1868607 : u32 col = surf->fill_col;
97 1868607 : u8 *dst = surf->pixels + y * surf->pitch_y;
98 : s32 i;
99 : u32 col_no_a, r, g, b;
100 :
101 1868607 : r = GF_COL_R(col);
102 1868607 : g = GF_COL_G(col);
103 : b = GF_COL_B(col);
104 :
105 1868607 : col_no_a = col & 0x00FFFFFF;
106 9147955 : for (i=0; i<count; i++) {
107 : u32 a, fin, len;
108 : char *p;
109 7279348 : len = spans[i].len;
110 7279348 : p = dst + spans[i].x * surf->pitch_x;
111 :
112 7279348 : if (spans[i].coverage != 0xFF) {
113 12950562 : a = mul255(0xFF, spans[i].coverage);
114 6475281 : fin = (a<<24) | col_no_a;
115 6475281 : overmask_rgb_const_run(fin, p, surf->pitch_x, len, surf);
116 : } else {
117 24526581 : while (len--) {
118 23722514 : p[surf->idx_r] = r;
119 23722514 : p[surf->idx_g] = g;
120 23722514 : p[surf->idx_b] = b;
121 23722514 : p += surf->pitch_x;
122 : }
123 : }
124 : }
125 1868607 : }
126 :
127 86579 : void evg_rgb_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
128 : {
129 86579 : u8 *dst = surf->pixels + y * surf->pitch_y;
130 86579 : u32 col = surf->fill_col;
131 : u32 a, fin;
132 : s32 i;
133 :
134 86579 : a = (col>>24)&0xFF;
135 86579 : if (surf->get_alpha) {
136 16 : for (i=0; i<count; i++) {
137 : u32 j;
138 256 : for (j=0; j<spans[i].len; j++) {
139 256 : s32 x = spans[i].x + j;
140 256 : u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
141 512 : fin = mul255(aa, spans[i].coverage);
142 256 : fin = (fin<<24) | (col&0x00FFFFFF);
143 256 : overmask_rgb_const_run(fin, dst + surf->pitch_x * x, surf->pitch_x, 1, surf);
144 : }
145 : }
146 : } else {
147 357391 : for (i=0; i<count; i++) {
148 714782 : fin = mul255(a, spans[i].coverage);
149 357391 : fin = (fin<<24) | (col&0x00FFFFFF);
150 357391 : overmask_rgb_const_run(fin, dst + surf->pitch_x * spans[i].x, surf->pitch_x, spans[i].len, surf);
151 : }
152 : }
153 86579 : }
154 :
155 :
156 492153 : void evg_rgb_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
157 : {
158 492153 : u8 *dst = surf->pixels + y * surf->pitch_y;
159 : s32 i;
160 :
161 2534301 : for (i=0; i<count; i++) {
162 : u8 spanalpha, col_a;
163 : s32 x;
164 : u32 len;
165 : u32 *col;
166 2042148 : len = spans[i].len;
167 2042148 : spanalpha = spans[i].coverage;
168 2042148 : evg_fill_run(surf->sten, surf, spans[i].x, y, len);
169 2042148 : col = surf->stencil_pix_run;
170 2042148 : x = surf->pitch_x * spans[i].x;
171 34247269 : while (len--) {
172 30162973 : col_a = GF_COL_A(*col);
173 30162973 : if (col_a) {
174 28150811 : if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
175 4071013 : overmask_rgb(*col, dst + x, spanalpha, surf);
176 : } else {
177 24079798 : dst[x + surf->idx_r] = GF_COL_R(*col);
178 24079798 : dst[x + surf->idx_g] = GF_COL_G(*col);
179 24079798 : dst[x + surf->idx_b] = GF_COL_B(*col);
180 : }
181 : }
182 30162973 : col++;
183 30162973 : x += surf->pitch_x;
184 : }
185 : }
186 492153 : }
187 :
188 2744 : GF_Err evg_surface_clear_rgb(GF_EVGSurface *surf, GF_IRect rc, GF_Color col)
189 : {
190 : u32 x, y, w, h, sx, sy;
191 : s32 st;
192 : u8 r, g, b;
193 : u8 *o_data;
194 : GF_EVGSurface *_this = (GF_EVGSurface *)surf;
195 2744 : st = _this->pitch_y;
196 :
197 2744 : h = rc.height;
198 2744 : w = rc.width;
199 2744 : sx = rc.x;
200 2744 : sy = rc.y;
201 :
202 2744 : r = GF_COL_R(col);
203 2744 : g = GF_COL_G(col);
204 2744 : b = GF_COL_B(col);
205 : o_data = NULL;
206 346393 : for (y = 0; y < h; y++) {
207 343649 : u8 *data = _this ->pixels + (y + sy) * st + _this->pitch_x*sx;
208 343649 : if (!y) {
209 : o_data = data;
210 361595 : for (x = 0; x < w; x++) {
211 361595 : data[surf->idx_r] = r;
212 361595 : data[surf->idx_g] = g;
213 361595 : data[surf->idx_b] = b;
214 361595 : data += _this->pitch_x;
215 : }
216 : } else {
217 340905 : memcpy(data, o_data, w*3);
218 : }
219 : }
220 2744 : return GF_OK;
221 : }
222 :
223 :
224 :
225 :
226 : /*
227 : grey part
228 : */
229 :
230 : static void overmask_grey(u32 src, char *dst, u32 alpha, u32 grey_type)
231 : {
232 5023 : s32 srca = (src >> 24) & 0xff;
233 : u32 srcc;
234 5023 : s32 dstc = *dst;
235 :
236 5023 : if (grey_type==0) srcc = (src >> 16) & 0xff;
237 0 : else if (grey_type==1) srcc = (src >> 8) & 0xff;
238 0 : else srcc = (src) & 0xff;
239 :
240 :
241 5023 : srca = mul255(srca, alpha);
242 10046 : *dst = mul255(srca, srcc - dstc) + dstc;
243 : }
244 :
245 : static void overmask_grey_const_run(u8 srca, u8 srcc, char *dst, s32 dst_pitch_x, u32 count)
246 : {
247 4144 : while (count) {
248 2472 : u8 dstc = *(dst);
249 4944 : *dst = (u8) mul255(srca, srcc - dstc) + dstc;
250 2472 : dst += dst_pitch_x;
251 2472 : count--;
252 : }
253 : }
254 :
255 8410 : void evg_grey_fill_single(s32 y, s32 x, u32 col, GF_EVGSurface *surf)
256 : {
257 8410 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
258 : u8 c;
259 :
260 8410 : if (surf->grey_type==0) c = GF_COL_R(col);
261 0 : else if (surf->grey_type==1) c = GF_COL_G(col);
262 0 : else c = GF_COL_B(col);
263 8410 : *dst = c;
264 8410 : }
265 :
266 792 : void evg_grey_fill_single_a(s32 y, s32 x, u8 coverage, u32 col, GF_EVGSurface *surf)
267 : {
268 792 : u8 *dst = surf->pixels + y * surf->pitch_y + x * surf->pitch_x;
269 792 : overmask_grey(col, dst, coverage, surf->grey_type);
270 792 : }
271 :
272 307 : void evg_grey_fill_const(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
273 : {
274 307 : u32 col = surf->fill_col;
275 : u32 c;
276 307 : u8 *dst = surf->pixels + y * surf->pitch_y;
277 : s32 i;
278 :
279 307 : if (surf->grey_type==0) c = GF_COL_R(col);
280 0 : else if (surf->grey_type==1) c = GF_COL_G(col);
281 : else c = GF_COL_B(col);
282 :
283 2032 : for (i=0; i<count; i++) {
284 : u32 a, len;
285 : char *p;
286 1725 : len = spans[i].len;
287 1725 : p = dst + spans[i].x * surf->pitch_x;
288 :
289 1725 : if (spans[i].coverage != 0xFF) {
290 1428 : a = mul255(0xFF, spans[i].coverage);
291 1428 : overmask_grey_const_run(a, c, p, surf->pitch_x, len);
292 : } else {
293 3226 : while (len--) {
294 2929 : *(p) = c;
295 2929 : p += surf->pitch_x;
296 : }
297 : }
298 : }
299 307 : }
300 :
301 56 : void evg_grey_fill_const_a(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
302 : {
303 56 : u8 *dst = surf->pixels + y * surf->pitch_y;
304 : u32 a, fin;
305 : s32 i;
306 : u8 c;
307 :
308 56 : if (surf->grey_type==0) c = GF_COL_R(surf->fill_col);
309 0 : else if (surf->grey_type==1) c = GF_COL_G(surf->fill_col);
310 0 : else c = GF_COL_B(surf->fill_col);
311 :
312 56 : a = GF_COL_A(surf->fill_col);
313 56 : if (surf->get_alpha) {
314 0 : for (i=0; i<count; i++) {
315 : u32 j;
316 0 : for (j=0; j<spans[i].len; j++) {
317 0 : s32 x = spans[i].x + j;
318 0 : u8 aa = surf->get_alpha(surf->get_alpha_udta, a, x, y);
319 0 : fin = mul255(aa, spans[i].coverage);
320 0 : overmask_grey_const_run(fin, c, dst + surf->pitch_x * x, surf->pitch_x, 1);
321 : }
322 : }
323 : } else {
324 244 : for (i=0; i<count; i++) {
325 244 : fin = mul255(a, spans[i].coverage);
326 244 : overmask_grey_const_run(fin, c, dst + surf->pitch_x * spans[i].x, surf->pitch_x, spans[i].len);
327 : }
328 : }
329 56 : }
330 :
331 :
332 1131 : void evg_grey_fill_var(s32 y, s32 count, EVG_Span *spans, GF_EVGSurface *surf)
333 : {
334 1131 : u8 *dst = surf->pixels + y * surf->pitch_y;
335 : s32 i;
336 :
337 2982 : for (i=0; i<count; i++) {
338 : u8 spanalpha, col_a;
339 : s32 x;
340 : u32 len;
341 : u32 *col;
342 1851 : len = spans[i].len;
343 1851 : spanalpha = spans[i].coverage;
344 1851 : evg_fill_run(surf->sten, surf, spans[i].x, y, len);
345 1851 : col = surf->stencil_pix_run;
346 1851 : x = surf->pitch_x * spans[i].x;
347 123381 : while (len--) {
348 119679 : col_a = GF_COL_A(*col);
349 119679 : if (col_a) {
350 107979 : if ((spanalpha!=0xFF) || (col_a != 0xFF)) {
351 4231 : overmask_grey(*col, dst + x, spanalpha, surf->grey_type);
352 : } else {
353 : u8 c;
354 :
355 103748 : if (surf->grey_type==0) c = GF_COL_R(*col);
356 0 : else if (surf->grey_type==1) c = GF_COL_G(*col);
357 0 : else c = GF_COL_B(*col);
358 :
359 103748 : *(dst + x) = c;
360 : }
361 : }
362 119679 : col++;
363 119679 : x += surf->pitch_x;
364 : }
365 : }
366 1131 : }
367 :
368 5 : GF_Err evg_surface_clear_grey(GF_EVGSurface *surf, GF_IRect rc, GF_Color col)
369 : {
370 : u32 y, w, h, sx, sy;
371 : s32 st;
372 : u8 r;
373 5 : st = surf->pitch_y;
374 :
375 5 : h = rc.height;
376 5 : w = rc.width;
377 5 : sx = rc.x;
378 5 : sy = rc.y;
379 :
380 5 : if (surf->grey_type==0) r = GF_COL_R(col);
381 0 : else if (surf->grey_type==1) r = GF_COL_G(col);
382 0 : else r = GF_COL_B(col);
383 :
384 817 : for (y = 0; y < h; y++) {
385 812 : char *data = surf ->pixels + (y + sy) * st + surf->pitch_x*sx;
386 812 : memset(data, r, w*surf->pitch_x);
387 : }
388 5 : return GF_OK;
389 : }
|