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
31using namespace qdutils;
32using namespace overlay;
33using overlay::Rotator;
34using namespace overlay::utils;
35
36namespace qhwc {
37
38namespace ovutils = overlay::utils;
39
40IFBUpdate* 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
49IFBUpdate::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
67void IFBUpdate::reset() {
68    mModeOn = false;
69    mRot = NULL;
70}
71
72bool 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====================================
81FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
82        IFBUpdate(ctx, dpy) {}
83
84void FBUpdateNonSplit::reset() {
85    IFBUpdate::reset();
86    mDest = ovutils::OV_INVALID;
87}
88
89bool 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
118bool 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
130bool 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
236bool 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====================================
260FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy):
261        IFBUpdate(ctx, dpy) {}
262
263void FBUpdateSplit::reset() {
264    IFBUpdate::reset();
265    mDestLeft = ovutils::OV_INVALID;
266    mDestRight = ovutils::OV_INVALID;
267    mRot = NULL;
268}
269
270bool 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
283bool 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
396bool 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====================================
421FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
422        FBUpdateSplit(ctx, dpy) {}
423
424bool 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