hwc_fbupdate.cpp revision 54a4a8e7d7b1aadb06153ee36935860cacf1e643
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 <gralloc_priv.h>
23#include "hwc_fbupdate.h"
24
25namespace qhwc {
26
27namespace ovutils = overlay::utils;
28
29IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) {
30    if(width > MAX_DISPLAY_DIM) {
31        return new FBUpdateHighRes(dpy);
32    }
33    return new FBUpdateLowRes(dpy);
34}
35
36inline void IFBUpdate::reset() {
37    mModeOn = false;
38}
39
40//================= Low res====================================
41FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
42
43inline void FBUpdateLowRes::reset() {
44    IFBUpdate::reset();
45    mDest = ovutils::OV_INVALID;
46}
47
48bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
49{
50    if(!ctx->mMDP.hasOverlay) {
51        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
52                __FUNCTION__);
53       return false;
54    }
55    mModeOn = configure(ctx, list);
56    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
57    return mModeOn;
58}
59
60// Configure
61bool FBUpdateLowRes::configure(hwc_context_t *ctx,
62                               hwc_display_contents_1 *list)
63{
64    bool ret = false;
65    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
66    if (LIKELY(ctx->mOverlay)) {
67        overlay::Overlay& ov = *(ctx->mOverlay);
68        private_handle_t *hnd = (private_handle_t *)layer->handle;
69        ovutils::Whf info(hnd->width, hnd->height,
70                ovutils::getMdpFormat(hnd->format), hnd->size);
71
72        //Request an RGB pipe
73        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
74        if(dest == ovutils::OV_INVALID) { //None available
75            return false;
76        }
77
78        mDest = dest;
79
80        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
81
82        ovutils::PipeArgs parg(mdpFlags,
83                info,
84                ovutils::ZORDER_0,
85                ovutils::IS_FG_SET,
86                ovutils::ROT_FLAGS_NONE);
87        ov.setSource(parg, dest);
88
89        hwc_rect_t sourceCrop;
90        getNonWormholeRegion(list, sourceCrop);
91        // x,y,w,h
92        ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
93                sourceCrop.right - sourceCrop.left,
94                sourceCrop.bottom - sourceCrop.top);
95        ov.setCrop(dcrop, dest);
96
97        int transform = layer->transform;
98        ovutils::eTransform orient =
99                static_cast<ovutils::eTransform>(transform);
100        ov.setTransform(orient, dest);
101
102        hwc_rect_t displayFrame = sourceCrop;
103        ovutils::Dim dpos(displayFrame.left,
104                displayFrame.top,
105                displayFrame.right - displayFrame.left,
106                displayFrame.bottom - displayFrame.top);
107        // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
108        if(mDpy)
109            getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
110        ov.setPosition(dpos, dest);
111
112        ret = true;
113        if (!ov.commit(dest)) {
114            ALOGE("%s: commit fails", __FUNCTION__);
115            ret = false;
116        }
117    }
118    return ret;
119}
120
121bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
122{
123    if(!mModeOn) {
124        return true;
125    }
126    bool ret = true;
127    overlay::Overlay& ov = *(ctx->mOverlay);
128    ovutils::eDest dest = mDest;
129    if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
130        ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
131        ret = false;
132    }
133    return ret;
134}
135
136//================= High res====================================
137FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
138
139inline void FBUpdateHighRes::reset() {
140    IFBUpdate::reset();
141    mDestLeft = ovutils::OV_INVALID;
142    mDestRight = ovutils::OV_INVALID;
143}
144
145bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
146{
147    if(!ctx->mMDP.hasOverlay) {
148        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
149                __FUNCTION__);
150       return false;
151    }
152    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
153    mModeOn = configure(ctx, list);
154    return mModeOn;
155}
156
157// Configure
158bool FBUpdateHighRes::configure(hwc_context_t *ctx,
159                                hwc_display_contents_1 *list)
160{
161    bool ret = false;
162    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
163    if (LIKELY(ctx->mOverlay)) {
164        overlay::Overlay& ov = *(ctx->mOverlay);
165        private_handle_t *hnd = (private_handle_t *)layer->handle;
166        ovutils::Whf info(hnd->width, hnd->height,
167                ovutils::getMdpFormat(hnd->format), hnd->size);
168
169        //Request left RGB pipe
170        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
171        if(destL == ovutils::OV_INVALID) { //None available
172            return false;
173        }
174        //Request right RGB pipe
175        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
176        if(destR == ovutils::OV_INVALID) { //None available
177            return false;
178        }
179
180        mDestLeft = destL;
181        mDestRight = destR;
182
183        ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
184
185        ovutils::PipeArgs pargL(mdpFlagsL,
186                info,
187                ovutils::ZORDER_0,
188                ovutils::IS_FG_SET,
189                ovutils::ROT_FLAGS_NONE);
190        ov.setSource(pargL, destL);
191
192        ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
193        ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
194        ovutils::PipeArgs pargR(mdpFlagsR,
195                info,
196                ovutils::ZORDER_0,
197                ovutils::IS_FG_SET,
198                ovutils::ROT_FLAGS_NONE);
199        ov.setSource(pargR, destR);
200
201        hwc_rect_t sourceCrop;
202        getNonWormholeRegion(list, sourceCrop);
203        ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
204                (sourceCrop.right - sourceCrop.left) / 2,
205                sourceCrop.bottom - sourceCrop.top);
206        ovutils::Dim dcropR(
207                sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2,
208                sourceCrop.top,
209                (sourceCrop.right - sourceCrop.left) / 2,
210                sourceCrop.bottom - sourceCrop.top);
211        ov.setCrop(dcropL, destL);
212        ov.setCrop(dcropR, destR);
213
214        int transform = layer->transform;
215        ovutils::eTransform orient =
216                static_cast<ovutils::eTransform>(transform);
217        ov.setTransform(orient, destL);
218        ov.setTransform(orient, destR);
219
220        hwc_rect_t displayFrame = sourceCrop;
221        //For FB left, top will always be 0
222        //That should also be the case if using 2 mixers for single display
223        ovutils::Dim dposL(displayFrame.left,
224                displayFrame.top,
225                (displayFrame.right - displayFrame.left) / 2,
226                displayFrame.bottom - displayFrame.top);
227        ov.setPosition(dposL, destL);
228        ovutils::Dim dposR(0,
229                displayFrame.top,
230                (displayFrame.right - displayFrame.left) / 2,
231                displayFrame.bottom - displayFrame.top);
232        ov.setPosition(dposR, destR);
233
234        ret = true;
235        if (!ov.commit(destL)) {
236            ALOGE("%s: commit fails for left", __FUNCTION__);
237            ret = false;
238        }
239        if (!ov.commit(destR)) {
240            ALOGE("%s: commit fails for right", __FUNCTION__);
241            ret = false;
242        }
243    }
244    return ret;
245}
246
247bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
248{
249    if(!mModeOn) {
250        return true;
251    }
252    bool ret = true;
253    overlay::Overlay& ov = *(ctx->mOverlay);
254    ovutils::eDest destL = mDestLeft;
255    ovutils::eDest destR = mDestRight;
256    if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
257        ALOGE("%s: queue failed for left of dpy = %d",
258                __FUNCTION__, mDpy);
259        ret = false;
260    }
261    if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
262        ALOGE("%s: queue failed for right of dpy = %d",
263                __FUNCTION__, mDpy);
264        ret = false;
265    }
266    return ret;
267}
268
269//---------------------------------------------------------------------
270}; //namespace qhwc
271