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