hwc_fbupdate.cpp revision 2e474227e216ee37ab84a3c9a22ea1f650626231
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, 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 <overlayRotator.h>
25#include "hwc_fbupdate.h"
26#include "mdp_version.h"
27#include "external.h"
28
29using namespace qdutils;
30
31using overlay::Rotator;
32
33namespace qhwc {
34
35namespace ovutils = overlay::utils;
36
37IFBUpdate* IFBUpdate::getObject(const int& width, const int& rightSplit,
38        const int& dpy) {
39    if(width > MAX_DISPLAY_DIM || rightSplit) {
40        return new FBUpdateHighRes(dpy);
41    }
42    return new FBUpdateLowRes(dpy);
43}
44
45inline void IFBUpdate::reset() {
46    mModeOn = false;
47    mRot = NULL;
48}
49
50//================= Low res====================================
51FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
52
53inline void FBUpdateLowRes::reset() {
54    IFBUpdate::reset();
55    mDest = ovutils::OV_INVALID;
56}
57
58bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
59                             int fbZorder) {
60    if(!ctx->mMDP.hasOverlay) {
61        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
62                 __FUNCTION__);
63        return false;
64    }
65    mModeOn = configure(ctx, list, fbZorder);
66    return mModeOn;
67}
68
69// Configure
70bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
71                               int fbZorder) {
72    bool ret = false;
73    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
74    if (LIKELY(ctx->mOverlay)) {
75        int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
76        // ext only layer present..
77        if(extOnlyLayerIndex != -1) {
78            layer = &list->hwLayers[extOnlyLayerIndex];
79            layer->compositionType = HWC_OVERLAY;
80        }
81        overlay::Overlay& ov = *(ctx->mOverlay);
82        private_handle_t *hnd = (private_handle_t *)layer->handle;
83        ovutils::Whf info(hnd->width, hnd->height,
84                          ovutils::getMdpFormat(hnd->format), hnd->size);
85
86        //Request a pipe
87        ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
88        if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) {
89            //For 8x26 external always use DMA pipe
90            type = ovutils::OV_MDP_PIPE_DMA;
91        }
92        ovutils::eDest dest = ov.nextPipe(type, mDpy);
93        if(dest == ovutils::OV_INVALID) { //None available
94            ALOGE("%s: No pipes available to configure fb for dpy %d",
95                __FUNCTION__, mDpy);
96            return false;
97        }
98
99        mDest = dest;
100
101        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
102        ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
103        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
104
105        hwc_rect_t sourceCrop = layer->sourceCrop;
106        hwc_rect_t displayFrame = layer->displayFrame;
107        int transform = layer->transform;
108        int fbWidth  = ctx->dpyAttr[mDpy].xres;
109        int fbHeight = ctx->dpyAttr[mDpy].yres;
110        int rotFlags = ovutils::ROT_FLAGS_NONE;
111
112        ovutils::eTransform orient =
113                    static_cast<ovutils::eTransform>(transform);
114        if(mDpy && ctx->mExtOrientation) {
115            // If there is a external orientation set, use that
116            transform = ctx->mExtOrientation;
117            orient = static_cast<ovutils::eTransform >(ctx->mExtOrientation);
118        }
119
120        // Do not use getNonWormholeRegion() function to calculate the
121        // sourceCrop during animation on external display and
122        // Dont do wormhole calculation when extorientation is set on External
123        if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
124            sourceCrop = layer->displayFrame;
125            displayFrame = sourceCrop;
126        } else if((!mDpy || (mDpy && !ctx->mExtOrientation))
127                               && extOnlyLayerIndex == -1) {
128            if(!qdutils::MDPVersion::getInstance().is8x26()) {
129                getNonWormholeRegion(list, sourceCrop);
130                displayFrame = sourceCrop;
131            }
132        }
133        ovutils::Dim dpos(displayFrame.left,
134                          displayFrame.top,
135                          displayFrame.right - displayFrame.left,
136                          displayFrame.bottom - displayFrame.top);
137
138        if(mDpy && !qdutils::MDPVersion::getInstance().is8x26()) {
139            // Get Aspect Ratio for external
140            getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
141                                    dpos.y, dpos.w, dpos.h);
142            // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
143            getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
144            // Convert dim to hwc_rect_t
145            displayFrame.left = dpos.x;
146            displayFrame.top = dpos.y;
147            displayFrame.right = dpos.w + displayFrame.left;
148            displayFrame.bottom = dpos.h + displayFrame.top;
149        }
150        setMdpFlags(layer, mdpFlags, 0, transform);
151        // For External use rotator if there is a rotation value set
152        if(mDpy && (ctx->mExtOrientation & HWC_TRANSFORM_ROT_90)) {
153            mRot = ctx->mRotMgr->getNext();
154            if(mRot == NULL) return -1;
155            //Configure rotator for pre-rotation
156            if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
157                ALOGE("%s: configRotator Failed!", __FUNCTION__);
158                mRot = NULL;
159                return -1;
160            }
161            info.format = (mRot)->getDstFormat();
162            updateSource(orient, info, sourceCrop);
163            rotFlags |= ovutils::ROT_PREROTATED;
164        }
165        //For the mdp, since either we are pre-rotating or MDP does flips
166        orient = ovutils::OVERLAY_TRANSFORM_0;
167        transform = 0;
168        ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
169                                static_cast<ovutils::eRotFlags>(rotFlags));
170        ret = true;
171        if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
172                    NULL, mDest) < 0) {
173            ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
174            ret = false;
175        }
176    }
177    return ret;
178}
179
180bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
181{
182    if(!mModeOn) {
183        return true;
184    }
185    bool ret = true;
186    overlay::Overlay& ov = *(ctx->mOverlay);
187    ovutils::eDest dest = mDest;
188    int fd = hnd->fd;
189    uint32_t offset = hnd->offset;
190    if(mRot) {
191        if(!mRot->queueBuffer(fd, offset))
192            return false;
193        fd = mRot->getDstMemId();
194        offset = mRot->getDstOffset();
195    }
196    if (!ov.queueBuffer(fd, offset, dest)) {
197        ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
198        ret = false;
199    }
200    return ret;
201}
202
203//================= High res====================================
204FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
205
206inline void FBUpdateHighRes::reset() {
207    IFBUpdate::reset();
208    mDestLeft = ovutils::OV_INVALID;
209    mDestRight = ovutils::OV_INVALID;
210    mRot = NULL;
211}
212
213bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
214                              int fbZorder) {
215    if(!ctx->mMDP.hasOverlay) {
216        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
217                 __FUNCTION__);
218        return false;
219    }
220    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
221    mModeOn = configure(ctx, list, fbZorder);
222    return mModeOn;
223}
224
225// Configure
226bool FBUpdateHighRes::configure(hwc_context_t *ctx,
227        hwc_display_contents_1 *list, int fbZorder) {
228    bool ret = false;
229    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
230    if (LIKELY(ctx->mOverlay)) {
231        int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
232        // ext only layer present..
233        if(extOnlyLayerIndex != -1) {
234            layer = &list->hwLayers[extOnlyLayerIndex];
235            layer->compositionType = HWC_OVERLAY;
236        }
237        overlay::Overlay& ov = *(ctx->mOverlay);
238        private_handle_t *hnd = (private_handle_t *)layer->handle;
239        ovutils::Whf info(hnd->width, hnd->height,
240                          ovutils::getMdpFormat(hnd->format), hnd->size);
241
242        //Request left pipe
243        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
244        if(destL == ovutils::OV_INVALID) { //None available
245            ALOGE("%s: No pipes available to configure fb for dpy %d's left"
246                    " mixer", __FUNCTION__, mDpy);
247            return false;
248        }
249        //Request right pipe
250        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
251        if(destR == ovutils::OV_INVALID) { //None available
252            ALOGE("%s: No pipes available to configure fb for dpy %d's right"
253                    " mixer", __FUNCTION__, mDpy);
254            return false;
255        }
256
257        mDestLeft = destL;
258        mDestRight = destR;
259
260        ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT;
261
262        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
263
264        ovutils::PipeArgs pargL(mdpFlagsL,
265                                info,
266                                zOrder,
267                                ovutils::IS_FG_OFF,
268                                ovutils::ROT_FLAGS_NONE);
269        ov.setSource(pargL, destL);
270
271        ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
272        ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
273        ovutils::PipeArgs pargR(mdpFlagsR,
274                                info,
275                                zOrder,
276                                ovutils::IS_FG_OFF,
277                                ovutils::ROT_FLAGS_NONE);
278        ov.setSource(pargR, destR);
279
280        hwc_rect_t sourceCrop = layer->sourceCrop;
281        hwc_rect_t displayFrame = layer->displayFrame;
282        // Do not use getNonWormholeRegion() function to calculate the
283        // sourceCrop during animation on external display.
284        if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
285            sourceCrop = layer->displayFrame;
286            displayFrame = sourceCrop;
287        } else if(extOnlyLayerIndex == -1) {
288            getNonWormholeRegion(list, sourceCrop);
289            displayFrame = sourceCrop;
290        }
291
292        const float xres = ctx->dpyAttr[mDpy].xres;
293        //Default even split for all displays with high res
294        float lSplit = xres / 2;
295        if(mDpy == HWC_DISPLAY_PRIMARY &&
296                qdutils::MDPVersion::getInstance().getLeftSplit()) {
297            //Override if split published by driver for primary
298            lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
299        }
300
301        const float lSplitRatio = lSplit / xres;
302
303        const float lCropWidth =
304                (sourceCrop.right - sourceCrop.left) * lSplitRatio;
305
306        ovutils::Dim dcropL(
307                sourceCrop.left,
308                sourceCrop.top,
309                lCropWidth,
310                sourceCrop.bottom - sourceCrop.top);
311
312        ovutils::Dim dcropR(
313                sourceCrop.left + lCropWidth,
314                sourceCrop.top,
315                (sourceCrop.right - sourceCrop.left) - lCropWidth,
316                sourceCrop.bottom - sourceCrop.top);
317
318        ov.setCrop(dcropL, destL);
319        ov.setCrop(dcropR, destR);
320
321        int transform = layer->transform;
322        ovutils::eTransform orient =
323            static_cast<ovutils::eTransform>(transform);
324        ov.setTransform(orient, destL);
325        ov.setTransform(orient, destR);
326
327        const int lWidth = (lSplit - displayFrame.left);
328        const int rWidth = (displayFrame.right - lSplit);
329        const int height = displayFrame.bottom - displayFrame.top;
330
331        ovutils::Dim dposL(displayFrame.left,
332                           displayFrame.top,
333                           lWidth,
334                           height);
335        ov.setPosition(dposL, destL);
336
337        ovutils::Dim dposR(0,
338                           displayFrame.top,
339                           rWidth,
340                           height);
341        ov.setPosition(dposR, destR);
342
343        ret = true;
344        if (!ov.commit(destL)) {
345            ALOGE("%s: commit fails for left", __FUNCTION__);
346            ret = false;
347        }
348        if (!ov.commit(destR)) {
349            ALOGE("%s: commit fails for right", __FUNCTION__);
350            ret = false;
351        }
352    }
353    return ret;
354}
355
356bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
357{
358    if(!mModeOn) {
359        return true;
360    }
361    bool ret = true;
362    overlay::Overlay& ov = *(ctx->mOverlay);
363    ovutils::eDest destL = mDestLeft;
364    ovutils::eDest destR = mDestRight;
365    if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
366        ALOGE("%s: queue failed for left of dpy = %d",
367              __FUNCTION__, mDpy);
368        ret = false;
369    }
370    if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
371        ALOGE("%s: queue failed for right of dpy = %d",
372              __FUNCTION__, mDpy);
373        ret = false;
374    }
375    return ret;
376}
377
378//---------------------------------------------------------------------
379}; //namespace qhwc
380