1 /*
2 (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <dfb_types.h>
36
37 #include <pthread.h>
38
39 #include <directfb.h>
40
41 #include <core/core.h>
42 #include <core/coredefs.h>
43 #include <core/coretypes.h>
44
45 #include <core/gfxcard.h>
46 #include <core/state.h>
47 #include <core/palette.h>
48
49 #include <misc/gfx_util.h>
50 #include <misc/util.h>
51 #include <misc/conf.h>
52
53 #include <direct/clock.h>
54 #include <direct/mem.h>
55 #include <direct/memcpy.h>
56 #include <direct/messages.h>
57 #include <direct/util.h>
58
59 #include <gfx/convert.h>
60 #include <gfx/util.h>
61
62 #include "generic.h"
63
64 /**********************************************************************************************************************/
65 /**********************************************************************************************************************/
66
Genefx_Aop_xy(GenefxState * gfxs,int x,int y)67 void Genefx_Aop_xy( GenefxState *gfxs, int x, int y )
68 {
69 int pitch = gfxs->dst_pitch;
70
71 gfxs->Aop[0] = gfxs->dst_org[0];
72 gfxs->AopY = y;
73
74 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
75 gfxs->Aop_field = y & 1;
76 if (gfxs->Aop_field)
77 gfxs->Aop[0] += gfxs->dst_field_offset;
78
79 y /= 2;
80 }
81
82 D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT(gfxs->dst_format)) );
83
84 gfxs->Aop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, x );
85
86 if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {
87 int dst_field_offset = gfxs->dst_field_offset;
88
89 switch (gfxs->dst_format) {
90 case DSPF_YV12:
91 case DSPF_I420:
92 dst_field_offset /= 4;
93 pitch /= 2;
94 y /= 2;
95 x /= 2;
96 break;
97 case DSPF_YV16:
98 dst_field_offset /= 2;
99 pitch /= 2;
100 x /= 2;
101 break;
102 case DSPF_NV12:
103 case DSPF_NV21:
104 dst_field_offset /= 2;
105 y /= 2;
106 case DSPF_NV16:
107 x &= ~1;
108 break;
109 case DSPF_YUV444P: /* nothing to adjust */
110 default:
111 break;
112 }
113
114 gfxs->Aop[1] = gfxs->dst_org[1];
115 gfxs->Aop[2] = gfxs->dst_org[2];
116
117 if (gfxs->dst_caps & DSCAPS_SEPARATED && gfxs->Aop_field) {
118 gfxs->Aop[1] += dst_field_offset;
119 gfxs->Aop[2] += dst_field_offset;
120 }
121
122 gfxs->Aop[1] += y * pitch + x;
123 gfxs->Aop[2] += y * pitch + x;
124 }
125 }
126
Genefx_Aop_crab(GenefxState * gfxs)127 void Genefx_Aop_crab( GenefxState *gfxs )
128 {
129 gfxs->Aop[0] += gfxs->dst_bpp;
130 gfxs->AopY++;
131 }
132
Genefx_Aop_prev_crab(GenefxState * gfxs)133 void Genefx_Aop_prev_crab( GenefxState *gfxs )
134 {
135 gfxs->Aop[0] -= gfxs->dst_bpp;
136 gfxs->AopY++;
137 }
138
Genefx_Aop_next(GenefxState * gfxs)139 void Genefx_Aop_next( GenefxState *gfxs )
140 {
141 int pitch = gfxs->dst_pitch;
142
143 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
144 gfxs->Aop_field++;
145
146 if (gfxs->Aop_field & 1)
147 gfxs->Aop[0] += gfxs->dst_field_offset;
148 else
149 gfxs->Aop[0] += pitch - gfxs->dst_field_offset;
150 }
151 else
152 gfxs->Aop[0] += pitch;
153
154 if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {
155 if (gfxs->dst_format == DSPF_YV12 || gfxs->dst_format == DSPF_I420) {
156 if (gfxs->AopY & 1) {
157 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
158 if (gfxs->Aop_field & 2) {
159 gfxs->Aop[1] += gfxs->dst_field_offset/4;
160 gfxs->Aop[2] += gfxs->dst_field_offset/4;
161 }
162 else {
163 gfxs->Aop[1] += pitch/2 - gfxs->dst_field_offset/4;
164 gfxs->Aop[2] += pitch/2 - gfxs->dst_field_offset/4;
165 }
166 }
167 else {
168 gfxs->Aop[1] += pitch/2;
169 gfxs->Aop[2] += pitch/2;
170 }
171 }
172 }
173 else if (gfxs->dst_format == DSPF_YV16) {
174 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
175 if (gfxs->Aop_field & 2) {
176 gfxs->Aop[1] += gfxs->dst_field_offset/2;
177 gfxs->Aop[2] += gfxs->dst_field_offset/2;
178 }
179 else {
180 gfxs->Aop[1] += pitch/2 - gfxs->dst_field_offset/2;
181 gfxs->Aop[2] += pitch/2 - gfxs->dst_field_offset/2;
182 }
183 }
184 else {
185 gfxs->Aop[1] += pitch/2;
186 gfxs->Aop[2] += pitch/2;
187 }
188 }
189 else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) {
190 if (gfxs->AopY & 1) {
191 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
192 if (gfxs->Aop_field & 2)
193 gfxs->Aop[1] += gfxs->dst_field_offset/2;
194 else
195 gfxs->Aop[1] += pitch - gfxs->dst_field_offset/2;
196 }
197 else {
198 gfxs->Aop[1] += pitch;
199 }
200 }
201 }
202 else if (gfxs->dst_format == DSPF_YUV444P) {
203 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
204 if (gfxs->Aop_field & 1) {
205 gfxs->Aop[1] += gfxs->dst_field_offset;
206 gfxs->Aop[2] += gfxs->dst_field_offset;
207 }
208 else {
209 gfxs->Aop[1] += pitch - gfxs->dst_field_offset;
210 gfxs->Aop[2] += pitch - gfxs->dst_field_offset;
211 }
212 }
213 else {
214 gfxs->Aop[1] += pitch;
215 gfxs->Aop[2] += pitch;
216 }
217 }
218 else { /* NV16 */
219 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
220 if (gfxs->Aop_field & 1)
221 gfxs->Aop[1] += gfxs->dst_field_offset;
222 else
223 gfxs->Aop[1] += pitch - gfxs->dst_field_offset;
224 }
225 else {
226 gfxs->Aop[1] += pitch;
227 }
228 }
229 }
230
231 gfxs->AopY++;
232 }
233
Genefx_Aop_prev(GenefxState * gfxs)234 void Genefx_Aop_prev( GenefxState *gfxs )
235 {
236 int pitch = gfxs->dst_pitch;
237
238 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
239 gfxs->Aop_field++;
240
241 if (gfxs->Aop_field & 1)
242 gfxs->Aop[0] += gfxs->dst_field_offset - pitch;
243 else
244 gfxs->Aop[0] -= gfxs->dst_field_offset;
245 }
246 else
247 gfxs->Aop[0] -= pitch;
248
249 if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) {
250 if (gfxs->dst_format == DSPF_YV12 || gfxs->dst_format == DSPF_I420) {
251 if (gfxs->AopY & 1) {
252 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
253 if (gfxs->Aop_field & 2) {
254 gfxs->Aop[1] += gfxs->dst_field_offset/4 - pitch/2;
255 gfxs->Aop[2] += gfxs->dst_field_offset/4 - pitch/2;
256 }
257 else {
258 gfxs->Aop[1] -= gfxs->dst_field_offset/4;
259 gfxs->Aop[2] -= gfxs->dst_field_offset/4;
260 }
261 }
262 else {
263 gfxs->Aop[1] -= pitch/2;
264 gfxs->Aop[2] -= pitch/2;
265 }
266 }
267 }
268 else if (gfxs->dst_format == DSPF_YV16) {
269 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
270 if (gfxs->Aop_field & 2) {
271 gfxs->Aop[1] += gfxs->dst_field_offset/2 - pitch/2;
272 gfxs->Aop[2] += gfxs->dst_field_offset/2 - pitch/2;
273 }
274 else {
275 gfxs->Aop[1] -= gfxs->dst_field_offset/2;
276 gfxs->Aop[2] -= gfxs->dst_field_offset/2;
277 }
278 }
279 else {
280 gfxs->Aop[1] -= pitch/2;
281 gfxs->Aop[2] -= pitch/2;
282 }
283 }
284 else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) {
285 if (gfxs->AopY & 1) {
286 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
287 if (gfxs->Aop_field & 2)
288 gfxs->Aop[1] += gfxs->dst_field_offset/2 - pitch;
289 else
290 gfxs->Aop[1] -= gfxs->dst_field_offset/2;
291 }
292 else {
293 gfxs->Aop[1] -= pitch;
294 }
295 }
296 }
297 else if (gfxs->dst_format == DSPF_YUV444P) {
298 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
299 if (gfxs->Aop_field & 1) {
300 gfxs->Aop[1] += gfxs->dst_field_offset - pitch;
301 gfxs->Aop[2] += gfxs->dst_field_offset - pitch;
302 }
303 else {
304 gfxs->Aop[1] -= gfxs->dst_field_offset;
305 gfxs->Aop[2] -= gfxs->dst_field_offset;
306 }
307 }
308 else {
309 gfxs->Aop[1] -= pitch;
310 gfxs->Aop[2] -= pitch;
311 }
312 }
313 else { /* NV16 */
314 if (gfxs->dst_caps & DSCAPS_SEPARATED) {
315 if (gfxs->Aop_field & 1)
316 gfxs->Aop[1] += gfxs->dst_field_offset - pitch;
317 else
318 gfxs->Aop[1] -= gfxs->dst_field_offset;
319 }
320 else {
321 gfxs->Aop[1] -= pitch;
322 }
323 }
324 }
325
326 gfxs->AopY--;
327 }
328
329
Genefx_Bop_xy(GenefxState * gfxs,int x,int y)330 void Genefx_Bop_xy( GenefxState *gfxs, int x, int y )
331 {
332 int pitch = gfxs->src_pitch;
333
334 gfxs->Bop[0] = gfxs->src_org[0];
335 gfxs->BopY = y;
336
337 if (gfxs->src_caps & DSCAPS_SEPARATED) {
338 gfxs->Bop_field = y & 1;
339 if (gfxs->Bop_field)
340 gfxs->Bop[0] += gfxs->src_field_offset;
341
342 y /= 2;
343 }
344
345 D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT(gfxs->src_format)) );
346
347 gfxs->Bop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->src_format, x );
348
349 if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {
350 int src_field_offset = gfxs->src_field_offset;
351
352 switch (gfxs->src_format) {
353 case DSPF_YV12:
354 case DSPF_I420:
355 src_field_offset /= 4;
356 pitch /= 2;
357 y /= 2;
358 x /= 2;
359 break;
360 case DSPF_YV16:
361 src_field_offset /= 2;
362 pitch /= 2;
363 x /= 2;
364 break;
365 case DSPF_NV12:
366 case DSPF_NV21:
367 src_field_offset /= 2;
368 y /= 2;
369 case DSPF_NV16:
370 x &= ~1;
371 break;
372 case DSPF_YUV444P: /* nothing to adjust */
373 default:
374 break;
375 }
376
377 gfxs->Bop[1] = gfxs->src_org[1];
378 gfxs->Bop[2] = gfxs->src_org[2];
379
380 if (gfxs->src_caps & DSCAPS_SEPARATED && gfxs->Bop_field) {
381 gfxs->Bop[1] += src_field_offset;
382 gfxs->Bop[2] += src_field_offset;
383 }
384
385 gfxs->Bop[1] += y * pitch + x;
386 gfxs->Bop[2] += y * pitch + x;
387 }
388 }
389
Genefx_Bop_next(GenefxState * gfxs)390 void Genefx_Bop_next( GenefxState *gfxs )
391 {
392 int pitch = gfxs->src_pitch;
393
394 if (gfxs->src_caps & DSCAPS_SEPARATED) {
395 gfxs->Bop_field++;
396
397 if (gfxs->Bop_field & 1)
398 gfxs->Bop[0] += gfxs->src_field_offset;
399 else
400 gfxs->Bop[0] += pitch - gfxs->src_field_offset;
401 }
402 else
403 gfxs->Bop[0] += pitch;
404
405 if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {
406 if (gfxs->src_format == DSPF_YV12 || gfxs->src_format == DSPF_I420) {
407 if (gfxs->BopY & 1) {
408 if (gfxs->src_caps & DSCAPS_SEPARATED) {
409 if (gfxs->Bop_field & 2) {
410 gfxs->Bop[1] += gfxs->src_field_offset/4;
411 gfxs->Bop[2] += gfxs->src_field_offset/4;
412 }
413 else {
414 gfxs->Bop[1] += pitch/2 - gfxs->src_field_offset/4;
415 gfxs->Bop[2] += pitch/2 - gfxs->src_field_offset/4;
416 }
417 }
418 else {
419 gfxs->Bop[1] += pitch/2;
420 gfxs->Bop[2] += pitch/2;
421 }
422 }
423 }
424 else if (gfxs->src_format == DSPF_YV16) {
425 if (gfxs->src_caps & DSCAPS_SEPARATED) {
426 if (gfxs->Bop_field & 2) {
427 gfxs->Bop[1] += gfxs->src_field_offset/2;
428 gfxs->Bop[2] += gfxs->src_field_offset/2;
429 }
430 else {
431 gfxs->Bop[1] += pitch/2 - gfxs->src_field_offset/2;
432 gfxs->Bop[2] += pitch/2 - gfxs->src_field_offset/2;
433 }
434 }
435 else {
436 gfxs->Bop[1] += pitch/2;
437 gfxs->Bop[2] += pitch/2;
438 }
439 }
440 else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) {
441 if (gfxs->BopY & 1) {
442 if (gfxs->src_caps & DSCAPS_SEPARATED) {
443 if (gfxs->Bop_field & 2)
444 gfxs->Bop[1] += gfxs->src_field_offset/2;
445 else
446 gfxs->Bop[1] += pitch - gfxs->src_field_offset/2;
447 }
448 else {
449 gfxs->Bop[1] += pitch;
450 }
451 }
452 }
453 else if (gfxs->src_format == DSPF_YUV444P) {
454 if (gfxs->src_caps & DSCAPS_SEPARATED) {
455 if (gfxs->Bop_field & 1) {
456 gfxs->Bop[1] += gfxs->src_field_offset;
457 gfxs->Bop[2] += gfxs->src_field_offset;
458 }
459 else {
460 gfxs->Bop[1] += pitch - gfxs->src_field_offset;
461 gfxs->Bop[2] += pitch - gfxs->src_field_offset;
462 }
463 }
464 else {
465 gfxs->Bop[1] += pitch;
466 gfxs->Bop[2] += pitch;
467 }
468 }
469 else { /* NV16 */
470 if (gfxs->src_caps & DSCAPS_SEPARATED) {
471 if (gfxs->Bop_field & 1)
472 gfxs->Bop[1] += gfxs->src_field_offset;
473 else
474 gfxs->Bop[1] += pitch - gfxs->src_field_offset;
475 }
476 else {
477 gfxs->Bop[1] += pitch;
478 }
479 }
480 }
481
482 gfxs->BopY++;
483 }
484
Genefx_Bop_prev(GenefxState * gfxs)485 void Genefx_Bop_prev( GenefxState *gfxs )
486 {
487 int pitch = gfxs->src_pitch;
488
489 if (gfxs->src_caps & DSCAPS_SEPARATED) {
490 gfxs->Bop_field++;
491
492 if (gfxs->Bop_field & 1)
493 gfxs->Bop[0] += gfxs->src_field_offset - pitch;
494 else
495 gfxs->Bop[0] -= gfxs->src_field_offset;
496 }
497 else
498 gfxs->Bop[0] -= pitch;
499
500 if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) {
501 if (gfxs->src_format == DSPF_YV12 || gfxs->src_format == DSPF_I420) {
502 if (gfxs->BopY & 1) {
503 if (gfxs->src_caps & DSCAPS_SEPARATED) {
504 if (gfxs->Bop_field & 2) {
505 gfxs->Bop[1] += gfxs->src_field_offset/4 - pitch/2;
506 gfxs->Bop[2] += gfxs->src_field_offset/4 - pitch/2;
507 }
508 else {
509 gfxs->Bop[1] -= gfxs->src_field_offset/4;
510 gfxs->Bop[2] -= gfxs->src_field_offset/4;
511 }
512 }
513 else {
514 gfxs->Bop[1] -= pitch/2;
515 gfxs->Bop[2] -= pitch/2;
516 }
517 }
518 }
519 else if (gfxs->src_format == DSPF_YV16) {
520 if (gfxs->src_caps & DSCAPS_SEPARATED) {
521 if (gfxs->Bop_field & 2) {
522 gfxs->Bop[1] += gfxs->src_field_offset/2 - pitch/2;
523 gfxs->Bop[2] += gfxs->src_field_offset/2 - pitch/2;
524 }
525 else {
526 gfxs->Bop[1] -= gfxs->src_field_offset/2;
527 gfxs->Bop[2] -= gfxs->src_field_offset/2;
528 }
529 }
530 else {
531 gfxs->Bop[1] -= pitch/2;
532 gfxs->Bop[2] -= pitch/2;
533 }
534 }
535 else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) {
536 if (gfxs->BopY & 1) {
537 if (gfxs->src_caps & DSCAPS_SEPARATED) {
538 if (gfxs->Bop_field & 2)
539 gfxs->Bop[1] += gfxs->src_field_offset/2 - pitch;
540 else
541 gfxs->Bop[1] -= gfxs->src_field_offset/2;
542 }
543 else {
544 gfxs->Bop[1] -= pitch;
545 }
546 }
547 }
548 else if (gfxs->src_format == DSPF_YUV444P) {
549 if (gfxs->src_caps & DSCAPS_SEPARATED) {
550 if (gfxs->Bop_field & 1) {
551 gfxs->Bop[1] += gfxs->src_field_offset - pitch;
552 gfxs->Bop[2] += gfxs->src_field_offset - pitch;
553 }
554 else {
555 gfxs->Bop[1] -= gfxs->src_field_offset;
556 gfxs->Bop[2] -= gfxs->src_field_offset;
557 }
558 }
559 else {
560 gfxs->Bop[1] -= pitch;
561 gfxs->Bop[2] -= pitch;
562 }
563 }
564 else { /* NV16 */
565 if (gfxs->src_caps & DSCAPS_SEPARATED) {
566 if (gfxs->Bop_field & 1)
567 gfxs->Bop[1] += gfxs->src_field_offset - pitch;
568 else
569 gfxs->Bop[1] -= gfxs->src_field_offset;
570 }
571 else {
572 gfxs->Bop[1] -= pitch;
573 }
574 }
575 }
576
577 gfxs->BopY--;
578 }
579
580 /**********************************************************************************************************************/
581
582 bool
Genefx_ABacc_prepare(GenefxState * gfxs,int width)583 Genefx_ABacc_prepare( GenefxState *gfxs, int width )
584 {
585 int size;
586
587 if (!gfxs->need_accumulator)
588 return true;
589
590 size = (width + 31) & ~31;
591
592 if (gfxs->ABsize < size) {
593 void *ABstart = D_MALLOC( size * sizeof(GenefxAccumulator) * 3 + 31 );
594
595 if (!ABstart) {
596 D_WARN( "out of memory" );
597 return false;
598 }
599
600 if (gfxs->ABstart)
601 D_FREE( gfxs->ABstart );
602
603 gfxs->ABstart = ABstart;
604 gfxs->ABsize = size;
605 gfxs->Aacc = (GenefxAccumulator*) (((unsigned long)ABstart+31) & ~31);
606 gfxs->Bacc = gfxs->Aacc + size;
607 gfxs->Tacc = gfxs->Aacc + size + size;
608 }
609
610 gfxs->Sacc = gfxs->Dacc = gfxs->Aacc;
611
612 return true;
613 }
614
615 void
Genefx_ABacc_flush(GenefxState * gfxs)616 Genefx_ABacc_flush( GenefxState *gfxs )
617 {
618 if (dfb_config->keep_accumulators >= 0 && gfxs->ABsize > dfb_config->keep_accumulators) {
619 D_FREE( gfxs->ABstart );
620
621 gfxs->ABsize = 0;
622 gfxs->ABstart = NULL;
623 gfxs->Aacc = NULL;
624 gfxs->Bacc = NULL;
625 gfxs->Sacc = NULL;
626 gfxs->Dacc = NULL;
627 }
628 }
629
630