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

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

Generated by doxygen