Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfb_blit_blend_ayuv_to_yv12.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsgui/fb/mmsfbconv.h"
00034 
00035 #ifdef __HAVE_PF_AYUV__
00036 #ifdef __HAVE_PF_YV12__
00037 
00038 #include "mmstools/mmstools.h"
00039 
00040 void mmsfb_blit_blend_ayuv_to_yv12(MMSFBExternalSurfaceBuffer *extbuf, int src_height, int sx, int sy, int sw, int sh,
00041                                    unsigned char *dst, int dst_pitch, int dst_height, int dx, int dy) {
00042     // first time?
00043     static bool firsttime = true;
00044     if (firsttime) {
00045         printf("DISKO: Using accelerated blend AYUV to YV12.\n");
00046         firsttime = false;
00047     }
00048 
00049     // get the first source ptr/pitch
00050     unsigned int *src = (unsigned int *)extbuf->ptr;
00051     int src_pitch = extbuf->pitch;
00052 
00053     // prepare...
00054     int  src_pitch_pix      = src_pitch >> 2;
00055     int dst_pitch_pix       = dst_pitch;
00056     int dst_pitch_pix_half  = dst_pitch_pix >> 1;
00057 
00058     src+= sx + sy * src_pitch_pix;
00059 
00060     // check the surface range
00061     if (dst_pitch_pix - dx < sw - sx)
00062         sw = dst_pitch_pix - dx - sx;
00063     if (dst_height - dy < sh - sy)
00064         sh = dst_height - dy - sy;
00065     if ((sw <= 0)||(sh <= 0))
00066         return;
00067 
00068     unsigned int OLDSRC  = (*src) + 1;
00069     unsigned int old_y;
00070     unsigned int old_u;
00071     unsigned int old_v;
00072 
00073     int  src_pixels = src_pitch_pix * sh;
00074 
00075     // check odd/even
00076     bool odd_left   = (dx & 0x01);
00077     bool odd_top    = (dy & 0x01);
00078     bool odd_right  = ((dx + sw) & 0x01);
00079     bool odd_bottom = ((dy + sh) & 0x01);
00080 
00081     // pointer to the pixel components of the first pixel
00082     unsigned char *dst_y = dst + dx + dy * dst_pitch_pix;
00083     unsigned char *dst_u = dst + dst_pitch_pix * dst_height + dst_pitch_pix_half * (dst_height >> 1) + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00084     unsigned char *dst_v = dst + dst_pitch_pix *  dst_height                                         + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00085 
00086     // offsets to the other three pixels
00087     unsigned int dst_y2_offs = 1;
00088     unsigned int dst_y3_offs = dst_pitch;
00089     unsigned int dst_y4_offs = dst_y3_offs + 1;
00090     unsigned int src2_offs = 1;
00091     unsigned int src3_offs = src_pitch_pix;
00092     unsigned int src4_offs = src3_offs + 1;
00093 
00094     // arithmetic mean
00095     register unsigned int d_u;
00096     register unsigned int d_v;
00097 
00098     // draw odd pixels around the even rectangle
00099     if (odd_top && odd_left) {
00100         // odd top-left pixel
00101         register unsigned int SRC;
00102         register unsigned int A;
00103 
00104         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00105         d_u = (*dst_u) * 3;
00106         d_v = (*dst_v) * 3;
00107 
00108         // calculate my pixel...
00109         MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00110 
00111         // calulate the arithmetic mean
00112         *dst_u = d_u >> 2;
00113         *dst_v = d_v >> 2;
00114     }
00115 
00116     if (odd_top && odd_right) {
00117         // odd top-right pixel
00118         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00119 
00120         // go to the pixel in the current line
00121         src   += sw - 1;
00122         dst_y += sw - 1;
00123         if (odd_left) {
00124             dst_u += sw >> 1;
00125             dst_v += sw >> 1;
00126         }
00127         else {
00128             dst_u += (sw - 1) >> 1;
00129             dst_v += (sw - 1) >> 1;
00130         }
00131 
00132         register unsigned int SRC;
00133         register unsigned int A;
00134 
00135         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00136         d_u = (*dst_u) * 3;
00137         d_v = (*dst_v) * 3;
00138 
00139         // calculate my pixel...
00140         MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00141 
00142         // calulate the arithmetic mean
00143         *dst_u = d_u >> 2;
00144         *dst_v = d_v >> 2;
00145 
00146         // restore the pointers
00147         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00148     }
00149 
00150     if (odd_bottom && odd_left) {
00151         // odd bottom-left pixel
00152         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00153 
00154         // go to the line
00155         src   += src_pitch_pix * (sh-1);
00156         dst_y += dst_pitch_pix * (sh-1);
00157         if (odd_top) {
00158             dst_u += dst_pitch_pix_half * (sh >> 1);
00159             dst_v += dst_pitch_pix_half * (sh >> 1);
00160         }
00161         else {
00162             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00163             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00164         }
00165 
00166         register unsigned int SRC;
00167         register unsigned int A;
00168 
00169         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00170         d_u = (*dst_u) * 3;
00171         d_v = (*dst_v) * 3;
00172 
00173         // calculate my pixel...
00174         MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00175 
00176         // calulate the arithmetic mean
00177         *dst_u = d_u >> 2;
00178         *dst_v = d_v >> 2;
00179 
00180         // restore the pointers
00181         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00182     }
00183 
00184     if (odd_bottom && odd_right) {
00185         // odd bottom-right pixel
00186         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00187 
00188         // go to the line
00189         src   += src_pitch_pix * (sh-1);
00190         dst_y += dst_pitch_pix * (sh-1);
00191         if (odd_top) {
00192             dst_u += dst_pitch_pix_half * (sh >> 1);
00193             dst_v += dst_pitch_pix_half * (sh >> 1);
00194         }
00195         else {
00196             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00197             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00198         }
00199 
00200         // go to the pixel in the current line
00201         src   += sw - 1;
00202         dst_y += sw - 1;
00203         if (odd_left) {
00204             dst_u += sw >> 1;
00205             dst_v += sw >> 1;
00206         }
00207         else {
00208             dst_u += (sw - 1) >> 1;
00209             dst_v += (sw - 1) >> 1;
00210         }
00211 
00212         register unsigned int SRC;
00213         register unsigned int A;
00214 
00215         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00216         d_u = (*dst_u) * 3;
00217         d_v = (*dst_v) * 3;
00218 
00219         // calculate my pixel...
00220         MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00221 
00222         // calulate the arithmetic mean
00223         *dst_u = d_u >> 2;
00224         *dst_v = d_v >> 2;
00225 
00226         // restore the pointers
00227         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00228     }
00229 
00230     if (odd_top) {
00231         // odd top line
00232         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00233 
00234         // calculate start and end
00235         unsigned int *line_end = src + sw;
00236         if (odd_left) {
00237             src++;
00238             dst_y++;
00239             dst_u++;
00240             dst_v++;
00241             line_end--;
00242         }
00243         if (odd_right)
00244             line_end--;
00245 
00246         // through the line
00247         while (src < line_end) {
00248             register unsigned int SRC;
00249             register unsigned int A;
00250 
00251             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00252             d_u = (*dst_u) << 1;
00253             d_v = (*dst_v) << 1;
00254 
00255             // calculate my two pixels...
00256             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00257             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00258 
00259             // calulate the arithmetic mean
00260             *dst_u = d_u >> 2;
00261             *dst_v = d_v >> 2;
00262 
00263             // go to the next two pixels
00264             src+=2;
00265             dst_y+=2;
00266             dst_u++;
00267             dst_v++;
00268         }
00269 
00270         // restore the pointers
00271         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00272     }
00273 
00274     if (odd_bottom) {
00275         // odd bottom line
00276         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00277 
00278         // calculate start and end
00279         src   += src_pitch_pix * (sh-1);
00280         dst_y += dst_pitch_pix * (sh-1);
00281         if (odd_top) {
00282             dst_u += dst_pitch_pix_half * (sh >> 1);
00283             dst_v += dst_pitch_pix_half * (sh >> 1);
00284         }
00285         else {
00286             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00287             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00288         }
00289 
00290         unsigned int *line_end = src + sw;
00291         if (odd_left) {
00292             src++;
00293             dst_y++;
00294             dst_u++;
00295             dst_v++;
00296             line_end--;
00297         }
00298         if (odd_right)
00299             line_end--;
00300 
00301         // through the line
00302         while (src < line_end) {
00303             register unsigned int SRC;
00304             register unsigned int A;
00305 
00306             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00307             d_u = (*dst_u) << 1;
00308             d_v = (*dst_v) << 1;
00309 
00310             // calculate my two pixels...
00311             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00312             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00313 
00314             // calulate the arithmetic mean
00315             *dst_u = d_u >> 2;
00316             *dst_v = d_v >> 2;
00317 
00318             // go to the next two pixels
00319             src+=2;
00320             dst_y+=2;
00321             dst_u++;
00322             dst_v++;
00323         }
00324 
00325         // restore the pointers
00326         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00327     }
00328 
00329     if (odd_left) {
00330         // odd left line
00331         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00332 
00333         // calculate start and end
00334         unsigned int *src_end = src + src_pixels;
00335         int src_pitch_diff    = src_pitch_pix << 1;
00336         int dst_pitch_diff    = dst_pitch_pix << 1;
00337         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00338         if (odd_top) {
00339             src     += src_pitch_pix;
00340             src_end -= src_pitch_pix;
00341             dst_y   += dst_pitch_pix;
00342             dst_u   += dst_pitch_pix_half;
00343             dst_v   += dst_pitch_pix_half;
00344         }
00345         if (odd_bottom)
00346             src_end -= src_pitch_pix;
00347 
00348         // through all lines
00349         while (src < src_end) {
00350             // for the first pixel in the line
00351             register unsigned int SRC;
00352             register unsigned int A;
00353 
00354             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00355             d_u = (*dst_u) << 1;
00356             d_v = (*dst_v) << 1;
00357 
00358             // calculate my two pixels...
00359             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00360             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00361 
00362             // calulate the arithmetic mean
00363             *dst_u = d_u >> 2;
00364             *dst_v = d_v >> 2;
00365 
00366             // go to the next two lines
00367             src   += src_pitch_diff;
00368             dst_y += dst_pitch_diff;
00369             dst_u += dst_pitch_uvdiff;
00370             dst_v += dst_pitch_uvdiff;
00371         }
00372 
00373         // restore the pointers
00374         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00375     }
00376 
00377     if (odd_right) {
00378         // odd right line
00379         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00380 
00381         // calculate start and end
00382         unsigned int *src_end = src + src_pixels;
00383         int src_pitch_diff    = src_pitch_pix << 1;
00384         int dst_pitch_diff    = dst_pitch_pix << 1;
00385         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00386         src   += sw - 1;
00387         dst_y += sw - 1;
00388         if (odd_left) {
00389             dst_u += sw >> 1;
00390             dst_v += sw >> 1;
00391         }
00392         else {
00393             dst_u += (sw - 1) >> 1;
00394             dst_v += (sw - 1) >> 1;
00395         }
00396         if (odd_top) {
00397             src     += src_pitch_pix;
00398             src_end -= src_pitch_pix;
00399             dst_y   += dst_pitch_pix;
00400             dst_u   += dst_pitch_pix_half;
00401             dst_v   += dst_pitch_pix_half;
00402         }
00403         if (odd_bottom)
00404             src_end -= src_pitch_pix;
00405 
00406         // through all lines
00407         while (src < src_end) {
00408             // for the first pixel in the line
00409             register unsigned int SRC;
00410             register unsigned int A;
00411 
00412             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00413             d_u = (*dst_u) << 1;
00414             d_v = (*dst_v) << 1;
00415 
00416             // calculate my two pixels...
00417             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00418             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00419 
00420             // calulate the arithmetic mean
00421             *dst_u = d_u >> 2;
00422             *dst_v = d_v >> 2;
00423 
00424             // go to the next two lines
00425             src   += src_pitch_diff;
00426             dst_y += dst_pitch_diff;
00427             dst_u += dst_pitch_uvdiff;
00428             dst_v += dst_pitch_uvdiff;
00429         }
00430 
00431         // restore the pointers
00432         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00433     }
00434 
00435     // calc even positions...
00436     if (odd_top) {
00437         // odd top
00438         dy++;
00439         sh--;
00440         src+=src_pitch_pix;
00441         src_pixels-=src_pitch_pix;
00442         dst_y+=dst_pitch;
00443         dst_u+=dst_pitch >> 1;
00444         dst_v+=dst_pitch >> 1;
00445     }
00446 
00447     if (odd_bottom) {
00448         // odd bottom
00449         src_height--;
00450         src_pixels-=src_pitch_pix;
00451     }
00452 
00453     if (odd_left) {
00454         // odd left
00455         dx++;
00456         sw--;
00457         src++;
00458         dst_y++;
00459         dst_u++;
00460         dst_v++;
00461     }
00462 
00463     if (odd_right) {
00464         // odd right
00465         sw--;
00466     }
00467 
00468     // now we are even aligned and can go through a optimized loop
00469     ////////////////////////////////////////////////////////////////////////
00470     unsigned int *src_end = src + src_pixels;
00471     int src_pitch_diff = (src_pitch_pix << 1) - sw;
00472     int dst_pitch_diff = (dst_pitch_pix << 1) - sw;
00473     int dst_pitch_uvdiff = (dst_pitch_pix - sw) >> 1;
00474 
00475     // for all lines
00476     while (src < src_end) {
00477         // for all pixels in the line
00478         unsigned int *line_end = src + sw;
00479 
00480         // go through two lines in parallel (square 2x2 pixel)
00481         while (src < line_end) {
00482             register unsigned int SRC;
00483             register unsigned int A;
00484 
00485             // calculate the four pixels...
00486             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u=, d_v=);
00487             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00488             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00489             MMSFB_CONV_BLEND_AYUV_TO_YV12_PIXEL(src[src4_offs], dst_y[dst_y4_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00490 
00491             // calulate the arithmetic mean
00492             *dst_u = d_u >> 2;
00493             *dst_v = d_v >> 2;
00494 
00495             // go to the next two pixels
00496             src  +=2;
00497             dst_y+=2;
00498             dst_u++;
00499             dst_v++;
00500         }
00501 
00502         // go to the next two lines
00503         src   += src_pitch_diff;
00504         dst_y += dst_pitch_diff;
00505         dst_u += dst_pitch_uvdiff;
00506         dst_v += dst_pitch_uvdiff;
00507     }
00508 }
00509 
00510 #endif
00511 #endif

Generated by doxygen