1 /* Copyright (c) 2012 - 2017, 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 <pthread.h> // pthread_mutex_*
32
C2DColorConverter()33 C2DColorConverter::C2DColorConverter()
34 : mC2DLibHandle(NULL),
35 mAdrenoUtilsHandle(NULL)
36 {
37
38 enabled = true;
39 mSrcSurface = 0;
40 mDstSurface = 0;
41
42 mSrcWidth = 0;
43 mSrcHeight = 0;
44 mSrcStride = 0;
45 mDstWidth = 0;
46 mDstHeight = 0;
47 mSrcFormat = NO_COLOR_FORMAT;
48 mDstFormat = NO_COLOR_FORMAT;
49 mSrcSurfaceDef = NULL;
50 mDstSurfaceDef = NULL;
51
52 mConversionNeeded = false;
53
54 pthread_mutex_init(&mLock, NULL);
55
56 mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW);
57 if (!mC2DLibHandle) {
58 ALOGE("%s: ERROR: could not dlopen libc2d2.so: %s. C2D is disabled.",
59 __FUNCTION__, dlerror());
60 enabled = false;
61 return;
62 }
63 mAdrenoUtilsHandle = dlopen("libadreno_utils.so", RTLD_NOW);
64 if (!mAdrenoUtilsHandle) {
65 ALOGE("%s: ERROR: could not dlopen libadreno_utils.so: %s.. C2D is disabled.",
66 __FUNCTION__, dlerror());
67 enabled = false;
68 return;
69 }
70
71 mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface");
72 mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface");
73 mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface");
74 mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw");
75 mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush");
76 mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish");
77 mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp");
78 mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface");
79 mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr");
80 mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr");
81
82 if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface
83 || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp
84 || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) {
85 ALOGE("%s: dlsym ERROR. C2D is disabled. mC2DCreateSurface[%p] mC2DUpdateSurface[%p] "
86 "mC2DReadSurface[%p] mC2DDraw[%p] mC2DFlush[%p] mC2DFinish[%p] mC2DWaitTimestamp[%p] "
87 "mC2DDestroySurface[%p] mC2DMapAddr[%p] mC2DUnMapAddr[%p]", __FUNCTION__,
88 mC2DCreateSurface, mC2DUpdateSurface, mC2DReadSurface, mC2DDraw, mC2DFlush, mC2DFinish,
89 mC2DWaitTimestamp, mC2DDestroySurface, mC2DMapAddr, mC2DUnMapAddr);
90 enabled = false;
91 return;
92 }
93
94 mAdrenoComputeFmtAlignedWidthAndHeight = (LINK_adreno_compute_fmt_aligned_width_and_height)dlsym(mAdrenoUtilsHandle, "compute_fmt_aligned_width_and_height");
95 if (!mAdrenoComputeFmtAlignedWidthAndHeight) {
96 ALOGE("%s: dlsym compute_aligned_width_and_height ERROR. C2D is disabled.", __FUNCTION__);
97 enabled = false;
98 return;
99 }
100 }
101
~C2DColorConverter()102 C2DColorConverter::~C2DColorConverter()
103 {
104 if (enabled) {
105
106 if (mDstSurface) {
107 mC2DDestroySurface(mDstSurface);
108 mDstSurface = 0;
109 }
110 if (mSrcSurface) {
111 mC2DDestroySurface(mSrcSurface);
112 mSrcSurface = 0;
113 }
114
115 if (mSrcSurfaceDef) {
116 if (isYUVSurface(mSrcFormat)) {
117 delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
118 } else {
119 delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
120 }
121 }
122
123 if (mDstSurfaceDef) {
124 if (isYUVSurface(mDstFormat)) {
125 delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
126 } else {
127 delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef);
128 }
129 }
130 mSrcSurfaceDef = NULL;
131 mDstSurfaceDef = NULL;
132 }
133
134 if (mC2DLibHandle) {
135 dlclose(mC2DLibHandle);
136 }
137 if (mAdrenoUtilsHandle) {
138 dlclose(mAdrenoUtilsHandle);
139 }
140
141 }
142
isPropChanged(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)143 bool C2DColorConverter::isPropChanged(size_t srcWidth, size_t srcHeight, size_t dstWidth,
144 size_t dstHeight, ColorConvertFormat srcFormat,
145 ColorConvertFormat dstFormat, int32_t flags,
146 size_t srcStride)
147 {
148 return (mSrcWidth != srcWidth ||
149 mSrcHeight != srcHeight ||
150 mDstWidth != dstWidth ||
151 mDstHeight != dstHeight ||
152 mSrcFormat != srcFormat ||
153 mDstFormat != dstFormat ||
154 mSrcStride != srcStride ||
155 (mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) !=
156 (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED));
157 }
158
setResolution(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)159 bool C2DColorConverter::setResolution(size_t srcWidth, size_t srcHeight,
160 size_t dstWidth, size_t dstHeight,
161 ColorConvertFormat srcFormat,
162 ColorConvertFormat dstFormat,
163 int32_t flags, size_t srcStride)
164 {
165 int32_t retval = -1;
166 if (enabled) {
167 pthread_mutex_lock(&mLock);
168 mSrcWidth = srcWidth;
169 mSrcHeight = srcHeight;
170 mSrcStride = srcStride;
171 mDstWidth = dstWidth;
172 mDstHeight = dstHeight;
173 mSrcFormat = srcFormat;
174 mDstFormat = dstFormat;
175 mSrcSize = calcSize(srcFormat, srcWidth, srcHeight);
176 mDstSize = calcSize(dstFormat, dstWidth, dstHeight);
177 mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight);
178 mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight);
179
180 mFlags = flags; // can be used for rotation
181
182 retval = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true);
183 retval |= getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false);
184
185 if (retval == 0) {
186 memset((void*)&mBlit,0,sizeof(C2D_OBJECT));
187 mBlit.source_rect.x = 0 << 16;
188 mBlit.source_rect.y = 0 << 16;
189 mBlit.source_rect.width = srcWidth << 16;
190 mBlit.source_rect.height = srcHeight << 16;
191 mBlit.target_rect.x = 0 << 16;
192 mBlit.target_rect.y = 0 << 16;
193 mBlit.target_rect.width = dstWidth << 16;
194 mBlit.target_rect.height = dstHeight << 16;
195 mBlit.config_mask = C2D_ALPHA_BLEND_NONE |
196 C2D_NO_BILINEAR_BIT |
197 C2D_NO_ANTIALIASING_BIT |
198 C2D_TARGET_RECT_BIT;
199 mBlit.surface_id = mSrcSurface;
200 }
201
202 pthread_mutex_unlock(&mLock);
203 }
204
205 return retval == 0? true:false;
206 }
207
208
convertC2D(int srcFd,void * srcBase,void * srcData,int dstFd,void * dstBase,void * dstData)209 bool C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData,
210 int dstFd, void *dstBase, void * dstData)
211 {
212 C2D_STATUS ret;
213 uint8_t *srcMappedGpuAddr = nullptr;
214 uint8_t *dstMappedGpuAddr = nullptr;
215 bool status = false;
216
217 if (enabled) {
218 pthread_mutex_lock(&mLock);
219 if (srcFd < 0 || dstFd < 0
220 || srcData == NULL || dstData == NULL
221 || srcBase == NULL || dstBase == NULL) {
222 ALOGE("%s: Color conversion failed. Incorrect input parameters", __FUNCTION__);
223 status = false;
224 } else {
225
226 srcMappedGpuAddr = (uint8_t *)getMappedGPUAddr(srcFd, srcData, mSrcSize);
227 if (!srcMappedGpuAddr) {
228 pthread_mutex_unlock(&mLock);
229 return false;
230 }
231
232 if (isYUVSurface(mSrcFormat)) {
233 ret = updateYUVSurfaceDef(srcMappedGpuAddr, srcBase, srcData, true);
234 } else {
235 ret = updateRGBSurfaceDef(srcMappedGpuAddr, srcData, true);
236 }
237
238 if (ret == C2D_STATUS_OK) {
239
240 dstMappedGpuAddr = (uint8_t *)getMappedGPUAddr(dstFd, dstData, mDstSize);
241 if (!dstMappedGpuAddr) {
242 unmapGPUAddr((unsigned long)srcMappedGpuAddr);
243 pthread_mutex_unlock(&mLock);
244 return false;
245 }
246
247 if (isYUVSurface(mDstFormat)) {
248 ret = updateYUVSurfaceDef(dstMappedGpuAddr, dstBase, dstData, false);
249 } else {
250 ret = updateRGBSurfaceDef(dstMappedGpuAddr, dstData, false);
251 }
252
253 if (ret == C2D_STATUS_OK) {
254
255 mBlit.surface_id = mSrcSurface;
256 ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1);
257 mC2DFinish(mDstSurface);
258
259 if (ret == C2D_STATUS_OK) {
260 bool unmappedSrcSuccess;
261 unmappedSrcSuccess = unmapGPUAddr((unsigned long)srcMappedGpuAddr);
262
263 bool unmappedDstSuccess;
264 unmappedDstSuccess = unmapGPUAddr((unsigned long)dstMappedGpuAddr);
265
266 if (!unmappedSrcSuccess || !unmappedDstSuccess) {
267 ALOGE("%s: unmapping GPU address failed (%d:%d)", __FUNCTION__,
268 unmappedSrcSuccess, unmappedDstSuccess);
269 status = false;
270 } else {
271 status = true;
272 }
273 } else {
274 ALOGE("%s: C2D Draw failed (%d)", __FUNCTION__, ret);
275 status = false;
276 }
277 } else {
278 ALOGE("%s: Update dst surface def failed (%d)", __FUNCTION__, ret);
279 unmapGPUAddr((unsigned long)srcMappedGpuAddr);
280 unmapGPUAddr((unsigned long)dstMappedGpuAddr);
281 status = false;
282 }
283 } else {
284 ALOGE("%s: Update src surface def failed (%d)", __FUNCTION__, ret);
285 unmapGPUAddr((unsigned long)srcMappedGpuAddr);
286 status = false;
287 }
288 }
289
290 pthread_mutex_unlock(&mLock);
291 }
292
293 return status;
294 }
295
isYUVSurface(ColorConvertFormat format)296 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format)
297 {
298 switch (format) {
299 case YCbCr420Tile:
300 case YCbCr420SP:
301 case YCbCr420P:
302 case YCrCb420P:
303 case NV12_2K:
304 case NV12_128m:
305 case NV12_UBWC:
306 case TP10_UBWC:
307 return true;
308 default:
309 return false;
310 }
311 }
312
getDummySurfaceDef(ColorConvertFormat format,size_t width,size_t height,bool isSource)313 int32_t C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format,
314 size_t width, size_t height,
315 bool isSource)
316 {
317 void *surfaceDef = NULL;
318 C2D_SURFACE_TYPE hostSurfaceType;
319 C2D_STATUS ret;
320
321 if (isSource){
322 if (mSrcSurface) {
323 mC2DDestroySurface(mSrcSurface);
324 mSrcSurface = 0;
325 }
326 } else if (mDstSurface) {
327 mC2DDestroySurface(mDstSurface);
328 mDstSurface = 0;
329 }
330
331 if (isYUVSurface(format)) {
332 C2D_YUV_SURFACE_DEF **surfaceYUVDef = (C2D_YUV_SURFACE_DEF **)
333 (isSource ? &mSrcSurfaceDef : &mDstSurfaceDef);
334 if (*surfaceYUVDef == NULL) {
335 *surfaceYUVDef = (C2D_YUV_SURFACE_DEF *)
336 calloc(1, sizeof(C2D_YUV_SURFACE_DEF));
337 if (*surfaceYUVDef == NULL) {
338 ALOGE("%s: surfaceYUVDef allocation failed", __FUNCTION__);
339 return -1;
340 }
341 } else {
342 memset(*surfaceYUVDef, 0, sizeof(C2D_YUV_SURFACE_DEF));
343 }
344 (*surfaceYUVDef)->format = getC2DFormat(format);
345 (*surfaceYUVDef)->width = width;
346 (*surfaceYUVDef)->height = height;
347 (*surfaceYUVDef)->plane0 = (void *)0xaaaaaaaa;
348 (*surfaceYUVDef)->phys0 = (void *)0xaaaaaaaa;
349 (*surfaceYUVDef)->stride0 = calcStride(format, width);
350 (*surfaceYUVDef)->plane1 = (void *)0xaaaaaaaa;
351 (*surfaceYUVDef)->phys1 = (void *)0xaaaaaaaa;
352 (*surfaceYUVDef)->stride1 = calcStride(format, width);
353 (*surfaceYUVDef)->stride2 = calcStride(format, width);
354 (*surfaceYUVDef)->phys2 = NULL;
355 (*surfaceYUVDef)->plane2 = NULL;
356
357 if (format == YCbCr420P ||
358 format == YCrCb420P) {
359 ALOGI("%s: half stride for Cb Cr planes \n", __FUNCTION__);
360 (*surfaceYUVDef)->stride1 = calcStride(format, width) / 2;
361 (*surfaceYUVDef)->phys2 = (void *)0xaaaaaaaa;
362 (*surfaceYUVDef)->stride2 = calcStride(format, width) / 2;
363 }
364
365 surfaceDef = *surfaceYUVDef;
366 hostSurfaceType = C2D_SURFACE_YUV_HOST;
367 } else {
368 C2D_RGB_SURFACE_DEF **surfaceRGBDef = (C2D_RGB_SURFACE_DEF **)
369 (isSource ? &mSrcSurfaceDef : &mDstSurfaceDef);
370 if (*surfaceRGBDef == NULL) {
371 *surfaceRGBDef = (C2D_RGB_SURFACE_DEF *)
372 calloc(1, sizeof(C2D_RGB_SURFACE_DEF));
373 if (*surfaceRGBDef == NULL) {
374 ALOGE("%s: surfaceRGBDef allocation failed", __FUNCTION__);
375 return -1;
376 }
377 } else {
378 memset(*surfaceRGBDef, 0, sizeof(C2D_RGB_SURFACE_DEF));
379 }
380 (*surfaceRGBDef)->format = getC2DFormat(format);
381
382 if (mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)
383 (*surfaceRGBDef)->format |= C2D_FORMAT_UBWC_COMPRESSED;
384 (*surfaceRGBDef)->width = width;
385 (*surfaceRGBDef)->height = height;
386 (*surfaceRGBDef)->buffer = (void *)0xaaaaaaaa;
387 (*surfaceRGBDef)->phys = (void *)0xaaaaaaaa;
388 (*surfaceRGBDef)->stride = calcStride(format, width);
389
390 surfaceDef = *surfaceRGBDef;
391 hostSurfaceType = C2D_SURFACE_RGB_HOST;
392 }
393
394 ret = mC2DCreateSurface(isSource ? &mSrcSurface :
395 &mDstSurface,
396 isSource ? C2D_SOURCE : C2D_TARGET,
397 (C2D_SURFACE_TYPE)(hostSurfaceType
398 | C2D_SURFACE_WITH_PHYS
399 | C2D_SURFACE_WITH_PHYS_DUMMY),
400 surfaceDef);
401 return (int32_t) ret;
402 }
403
updateYUVSurfaceDef(uint8_t * gpuAddr,void * base,void * data,bool isSource)404 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(uint8_t *gpuAddr, void *base,
405 void *data, bool isSource)
406 {
407 if (isSource) {
408 C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
409 srcSurfaceDef->plane0 = data;
410 srcSurfaceDef->phys0 = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
411 srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
412 srcSurfaceDef->phys1 = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
413 if (srcSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
414 srcSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
415 srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
416 srcSurfaceDef->phys2 = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
417 }
418 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
419 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
420 &(*srcSurfaceDef));
421 } else {
422 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
423 dstSurfaceDef->plane0 = data;
424 dstSurfaceDef->phys0 = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
425 dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
426 dstSurfaceDef->phys1 = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
427 if (dstSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
428 dstSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
429 dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
430 dstSurfaceDef->phys2 = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
431 }
432
433 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
434 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
435 &(*dstSurfaceDef));
436 }
437 }
438
updateRGBSurfaceDef(uint8_t * gpuAddr,void * data,bool isSource)439 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(uint8_t *gpuAddr, void * data, bool isSource)
440 {
441 if (isSource) {
442 C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
443 srcSurfaceDef->buffer = data;
444 srcSurfaceDef->phys = gpuAddr;
445 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
446 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
447 &(*srcSurfaceDef));
448 } else {
449 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
450 dstSurfaceDef->buffer = data;
451 ALOGV("%s: dstSurfaceDef->buffer = %p", __FUNCTION__, data);
452 dstSurfaceDef->phys = gpuAddr;
453 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
454 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
455 &(*dstSurfaceDef));
456 }
457 }
458
getC2DFormat(ColorConvertFormat format)459 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format)
460 {
461 switch (format) {
462 case RGB565:
463 return C2D_COLOR_FORMAT_565_RGB;
464 case RGBA8888:
465 return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED;
466 case RGBA8888_UBWC:
467 return C2D_COLOR_FORMAT_8888_RGBA |
468 C2D_FORMAT_SWAP_ENDIANNESS |
469 C2D_FORMAT_PREMULTIPLIED |
470 C2D_FORMAT_UBWC_COMPRESSED;
471 case YCbCr420Tile:
472 return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
473 case YCbCr420SP:
474 case NV12_2K:
475 case NV12_128m:
476 return C2D_COLOR_FORMAT_420_NV12;
477 case YCbCr420P:
478 return C2D_COLOR_FORMAT_420_I420;
479 case YCrCb420P:
480 return C2D_COLOR_FORMAT_420_YV12;
481 case NV12_UBWC:
482 return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_UBWC_COMPRESSED;
483 case TP10_UBWC:
484 return C2D_COLOR_FORMAT_420_TP10 | C2D_FORMAT_UBWC_COMPRESSED;
485 default:
486 ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
487 return -1;
488 }
489 }
490
calcStride(ColorConvertFormat format,size_t width)491 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
492 {
493 switch (format) {
494 case RGB565:
495 return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
496 case RGBA8888:
497 if (mSrcStride)
498 return mSrcStride * 4;
499 else
500 return ALIGN(width, ALIGN32) * 4;
501 case YCbCr420Tile:
502 return ALIGN(width, ALIGN128);
503 case YCbCr420SP:
504 return ALIGN(width, ALIGN16);
505 case NV12_2K:
506 return ALIGN(width, ALIGN16);
507 case NV12_128m:
508 return ALIGN(width, ALIGN128);
509 case YCbCr420P:
510 return ALIGN(width, ALIGN16);
511 case YCrCb420P:
512 return ALIGN(width, ALIGN16);
513 case NV12_UBWC:
514 return VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
515 case TP10_UBWC:
516 return VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width);
517 default:
518 ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
519 return 0;
520 }
521 }
522
calcYSize(ColorConvertFormat format,size_t width,size_t height)523 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height)
524 {
525 switch (format) {
526 case YCbCr420SP:
527 return (ALIGN(width, ALIGN16) * height);
528 case YCbCr420P:
529 return ALIGN(width, ALIGN16) * height;
530 case YCrCb420P:
531 return ALIGN(width, ALIGN16) * height;
532 case YCbCr420Tile:
533 return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K);
534 case NV12_2K: {
535 size_t alignedw = ALIGN(width, ALIGN16);
536 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
537 return lumaSize;
538 }
539 case NV12_128m:
540 return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32);
541 case NV12_UBWC:
542 return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width) *
543 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K) +
544 ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, width) *
545 VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K);
546 case TP10_UBWC:
547 return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) *
548 VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height), ALIGN4K) +
549 ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) *
550 VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height), ALIGN4K);
551 default:
552 ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
553 return 0;
554 }
555 }
556
calcSize(ColorConvertFormat format,size_t width,size_t height)557 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height)
558 {
559 int32_t alignedw = 0;
560 int32_t alignedh = 0;
561 int32_t size = 0;
562 int32_t tile_mode = 0;
563 int32_t raster_mode = 0;
564 int32_t padding_threshold = 512; /* hardcode for RGB formats */
565 int32_t bpp = 0;
566
567 switch (format) {
568 case RGB565:
569 bpp = 2;
570 mAdrenoComputeFmtAlignedWidthAndHeight(width, height,
571 0, ADRENO_PIXELFORMAT_B5G6R5,
572 1, tile_mode, raster_mode,
573 padding_threshold,
574 &alignedw, &alignedh);
575 ALOGV("%s: alignedw %d alignedh %d", __FUNCTION__,alignedw, alignedh);
576 size = alignedw * alignedh * bpp;
577 size = ALIGN(size, ALIGN4K);
578 break;
579 case RGBA8888:
580 bpp = 4;
581 mAdrenoComputeFmtAlignedWidthAndHeight(width, height,
582 0, ADRENO_PIXELFORMAT_R8G8B8A8 ,
583 1, tile_mode, raster_mode,
584 padding_threshold,
585 &alignedw, &alignedh);
586 ALOGV("%s: alignedw %d alignedh %d", __FUNCTION__,alignedw, alignedh);
587 if (mSrcStride)
588 size = mSrcStride * alignedh * bpp;
589 else
590 size = alignedw * alignedh * bpp;
591 size = ALIGN(size, ALIGN4K);
592 break;
593 case YCbCr420SP:
594 alignedw = ALIGN(width, ALIGN16);
595 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K);
596 break;
597 case YCbCr420P:
598 alignedw = ALIGN(width, ALIGN16);
599 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
600 break;
601 case YCrCb420P:
602 alignedw = ALIGN(width, ALIGN16);
603 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
604 break;
605 case YCbCr420Tile:
606 alignedw = ALIGN(width, ALIGN128);
607 alignedh = ALIGN(height, ALIGN32);
608 size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K);
609 break;
610 case NV12_2K: {
611 alignedw = ALIGN(width, ALIGN16);
612 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
613 size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
614 size = ALIGN(lumaSize + chromaSize, ALIGN4K);
615 ALOGV("%s: NV12_2k, width = %zu, height = %zu, size = %d",
616 __FUNCTION__, width, height, size);
617 }
618 break;
619 case NV12_128m:
620 alignedw = ALIGN(width, ALIGN128);
621 alignedh = ALIGN(height, ALIGN32);
622 size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K);
623 break;
624 case NV12_UBWC:
625 size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
626 break;
627 case TP10_UBWC:
628 size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
629 break;
630 default:
631 ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
632 break;
633 }
634 return size;
635 }
636 /*
637 * Tells GPU to map given buffer and returns a physical address of mapped buffer
638 */
getMappedGPUAddr(int bufFD,void * bufPtr,size_t bufLen)639 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
640 {
641 C2D_STATUS status;
642 void *gpuaddr = NULL;
643
644 status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION,
645 &gpuaddr);
646 if (status != C2D_STATUS_OK) {
647 ALOGE("%s: c2dMapAddr failed: status %d fd %d ptr %p len %zu flags %d",
648 __FUNCTION__, status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION);
649 return NULL;
650 }
651 ALOGV("%s: c2d mapping created: gpuaddr %p fd %d ptr %p len %zu",
652 __FUNCTION__, gpuaddr, bufFD, bufPtr, bufLen);
653
654 return gpuaddr;
655 }
656
unmapGPUAddr(unsigned long gAddr)657 bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr)
658 {
659
660 C2D_STATUS status = mC2DUnMapAddr((void*)gAddr);
661
662 if (status != C2D_STATUS_OK)
663 ALOGE("%s: c2dUnMapAddr failed: status %d gpuaddr %08lx",
664 __FUNCTION__, status, gAddr);
665
666 return (status == C2D_STATUS_OK);
667 }
668
getBuffSize(int32_t port)669 int32_t C2DColorConverter::getBuffSize(int32_t port)
670 {
671 if (enabled) {
672 if (port == C2D_INPUT) {
673 return calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
674 } else if (port == C2D_OUTPUT) {
675 return calcSize(mDstFormat, mDstWidth, mDstHeight);
676 }
677 }
678 return 0;
679 }
680
getBuffFilledLen(int32_t port,unsigned int & filled_length)681 bool C2DColorConverter::getBuffFilledLen(int32_t port, unsigned int &filled_length)
682 {
683 bool ret = false;
684 C2DBuffReq req;
685 if (enabled) {
686 ret = getBuffReq(port, &req);
687 if (ret && req.bpp.denominator > 0) {
688 filled_length = (req.stride * req.sliceHeight * req.bpp.numerator);
689 filled_length /= req.bpp.denominator;
690 }
691 }
692
693 return ret;
694 }
695
getBuffReq(int32_t port,C2DBuffReq * req)696 bool C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
697 if (!req
698 || (port != C2D_INPUT
699 && port != C2D_OUTPUT)) return false;
700
701 memset(req, 0, sizeof(C2DBuffReq));
702 if (port == C2D_INPUT) {
703 req->width = mSrcWidth;
704 req->height = mSrcHeight;
705 req->stride = calcStride(mSrcFormat, mSrcWidth);
706 req->sliceHeight = mSrcHeight;
707 req->lumaAlign = calcLumaAlign(mSrcFormat);
708 req->sizeAlign = calcSizeAlign(mSrcFormat);
709 req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
710 req->bpp = calcBytesPerPixel(mSrcFormat);
711 ALOGV("%s: input req->size = %d", __FUNCTION__, req->size);
712 } else if (port == C2D_OUTPUT) {
713 req->width = mDstWidth;
714 req->height = mDstHeight;
715 req->stride = calcStride(mDstFormat, mDstWidth);
716 req->sliceHeight = mDstHeight;
717 req->lumaAlign = calcLumaAlign(mDstFormat);
718 req->sizeAlign = calcSizeAlign(mDstFormat);
719 req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
720 req->bpp = calcBytesPerPixel(mDstFormat);
721 ALOGV("%s: output req->size = %d", __FUNCTION__, req->size);
722 }
723 return true;
724 }
725
calcLumaAlign(ColorConvertFormat format)726 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
727 if (!isYUVSurface(format)) return 1; //no requirement
728
729 switch (format) {
730 case NV12_2K:
731 return ALIGN2K;
732 case NV12_128m:
733 return 1;
734 case NV12_UBWC:
735 case TP10_UBWC:
736 return ALIGN4K;
737 default:
738 ALOGW("%s: unknown format (%d) passed for luma alignment number.",
739 __FUNCTION__, format);
740 return 1;
741 }
742 }
743
calcSizeAlign(ColorConvertFormat format)744 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
745 if (!isYUVSurface(format)) return 1; //no requirement
746
747 switch (format) {
748 case YCbCr420SP: //OR NV12
749 case YCbCr420P:
750 case NV12_2K:
751 case NV12_128m:
752 case NV12_UBWC:
753 case TP10_UBWC:
754 return ALIGN4K;
755 default:
756 ALOGW("%s: unknown format (%d) passed for size alignment number",
757 __FUNCTION__, format);
758 return 1;
759 }
760 }
761
calcBytesPerPixel(ColorConvertFormat format)762 C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) {
763 C2DBytesPerPixel bpp;
764 bpp.numerator = 0;
765 bpp.denominator = 1;
766
767 switch (format) {
768 case RGB565:
769 bpp.numerator = 2;
770 break;
771 case RGBA8888:
772 case RGBA8888_UBWC:
773 bpp.numerator = 4;
774 break;
775 case YCbCr420SP:
776 case YCbCr420P:
777 case YCrCb420P:
778 case YCbCr420Tile:
779 case NV12_2K:
780 case NV12_128m:
781 case NV12_UBWC:
782 case TP10_UBWC:
783 bpp.numerator = 3;
784 bpp.denominator = 2;
785 break;
786 default:
787 ALOGW("%s: unknown format (%d) passed.", __FUNCTION__, format);
788 break;
789 }
790 return bpp;
791 }
792
dumpOutput(char * filename,char mode)793 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
794 int fd;
795 size_t stride, sliceHeight;
796 if (!filename) return -1;
797
798 int flags = O_RDWR | O_CREAT;
799 if (mode == 'a') {
800 flags |= O_APPEND;
801 }
802
803 if ((fd = open(filename, flags)) < 0) {
804 ALOGE("%s: open dump file failed w/ errno %s", __FUNCTION__, strerror(errno));
805 return -1;
806 }
807
808 int ret = 0;
809 if (isYUVSurface(mDstFormat)) {
810 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
811 uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
812 stride = dstSurfaceDef->stride0;
813 sliceHeight = dstSurfaceDef->height;
814 /* dump luma */
815 for (size_t i = 0; i < sliceHeight; i++) {
816 ret = write(fd, base, mDstWidth); //will work only for the 420 ones
817 if (ret < 0) goto cleanup;
818 base += stride;
819 }
820
821 if (mDstFormat == YCbCr420P ||
822 mDstFormat == YCrCb420P) {
823 ALOGI("%s: Dump Cb and Cr separately for Planar\n", __FUNCTION__);
824 //dump Cb/Cr
825 base = (uint8_t *)dstSurfaceDef->plane1;
826 stride = dstSurfaceDef->stride1;
827 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
828 ret = write(fd, base, mDstWidth/2);
829 if (ret < 0) goto cleanup;
830 base += stride;
831 }
832
833 //dump Cr/Cb
834 base = (uint8_t *)dstSurfaceDef->plane2;
835 stride = dstSurfaceDef->stride2;
836
837 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
838 ret = write(fd, base, mDstWidth/2);
839 if (ret < 0) goto cleanup;
840 base += stride;
841 }
842
843 } else {
844 /* dump chroma */
845 base = (uint8_t *)dstSurfaceDef->plane1;
846 stride = dstSurfaceDef->stride1;
847 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
848 ret = write(fd, base, mDstWidth);
849 if (ret < 0) goto cleanup;
850 base += stride;
851 }
852 }
853 } else {
854 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
855 uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
856 stride = dstSurfaceDef->stride;
857 sliceHeight = dstSurfaceDef->height;
858
859 ALOGI("%s: rgb surface base is %p", __FUNCTION__, base);
860 ALOGI("%s: rgb surface dumpsslice height is %lu\n",
861 __FUNCTION__, (unsigned long)sliceHeight);
862 ALOGI("%s: rgb surface dump stride is %lu\n",
863 __FUNCTION__, (unsigned long)stride);
864
865 int bpp = 1; //bytes per pixel
866 if (mDstFormat == RGB565) {
867 bpp = 2;
868 } else if (mDstFormat == RGBA8888 || mDstFormat == RGBA8888_UBWC) {
869 bpp = 4;
870 }
871
872 int count = 0;
873 for (size_t i = 0; i < sliceHeight; i++) {
874 ret = write(fd, base, mDstWidth*bpp);
875 if (ret < 0) {
876 ALOGI("%s: write failed, count = %d\n", __FUNCTION__, count);
877 goto cleanup;
878 }
879 base += stride;
880 count += stride;
881 }
882 }
883 cleanup:
884 if (ret < 0) {
885 ALOGE("%s: file write failed w/ errno %s", __FUNCTION__, strerror(errno));
886 }
887 close(fd);
888 return ret < 0 ? ret : 0;
889 }
890