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