1 /* Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved. 2 * 3 * redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * this software is provided "as is" and any express or implied 17 * warranties, including, but not limited to, the implied warranties of 18 * merchantability, fitness for a particular purpose and non-infringement 19 * are disclaimed. in no event shall the copyright owner or contributors 20 * be liable for any direct, indirect, incidental, special, exemplary, or 21 * consequential damages (including, but not limited to, procurement of 22 * substitute goods or services; loss of use, data, or profits; or 23 * business interruption) however caused and on any theory of liability, 24 * whether in contract, strict liability, or tort (including negligence 25 * or otherwise) arising in any way out of the use of this software, even 26 * if advised of the possibility of such damage. 27 * 28 */ 29 30 #include <C2DColorConverter.h> 31 #include <stdlib.h> 32 #include <fcntl.h> 33 #include <linux/msm_kgsl.h> 34 #include <sys/ioctl.h> 35 #include <utils/Log.h> 36 #include <dlfcn.h> 37 38 #undef LOG_TAG 39 #define LOG_TAG "C2DColorConvert" 40 #define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1))) 41 #define ALIGN8K 8192 42 #define ALIGN4K 4096 43 #define ALIGN2K 2048 44 #define ALIGN128 128 45 #define ALIGN32 32 46 #define ALIGN16 16 47 48 //----------------------------------------------------- 49 namespace android { 50 51 class C2DColorConverter : public C2DColorConverterBase { 52 53 public: 54 C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags,size_t srcStride); 55 int32_t getBuffReq(int32_t port, C2DBuffReq *req); 56 int32_t dumpOutput(char * filename, char mode); 57 protected: 58 virtual ~C2DColorConverter(); 59 virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData); 60 61 private: 62 bool isYUVSurface(ColorConvertFormat format); 63 void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource); 64 C2D_STATUS updateYUVSurfaceDef(int fd, void *base, void * data, bool isSource); 65 C2D_STATUS updateRGBSurfaceDef(int fd, void * data, bool isSource); 66 uint32_t getC2DFormat(ColorConvertFormat format); 67 size_t calcStride(ColorConvertFormat format, size_t width); 68 size_t calcYSize(ColorConvertFormat format, size_t width, size_t height); 69 size_t calcSize(ColorConvertFormat format, size_t width, size_t height); 70 void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen); 71 bool unmapGPUAddr(unsigned long gAddr); 72 size_t calcLumaAlign(ColorConvertFormat format); 73 size_t calcSizeAlign(ColorConvertFormat format); 74 C2DBytesPerPixel calcBytesPerPixel(ColorConvertFormat format); 75 76 void *mC2DLibHandle; 77 LINK_c2dCreateSurface mC2DCreateSurface; 78 LINK_c2dUpdateSurface mC2DUpdateSurface; 79 LINK_c2dReadSurface mC2DReadSurface; 80 LINK_c2dDraw mC2DDraw; 81 LINK_c2dFlush mC2DFlush; 82 LINK_c2dFinish mC2DFinish; 83 LINK_c2dWaitTimestamp mC2DWaitTimestamp; 84 LINK_c2dDestroySurface mC2DDestroySurface; 85 LINK_c2dMapAddr mC2DMapAddr; 86 LINK_c2dUnMapAddr mC2DUnMapAddr; 87 88 uint32_t mSrcSurface, mDstSurface; 89 void * mSrcSurfaceDef; 90 void * mDstSurfaceDef; 91 92 C2D_OBJECT mBlit; 93 size_t mSrcWidth; 94 size_t mSrcHeight; 95 size_t mSrcStride; 96 size_t mDstWidth; 97 size_t mDstHeight; 98 size_t mSrcSize; 99 size_t mDstSize; 100 size_t mSrcYSize; 101 size_t mDstYSize; 102 enum ColorConvertFormat mSrcFormat; 103 enum ColorConvertFormat mDstFormat; 104 int32_t mFlags; 105 106 int mError; 107 }; 108 109 C2DColorConverter::C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride) 110 { 111 mError = 0; 112 mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW); 113 if (!mC2DLibHandle) { 114 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); 115 mError = -1; 116 return; 117 } 118 mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface"); 119 mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface"); 120 mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface"); 121 mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw"); 122 mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush"); 123 mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish"); 124 mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp"); 125 mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface"); 126 mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr"); 127 mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr"); 128 129 if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface 130 || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp 131 || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) { 132 ALOGE("%s: dlsym ERROR", __FUNCTION__); 133 mError = -1; 134 return; 135 } 136 137 mSrcWidth = srcWidth; 138 mSrcHeight = srcHeight; 139 mSrcStride = srcStride;; 140 mDstWidth = dstWidth; 141 mDstHeight = dstHeight; 142 mSrcFormat = srcFormat; 143 mDstFormat = dstFormat; 144 mSrcSize = calcSize(srcFormat, srcWidth, srcHeight); 145 mDstSize = calcSize(dstFormat, dstWidth, dstHeight); 146 mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight); 147 mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight); 148 149 mFlags = flags; // can be used for rotation 150 151 mSrcSurfaceDef = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true); 152 mDstSurfaceDef = getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false); 153 154 memset((void*)&mBlit,0,sizeof(C2D_OBJECT)); 155 mBlit.source_rect.x = 0 << 16; 156 mBlit.source_rect.y = 0 << 16; 157 mBlit.source_rect.width = srcWidth << 16; 158 mBlit.source_rect.height = srcHeight << 16; 159 mBlit.target_rect.x = 0 << 16; 160 mBlit.target_rect.y = 0 << 16; 161 mBlit.target_rect.width = dstWidth << 16; 162 mBlit.target_rect.height = dstHeight << 16; 163 mBlit.config_mask = C2D_ALPHA_BLEND_NONE | C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | C2D_TARGET_RECT_BIT; 164 mBlit.surface_id = mSrcSurface; 165 } 166 167 C2DColorConverter::~C2DColorConverter() 168 { 169 if (mError) { 170 if (mC2DLibHandle) { 171 dlclose(mC2DLibHandle); 172 } 173 return; 174 } 175 176 mC2DDestroySurface(mDstSurface); 177 mC2DDestroySurface(mSrcSurface); 178 179 if (mSrcSurfaceDef) { 180 free(mSrcSurfaceDef); 181 } 182 183 if (mDstSurfaceDef) { 184 free(mDstSurfaceDef); 185 } 186 187 dlclose(mC2DLibHandle); 188 } 189 190 int C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData) 191 { 192 C2D_STATUS ret; 193 194 if (mError) { 195 ALOGE("C2D library initialization failed\n"); 196 return mError; 197 } 198 199 if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) { 200 ALOGE("Incorrect input parameters\n"); 201 return -1; 202 } 203 204 if (isYUVSurface(mSrcFormat)) { 205 ret = updateYUVSurfaceDef(srcFd, srcBase, srcData, true); 206 } else { 207 ret = updateRGBSurfaceDef(srcFd, srcData, true); 208 } 209 210 if (ret != C2D_STATUS_OK) { 211 ALOGE("Update src surface def failed\n"); 212 return -ret; 213 } 214 215 if (isYUVSurface(mDstFormat)) { 216 ret = updateYUVSurfaceDef(dstFd, dstBase, dstData, false); 217 } else { 218 ret = updateRGBSurfaceDef(dstFd, dstData, false); 219 } 220 221 if (ret != C2D_STATUS_OK) { 222 ALOGE("Update dst surface def failed\n"); 223 return -ret; 224 } 225 226 mBlit.surface_id = mSrcSurface; 227 ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1); 228 mC2DFinish(mDstSurface); 229 230 bool unmappedSrcSuccess; 231 if (isYUVSurface(mSrcFormat)) { 232 unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0); 233 } else { 234 unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys); 235 } 236 237 bool unmappedDstSuccess; 238 if (isYUVSurface(mDstFormat)) { 239 unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0); 240 } else { 241 unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef)->phys); 242 } 243 244 if (ret != C2D_STATUS_OK) { 245 ALOGE("C2D Draw failed\n"); 246 return -ret; //c2d err values are positive 247 } else { 248 if (!unmappedSrcSuccess || !unmappedDstSuccess) { 249 ALOGE("unmapping GPU address failed\n"); 250 return -1; 251 } 252 return ret; 253 } 254 } 255 256 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format) 257 { 258 switch (format) { 259 case YCbCr420Tile: 260 case YCbCr420SP: 261 case YCbCr420P: 262 case YCrCb420P: 263 case NV12_2K: 264 case NV12_128m: 265 return true; 266 case RGB565: 267 case RGBA8888: 268 default: 269 return false; 270 } 271 } 272 273 void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource) 274 { 275 if (isYUVSurface(format)) { 276 C2D_YUV_SURFACE_DEF * surfaceDef = (C2D_YUV_SURFACE_DEF *)malloc(sizeof(C2D_YUV_SURFACE_DEF)); 277 memset(surfaceDef, 0x0, sizeof(C2D_YUV_SURFACE_DEF)); 278 surfaceDef->format = getC2DFormat(format); 279 surfaceDef->width = width; 280 surfaceDef->height = height; 281 surfaceDef->plane0 = (void *)0xaaaaaaaa; 282 surfaceDef->phys0 = (void *)0xaaaaaaaa; 283 surfaceDef->stride0 = calcStride(format, width); 284 surfaceDef->plane1 = (void *)0xaaaaaaaa; 285 surfaceDef->phys1 = (void *)0xaaaaaaaa; 286 surfaceDef->stride1 = calcStride(format, width); 287 288 if (format == YCbCr420P || 289 format == YCrCb420P) { 290 printf("half stride for Cb Cr planes \n"); 291 surfaceDef->stride1 = calcStride(format, width) / 2; 292 surfaceDef->phys2 = (void *)0xaaaaaaaa; 293 surfaceDef->stride2 = calcStride(format, width) / 2; 294 } 295 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET, 296 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), 297 &(*surfaceDef)); 298 return ((void *)surfaceDef); 299 } else { 300 C2D_RGB_SURFACE_DEF * surfaceDef = (C2D_RGB_SURFACE_DEF *)malloc(sizeof(C2D_RGB_SURFACE_DEF)); 301 memset(surfaceDef, 0x0, sizeof(C2D_RGB_SURFACE_DEF)); 302 surfaceDef->format = getC2DFormat(format); 303 surfaceDef->width = width; 304 surfaceDef->height = height; 305 surfaceDef->buffer = (void *)0xaaaaaaaa; 306 surfaceDef->phys = (void *)0xaaaaaaaa; 307 surfaceDef->stride = calcStride(format, width); 308 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET, 309 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), 310 &(*surfaceDef)); 311 return ((void *)surfaceDef); 312 } 313 } 314 315 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(int fd, void *base, void *data, bool isSource) 316 { 317 if (isSource) { 318 C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef; 319 srcSurfaceDef->plane0 = data; 320 srcSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mSrcSize) + ((uint8_t *)data - (uint8_t *)base); 321 srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize; 322 srcSurfaceDef->phys1 = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize; 323 srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4; 324 srcSurfaceDef->phys2 = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4; 325 326 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE, 327 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), 328 &(*srcSurfaceDef)); 329 } else { 330 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef; 331 dstSurfaceDef->plane0 = data; 332 dstSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mDstSize) + ((uint8_t *)data - (uint8_t *)base); 333 dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize; 334 dstSurfaceDef->phys1 = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize; 335 dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4; 336 dstSurfaceDef->phys2 = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4; 337 338 return mC2DUpdateSurface(mDstSurface, C2D_TARGET, 339 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), 340 &(*dstSurfaceDef)); 341 } 342 } 343 344 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(int fd, void * data, bool isSource) 345 { 346 if (isSource) { 347 C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef; 348 srcSurfaceDef->buffer = data; 349 srcSurfaceDef->phys = getMappedGPUAddr(fd, data, mSrcSize); 350 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE, 351 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), 352 &(*srcSurfaceDef)); 353 } else { 354 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef; 355 dstSurfaceDef->buffer = data; 356 ALOGV("dstSurfaceDef->buffer = %p\n", data); 357 dstSurfaceDef->phys = getMappedGPUAddr(fd, data, mDstSize); 358 return mC2DUpdateSurface(mDstSurface, C2D_TARGET, 359 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), 360 &(*dstSurfaceDef)); 361 } 362 } 363 364 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format) 365 { 366 switch (format) { 367 case RGB565: 368 return C2D_COLOR_FORMAT_565_RGB; 369 case RGBA8888: 370 return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED; 371 case YCbCr420Tile: 372 return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED); 373 case YCbCr420SP: 374 case NV12_2K: 375 case NV12_128m: 376 return C2D_COLOR_FORMAT_420_NV12; 377 case YCbCr420P: 378 return C2D_COLOR_FORMAT_420_I420; 379 case YCrCb420P: 380 return C2D_COLOR_FORMAT_420_YV12; 381 default: 382 ALOGE("Format not supported , %d\n", format); 383 return -1; 384 } 385 } 386 387 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width) 388 { 389 switch (format) { 390 case RGB565: 391 return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice 392 case RGBA8888: 393 if (mSrcStride) 394 return mSrcStride * 4; 395 else 396 return ALIGN(width, ALIGN32) * 4; 397 case YCbCr420Tile: 398 return ALIGN(width, ALIGN128); 399 case YCbCr420SP: 400 return ALIGN(width, ALIGN16); 401 case NV12_2K: 402 return ALIGN(width, ALIGN16); 403 case NV12_128m: 404 return ALIGN(width, ALIGN128); 405 case YCbCr420P: 406 return width; 407 case YCrCb420P: 408 return ALIGN(width, ALIGN16); 409 default: 410 return 0; 411 } 412 } 413 414 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height) 415 { 416 switch (format) { 417 case YCbCr420SP: 418 return (ALIGN(width, ALIGN16) * height); 419 case YCbCr420P: 420 return width * height; 421 case YCrCb420P: 422 return ALIGN(width, ALIGN16) * height; 423 case YCbCr420Tile: 424 return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K); 425 case NV12_2K: { 426 size_t alignedw = ALIGN(width, ALIGN16); 427 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K); 428 return lumaSize; 429 } 430 case NV12_128m: 431 return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32); 432 default: 433 return 0; 434 } 435 } 436 437 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height) 438 { 439 int32_t alignedw = 0; 440 int32_t alignedh = 0; 441 int32_t size = 0; 442 443 switch (format) { 444 case RGB565: 445 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 2; 446 size = ALIGN(size, ALIGN4K); 447 break; 448 case RGBA8888: 449 if (mSrcStride) 450 size = mSrcStride * ALIGN(height, ALIGN32) * 4; 451 else 452 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 4; 453 size = ALIGN(size, ALIGN4K); 454 break; 455 case YCbCr420SP: 456 alignedw = ALIGN(width, ALIGN16); 457 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K); 458 break; 459 case YCbCr420P: 460 size = ALIGN((width * height * 3 / 2), ALIGN4K); 461 break; 462 case YCrCb420P: 463 alignedw = ALIGN(width, ALIGN16); 464 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K); 465 break; 466 case YCbCr420Tile: 467 alignedw = ALIGN(width, ALIGN128); 468 alignedh = ALIGN(height, ALIGN32); 469 size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K); 470 break; 471 case NV12_2K: { 472 alignedw = ALIGN(width, ALIGN16); 473 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K); 474 size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K); 475 size = ALIGN(lumaSize + chromaSize, ALIGN4K); 476 ALOGV("NV12_2k, width = %d, height = %d, size = %d", width, height, size); 477 } 478 break; 479 case NV12_128m: 480 alignedw = ALIGN(width, ALIGN128); 481 alignedh = ALIGN(height, ALIGN32); 482 size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K); 483 break; 484 default: 485 break; 486 } 487 return size; 488 } 489 /* 490 * Tells GPU to map given buffer and returns a physical address of mapped buffer 491 */ 492 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen) 493 { 494 C2D_STATUS status; 495 void *gpuaddr = NULL; 496 497 status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION, 498 &gpuaddr); 499 if (status != C2D_STATUS_OK) { 500 ALOGE("c2dMapAddr failed: status %d fd %d ptr %p len %d flags %d\n", 501 status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION); 502 return NULL; 503 } 504 ALOGV("c2d mapping created: gpuaddr %p fd %d ptr %p len %d\n", 505 gpuaddr, bufFD, bufPtr, bufLen); 506 507 return gpuaddr; 508 } 509 510 bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr) 511 { 512 513 C2D_STATUS status = mC2DUnMapAddr((void*)gAddr); 514 515 if (status != C2D_STATUS_OK) 516 ALOGE("c2dUnMapAddr failed: status %d gpuaddr %08lx\n", status, gAddr); 517 518 return (status == C2D_STATUS_OK); 519 } 520 521 int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) { 522 if (!req) return -1; 523 524 if (port != C2D_INPUT && port != C2D_OUTPUT) return -1; 525 526 memset(req, 0, sizeof(C2DBuffReq)); 527 if (port == C2D_INPUT) { 528 req->width = mSrcWidth; 529 req->height = mSrcHeight; 530 req->stride = calcStride(mSrcFormat, mSrcWidth); 531 req->sliceHeight = mSrcHeight; 532 req->lumaAlign = calcLumaAlign(mSrcFormat); 533 req->sizeAlign = calcSizeAlign(mSrcFormat); 534 req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight); 535 req->bpp = calcBytesPerPixel(mSrcFormat); 536 ALOGV("input req->size = %d\n", req->size); 537 } else if (port == C2D_OUTPUT) { 538 req->width = mDstWidth; 539 req->height = mDstHeight; 540 req->stride = calcStride(mDstFormat, mDstWidth); 541 req->sliceHeight = mDstHeight; 542 req->lumaAlign = calcLumaAlign(mDstFormat); 543 req->sizeAlign = calcSizeAlign(mDstFormat); 544 req->size = calcSize(mDstFormat, mDstWidth, mDstHeight); 545 req->bpp = calcBytesPerPixel(mDstFormat); 546 ALOGV("output req->size = %d\n", req->size); 547 } 548 return 0; 549 } 550 551 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) { 552 if (!isYUVSurface(format)) return 1; //no requirement 553 554 switch (format) { 555 case NV12_2K: 556 return ALIGN2K; 557 case NV12_128m: 558 case YCbCr420SP: //OR NV12 559 case YCbCr420P: 560 return 1; 561 default: 562 ALOGE("unknown format passed for luma alignment number"); 563 return 1; 564 } 565 } 566 567 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) { 568 if (!isYUVSurface(format)) return 1; //no requirement 569 570 switch (format) { 571 case YCbCr420SP: //OR NV12 572 case YCbCr420P: 573 case NV12_2K: 574 case NV12_128m: 575 return ALIGN4K; 576 default: 577 ALOGE("unknown format passed for size alignment number"); 578 return 1; 579 } 580 } 581 582 C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) { 583 C2DBytesPerPixel bpp; 584 bpp.numerator = 0; 585 bpp.denominator = 1; 586 587 switch (format) { 588 case RGB565: 589 bpp.numerator = 2; 590 break; 591 case RGBA8888: 592 bpp.numerator = 4; 593 break; 594 case YCbCr420SP: 595 case YCbCr420P: 596 case YCrCb420P: 597 case YCbCr420Tile: 598 case NV12_2K: 599 case NV12_128m: 600 bpp.numerator = 3; 601 bpp.denominator = 2; 602 break; 603 default: 604 break; 605 } 606 return bpp; 607 } 608 609 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) { 610 int fd; 611 size_t stride, sliceHeight; 612 if (!filename) return -1; 613 614 int flags = O_RDWR | O_CREAT; 615 if (mode == 'a') { 616 flags |= O_APPEND; 617 } 618 619 if ((fd = open(filename, flags)) < 0) { 620 ALOGE("open dump file failed w/ errno %s", strerror(errno)); 621 return -1; 622 } 623 624 int ret = 0; 625 if (isYUVSurface(mDstFormat)) { 626 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef; 627 uint8_t * base = (uint8_t *)dstSurfaceDef->plane0; 628 stride = dstSurfaceDef->stride0; 629 sliceHeight = dstSurfaceDef->height; 630 /* dump luma */ 631 for (size_t i = 0; i < sliceHeight; i++) { 632 ret = write(fd, base, mDstWidth); //will work only for the 420 ones 633 if (ret < 0) goto cleanup; 634 base += stride; 635 } 636 637 if (mDstFormat == YCbCr420P || 638 mDstFormat == YCrCb420P) { 639 printf("Dump Cb and Cr separately for Planar\n"); 640 //dump Cb/Cr 641 base = (uint8_t *)dstSurfaceDef->plane1; 642 stride = dstSurfaceDef->stride1; 643 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones 644 ret = write(fd, base, mDstWidth/2); 645 if (ret < 0) goto cleanup; 646 base += stride; 647 } 648 649 //dump Cr/Cb 650 base = (uint8_t *)dstSurfaceDef->plane2; 651 stride = dstSurfaceDef->stride2; 652 653 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones 654 ret = write(fd, base, mDstWidth/2); 655 if (ret < 0) goto cleanup; 656 base += stride; 657 } 658 659 } else { 660 /* dump chroma */ 661 base = (uint8_t *)dstSurfaceDef->plane1; 662 stride = dstSurfaceDef->stride1; 663 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones 664 ret = write(fd, base, mDstWidth); 665 if (ret < 0) goto cleanup; 666 base += stride; 667 } 668 } 669 } else { 670 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef; 671 uint8_t * base = (uint8_t *)dstSurfaceDef->buffer; 672 stride = dstSurfaceDef->stride; 673 sliceHeight = dstSurfaceDef->height; 674 675 printf("rgb surface base is %p", base); 676 printf("rgb surface dumpsslice height is %lu\n", (unsigned long)sliceHeight); 677 printf("rgb surface dump stride is %lu\n", (unsigned long)stride); 678 679 int bpp = 1; //bytes per pixel 680 if (mDstFormat == RGB565) { 681 bpp = 2; 682 } else if (mDstFormat == RGBA8888) { 683 bpp = 4; 684 } 685 686 int count = 0; 687 for (size_t i = 0; i < sliceHeight; i++) { 688 ret = write(fd, base, mDstWidth*bpp); 689 if (ret < 0) { 690 printf("write failed, count = %d\n", count); 691 goto cleanup; 692 } 693 base += stride; 694 count += stride; 695 } 696 } 697 cleanup: 698 if (ret < 0) { 699 ALOGE("file write failed w/ errno %s", strerror(errno)); 700 } 701 close(fd); 702 return ret < 0 ? ret : 0; 703 } 704 705 extern "C" C2DColorConverterBase* createC2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride) 706 { 707 return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags, srcStride); 708 } 709 710 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC) 711 { 712 delete C2DCC; 713 } 714 715 } 716