Commit | Line | Data |
---|---|---|
5763fb39 T |
1 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS |
2 | ||
3 | #include <utils/Trace.h> | |
4 | #include "ExynosMPP.h" | |
5 | #include "ExynosHWCUtils.h" | |
6 | #ifdef USES_VIRTUAL_DISPLAY | |
7 | #include "ExynosVirtualDisplay.h" | |
8 | #endif | |
9 | ||
10 | size_t visibleWidth(ExynosMPP *processor, hwc_layer_1_t &layer, int format, | |
11 | int xres) | |
12 | { | |
13 | int bpp; | |
14 | if (processor->isProcessingRequired(layer, format) && format != HAL_PIXEL_FORMAT_RGB_565) | |
15 | bpp = 32; | |
16 | else | |
17 | bpp = formatToBpp(format); | |
18 | int left = max(layer.displayFrame.left, 0); | |
19 | int right = min(layer.displayFrame.right, xres); | |
20 | ||
21 | return (right - left) * bpp / 8; | |
22 | } | |
23 | ||
24 | ExynosMPP::ExynosMPP() | |
25 | { | |
26 | ExynosMPP(NULL, 0); | |
27 | } | |
28 | ||
29 | ExynosMPP::ExynosMPP(ExynosDisplay *display, int gscIndex) | |
30 | { | |
31 | ATRACE_CALL(); | |
32 | this->mDisplay = display; | |
33 | this->mIndex = gscIndex; | |
34 | mNeedReqbufs = false; | |
35 | mWaitVsyncCount = 0; | |
36 | mCountSameConfig = 0; | |
37 | mGscHandle = NULL; | |
38 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
39 | memset(&mMidConfig, 0, sizeof(mMidConfig)); | |
40 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
41 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
42 | mDstBuffers[i] = NULL; | |
43 | mMidBuffers[i] = NULL; | |
44 | mDstBufFence[i] = -1; | |
45 | mMidBufFence[i] = -1; | |
46 | } | |
47 | mNumAvailableDstBuffers = NUM_GSC_DST_BUFS; | |
48 | mCurrentBuf = 0; | |
49 | mGSCMode = 0; | |
50 | mLastGSCLayerHandle = -1; | |
51 | mS3DMode = 0; | |
52 | mppFact = NULL; | |
53 | libmpp = NULL; | |
54 | mDoubleOperation = false; | |
55 | mBufferFreeThread = new BufferFreeThread(this); | |
56 | mBufferFreeThread->mRunning = true; | |
ad0fa79e | 57 | mBufferFreeThread->run("MPPThread"); |
5763fb39 T |
58 | } |
59 | ||
60 | ExynosMPP::~ExynosMPP() | |
61 | { | |
62 | if (mBufferFreeThread != NULL) { | |
63 | mBufferFreeThread->mRunning = false; | |
64 | mBufferFreeThread->requestExitAndWait(); | |
65 | delete mBufferFreeThread; | |
66 | } | |
67 | } | |
68 | ||
69 | bool ExynosMPP::isM2M() | |
70 | { | |
71 | return mGSCMode == exynos5_gsc_map_t::GSC_M2M; | |
72 | } | |
73 | ||
74 | bool ExynosMPP::isUsingMSC() | |
75 | { | |
76 | return (AVAILABLE_GSC_UNITS[mIndex] >= 4 && AVAILABLE_GSC_UNITS[mIndex] <= 6); | |
77 | } | |
78 | ||
79 | bool ExynosMPP::isOTF() | |
80 | { | |
81 | return mGSCMode == exynos5_gsc_map_t::GSC_LOCAL; | |
82 | } | |
83 | ||
84 | void ExynosMPP::setMode(int mode) | |
85 | { | |
86 | mGSCMode = mode; | |
87 | } | |
88 | ||
89 | void ExynosMPP::free() | |
90 | { | |
91 | if (mNeedReqbufs) { | |
92 | if (mWaitVsyncCount > 0) { | |
93 | if (mGscHandle) | |
94 | freeMPP(mGscHandle); | |
95 | mNeedReqbufs = false; | |
96 | mWaitVsyncCount = 0; | |
97 | mDisplay->mOtfMode = OTF_OFF; | |
98 | mGscHandle = NULL; | |
99 | libmpp = NULL; | |
100 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
101 | memset(&mMidConfig, 0, sizeof(mMidConfig)); | |
102 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
103 | memset(mDstBuffers, 0, sizeof(mDstBuffers)); | |
104 | memset(mMidBuffers, 0, sizeof(mMidBuffers)); | |
105 | mCurrentBuf = 0; | |
106 | mGSCMode = 0; | |
107 | mLastGSCLayerHandle = 0; | |
108 | ||
109 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
110 | mDstBufFence[i] = -1; | |
111 | mMidBufFence[i] = -1; | |
112 | } | |
113 | } else { | |
114 | mWaitVsyncCount++; | |
115 | } | |
116 | } | |
117 | } | |
118 | ||
119 | bool ExynosMPP::isSrcConfigChanged(exynos_mpp_img &c1, exynos_mpp_img &c2) | |
120 | { | |
121 | return isDstConfigChanged(c1, c2) || | |
122 | c1.fw != c2.fw || | |
123 | c1.fh != c2.fh; | |
124 | } | |
125 | ||
126 | bool ExynosMPP::isFormatSupportedByGsc(int format) | |
127 | { | |
128 | ||
129 | switch (format) { | |
130 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
131 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
132 | case HAL_PIXEL_FORMAT_RGB_565: | |
133 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
134 | case HAL_PIXEL_FORMAT_YV12: | |
135 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
136 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
137 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
138 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
139 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
140 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
141 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
142 | return true; | |
143 | ||
144 | default: | |
145 | return false; | |
146 | } | |
147 | } | |
148 | ||
149 | bool ExynosMPP::formatRequiresGsc(int format) | |
150 | { | |
151 | return (isFormatSupportedByGsc(format) && | |
152 | (format != HAL_PIXEL_FORMAT_RGBX_8888) && (format != HAL_PIXEL_FORMAT_RGB_565) && | |
153 | (format != HAL_PIXEL_FORMAT_RGBA_8888)); | |
154 | } | |
155 | ||
156 | int ExynosMPP::getDownscaleRatio(int *downNumerator, int *downDenominator) | |
157 | { | |
158 | *downNumerator = 0; | |
159 | *downDenominator = 0; | |
160 | return -1; | |
161 | } | |
162 | ||
163 | bool ExynosMPP::isFormatSupportedByGscOtf(int format) | |
164 | { | |
165 | switch (format) { | |
166 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
167 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
168 | case HAL_PIXEL_FORMAT_RGB_565: | |
169 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
170 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
171 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
172 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
173 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
174 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
175 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
176 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
177 | return true; | |
178 | default: | |
179 | return false; | |
180 | } | |
181 | } | |
182 | ||
183 | int ExynosMPP::isProcessingSupported(hwc_layer_1_t &layer, int format, | |
184 | bool local_path, int downNumerator, int downDenominator) | |
185 | { | |
186 | if (local_path && downNumerator == 0) { | |
187 | return -eMPPUnsupportedDownScale; | |
188 | } | |
189 | ||
190 | if (isUsingMSC() && local_path) { | |
191 | return -eMPPUnsupportedHW; | |
192 | } | |
193 | ||
194 | if (!isUsingMSC() && layer.blending != HWC_BLENDING_NONE) | |
195 | return -eMPPUnsupportedBlending; | |
196 | ||
197 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
198 | ||
199 | if (isUsingMSC() && handle && | |
200 | isFormatRgb(handle->format) && !hasAlpha(handle->format) && | |
201 | (layer.blending == HWC_BLENDING_PREMULT)) | |
202 | return -eMPPUnsupportedBlending; | |
203 | ||
204 | int max_w = maxWidth(layer); | |
205 | int max_h = maxHeight(layer); | |
206 | int min_w = minWidth(layer); | |
207 | int min_h = minHeight(layer); | |
208 | int crop_max_w = 0; | |
209 | int crop_max_h = 0; | |
210 | int dest_min_h = 0; | |
211 | ||
212 | if (isUsingMSC()) { | |
213 | crop_max_w = 8192; | |
214 | crop_max_h = 8192; | |
215 | } else { | |
216 | crop_max_w = isRotated(layer) ? 2016 : 4800; | |
217 | crop_max_h = isRotated(layer) ? 2016 : 3344; | |
218 | } | |
219 | int crop_min_w = isRotated(layer) ? 32: 64; | |
220 | int crop_min_h = isRotated(layer) ? 64: 32; | |
221 | ||
222 | if (local_path) | |
223 | dest_min_h = 64; | |
224 | else | |
225 | dest_min_h = 32; | |
226 | ||
227 | int srcWidthAlign = sourceWidthAlign(handle->format); | |
228 | int srcHeightAlign = sourceHeightAlign(handle->format); | |
229 | int dstAlign; | |
230 | if (local_path) | |
231 | dstAlign = destinationAlign(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M); | |
232 | else | |
233 | dstAlign = destinationAlign(HAL_PIXEL_FORMAT_BGRA_8888); | |
234 | ||
235 | int maxDstWidth; | |
236 | int maxDstHeight; | |
237 | ||
238 | bool rot90or270 = !!(layer.transform & HAL_TRANSFORM_ROT_90); | |
239 | // n.b.: HAL_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_90 | | |
240 | // HAL_TRANSFORM_ROT_180 | |
241 | ||
242 | int src_w = WIDTH(layer.sourceCropf), src_h = HEIGHT(layer.sourceCropf); | |
243 | if (!isUsingMSC()) { | |
244 | src_w = getAdjustedCrop(src_w, WIDTH(layer.displayFrame), handle->format, false, rot90or270); | |
245 | src_h = getAdjustedCrop(src_h, HEIGHT(layer.displayFrame), handle->format, true, rot90or270); | |
246 | } | |
247 | int dest_w, dest_h; | |
248 | if (rot90or270) { | |
249 | dest_w = HEIGHT(layer.displayFrame); | |
250 | dest_h = WIDTH(layer.displayFrame); | |
251 | } else { | |
252 | dest_w = WIDTH(layer.displayFrame); | |
253 | dest_h = HEIGHT(layer.displayFrame); | |
254 | } | |
255 | ||
256 | if (getDrmMode(handle->flags) != NO_DRM) | |
257 | alignCropAndCenter(dest_w, dest_h, NULL, | |
258 | GSC_DST_CROP_W_ALIGNMENT_RGB888); | |
259 | ||
260 | maxDstWidth = 2560; | |
261 | maxDstHeight = 2560; | |
262 | int max_upscale = 8; | |
263 | ||
264 | /* check whether GSC can handle with local path */ | |
265 | if (local_path) { | |
266 | if (isFormatRgb(format) && rot90or270) | |
267 | return -eMPPUnsupportedRotation; | |
268 | ||
269 | /* GSC OTF can't handle rot90 or rot270 */ | |
270 | if (!rotationSupported(rot90or270)) | |
271 | return -eMPPUnsupportedRotation; | |
272 | /* | |
273 | * if display co-ordinates are out of the lcd resolution, | |
274 | * skip that scenario to OpenGL. | |
275 | * GSC OTF can't handle such scenarios. | |
276 | */ | |
277 | if (layer.displayFrame.left < 0 || layer.displayFrame.top < 0 || | |
278 | layer.displayFrame.right > mDisplay->mXres || layer.displayFrame.bottom > mDisplay->mYres) | |
279 | return -eMPPUnsupportedCoordinate; | |
280 | ||
281 | /* GSC OTF can't handle GRALLOC_USAGE_PROTECTED layer */ | |
282 | if (getDrmMode(handle->flags) != NO_DRM) | |
283 | return -eMPPUnsupportedDRMContents; | |
284 | ||
285 | if (!isFormatSupportedByGsc(format)) | |
286 | return -eMPPUnsupportedFormat; | |
287 | else if (!isFormatSupportedByGscOtf(format)) | |
288 | return -eMPPUnsupportedFormat; | |
289 | else if (format == HAL_PIXEL_FORMAT_RGBA_8888 && layer.blending != HWC_BLENDING_NONE) | |
290 | return -eMPPUnsupportedBlending; | |
291 | else if (mDisplay->mHwc->mS3DMode != S3D_MODE_DISABLED) | |
292 | return -eMPPUnsupportedS3DContents; | |
293 | else if (!paritySupported(dest_w, dest_h)) | |
294 | return -eMPPNotAlignedDstSize; | |
295 | else if (handle->stride > max_w) | |
296 | return -eMPPExceedHStrideMaximum; | |
297 | else if (src_w * downNumerator > dest_w * downDenominator) | |
298 | return -eMPPExeedMaxDownScale; | |
299 | else if (dest_w > maxDstWidth) | |
300 | return -eMPPExeedMaxDstWidth; | |
301 | else if (dest_w > src_w * max_upscale) | |
302 | return -eMPPExeedMaxUpScale; | |
303 | else if (handle->vstride > max_h) | |
304 | return -eMPPExceedVStrideMaximum; | |
305 | else if (src_h * downNumerator > dest_h * downDenominator) | |
306 | return -eMPPExeedMaxDownScale; | |
307 | else if (dest_h > maxDstHeight) | |
308 | return -eMPPExeedMaxDstHeight; | |
309 | else if (dest_h > src_h * max_upscale) | |
310 | return -eMPPExeedMaxUpScale; | |
311 | else if (src_w > crop_max_w) | |
312 | return -eMPPExeedSrcWCropMax; | |
313 | else if (src_h > crop_max_h) | |
314 | return -eMPPExeedSrcHCropMax; | |
315 | else if (src_w < crop_min_w) | |
316 | return -eMPPExeedSrcWCropMin; | |
317 | else if (src_h < crop_min_h) | |
318 | return -eMPPExeedSrcHCropMin; | |
319 | else if (dest_h < dest_min_h) | |
320 | return -eMPPExeedMinDstHeight; | |
321 | ||
322 | return 1; | |
323 | } | |
324 | ||
325 | bool need_gsc_op_twice = false; | |
326 | if (getDrmMode(handle->flags) != NO_DRM) { | |
327 | need_gsc_op_twice = ((dest_w > src_w * max_upscale) || | |
328 | (dest_h > src_h * max_upscale)) ? true : false; | |
329 | if (need_gsc_op_twice) | |
330 | max_upscale = 8 * 8; | |
331 | } else { | |
332 | if (!mDisplay->mHasDrmSurface) { | |
333 | need_gsc_op_twice = false; | |
334 | max_upscale = 8; | |
335 | } | |
336 | } | |
337 | ||
338 | if (getDrmMode(handle->flags) != NO_DRM) { | |
339 | /* make even for gscaler */ | |
340 | layer.sourceCropf.top = (unsigned int)layer.sourceCropf.top & ~1; | |
341 | layer.sourceCropf.left = (unsigned int)layer.sourceCropf.left & ~1; | |
342 | layer.sourceCropf.bottom = (unsigned int)layer.sourceCropf.bottom & ~1; | |
343 | layer.sourceCropf.right = (unsigned int)layer.sourceCropf.right & ~1; | |
344 | } | |
345 | ||
346 | /* check whether GSC can handle with M2M */ | |
347 | if (!isFormatSupportedByGsc(format)) | |
348 | return -eMPPUnsupportedFormat; | |
349 | else if (src_w < min_w) | |
350 | return -eMPPExeedMinSrcWidth; | |
351 | else if (src_h < min_h) | |
352 | return -eMPPExeedMinSrcHeight; | |
353 | else if (!isDstCropWidthAligned(dest_w)) | |
354 | return -eMPPNotAlignedDstSize; | |
355 | else if (handle->stride > max_w) | |
356 | return -eMPPExceedHStrideMaximum; | |
357 | else if (handle->stride % srcWidthAlign != 0) | |
358 | return -eMPPNotAlignedHStride; | |
359 | else if (src_w * downNumerator >= dest_w * downDenominator) | |
360 | return -eMPPExeedMaxDownScale; | |
361 | else if (dest_w > src_w * max_upscale) | |
362 | return -eMPPExeedMaxUpScale; | |
363 | else if (handle->vstride > max_h) | |
364 | return -eMPPExceedVStrideMaximum; | |
365 | else if (handle->vstride % srcHeightAlign != 0) | |
366 | return -eMPPNotAlignedVStride; | |
367 | else if (src_h * downNumerator >= dest_h * downDenominator) | |
368 | return -eMPPExeedMaxDownScale; | |
369 | else if (dest_h > src_h * max_upscale) | |
370 | return -eMPPExeedMaxUpScale; | |
371 | else if (src_w > crop_max_w) | |
372 | return -eMPPExeedSrcWCropMax; | |
373 | else if (src_h > crop_max_h) | |
374 | return -eMPPExeedSrcHCropMax; | |
375 | else if (src_w < crop_min_w) | |
376 | return -eMPPExeedSrcWCropMin; | |
377 | else if (src_h < crop_min_h) | |
378 | return -eMPPExeedSrcHCropMin; | |
379 | else if (dest_h < dest_min_h) | |
380 | return -eMPPExeedMinDstHeight; | |
381 | // per 46.3.1.6 | |
382 | ||
383 | return 1; | |
384 | } | |
385 | ||
386 | bool ExynosMPP::isProcessingRequired(hwc_layer_1_t &layer, int format) | |
387 | { | |
388 | return formatRequiresGsc(format) || isScaled(layer) | |
389 | || isTransformed(layer); | |
390 | } | |
391 | ||
ad0fa79e | 392 | int ExynosMPP::getAdjustedCrop(int rawSrcSize, int dstSize, int format, bool isVertical __unused, bool isRotated) |
5763fb39 T |
393 | { |
394 | int ratio; | |
5763fb39 T |
395 | int align; |
396 | ||
397 | if (dstSize >= rawSrcSize || rawSrcSize <= dstSize * FIRST_PRESCALER_THRESHOLD) | |
398 | ratio = 1; | |
399 | else if (rawSrcSize < dstSize * SECOND_PRESCALER_THRESHOLD) | |
400 | ratio = 2; | |
401 | else | |
402 | ratio = 4; | |
403 | ||
404 | if (isFormatRgb(format)) { | |
405 | if (isRotated) | |
406 | align = ratio << 1; | |
407 | else | |
408 | align = ratio; | |
409 | } else { | |
410 | align = ratio << 1; | |
411 | } | |
412 | ||
413 | return rawSrcSize - (rawSrcSize % align); | |
414 | } | |
415 | ||
416 | void ExynosMPP::setupSource(exynos_mpp_img &src_img, hwc_layer_1_t &layer) | |
417 | { | |
418 | bool rotation = !!(layer.transform & HAL_TRANSFORM_ROT_90); | |
419 | private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle); | |
420 | src_img.x = ALIGN((unsigned int)layer.sourceCropf.left, srcXOffsetAlign(layer)); | |
421 | src_img.y = ALIGN((unsigned int)layer.sourceCropf.top, srcYOffsetAlign(layer)); | |
422 | src_img.w = WIDTH(layer.sourceCropf) - (src_img.x - (uint32_t)layer.sourceCropf.left); | |
423 | src_img.fw = src_handle->stride; | |
424 | if (src_img.x + src_img.w > src_img.fw) | |
425 | src_img.w = src_img.fw - src_img.x; | |
426 | src_img.h = HEIGHT(layer.sourceCropf) - (src_img.y - (uint32_t)layer.sourceCropf.top); | |
427 | src_img.fh = src_handle->vstride; | |
428 | if (src_img.y + src_img.h > src_img.fh) | |
429 | src_img.h = src_img.fh - src_img.y; | |
430 | src_img.yaddr = src_handle->fd; | |
431 | if (!isUsingMSC()) { | |
432 | src_img.w = getAdjustedCrop(src_img.w, WIDTH(layer.displayFrame), src_handle->format, false, rotation); | |
433 | src_img.h = getAdjustedCrop(src_img.h, HEIGHT(layer.displayFrame), src_handle->format, true, rotation); | |
434 | } | |
435 | if (mS3DMode == S3D_SBS) | |
436 | src_img.w /= 2; | |
437 | if (mS3DMode == S3D_TB) | |
438 | src_img.h /= 2; | |
439 | if (isFormatYCrCb(src_handle->format)) { | |
440 | src_img.uaddr = src_handle->fd2; | |
441 | src_img.vaddr = src_handle->fd1; | |
442 | } else { | |
443 | src_img.uaddr = src_handle->fd1; | |
444 | src_img.vaddr = src_handle->fd2; | |
445 | } | |
446 | if (src_handle->format != HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL) | |
447 | src_img.format = src_handle->format; | |
448 | else | |
449 | src_img.format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; | |
450 | ||
451 | if (layer.blending == HWC_BLENDING_COVERAGE) | |
452 | src_img.pre_multi = false; | |
453 | else | |
454 | src_img.pre_multi = true; | |
455 | ||
456 | src_img.drmMode = !!(getDrmMode(src_handle->flags) == SECURE_DRM); | |
457 | src_img.acquireFenceFd = layer.acquireFenceFd; | |
458 | } | |
459 | ||
460 | void ExynosMPP::setupOtfDestination(exynos_mpp_img &src_img, exynos_mpp_img &dst_img, hwc_layer_1_t &layer) | |
461 | { | |
462 | dst_img.x = layer.displayFrame.left; | |
463 | dst_img.y = layer.displayFrame.top; | |
464 | dst_img.fw = mDisplay->mXres; | |
465 | dst_img.fh = mDisplay->mYres; | |
466 | dst_img.w = WIDTH(layer.displayFrame); | |
467 | dst_img.h = HEIGHT(layer.displayFrame); | |
468 | dst_img.w = min(dst_img.w, dst_img.fw - dst_img.x); | |
469 | dst_img.h = min(dst_img.h, dst_img.fh - dst_img.y); | |
470 | dst_img.format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M; | |
471 | dst_img.rot = layer.transform; | |
472 | dst_img.drmMode = src_img.drmMode; | |
473 | dst_img.yaddr = (ptrdiff_t)NULL; | |
474 | } | |
475 | ||
ad0fa79e | 476 | int ExynosMPP::sourceWidthAlign(int format __unused) |
5763fb39 T |
477 | { |
478 | return 16; | |
479 | } | |
480 | ||
ad0fa79e | 481 | int ExynosMPP::sourceHeightAlign(int format __unused) |
5763fb39 T |
482 | { |
483 | return 16; | |
484 | } | |
485 | ||
ad0fa79e | 486 | int ExynosMPP::destinationAlign(int format __unused) |
5763fb39 T |
487 | { |
488 | return 16; | |
489 | } | |
490 | ||
491 | int ExynosMPP::reconfigureOtf(exynos_mpp_img *src_img, exynos_mpp_img *dst_img) | |
492 | { | |
493 | int ret = 0; | |
494 | if (mGscHandle) { | |
495 | ret = stopMPP(mGscHandle); | |
496 | if (ret < 0) { | |
497 | ALOGE("failed to stop gscaler %u", mIndex); | |
498 | return ret; | |
499 | } | |
500 | mNeedReqbufs = true; | |
501 | mCountSameConfig = 0; | |
502 | } | |
503 | ||
504 | if (!mGscHandle) { | |
505 | mGscHandle = createMPP(AVAILABLE_GSC_UNITS[mIndex], | |
506 | GSC_OUTPUT_MODE, GSC_OUT_FIMD, false); | |
507 | if (!mGscHandle) { | |
508 | ALOGE("failed to create gscaler handle"); | |
509 | return -1; | |
510 | } | |
511 | } | |
512 | ||
513 | ret = configMPP(mGscHandle, src_img, dst_img); | |
514 | if (ret < 0) { | |
515 | ALOGE("failed to configure gscaler %u", mIndex); | |
516 | return ret; | |
517 | } | |
518 | ||
519 | return ret; | |
520 | } | |
521 | ||
522 | int ExynosMPP::processOTF(hwc_layer_1_t &layer) | |
523 | { | |
524 | ATRACE_CALL(); | |
525 | ALOGV("configuring gscaler %u for memory-to-fimd-localout", mIndex); | |
526 | ||
5763fb39 T |
527 | int ret = 0; |
528 | ||
529 | int dstAlign; | |
530 | ||
531 | exynos_mpp_img src_img, dst_img; | |
532 | memset(&src_img, 0, sizeof(src_img)); | |
533 | memset(&dst_img, 0, sizeof(dst_img)); | |
534 | ||
535 | setupSource(src_img, layer); | |
536 | setupOtfDestination(src_img, dst_img, layer); | |
537 | ||
538 | dstAlign = destinationAlign(dst_img.format); | |
539 | ||
540 | ALOGV("source configuration:"); | |
541 | dumpMPPImage(src_img); | |
542 | ||
543 | if (!mGscHandle || isSrcConfigChanged(src_img, mSrcConfig) || | |
544 | isDstConfigChanged(dst_img, mDstConfig)) { | |
545 | if (!isPerFrameSrcChanged(src_img, mSrcConfig) || | |
546 | !isPerFrameDstChanged(dst_img, mDstConfig)) { | |
547 | ret = reconfigureOtf(&src_img, &dst_img); | |
548 | if (ret < 0) | |
549 | goto err_gsc_local; | |
550 | } | |
551 | } | |
552 | ||
553 | if (isSourceCropChanged(src_img, mSrcConfig)) { | |
554 | setInputCrop(mGscHandle, &src_img, &dst_img); | |
555 | } | |
556 | ||
557 | ALOGV("destination configuration:"); | |
558 | dumpMPPImage(dst_img); | |
559 | ||
560 | ret = runMPP(mGscHandle, &src_img, &dst_img); | |
561 | if (ret < 0) { | |
562 | ALOGE("failed to run gscaler %u", mIndex); | |
563 | goto err_gsc_local; | |
564 | } | |
565 | ||
566 | memcpy(&mSrcConfig, &src_img, sizeof(mSrcConfig)); | |
567 | memcpy(&mDstConfig, &dst_img, sizeof(mDstConfig)); | |
568 | ||
569 | return 0; | |
570 | ||
571 | err_gsc_local: | |
572 | if (src_img.acquireFenceFd >= 0) | |
573 | close(src_img.acquireFenceFd); | |
574 | ||
575 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
576 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
577 | ||
578 | return ret; | |
579 | } | |
580 | ||
581 | bool ExynosMPP::setupDoubleOperation(exynos_mpp_img &src_img, exynos_mpp_img &mid_img, hwc_layer_1_t &layer) | |
582 | { | |
583 | /* check if GSC need to operate twice */ | |
584 | bool need_gsc_op_twice = false; | |
585 | bool need_unscaled_csc = false; | |
586 | private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle); | |
587 | const int max_upscale = 8; | |
588 | bool rot90or270 = !!(layer.transform & HAL_TRANSFORM_ROT_90); | |
589 | int src_w = WIDTH(layer.sourceCropf), src_h = HEIGHT(layer.sourceCropf); | |
590 | int dest_w, dest_h; | |
591 | if (rot90or270) { | |
592 | dest_w = HEIGHT(layer.displayFrame); | |
593 | dest_h = WIDTH(layer.displayFrame); | |
594 | } else { | |
595 | dest_w = WIDTH(layer.displayFrame); | |
596 | dest_h = HEIGHT(layer.displayFrame); | |
597 | } | |
598 | if (getDrmMode(src_handle->flags) != NO_DRM) | |
599 | need_gsc_op_twice = ((dest_w > src_w * max_upscale) || | |
600 | (dest_h > src_h * max_upscale)) ? true : false; | |
601 | ||
602 | if (isUsingMSC() && src_handle->format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED) { | |
603 | need_gsc_op_twice = true; | |
604 | need_unscaled_csc = true; | |
605 | } | |
606 | ||
607 | if (need_gsc_op_twice) { | |
608 | mid_img.x = 0; | |
609 | mid_img.y = 0; | |
610 | ||
611 | int mid_w = 0, mid_h = 0; | |
612 | ||
613 | if (need_unscaled_csc) { | |
614 | mid_img.w = src_w; | |
615 | mid_img.h = src_h; | |
616 | } else { | |
617 | if (rot90or270) { | |
618 | mid_w = HEIGHT(layer.displayFrame); | |
619 | mid_h = WIDTH(layer.displayFrame); | |
620 | } else { | |
621 | mid_w = WIDTH(layer.displayFrame); | |
622 | mid_h = HEIGHT(layer.displayFrame); | |
623 | } | |
624 | ||
625 | if (WIDTH(layer.sourceCropf) * max_upscale < mid_w) | |
626 | mid_img.w = (((mid_w + 7) / 8) + 1) & ~1; | |
627 | else | |
628 | mid_img.w = mid_w; | |
629 | ||
630 | if (HEIGHT(layer.sourceCropf) * max_upscale < mid_h) | |
631 | mid_img.h = (((mid_h + 7) / 8) + 1) & ~1; | |
632 | else | |
633 | mid_img.h = mid_h; | |
634 | } | |
635 | mid_img.drmMode = src_img.drmMode; | |
636 | mid_img.format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; | |
637 | ||
638 | if (layer.blending == HWC_BLENDING_PREMULT || layer.blending == HWC_BLENDING_COVERAGE) | |
639 | mid_img.pre_multi = false; | |
640 | else | |
641 | mid_img.pre_multi = true; | |
642 | ||
643 | mid_img.mem_type = GSC_MEM_DMABUF; | |
644 | mid_img.narrowRgb = !isFormatRgb(src_handle->format); | |
645 | } | |
646 | ||
647 | return need_gsc_op_twice; | |
648 | } | |
649 | ||
650 | void ExynosMPP::setupM2MDestination(exynos_mpp_img &src_img, exynos_mpp_img &dst_img, | |
651 | int dst_format, hwc_layer_1_t &layer, hwc_frect_t *sourceCrop) | |
652 | { | |
653 | private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle); | |
654 | dst_img.x = 0; | |
655 | dst_img.y = 0; | |
656 | dst_img.w = WIDTH(layer.displayFrame); | |
657 | dst_img.h = HEIGHT(layer.displayFrame); | |
658 | dst_img.rot = layer.transform; | |
659 | dst_img.drmMode = src_img.drmMode; | |
660 | dst_img.format = dst_format; | |
661 | ||
662 | if (layer.blending == HWC_BLENDING_PREMULT || layer.blending == HWC_BLENDING_COVERAGE) | |
663 | dst_img.pre_multi = false; | |
664 | else | |
665 | dst_img.pre_multi = true; | |
666 | ||
667 | dst_img.mem_type = GSC_MEM_DMABUF; | |
668 | if (src_handle->format == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL) | |
669 | dst_img.narrowRgb = 0; | |
670 | else | |
671 | dst_img.narrowRgb = !isFormatRgb(src_handle->format); | |
672 | if (dst_img.drmMode) | |
673 | alignCropAndCenter(dst_img.w, dst_img.h, sourceCrop, | |
674 | GSC_DST_CROP_W_ALIGNMENT_RGB888); | |
675 | } | |
676 | ||
677 | int ExynosMPP::reallocateBuffers(private_handle_t *src_handle, exynos_mpp_img &dst_img, exynos_mpp_img &mid_img, bool need_gsc_op_twice) | |
678 | { | |
679 | ATRACE_CALL(); | |
680 | alloc_device_t* alloc_device = mDisplay->mAllocDevice; | |
681 | int ret = 0; | |
682 | int dst_stride; | |
683 | int usage = GRALLOC_USAGE_SW_READ_NEVER | | |
684 | GRALLOC_USAGE_SW_WRITE_NEVER | | |
685 | GRALLOC_USAGE_NOZEROED | | |
686 | #ifdef USE_FB_PHY_LINEAR | |
687 | ((mIndex == FIMD_GSC_IDX) ? GRALLOC_USAGE_PHYSICALLY_LINEAR : 0) | | |
688 | #endif | |
689 | GRALLOC_USAGE_HW_COMPOSER; | |
690 | ||
691 | #ifdef USE_FB_PHY_LINEAR | |
692 | usage |= GRALLOC_USAGE_PROTECTED; | |
693 | usage &= ~GRALLOC_USAGE_PRIVATE_NONSECURE; | |
694 | #else | |
695 | if (getDrmMode(src_handle->flags) == SECURE_DRM) { | |
696 | usage |= GRALLOC_USAGE_PROTECTED; | |
697 | usage &= ~GRALLOC_USAGE_PRIVATE_NONSECURE; | |
698 | } else if (getDrmMode(src_handle->flags) == NORMAL_DRM) { | |
699 | usage |= GRALLOC_USAGE_PROTECTED; | |
700 | usage |= GRALLOC_USAGE_PRIVATE_NONSECURE; | |
701 | } | |
702 | #endif | |
703 | /* HACK: for distinguishing FIMD_VIDEO region */ | |
704 | if (!(src_handle->format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN || | |
705 | src_handle->format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN || | |
706 | src_handle->format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED)) { | |
707 | usage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER); | |
708 | } | |
709 | ||
710 | int w, h; | |
711 | { | |
712 | int dstAlign = destinationAlign(dst_img.format); | |
713 | w = ALIGN(mDisplay->mXres, dstAlign); | |
714 | h = ALIGN(mDisplay->mYres, dstAlign); | |
715 | } | |
716 | ||
717 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
718 | if (mDstBuffers[i]) { | |
719 | android::Mutex::Autolock lock(mMutex); | |
720 | mFreedBuffers.push_back(mDstBuffers[i]); | |
721 | mDstBuffers[i] = NULL; | |
722 | } | |
723 | ||
724 | if (mDstBufFence[i] >= 0) { | |
725 | close(mDstBufFence[i]); | |
726 | mDstBufFence[i] = -1; | |
727 | } | |
728 | ||
729 | if (mMidBuffers[i] != NULL) { | |
730 | android::Mutex::Autolock lock(mMutex); | |
731 | mFreedBuffers.push_back(mMidBuffers[i]); | |
732 | mMidBuffers[i] = NULL; | |
733 | } | |
734 | ||
735 | if (mMidBufFence[i] >= 0) { | |
736 | close(mMidBufFence[i]); | |
737 | mMidBufFence[i] = -1; | |
738 | } | |
739 | } | |
740 | ||
741 | if (getDrmMode(src_handle->flags) != NO_DRM && | |
742 | mDisplay != NULL && mDisplay->mHwc != NULL && | |
743 | (ExynosDisplay *)mDisplay->mHwc->externalDisplay == mDisplay) | |
744 | mNumAvailableDstBuffers = NUM_DRM_GSC_DST_BUFS; | |
745 | else | |
746 | mNumAvailableDstBuffers = NUM_GSC_DST_BUFS; | |
747 | ||
748 | for (size_t i = 0; i < mNumAvailableDstBuffers; i++) { | |
749 | int format = dst_img.format; | |
750 | ret = alloc_device->alloc(alloc_device, w, h, | |
751 | format, usage, &mDstBuffers[i], | |
752 | &dst_stride); | |
753 | if (ret < 0) { | |
754 | ALOGE("failed to allocate destination buffer(%dx%d): %s", w, h, | |
755 | strerror(-ret)); | |
756 | return ret; | |
757 | } | |
758 | ||
759 | if (need_gsc_op_twice) { | |
760 | ret = alloc_device->alloc(alloc_device, mid_img.w, mid_img.h, | |
761 | HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, usage, &mMidBuffers[i], | |
762 | &dst_stride); | |
763 | if (ret < 0) { | |
764 | ALOGE("failed to allocate intermediate buffer(%dx%d): %s", mid_img.w, mid_img.h, | |
765 | strerror(-ret)); | |
766 | return ret; | |
767 | } | |
768 | } | |
769 | } | |
770 | { | |
771 | android::Mutex::Autolock lock(mMutex); | |
772 | mBufferFreeThread->mCondition.signal(); | |
773 | } | |
774 | return ret; | |
775 | } | |
776 | ||
777 | #ifdef USES_VIRTUAL_DISPLAY | |
778 | int ExynosMPP::processM2M(hwc_layer_1_t &layer, int dst_format, hwc_frect_t *sourceCrop, bool isNeedBufferAlloc) | |
779 | #else | |
780 | int ExynosMPP::processM2M(hwc_layer_1_t &layer, int dst_format, hwc_frect_t *sourceCrop) | |
781 | #endif | |
782 | { | |
783 | ATRACE_CALL(); | |
784 | ALOGV("configuring gscaler %u for memory-to-memory", AVAILABLE_GSC_UNITS[mIndex]); | |
785 | ||
ad0fa79e | 786 | #ifdef USES_VIRTUAL_DISPLAY |
5763fb39 | 787 | alloc_device_t* alloc_device = mDisplay->mAllocDevice; |
ad0fa79e | 788 | #endif |
5763fb39 T |
789 | private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle); |
790 | buffer_handle_t dst_buf; | |
791 | private_handle_t *dst_handle; | |
792 | buffer_handle_t mid_buf; | |
793 | private_handle_t *mid_handle; | |
794 | int ret = 0; | |
5763fb39 T |
795 | |
796 | if (isUsingMSC()) { | |
797 | if (dst_format != HAL_PIXEL_FORMAT_RGB_565) | |
798 | dst_format = HAL_PIXEL_FORMAT_BGRA_8888; | |
799 | } | |
800 | ||
801 | exynos_mpp_img src_img, dst_img; | |
802 | memset(&src_img, 0, sizeof(src_img)); | |
803 | memset(&dst_img, 0, sizeof(dst_img)); | |
804 | exynos_mpp_img mid_img; | |
805 | memset(&mid_img, 0, sizeof(mid_img)); | |
806 | ||
807 | hwc_frect_t sourceCropTemp; | |
808 | if (!sourceCrop) | |
809 | sourceCrop = &sourceCropTemp; | |
810 | ||
811 | setupSource(src_img, layer); | |
812 | src_img.mem_type = GSC_MEM_DMABUF; | |
813 | ||
814 | if (isUsingMSC()) { | |
815 | if (src_img.format == HAL_PIXEL_FORMAT_RGBA_8888 || src_img.format == HAL_PIXEL_FORMAT_RGBX_8888) | |
816 | src_img.format = HAL_PIXEL_FORMAT_BGRA_8888; | |
817 | } | |
818 | ||
819 | bool need_gsc_op_twice = setupDoubleOperation(src_img, mid_img, layer); | |
820 | ||
821 | setupM2MDestination(src_img, dst_img, dst_format, layer, sourceCrop); | |
822 | ||
823 | #ifdef USES_VIRTUAL_DISPLAY | |
824 | if (!isNeedBufferAlloc) { | |
825 | dst_img.x = mDisplay->mHwc->mVirtualDisplayRect.left; | |
826 | dst_img.y = mDisplay->mHwc->mVirtualDisplayRect.top; | |
827 | dst_img.w = mDisplay->mHwc->mVirtualDisplayRect.width; | |
828 | dst_img.h = mDisplay->mHwc->mVirtualDisplayRect.height; | |
829 | } | |
830 | #endif | |
831 | ||
832 | ALOGV("source configuration:"); | |
833 | dumpMPPImage(src_img); | |
834 | ||
835 | bool reconfigure = isSrcConfigChanged(src_img, mSrcConfig) || | |
836 | isDstConfigChanged(dst_img, mDstConfig); | |
837 | ||
838 | #ifdef USES_VIRTUAL_DISPLAY | |
839 | if (isNeedBufferAlloc) { | |
840 | #endif | |
841 | bool realloc = mDstConfig.fw <= 0 || formatToBpp(mDstConfig.format) != formatToBpp(dst_format); | |
842 | ||
843 | /* ext_only andn int_only changes */ | |
844 | if (!need_gsc_op_twice && getDrmMode(src_handle->flags) == SECURE_DRM) { | |
845 | if (dst_img.drmMode != mDstConfig.drmMode) | |
846 | realloc = true; | |
847 | else | |
848 | realloc = false; | |
849 | } | |
850 | ||
851 | if (need_gsc_op_twice && isSrcConfigChanged(mid_img, mMidConfig)) | |
852 | realloc = true; | |
853 | ||
854 | if (need_gsc_op_twice && !mDoubleOperation) | |
855 | realloc = true; | |
856 | mDoubleOperation = need_gsc_op_twice; | |
857 | ||
858 | if (reconfigure && realloc) { | |
859 | if ((ret = reallocateBuffers(src_handle, dst_img, mid_img, need_gsc_op_twice)) < 0) | |
860 | goto err_alloc; | |
861 | ||
862 | mCurrentBuf = 0; | |
863 | mLastGSCLayerHandle = 0; | |
864 | } | |
865 | ||
866 | if (!reconfigure && (mLastGSCLayerHandle == (ptrdiff_t)layer.handle)) { | |
867 | ALOGV("[USE] GSC_SKIP_DUPLICATE_FRAME_PROCESSING\n"); | |
868 | if (layer.acquireFenceFd >= 0) | |
869 | close(layer.acquireFenceFd); | |
870 | ||
871 | layer.releaseFenceFd = -1; | |
872 | layer.acquireFenceFd = -1; | |
873 | mDstConfig.releaseFenceFd = -1; | |
874 | ||
875 | mCurrentBuf = (mCurrentBuf + mNumAvailableDstBuffers- 1) % mNumAvailableDstBuffers; | |
876 | return 0; | |
877 | } else { | |
878 | mLastGSCLayerHandle = (ptrdiff_t)layer.handle; | |
879 | } | |
880 | #ifdef USES_VIRTUAL_DISPLAY | |
881 | } else { | |
882 | if (reconfigure && need_gsc_op_twice) { | |
883 | int dst_stride; | |
884 | if (mMidBuffers[0] != NULL) { | |
885 | android::Mutex::Autolock lock(mMutex); | |
886 | mFreedBuffers.push_back(mMidBuffers[0]); | |
887 | mBufferFreeThread->mCondition.signal(); | |
888 | mMidBuffers[0] = NULL; | |
889 | } | |
890 | ||
891 | if (mMidBufFence[0] >= 0) { | |
892 | close(mMidBufFence[0]); | |
893 | mMidBufFence[0] = -1; | |
894 | } | |
895 | ||
896 | ret = alloc_device->alloc(alloc_device, mid_img.w, mid_img.h, | |
897 | HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, ((ExynosVirtualDisplay*)mDisplay)->mSinkUsage, &mMidBuffers[0], | |
898 | &dst_stride); | |
899 | if (ret < 0) { | |
900 | ALOGE("failed to allocate intermediate buffer(%dx%d): %s", mid_img.w, mid_img.h, | |
901 | strerror(-ret)); | |
902 | goto err_alloc; | |
903 | } | |
904 | } | |
905 | } | |
906 | #endif | |
907 | ||
908 | layer.acquireFenceFd = -1; | |
909 | if (need_gsc_op_twice) { | |
910 | mid_img.acquireFenceFd = mMidBufFence[mCurrentBuf]; | |
911 | mMidBufFence[mCurrentBuf] = -1; | |
912 | mid_buf = mMidBuffers[mCurrentBuf]; | |
913 | mid_handle = private_handle_t::dynamicCast(mid_buf); | |
914 | ||
915 | mid_img.fw = mid_handle->stride; | |
916 | mid_img.fh = mid_handle->vstride; | |
917 | mid_img.yaddr = mid_handle->fd; | |
918 | if (isFormatYCrCb(mid_handle->format)) { | |
919 | mid_img.uaddr = mid_handle->fd2; | |
920 | mid_img.vaddr = mid_handle->fd1; | |
921 | } else { | |
922 | mid_img.uaddr = mid_handle->fd1; | |
923 | mid_img.vaddr = mid_handle->fd2; | |
924 | } | |
925 | //mid_img.acquireFenceFd = -1; | |
926 | ||
927 | ALOGV("mid configuration:"); | |
928 | dumpMPPImage(mid_img); | |
929 | } | |
930 | ||
931 | dst_buf = mDstBuffers[mCurrentBuf]; | |
932 | dst_handle = private_handle_t::dynamicCast(dst_buf); | |
933 | ||
934 | dst_img.fw = dst_handle->stride; | |
935 | dst_img.fh = dst_handle->vstride; | |
936 | dst_img.yaddr = dst_handle->fd; | |
937 | dst_img.uaddr = dst_handle->fd1; | |
938 | dst_img.vaddr = dst_handle->fd2; | |
939 | dst_img.acquireFenceFd = mDstBufFence[mCurrentBuf]; | |
940 | mDstBufFence[mCurrentBuf] = -1; | |
941 | ||
942 | ALOGV("destination configuration:"); | |
943 | dumpMPPImage(dst_img); | |
944 | ||
945 | if ((int)dst_img.w != WIDTH(layer.displayFrame)) | |
946 | ALOGV("padding %u x %u output to %u x %u and cropping to {%7.1f,%7.1f,%7.1f,%7.1f}", | |
947 | WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame), | |
948 | dst_img.w, dst_img.h, sourceCrop->left, sourceCrop->top, | |
949 | sourceCrop->right, sourceCrop->bottom); | |
950 | ||
951 | if (mGscHandle) { | |
952 | ALOGV("reusing open gscaler %u", AVAILABLE_GSC_UNITS[mIndex]); | |
953 | } else { | |
954 | ALOGV("opening gscaler %u", AVAILABLE_GSC_UNITS[mIndex]); | |
955 | mGscHandle = createMPP( | |
956 | AVAILABLE_GSC_UNITS[mIndex], GSC_M2M_MODE, GSC_DUMMY, (getDrmMode(src_handle->flags) != NO_DRM)); | |
957 | if (!mGscHandle) { | |
958 | ALOGE("failed to create gscaler handle"); | |
959 | ret = -1; | |
960 | goto err_alloc; | |
961 | } | |
962 | } | |
963 | ||
964 | if (!need_gsc_op_twice) | |
965 | memcpy(&mid_img, &dst_img, sizeof(exynos_mpp_img)); | |
966 | ||
967 | /* src -> mid or src->dest */ | |
968 | if (reconfigure || need_gsc_op_twice) { | |
969 | ret = stopMPP(mGscHandle); | |
970 | if (ret < 0) { | |
971 | ALOGE("failed to stop gscaler %u", mIndex); | |
972 | goto err_gsc_config; | |
973 | } | |
974 | ||
975 | ret = setCSCProperty(mGscHandle, 0, !mid_img.narrowRgb, 1); | |
976 | ret = configMPP(mGscHandle, &src_img, &mid_img); | |
977 | if (ret < 0) { | |
978 | ALOGE("failed to configure gscaler %u", mIndex); | |
979 | goto err_gsc_config; | |
980 | } | |
981 | } | |
982 | ||
983 | ret = runMPP(mGscHandle, &src_img, &mid_img); | |
984 | if (ret < 0) { | |
985 | ALOGE("failed to run gscaler %u", mIndex); | |
986 | goto err_gsc_config; | |
987 | } | |
988 | ||
989 | /* mid -> dst */ | |
990 | if (need_gsc_op_twice) { | |
991 | ret = stopMPP(mGscHandle); | |
992 | if (ret < 0) { | |
993 | ALOGE("failed to stop gscaler %u", mIndex); | |
994 | goto err_gsc_config; | |
995 | } | |
996 | ||
997 | mid_img.acquireFenceFd = mid_img.releaseFenceFd; | |
998 | ||
999 | ret = setCSCProperty(mGscHandle, 0, !dst_img.narrowRgb, 1); | |
1000 | ret = configMPP(mGscHandle, &mid_img, &dst_img); | |
1001 | if (ret < 0) { | |
1002 | ALOGE("failed to configure gscaler %u", mIndex); | |
1003 | goto err_gsc_config; | |
1004 | } | |
1005 | ||
1006 | ret = runMPP(mGscHandle, &mid_img, &dst_img); | |
1007 | if (ret < 0) { | |
1008 | ALOGE("failed to run gscaler %u", mIndex); | |
1009 | goto err_gsc_config; | |
1010 | } | |
1011 | mMidBufFence[mCurrentBuf] = mid_img.releaseFenceFd; | |
1012 | } | |
1013 | ||
1014 | mSrcConfig = src_img; | |
1015 | mMidConfig = mid_img; | |
1016 | ||
1017 | if (need_gsc_op_twice) { | |
1018 | mDstConfig = dst_img; | |
1019 | } else { | |
1020 | mDstConfig = mid_img; | |
1021 | } | |
1022 | ||
1023 | layer.releaseFenceFd = src_img.releaseFenceFd; | |
1024 | ||
1025 | return 0; | |
1026 | ||
1027 | err_gsc_config: | |
1028 | if (mGscHandle) | |
1029 | destroyMPP(mGscHandle); | |
1030 | mGscHandle = NULL; | |
1031 | libmpp = NULL; | |
1032 | err_alloc: | |
1033 | if (src_img.acquireFenceFd >= 0) | |
1034 | close(src_img.acquireFenceFd); | |
1035 | #ifdef USES_VIRTUAL_DISPLAY | |
1036 | if (isNeedBufferAlloc) { | |
1037 | #endif | |
1038 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
1039 | if (mDstBuffers[i]) { | |
1040 | android::Mutex::Autolock lock(mMutex); | |
1041 | mFreedBuffers.push_back(mDstBuffers[i]); | |
1042 | mDstBuffers[i] = NULL; | |
1043 | } | |
1044 | if (mDstBufFence[i] >= 0) { | |
1045 | close(mDstBufFence[i]); | |
1046 | mDstBufFence[i] = -1; | |
1047 | } | |
1048 | if (mMidBuffers[i]) { | |
1049 | android::Mutex::Autolock lock(mMutex); | |
1050 | mFreedBuffers.push_back(mMidBuffers[i]); | |
1051 | mMidBuffers[i] = NULL; | |
1052 | } | |
1053 | if (mMidBufFence[i] >= 0) { | |
1054 | close(mMidBufFence[i]); | |
1055 | mMidBufFence[i] = -1; | |
1056 | } | |
1057 | } | |
1058 | #ifdef USES_VIRTUAL_DISPLAY | |
1059 | } else { | |
1060 | if (mMidBuffers[0]) { | |
1061 | android::Mutex::Autolock lock(mMutex); | |
1062 | mFreedBuffers.push_back(mMidBuffers[0]); | |
1063 | mMidBuffers[0] = NULL; | |
1064 | } | |
1065 | if (mMidBufFence[0] >= 0) { | |
1066 | close(mMidBufFence[0]); | |
1067 | mMidBufFence[0] = -1; | |
1068 | } | |
1069 | } | |
1070 | #endif | |
1071 | { | |
1072 | android::Mutex::Autolock lock(mMutex); | |
1073 | mBufferFreeThread->mCondition.signal(); | |
1074 | } | |
1075 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
1076 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
1077 | memset(&mMidConfig, 0, sizeof(mMidConfig)); | |
1078 | return ret; | |
1079 | } | |
1080 | ||
1081 | void ExynosMPP::cleanupM2M() | |
1082 | { | |
1083 | cleanupM2M(false); | |
1084 | } | |
1085 | ||
1086 | void ExynosMPP::cleanupM2M(bool noFenceWait) | |
1087 | { | |
1088 | ATRACE_CALL(); | |
1089 | if (!mGscHandle) | |
1090 | return; | |
1091 | ||
1092 | ALOGV("closing gscaler %u", AVAILABLE_GSC_UNITS[mIndex]); | |
1093 | ||
1094 | if (!noFenceWait) { | |
1095 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
1096 | #ifndef FORCEFB_YUVLAYER | |
1097 | if (mDstBufFence[i] >= 0) | |
1098 | if (sync_wait(mDstBufFence[i], 1000) < 0) | |
1099 | ALOGE("sync_wait error"); | |
1100 | #endif | |
1101 | if (mMidBufFence[i] >= 0) | |
1102 | if (sync_wait(mMidBufFence[i], 1000) < 0) | |
1103 | ALOGE("sync_wait error"); | |
1104 | } | |
1105 | } | |
1106 | ||
1107 | if (mGscHandle) { | |
1108 | stopMPP(mGscHandle); | |
1109 | destroyMPP(mGscHandle); | |
1110 | } | |
1111 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
1112 | if (mDstBuffers[i]) { | |
1113 | android::Mutex::Autolock lock(mMutex); | |
1114 | mFreedBuffers.push_back(mDstBuffers[i]); | |
1115 | } | |
1116 | if (mDstBufFence[i] >= 0) | |
1117 | close(mDstBufFence[i]); | |
1118 | if (mMidBuffers[i]) { | |
1119 | android::Mutex::Autolock lock(mMutex); | |
1120 | mFreedBuffers.push_back(mMidBuffers[i]); | |
1121 | mMidBuffers[i] = NULL; | |
1122 | } | |
1123 | if (mMidBufFence[i] >= 0) | |
1124 | close(mMidBufFence[i]); | |
1125 | } | |
1126 | { | |
1127 | android::Mutex::Autolock lock(mMutex); | |
1128 | mBufferFreeThread->mCondition.signal(); | |
1129 | } | |
1130 | ||
1131 | mGscHandle = NULL; | |
1132 | libmpp = NULL; | |
1133 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
1134 | memset(&mMidConfig, 0, sizeof(mMidConfig)); | |
1135 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
1136 | memset(mDstBuffers, 0, sizeof(mDstBuffers)); | |
1137 | memset(mMidBuffers, 0, sizeof(mMidBuffers)); | |
1138 | mCurrentBuf = 0; | |
1139 | mGSCMode = 0; | |
1140 | mLastGSCLayerHandle = 0; | |
1141 | ||
1142 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
1143 | mDstBufFence[i] = -1; | |
1144 | mMidBufFence[i] = -1; | |
1145 | } | |
1146 | } | |
1147 | ||
1148 | void ExynosMPP::cleanupOTF() | |
1149 | { | |
1150 | if (mGscHandle) { | |
1151 | stopMPP(mGscHandle); | |
1152 | freeMPP(mGscHandle); | |
1153 | } | |
1154 | ||
1155 | mNeedReqbufs = false; | |
1156 | mWaitVsyncCount = 0; | |
1157 | mDisplay->mOtfMode = OTF_OFF; | |
1158 | mGscHandle = NULL; | |
1159 | libmpp = NULL; | |
1160 | memset(&mSrcConfig, 0, sizeof(mSrcConfig)); | |
1161 | memset(&mMidConfig, 0, sizeof(mMidConfig)); | |
1162 | memset(&mDstConfig, 0, sizeof(mDstConfig)); | |
1163 | memset(mDstBuffers, 0, sizeof(mDstBuffers)); | |
1164 | memset(mMidBuffers, 0, sizeof(mMidBuffers)); | |
1165 | mCurrentBuf = 0; | |
1166 | mGSCMode = 0; | |
1167 | mLastGSCLayerHandle = 0; | |
1168 | ||
1169 | for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { | |
1170 | mDstBufFence[i] = -1; | |
1171 | mMidBufFence[i] = -1; | |
1172 | } | |
1173 | } | |
1174 | ||
1175 | bool ExynosMPP::rotationSupported(bool rotation) | |
1176 | { | |
1177 | return !rotation; | |
1178 | } | |
1179 | ||
1180 | bool ExynosMPP::paritySupported(int w, int h) | |
1181 | { | |
1182 | return (w % 2 == 0) && (h % 2 == 0); | |
1183 | } | |
1184 | ||
1185 | bool ExynosMPP::isDstConfigChanged(exynos_mpp_img &c1, exynos_mpp_img &c2) | |
1186 | { | |
1187 | return c1.x != c2.x || | |
1188 | c1.y != c2.y || | |
1189 | c1.w != c2.w || | |
1190 | c1.h != c2.h || | |
1191 | c1.format != c2.format || | |
1192 | c1.rot != c2.rot || | |
1193 | c1.narrowRgb != c2.narrowRgb || | |
1194 | c1.cacheable != c2.cacheable || | |
1195 | c1.pre_multi != c2.pre_multi || | |
1196 | c1.drmMode != c2.drmMode; | |
1197 | } | |
1198 | ||
ad0fa79e | 1199 | bool ExynosMPP::isSourceCropChanged(exynos_mpp_img &c1 __unused, exynos_mpp_img &c2 __unused) |
5763fb39 T |
1200 | { |
1201 | return false; | |
1202 | } | |
1203 | ||
ad0fa79e | 1204 | bool ExynosMPP::isPerFrameSrcChanged(exynos_mpp_img &c1 __unused, exynos_mpp_img &c2 __unused) |
5763fb39 T |
1205 | { |
1206 | return false; | |
1207 | } | |
1208 | ||
ad0fa79e | 1209 | bool ExynosMPP::isPerFrameDstChanged(exynos_mpp_img &c1 __unused, exynos_mpp_img &c2 __unused) |
5763fb39 T |
1210 | { |
1211 | return false; | |
1212 | } | |
1213 | ||
1214 | bool ExynosMPP::isReallocationRequired(int w, int h, exynos_mpp_img &c1, exynos_mpp_img &c2) | |
1215 | { | |
1216 | return ALIGN(w, GSC_W_ALIGNMENT) != ALIGN(c2.fw, GSC_W_ALIGNMENT) || | |
1217 | ALIGN(h, GSC_H_ALIGNMENT) != ALIGN(c2.fh, GSC_H_ALIGNMENT) || | |
1218 | c1.format != c2.format || | |
1219 | c1.drmMode != c2.drmMode; | |
1220 | } | |
1221 | ||
1222 | uint32_t ExynosMPP::halFormatToMPPFormat(int format) | |
1223 | { | |
1224 | switch (format) { | |
1225 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1226 | return HAL_PIXEL_FORMAT_BGRA_8888; | |
1227 | case HAL_PIXEL_FORMAT_BGRA_8888: | |
1228 | return HAL_PIXEL_FORMAT_RGBA_8888; | |
1229 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1230 | return HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; | |
1231 | default: | |
1232 | return format; | |
1233 | } | |
1234 | } | |
1235 | ||
1236 | int ExynosMPP::minWidth(hwc_layer_1_t &layer) | |
1237 | { | |
1238 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1239 | switch (handle->format) { | |
1240 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1241 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1242 | case HAL_PIXEL_FORMAT_RGB_565: | |
1243 | return isRotated(layer) ? 16 : 32; | |
1244 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1245 | case HAL_PIXEL_FORMAT_YV12: | |
1246 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1247 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1248 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1249 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1250 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1251 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1252 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1253 | default: | |
1254 | return isRotated(layer) ? 32 : 64; | |
1255 | } | |
1256 | } | |
1257 | ||
1258 | int ExynosMPP::minHeight(hwc_layer_1_t &layer) | |
1259 | { | |
1260 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1261 | switch (handle->format) { | |
1262 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1263 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1264 | case HAL_PIXEL_FORMAT_RGB_565: | |
1265 | return isRotated(layer) ? 32 : 16; | |
1266 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1267 | case HAL_PIXEL_FORMAT_YV12: | |
1268 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1269 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1270 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1271 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1272 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1273 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1274 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1275 | default: | |
1276 | return isRotated(layer) ? 64 : 32; | |
1277 | } | |
1278 | } | |
1279 | ||
1280 | int ExynosMPP::maxWidth(hwc_layer_1_t &layer) | |
1281 | { | |
1282 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1283 | ||
1284 | if (isUsingMSC()) | |
1285 | return 8192; | |
1286 | ||
1287 | switch (handle->format) { | |
1288 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1289 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1290 | case HAL_PIXEL_FORMAT_RGB_565: | |
1291 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1292 | case HAL_PIXEL_FORMAT_YV12: | |
1293 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1294 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1295 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1296 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1297 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1298 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1299 | return 4800; | |
1300 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1301 | default: | |
1302 | return 2047; | |
1303 | } | |
1304 | } | |
1305 | ||
1306 | int ExynosMPP::maxHeight(hwc_layer_1_t &layer) | |
1307 | { | |
1308 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1309 | ||
1310 | if (isUsingMSC()) | |
1311 | return 8192; | |
1312 | ||
1313 | switch (handle->format) { | |
1314 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1315 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1316 | case HAL_PIXEL_FORMAT_RGB_565: | |
1317 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1318 | case HAL_PIXEL_FORMAT_YV12: | |
1319 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1320 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1321 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1322 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1323 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1324 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1325 | return 3344; | |
1326 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1327 | default: | |
1328 | return 2047; | |
1329 | } | |
1330 | } | |
1331 | ||
1332 | int ExynosMPP::srcXOffsetAlign(hwc_layer_1_t &layer) | |
1333 | { | |
1334 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1335 | switch (handle->format) { | |
1336 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1337 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1338 | case HAL_PIXEL_FORMAT_RGB_565: | |
1339 | return 1; | |
1340 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1341 | case HAL_PIXEL_FORMAT_YV12: | |
1342 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1343 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1344 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1345 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1346 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1347 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1348 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1349 | default: | |
1350 | return 2; | |
1351 | } | |
1352 | } | |
1353 | ||
1354 | int ExynosMPP::srcYOffsetAlign(hwc_layer_1_t &layer) | |
1355 | { | |
1356 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1357 | switch (handle->format) { | |
1358 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
1359 | case HAL_PIXEL_FORMAT_RGBX_8888: | |
1360 | case HAL_PIXEL_FORMAT_RGB_565: | |
1361 | case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: | |
1362 | case HAL_PIXEL_FORMAT_YV12: | |
1363 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: | |
1364 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: | |
1365 | case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: | |
1366 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: | |
1367 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: | |
1368 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: | |
1369 | return 1; | |
1370 | case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: | |
1371 | default: | |
1372 | return isRotated(layer) ? 2 : 1; | |
1373 | } | |
1374 | } | |
1375 | ||
1376 | void *ExynosMPP::createMPP(int id, int mode, int outputMode, int drm) | |
1377 | { | |
1378 | ATRACE_CALL(); | |
1379 | mppFact = new MppFactory(); | |
1380 | libmpp = mppFact->CreateMpp(id, mode, outputMode, drm); | |
1381 | ||
1382 | return reinterpret_cast<void *>(libmpp); | |
1383 | } | |
1384 | ||
1385 | int ExynosMPP::configMPP(void *handle, exynos_mpp_img *src, exynos_mpp_img *dst) | |
1386 | { | |
1387 | ATRACE_CALL(); | |
1388 | return libmpp->ConfigMpp(handle, src, dst); | |
1389 | } | |
1390 | ||
1391 | int ExynosMPP::runMPP(void *handle, exynos_mpp_img *src, exynos_mpp_img *dst) | |
1392 | { | |
1393 | ATRACE_CALL(); | |
1394 | return libmpp->RunMpp(handle, src, dst); | |
1395 | } | |
1396 | ||
1397 | int ExynosMPP::stopMPP(void *handle) | |
1398 | { | |
1399 | ATRACE_CALL(); | |
1400 | return libmpp->StopMpp(handle); | |
1401 | } | |
1402 | ||
1403 | void ExynosMPP::destroyMPP(void *handle) | |
1404 | { | |
1405 | ATRACE_CALL(); | |
1406 | libmpp->DestroyMpp(handle); | |
1407 | delete(mppFact); | |
1408 | } | |
1409 | ||
1410 | int ExynosMPP::setCSCProperty(void *handle, unsigned int eqAuto, unsigned int fullRange, unsigned int colorspace) | |
1411 | { | |
1412 | return libmpp->SetCSCProperty(handle, eqAuto, fullRange, colorspace); | |
1413 | } | |
1414 | ||
1415 | int ExynosMPP::freeMPP(void *handle) | |
1416 | { | |
1417 | ATRACE_CALL(); | |
1418 | return libmpp->FreeMpp(handle); | |
1419 | } | |
1420 | ||
1421 | int ExynosMPP::setInputCrop(void *handle, exynos_mpp_img *src, exynos_mpp_img *dst) | |
1422 | { | |
1423 | return libmpp->SetInputCrop(handle, src, dst); | |
1424 | } | |
1425 | ||
1426 | bool ExynosMPP::bufferChanged(hwc_layer_1_t &layer) | |
1427 | { | |
1428 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1429 | return mSrcConfig.fw != (uint32_t)handle->stride || | |
1430 | mSrcConfig.fh != (uint32_t)handle->vstride || | |
1431 | mSrcConfig.format != (uint32_t)handle->format || | |
1432 | mDstConfig.rot != (uint32_t)layer.transform; | |
1433 | } | |
1434 | ||
1435 | bool ExynosMPP::needsReqbufs() | |
1436 | { | |
1437 | return mNeedReqbufs; | |
1438 | } | |
1439 | ||
1440 | bool ExynosMPP::inUse() | |
1441 | { | |
1442 | return mGscHandle != NULL; | |
1443 | } | |
1444 | ||
1445 | void ExynosMPP::freeBuffers() | |
1446 | { | |
1447 | alloc_device_t* alloc_device = mDisplay->mAllocDevice; | |
1448 | android::List<buffer_handle_t >::iterator it; | |
1449 | android::List<buffer_handle_t >::iterator end; | |
1450 | { | |
1451 | android::Mutex::Autolock lock(mMutex); | |
1452 | it = mFreedBuffers.begin(); | |
1453 | end = mFreedBuffers.end(); | |
1454 | } | |
1455 | while (it != end) { | |
1456 | buffer_handle_t buffer = (buffer_handle_t)(*it); | |
1457 | alloc_device->free(alloc_device, buffer); | |
1458 | { | |
1459 | android::Mutex::Autolock lock(mMutex); | |
1460 | it = mFreedBuffers.erase(it); | |
1461 | } | |
1462 | } | |
1463 | } | |
1464 | ||
1465 | bool BufferFreeThread::threadLoop() | |
1466 | { | |
1467 | while(mRunning) { | |
1468 | { | |
1469 | android::Mutex::Autolock lock(mExynosMPP->mMutex); | |
1470 | while(mExynosMPP->mFreedBuffers.size() == 0) { | |
1471 | mCondition.wait(mExynosMPP->mMutex); | |
1472 | } | |
1473 | } | |
1474 | mExynosMPP->freeBuffers(); | |
1475 | } | |
1476 | return true; | |
1477 | } | |
1478 | ||
1479 | bool ExynosMPP::isSrcCropAligned(hwc_layer_1_t &layer, bool rotation) | |
1480 | { | |
1481 | return !rotation || | |
1482 | ((uint32_t)layer.sourceCropf.left % srcXOffsetAlign(layer) == 0 && | |
1483 | (uint32_t)layer.sourceCropf.top % srcYOffsetAlign(layer) == 0); | |
1484 | } |