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

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

Generated by doxygen