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