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