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

mmsfb_blit_blend_coloralpha_argb_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_ARGB__
00036 #ifdef __HAVE_PF_YV12__
00037 
00038 #include "mmstools/mmstools.h"
00039 
00040 void mmsfb_blit_blend_coloralpha_argb_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                                               unsigned char alpha) {
00043     // check for full alpha value
00044     if (alpha == 0xff) {
00045         // max alpha is specified, so i can ignore it and use faster routine
00046         mmsfb_blit_blend_argb_to_yv12(extbuf, src_height, sx, sy, sw, sh,
00047                                       dst, dst_pitch, dst_height, dx, dy);
00048         return;
00049     }
00050 
00051     // first time?
00052     static bool firsttime = true;
00053     if (firsttime) {
00054         printf("DISKO: Using accelerated blend coloralpha ARGB to YV12.\n");
00055         firsttime = false;
00056     }
00057 
00058     // something to do?
00059     if (!alpha)
00060         // source should blitted full transparent, so leave destination as is
00061         return;
00062 
00063     // get the first source ptr/pitch
00064     unsigned int *src = (unsigned int *)extbuf->ptr;
00065     int src_pitch = extbuf->pitch;
00066 
00067     // prepare...
00068     int  src_pitch_pix      = src_pitch >> 2;
00069     int dst_pitch_pix       = dst_pitch;
00070     int dst_pitch_pix_half  = dst_pitch_pix >> 1;
00071 
00072     src+= sx + sy * src_pitch_pix;
00073 
00074     // check the surface range
00075     if (dst_pitch_pix - dx < sw - sx)
00076         sw = dst_pitch_pix - dx - sx;
00077     if (dst_height - dy < sh - sy)
00078         sh = dst_height - dy - sy;
00079     if ((sw <= 0)||(sh <= 0))
00080         return;
00081 
00082     unsigned int OLDSRC  = (*src) + 1;
00083     unsigned int old_y;
00084     unsigned int old_u;
00085     unsigned int old_v;
00086 
00087     int  src_pixels = src_pitch_pix * sh;
00088 
00089     // check odd/even
00090     bool odd_left   = (dx & 0x01);
00091     bool odd_top    = (dy & 0x01);
00092     bool odd_right  = ((dx + sw) & 0x01);
00093     bool odd_bottom = ((dy + sh) & 0x01);
00094 
00095     // pointer to the pixel components of the first pixel
00096     unsigned char *dst_y = dst + dx + dy * dst_pitch_pix;
00097     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;
00098     unsigned char *dst_v = dst + dst_pitch_pix *  dst_height                                         + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00099 
00100     // offsets to the other three pixels
00101     unsigned int dst_y2_offs = 1;
00102     unsigned int dst_y3_offs = dst_pitch;
00103     unsigned int dst_y4_offs = dst_y3_offs + 1;
00104     unsigned int src2_offs = 1;
00105     unsigned int src3_offs = src_pitch_pix;
00106     unsigned int src4_offs = src3_offs + 1;
00107 
00108     // arithmetic mean
00109     register unsigned int d_u;
00110     register unsigned int d_v;
00111 
00112     // calc alpha
00113     register unsigned int ALPHA = alpha;
00114     ALPHA++;
00115 
00116     // draw odd pixels around the even rectangle
00117     if (odd_top && odd_left) {
00118         // odd top-left pixel
00119         register unsigned int SRC;
00120         register unsigned int A;
00121 
00122         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00123         d_u = (*dst_u) * 3;
00124         d_v = (*dst_v) * 3;
00125 
00126         // calculate my pixel...
00127         MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00128 
00129         // calulate the arithmetic mean
00130         *dst_u = d_u >> 2;
00131         *dst_v = d_v >> 2;
00132     }
00133 
00134     if (odd_top && odd_right) {
00135         // odd top-right pixel
00136         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00137 
00138         // go to the pixel in the current line
00139         src   += sw - 1;
00140         dst_y += sw - 1;
00141         if (odd_left) {
00142             dst_u += sw >> 1;
00143             dst_v += sw >> 1;
00144         }
00145         else {
00146             dst_u += (sw - 1) >> 1;
00147             dst_v += (sw - 1) >> 1;
00148         }
00149 
00150         register unsigned int SRC;
00151         register unsigned int A;
00152 
00153         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00154         d_u = (*dst_u) * 3;
00155         d_v = (*dst_v) * 3;
00156 
00157         // calculate my pixel...
00158         MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00159 
00160         // calulate the arithmetic mean
00161         *dst_u = d_u >> 2;
00162         *dst_v = d_v >> 2;
00163 
00164         // restore the pointers
00165         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00166     }
00167 
00168     if (odd_bottom && odd_left) {
00169         // odd bottom-left pixel
00170         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00171 
00172         // go to the line
00173         src   += src_pitch_pix * (sh-1);
00174         dst_y += dst_pitch_pix * (sh-1);
00175         if (odd_top) {
00176             dst_u += dst_pitch_pix_half * (sh >> 1);
00177             dst_v += dst_pitch_pix_half * (sh >> 1);
00178         }
00179         else {
00180             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00181             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00182         }
00183 
00184         register unsigned int SRC;
00185         register unsigned int A;
00186 
00187         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00188         d_u = (*dst_u) * 3;
00189         d_v = (*dst_v) * 3;
00190 
00191         // calculate my pixel...
00192         MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00193 
00194         // calulate the arithmetic mean
00195         *dst_u = d_u >> 2;
00196         *dst_v = d_v >> 2;
00197 
00198         // restore the pointers
00199         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00200     }
00201 
00202     if (odd_bottom && odd_right) {
00203         // odd bottom-right pixel
00204         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00205 
00206         // go to the line
00207         src   += src_pitch_pix * (sh-1);
00208         dst_y += dst_pitch_pix * (sh-1);
00209         if (odd_top) {
00210             dst_u += dst_pitch_pix_half * (sh >> 1);
00211             dst_v += dst_pitch_pix_half * (sh >> 1);
00212         }
00213         else {
00214             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00215             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00216         }
00217 
00218         // go to the pixel in the current line
00219         src   += sw - 1;
00220         dst_y += sw - 1;
00221         if (odd_left) {
00222             dst_u += sw >> 1;
00223             dst_v += sw >> 1;
00224         }
00225         else {
00226             dst_u += (sw - 1) >> 1;
00227             dst_v += (sw - 1) >> 1;
00228         }
00229 
00230         register unsigned int SRC;
00231         register unsigned int A;
00232 
00233         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00234         d_u = (*dst_u) * 3;
00235         d_v = (*dst_v) * 3;
00236 
00237         // calculate my pixel...
00238         MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00239 
00240         // calulate the arithmetic mean
00241         *dst_u = d_u >> 2;
00242         *dst_v = d_v >> 2;
00243 
00244         // restore the pointers
00245         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00246     }
00247 
00248     if (odd_top) {
00249         // odd top line
00250         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00251 
00252         // calculate start and end
00253         unsigned int *line_end = src + sw;
00254         if (odd_left) {
00255             src++;
00256             dst_y++;
00257             dst_u++;
00258             dst_v++;
00259             line_end--;
00260         }
00261         if (odd_right)
00262             line_end--;
00263 
00264         // through the line
00265         while (src < line_end) {
00266             register unsigned int SRC;
00267             register unsigned int A;
00268 
00269             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00270             d_u = (*dst_u) << 1;
00271             d_v = (*dst_v) << 1;
00272 
00273             // calculate my two pixels...
00274             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00275             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00276 
00277             // calulate the arithmetic mean
00278             *dst_u = d_u >> 2;
00279             *dst_v = d_v >> 2;
00280 
00281             // go to the next two pixels
00282             src+=2;
00283             dst_y+=2;
00284             dst_u++;
00285             dst_v++;
00286         }
00287 
00288         // restore the pointers
00289         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00290     }
00291 
00292     if (odd_bottom) {
00293         // odd bottom line
00294         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00295 
00296         // calculate start and end
00297         src   += src_pitch_pix * (sh-1);
00298         dst_y += dst_pitch_pix * (sh-1);
00299         if (odd_top) {
00300             dst_u += dst_pitch_pix_half * (sh >> 1);
00301             dst_v += dst_pitch_pix_half * (sh >> 1);
00302         }
00303         else {
00304             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00305             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00306         }
00307 
00308         unsigned int *line_end = src + sw;
00309         if (odd_left) {
00310             src++;
00311             dst_y++;
00312             dst_u++;
00313             dst_v++;
00314             line_end--;
00315         }
00316         if (odd_right)
00317             line_end--;
00318 
00319         // through the line
00320         while (src < line_end) {
00321             register unsigned int SRC;
00322             register unsigned int A;
00323 
00324             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00325             d_u = (*dst_u) << 1;
00326             d_v = (*dst_v) << 1;
00327 
00328             // calculate my two pixels...
00329             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00330             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00331 
00332             // calulate the arithmetic mean
00333             *dst_u = d_u >> 2;
00334             *dst_v = d_v >> 2;
00335 
00336             // go to the next two pixels
00337             src+=2;
00338             dst_y+=2;
00339             dst_u++;
00340             dst_v++;
00341         }
00342 
00343         // restore the pointers
00344         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00345     }
00346 
00347     if (odd_left) {
00348         // odd left line
00349         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00350 
00351         // calculate start and end
00352         unsigned int *src_end = src + src_pixels;
00353         int src_pitch_diff    = src_pitch_pix << 1;
00354         int dst_pitch_diff    = dst_pitch_pix << 1;
00355         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00356         if (odd_top) {
00357             src     += src_pitch_pix;
00358             src_end -= src_pitch_pix;
00359             dst_y   += dst_pitch_pix;
00360             dst_u   += dst_pitch_pix_half;
00361             dst_v   += dst_pitch_pix_half;
00362         }
00363         if (odd_bottom)
00364             src_end -= src_pitch_pix;
00365 
00366         // through all lines
00367         while (src < src_end) {
00368             // for the first pixel in the line
00369             register unsigned int SRC;
00370             register unsigned int A;
00371 
00372             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00373             d_u = (*dst_u) << 1;
00374             d_v = (*dst_v) << 1;
00375 
00376             // calculate my two pixels...
00377             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00378             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00379 
00380             // calulate the arithmetic mean
00381             *dst_u = d_u >> 2;
00382             *dst_v = d_v >> 2;
00383 
00384             // go to the next two lines
00385             src   += src_pitch_diff;
00386             dst_y += dst_pitch_diff;
00387             dst_u += dst_pitch_uvdiff;
00388             dst_v += dst_pitch_uvdiff;
00389         }
00390 
00391         // restore the pointers
00392         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00393     }
00394 
00395     if (odd_right) {
00396         // odd right line
00397         MMSFB_CONV_BLEND_ARGB_TO_YV12_PUSHPTR;
00398 
00399         // calculate start and end
00400         unsigned int *src_end = src + src_pixels;
00401         int src_pitch_diff    = src_pitch_pix << 1;
00402         int dst_pitch_diff    = dst_pitch_pix << 1;
00403         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00404         src   += sw - 1;
00405         dst_y += sw - 1;
00406         if (odd_left) {
00407             dst_u += sw >> 1;
00408             dst_v += sw >> 1;
00409         }
00410         else {
00411             dst_u += (sw - 1) >> 1;
00412             dst_v += (sw - 1) >> 1;
00413         }
00414         if (odd_top) {
00415             src     += src_pitch_pix;
00416             src_end -= src_pitch_pix;
00417             dst_y   += dst_pitch_pix;
00418             dst_u   += dst_pitch_pix_half;
00419             dst_v   += dst_pitch_pix_half;
00420         }
00421         if (odd_bottom)
00422             src_end -= src_pitch_pix;
00423 
00424         // through all lines
00425         while (src < src_end) {
00426             // for the first pixel in the line
00427             register unsigned int SRC;
00428             register unsigned int A;
00429 
00430             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00431             d_u = (*dst_u) << 1;
00432             d_v = (*dst_v) << 1;
00433 
00434             // calculate my two pixels...
00435             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00436             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00437 
00438             // calulate the arithmetic mean
00439             *dst_u = d_u >> 2;
00440             *dst_v = d_v >> 2;
00441 
00442             // go to the next two lines
00443             src   += src_pitch_diff;
00444             dst_y += dst_pitch_diff;
00445             dst_u += dst_pitch_uvdiff;
00446             dst_v += dst_pitch_uvdiff;
00447         }
00448 
00449         // restore the pointers
00450         MMSFB_CONV_BLEND_ARGB_TO_YV12_POPPTR;
00451     }
00452 
00453     // calc even positions...
00454     if (odd_top) {
00455         // odd top
00456         dy++;
00457         sh--;
00458         src+=src_pitch_pix;
00459         src_pixels-=src_pitch_pix;
00460         dst_y+=dst_pitch;
00461         dst_u+=dst_pitch >> 1;
00462         dst_v+=dst_pitch >> 1;
00463     }
00464 
00465     if (odd_bottom) {
00466         // odd bottom
00467         src_height--;
00468         src_pixels-=src_pitch_pix;
00469     }
00470 
00471     if (odd_left) {
00472         // odd left
00473         dx++;
00474         sw--;
00475         src++;
00476         dst_y++;
00477         dst_u++;
00478         dst_v++;
00479     }
00480 
00481     if (odd_right) {
00482         // odd right
00483         sw--;
00484     }
00485 
00486     // now we are even aligned and can go through a optimized loop
00487     ////////////////////////////////////////////////////////////////////////
00488     unsigned int *src_end = src + src_pixels;
00489     int src_pitch_diff = (src_pitch_pix << 1) - sw;
00490     int dst_pitch_diff = (dst_pitch_pix << 1) - sw;
00491     int dst_pitch_uvdiff = (dst_pitch_pix - sw) >> 1;
00492 
00493     // for all lines
00494     while (src < src_end) {
00495         // for all pixels in the line
00496         unsigned int *line_end = src + sw;
00497 
00498         // go through two lines in parallel (square 2x2 pixel)
00499         while (src < line_end) {
00500             register unsigned int SRC;
00501             register unsigned int A;
00502 
00503             // calculate the four pixels...
00504             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(*src, *dst_y, *dst_u, *dst_v, d_u=, d_v=);
00505             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src2_offs], dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00506             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src3_offs], dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00507             MMSFB_CONV_BLEND_COLORALPHA_ARGB_TO_YV12_PIXEL(src[src4_offs], dst_y[dst_y4_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00508 
00509             // calulate the arithmetic mean
00510             *dst_u = d_u >> 2;
00511             *dst_v = d_v >> 2;
00512 
00513             // go to the next two pixels
00514             src  +=2;
00515             dst_y+=2;
00516             dst_u++;
00517             dst_v++;
00518         }
00519 
00520         // go to the next two lines
00521         src   += src_pitch_diff;
00522         dst_y += dst_pitch_diff;
00523         dst_u += dst_pitch_uvdiff;
00524         dst_v += dst_pitch_uvdiff;
00525     }
00526 }
00527 
00528 #endif
00529 #endif

Generated by doxygen