1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
4  *
5  * Not a Contribution, Apache license notifications and license are
6  * retained for attribution purposes only.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #define DEBUG_FBUPDATE 0
22 #include <cutils/properties.h>
23 #include <gralloc_priv.h>
24 #include <overlay.h>
25 #include <overlayRotator.h>
26 #include "hwc_fbupdate.h"
27 #include "mdp_version.h"
28 #include "external.h"
29 #include "virtual.h"
30 
31 using namespace qdutils;
32 using namespace overlay;
33 using overlay::Rotator;
34 using namespace overlay::utils;
35 
36 namespace qhwc {
37 
38 namespace ovutils = overlay::utils;
39 
getObject(hwc_context_t * ctx,const int & dpy)40 IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
41     if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
42         return new FBSrcSplit(ctx, dpy);
43     } else if(isDisplaySplit(ctx, dpy)) {
44         return new FBUpdateSplit(ctx, dpy);
45     }
46     return new FBUpdateNonSplit(ctx, dpy);
47 }
48 
IFBUpdate(hwc_context_t * ctx,const int & dpy)49 IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
50     unsigned int size = 0;
51     uint32_t xres = ctx->dpyAttr[mDpy].xres;
52     uint32_t yres = ctx->dpyAttr[mDpy].yres;
53     if (ctx->dpyAttr[dpy].customFBSize) {
54         //GPU will render and compose at new resolution
55         //So need to have FB at new resolution
56         xres = ctx->dpyAttr[mDpy].xres_new;
57         yres = ctx->dpyAttr[mDpy].yres_new;
58     }
59     getBufferAttributes((int)xres, (int)yres,
60             HAL_PIXEL_FORMAT_RGBA_8888,
61             0,
62             mAlignedFBWidth,
63             mAlignedFBHeight,
64             mTileEnabled, size);
65 }
66 
reset()67 void IFBUpdate::reset() {
68     mModeOn = false;
69     mRot = NULL;
70 }
71 
prepareAndValidate(hwc_context_t * ctx,hwc_display_contents_1 * list,int fbZorder)72 bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
73             hwc_display_contents_1 *list, int fbZorder) {
74     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
75     mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) &&
76             ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
77     return mModeOn;
78 }
79 
80 //================= Low res====================================
FBUpdateNonSplit(hwc_context_t * ctx,const int & dpy)81 FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
82         IFBUpdate(ctx, dpy) {}
83 
reset()84 void FBUpdateNonSplit::reset() {
85     IFBUpdate::reset();
86     mDest = ovutils::OV_INVALID;
87 }
88 
preRotateExtDisplay(hwc_context_t * ctx,hwc_layer_1_t * layer,ovutils::Whf & info,hwc_rect_t & sourceCrop,ovutils::eMdpFlags & mdpFlags,int & rotFlags)89 bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx,
90                                             hwc_layer_1_t *layer,
91                                             ovutils::Whf &info,
92                                             hwc_rect_t& sourceCrop,
93                                             ovutils::eMdpFlags& mdpFlags,
94                                             int& rotFlags)
95 {
96     int extOrient = getExtOrientation(ctx);
97     ovutils::eTransform orient = static_cast<ovutils::eTransform >(extOrient);
98     if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
99         mRot = ctx->mRotMgr->getNext();
100         if(mRot == NULL) return false;
101         ctx->mLayerRotMap[mDpy]->add(layer, mRot);
102         // Composed FB content will have black bars, if the viewFrame of the
103         // external is different from {0, 0, fbWidth, fbHeight}, so intersect
104         // viewFrame with sourceCrop to avoid those black bars
105         sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]);
106         //Configure rotator for pre-rotation
107         if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
108             ALOGE("%s: configRotator Failed!", __FUNCTION__);
109             mRot = NULL;
110             return false;
111         }
112         updateSource(orient, info, sourceCrop, mRot);
113         rotFlags |= ovutils::ROT_PREROTATED;
114     }
115     return true;
116 }
117 
prepare(hwc_context_t * ctx,hwc_display_contents_1 * list,hwc_rect_t fbUpdatingRect,int fbZorder)118 bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
119                              hwc_rect_t fbUpdatingRect, int fbZorder) {
120     if(!ctx->mMDP.hasOverlay) {
121         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
122                  __FUNCTION__);
123         return false;
124     }
125     mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
126     return mModeOn;
127 }
128 
129 // Configure
configure(hwc_context_t * ctx,hwc_display_contents_1 * list,hwc_rect_t fbUpdatingRect,int fbZorder)130 bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
131                                hwc_rect_t fbUpdatingRect, int fbZorder) {
132     bool ret = false;
133     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
134     if (LIKELY(ctx->mOverlay)) {
135         int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
136         // ext only layer present..
137         if(extOnlyLayerIndex != -1) {
138             layer = &list->hwLayers[extOnlyLayerIndex];
139             layer->compositionType = HWC_OVERLAY;
140         }
141         overlay::Overlay& ov = *(ctx->mOverlay);
142 
143         ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
144                 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
145                     mTileEnabled));
146 
147         Overlay::PipeSpecs pipeSpecs;
148         pipeSpecs.formatClass = Overlay::FORMAT_RGB;
149         pipeSpecs.needsScaling = qhwc::needsScaling(layer);
150         pipeSpecs.dpy = mDpy;
151         pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
152         pipeSpecs.fb = true;
153 
154         ovutils::eDest dest = ov.getPipe(pipeSpecs);
155         if(dest == ovutils::OV_INVALID) { //None available
156             ALOGE("%s: No pipes available to configure fb for dpy %d",
157                 __FUNCTION__, mDpy);
158             return false;
159         }
160         mDest = dest;
161 
162         if((mDpy && ctx->deviceOrientation) &&
163             ctx->listStats[mDpy].isDisplayAnimating) {
164             fbZorder = 0;
165         }
166 
167         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
168         ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
169         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
170 
171         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
172         hwc_rect_t displayFrame = layer->displayFrame;
173 
174         // No FB update optimization on (1) Custom FB resolution,
175         // (2) External Mirror mode, (3) External orientation
176         if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
177            && !ctx->mExtOrientation) {
178             sourceCrop = fbUpdatingRect;
179             displayFrame = fbUpdatingRect;
180         }
181 
182         int transform = layer->transform;
183         int rotFlags = ovutils::ROT_FLAGS_NONE;
184 
185         ovutils::eTransform orient =
186                     static_cast<ovutils::eTransform>(transform);
187         // use ext orientation if any
188         int extOrient = getExtOrientation(ctx);
189 
190         // Do not use getNonWormholeRegion() function to calculate the
191         // sourceCrop during animation on external display and
192         // Dont do wormhole calculation when extorientation is set on External
193         // Dont do wormhole calculation when extDownscale is enabled on External
194         if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
195             sourceCrop = layer->displayFrame;
196         } else if((!mDpy ||
197                   (mDpy && !extOrient
198                   && !ctx->dpyAttr[mDpy].mDownScaleMode))
199                   && (extOnlyLayerIndex == -1)) {
200             if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
201                 !ctx->dpyAttr[mDpy].customFBSize) {
202                 getNonWormholeRegion(list, sourceCrop);
203                 displayFrame = sourceCrop;
204             }
205         }
206         calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
207                                    transform, orient);
208         //Store the displayFrame, will be used in getDisplayViewFrame
209         ctx->dpyAttr[mDpy].mDstRect = displayFrame;
210         setMdpFlags(ctx, layer, mdpFlags, 0, transform);
211         // For External use rotator if there is a rotation value set
212         ret = preRotateExtDisplay(ctx, layer, info,
213                 sourceCrop, mdpFlags, rotFlags);
214         if(!ret) {
215             ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
216             return false;
217         }
218         //For the mdp, since either we are pre-rotating or MDP does flips
219         orient = ovutils::OVERLAY_TRANSFORM_0;
220         transform = 0;
221         ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
222                                static_cast<ovutils::eRotFlags>(rotFlags),
223                                ovutils::DEFAULT_PLANE_ALPHA,
224                                (ovutils::eBlending)
225                                getBlending(layer->blending));
226         ret = true;
227         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
228                     NULL, mDest) < 0) {
229             ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
230             ret = false;
231         }
232     }
233     return ret;
234 }
235 
draw(hwc_context_t * ctx,private_handle_t * hnd)236 bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
237 {
238     if(!mModeOn) {
239         return true;
240     }
241     bool ret = true;
242     overlay::Overlay& ov = *(ctx->mOverlay);
243     ovutils::eDest dest = mDest;
244     int fd = hnd->fd;
245     uint32_t offset = (uint32_t)hnd->offset;
246     if(mRot) {
247         if(!mRot->queueBuffer(fd, offset))
248             return false;
249         fd = mRot->getDstMemId();
250         offset = mRot->getDstOffset();
251     }
252     if (!ov.queueBuffer(fd, offset, dest)) {
253         ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
254         ret = false;
255     }
256     return ret;
257 }
258 
259 //================= High res====================================
FBUpdateSplit(hwc_context_t * ctx,const int & dpy)260 FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy):
261         IFBUpdate(ctx, dpy) {}
262 
reset()263 void FBUpdateSplit::reset() {
264     IFBUpdate::reset();
265     mDestLeft = ovutils::OV_INVALID;
266     mDestRight = ovutils::OV_INVALID;
267     mRot = NULL;
268 }
269 
prepare(hwc_context_t * ctx,hwc_display_contents_1 * list,hwc_rect_t fbUpdatingRect,int fbZorder)270 bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
271                               hwc_rect_t fbUpdatingRect, int fbZorder) {
272     if(!ctx->mMDP.hasOverlay) {
273         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
274                  __FUNCTION__);
275         return false;
276     }
277     mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
278     ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
279     return mModeOn;
280 }
281 
282 // Configure
configure(hwc_context_t * ctx,hwc_display_contents_1 * list,hwc_rect_t fbUpdatingRect,int fbZorder)283 bool FBUpdateSplit::configure(hwc_context_t *ctx,
284         hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
285     bool ret = false;
286     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
287     if (LIKELY(ctx->mOverlay)) {
288         /*  External only layer present */
289         int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
290         if(extOnlyLayerIndex != -1) {
291             layer = &list->hwLayers[extOnlyLayerIndex];
292             layer->compositionType = HWC_OVERLAY;
293         }
294         ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
295                           ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
296                                                 mTileEnabled));
297 
298         overlay::Overlay& ov = *(ctx->mOverlay);
299         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
300         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
301         ovutils::eTransform orient =
302             static_cast<ovutils::eTransform>(layer->transform);
303         const int hw_w = ctx->dpyAttr[mDpy].xres;
304         const int hw_h = ctx->dpyAttr[mDpy].yres;
305         const int lSplit = getLeftSplit(ctx, mDpy);
306         mDestLeft = ovutils::OV_INVALID;
307         mDestRight = ovutils::OV_INVALID;
308 
309         hwc_rect_t sourceCrop = fbUpdatingRect;
310         hwc_rect_t displayFrame = fbUpdatingRect;
311 
312         ret = true;
313         Overlay::PipeSpecs pipeSpecs;
314         pipeSpecs.formatClass = Overlay::FORMAT_RGB;
315         pipeSpecs.needsScaling = qhwc::needsScaling(layer);
316         pipeSpecs.dpy = mDpy;
317         pipeSpecs.fb = true;
318 
319         /* Configure left pipe */
320         if(displayFrame.left < lSplit) {
321             pipeSpecs.mixer = Overlay::MIXER_LEFT;
322             ovutils::eDest destL = ov.getPipe(pipeSpecs);
323             if(destL == ovutils::OV_INVALID) { //None available
324                 ALOGE("%s: No pipes available to configure fb for dpy %d's left"
325                       " mixer", __FUNCTION__, mDpy);
326                 return false;
327             }
328 
329             mDestLeft = destL;
330 
331             //XXX: FB layer plane alpha is currently sent as zero from
332             //surfaceflinger
333             ovutils::PipeArgs pargL(mdpFlags,
334                                     info,
335                                     zOrder,
336                                     ovutils::IS_FG_OFF,
337                                     ovutils::ROT_FLAGS_NONE,
338                                     ovutils::DEFAULT_PLANE_ALPHA,
339                                     (ovutils::eBlending)
340                                     getBlending(layer->blending));
341             hwc_rect_t cropL = sourceCrop;
342             hwc_rect_t dstL = displayFrame;
343             hwc_rect_t scissorL = {0, 0, lSplit, hw_h };
344             qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
345 
346             if (configMdp(ctx->mOverlay, pargL, orient, cropL,
347                            dstL, NULL, destL)< 0) {
348                 ALOGE("%s: configMdp fails for left FB", __FUNCTION__);
349                 ret = false;
350             }
351         }
352 
353         /* Configure right pipe */
354         if(displayFrame.right > lSplit) {
355             pipeSpecs.mixer = Overlay::MIXER_RIGHT;
356             ovutils::eDest destR = ov.getPipe(pipeSpecs);
357             if(destR == ovutils::OV_INVALID) { //None available
358                 ALOGE("%s: No pipes available to configure fb for dpy %d's"
359                       " right mixer", __FUNCTION__, mDpy);
360                 return false;
361             }
362 
363             mDestRight = destR;
364             ovutils::eMdpFlags mdpFlagsR = mdpFlags;
365             ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
366 
367             //XXX: FB layer plane alpha is currently sent as zero from
368             //surfaceflinger
369             ovutils::PipeArgs pargR(mdpFlagsR,
370                                     info,
371                                     zOrder,
372                                     ovutils::IS_FG_OFF,
373                                     ovutils::ROT_FLAGS_NONE,
374                                     ovutils::DEFAULT_PLANE_ALPHA,
375                                     (ovutils::eBlending)
376                                     getBlending(layer->blending));
377 
378             hwc_rect_t cropR = sourceCrop;
379             hwc_rect_t dstR = displayFrame;
380             hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h };
381             qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
382 
383             dstR.left -= lSplit;
384             dstR.right -= lSplit;
385 
386             if (configMdp(ctx->mOverlay, pargR, orient, cropR,
387                            dstR, NULL, destR) < 0) {
388                 ALOGE("%s: configMdp fails for right FB", __FUNCTION__);
389                 ret = false;
390             }
391         }
392     }
393     return ret;
394 }
395 
draw(hwc_context_t * ctx,private_handle_t * hnd)396 bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
397 {
398     if(!mModeOn) {
399         return true;
400     }
401     bool ret = true;
402     overlay::Overlay& ov = *(ctx->mOverlay);
403     if(mDestLeft != ovutils::OV_INVALID) {
404         if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) {
405             ALOGE("%s: queue failed for left of dpy = %d",
406                   __FUNCTION__, mDpy);
407             ret = false;
408         }
409     }
410     if(mDestRight != ovutils::OV_INVALID) {
411         if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) {
412             ALOGE("%s: queue failed for right of dpy = %d",
413                   __FUNCTION__, mDpy);
414             ret = false;
415         }
416     }
417     return ret;
418 }
419 
420 //=================FBSrcSplit====================================
FBSrcSplit(hwc_context_t * ctx,const int & dpy)421 FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
422         FBUpdateSplit(ctx, dpy) {}
423 
configure(hwc_context_t * ctx,hwc_display_contents_1 * list,hwc_rect_t fbUpdatingRect,int fbZorder)424 bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
425         hwc_rect_t fbUpdatingRect, int fbZorder) {
426     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
427     int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
428     // ext only layer present..
429     if(extOnlyLayerIndex != -1) {
430         layer = &list->hwLayers[extOnlyLayerIndex];
431         layer->compositionType = HWC_OVERLAY;
432     }
433 
434     overlay::Overlay& ov = *(ctx->mOverlay);
435 
436     ovutils::Whf info(mAlignedFBWidth,
437             mAlignedFBHeight,
438             ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
439                 mTileEnabled));
440 
441     ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
442     ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
443 
444     ovutils::PipeArgs parg(mdpFlags,
445             info,
446             zOrder,
447             ovutils::IS_FG_OFF,
448             ovutils::ROT_FLAGS_NONE,
449             ovutils::DEFAULT_PLANE_ALPHA,
450             (ovutils::eBlending)
451             getBlending(layer->blending));
452 
453     int transform = layer->transform;
454     ovutils::eTransform orient =
455             static_cast<ovutils::eTransform>(transform);
456 
457     hwc_rect_t cropL = fbUpdatingRect;
458     hwc_rect_t cropR = fbUpdatingRect;
459 
460     //Request left pipe (or 1 by default)
461     Overlay::PipeSpecs pipeSpecs;
462     pipeSpecs.formatClass = Overlay::FORMAT_RGB;
463     pipeSpecs.needsScaling = qhwc::needsScaling(layer);
464     pipeSpecs.dpy = mDpy;
465     pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
466     pipeSpecs.fb = true;
467     ovutils::eDest destL = ov.getPipe(pipeSpecs);
468     if(destL == ovutils::OV_INVALID) {
469         ALOGE("%s: No pipes available to configure fb for dpy %d's left"
470                 " mixer", __FUNCTION__, mDpy);
471         return false;
472     }
473 
474     ovutils::eDest destR = ovutils::OV_INVALID;
475 
476     /*  Use 2 pipes IF
477         a) FB's width is > 2048 or
478         b) On primary, driver has indicated with caps to split always. This is
479            based on an empirically derived value of panel height.
480     */
481 
482     bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
483             qdutils::MDPVersion::getInstance().isSrcSplitAlways();
484 
485     if(((fbUpdatingRect.right - fbUpdatingRect.left) >
486             qdutils::MAX_DISPLAY_DIM) or
487             primarySplitAlways) {
488         destR = ov.getPipe(pipeSpecs);
489         if(destR == ovutils::OV_INVALID) {
490             ALOGE("%s: No pipes available to configure fb for dpy %d's right"
491                     " mixer", __FUNCTION__, mDpy);
492             return false;
493         }
494 
495         if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
496             qhwc::swap(destL, destR);
497         }
498 
499         //Split crop equally when using 2 pipes
500         cropL.right = (fbUpdatingRect.right + fbUpdatingRect.left) / 2;
501         cropR.left = cropL.right;
502     }
503 
504     mDestLeft = destL;
505     mDestRight = destR;
506 
507     if(destL != OV_INVALID) {
508         if(configMdp(ctx->mOverlay, parg, orient,
509                     cropL, cropL, NULL /*metadata*/, destL) < 0) {
510             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
511             return false;
512         }
513     }
514 
515     //configure right pipe
516     if(destR != OV_INVALID) {
517         if(configMdp(ctx->mOverlay, parg, orient,
518                     cropR, cropR, NULL /*metadata*/, destR) < 0) {
519             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
520             return false;
521         }
522     }
523 
524     return true;
525 }
526 
527 //---------------------------------------------------------------------
528 }; //namespace qhwc
529