hwc_fbupdate.cpp revision 04af919f7d16572b16a91d8b681afe42386fb4e1
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2013, 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#include "mdp_version.h"
25
26using namespace qdutils;
27
28namespace qhwc {
29
30namespace ovutils = overlay::utils;
31
32IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) {
33    if(width > MAX_DISPLAY_DIM) {
34        return new FBUpdateHighRes(dpy);
35    }
36    return new FBUpdateLowRes(dpy);
37}
38
39inline void IFBUpdate::reset() {
40    mModeOn = false;
41}
42
43//================= Low res====================================
44FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
45
46inline void FBUpdateLowRes::reset() {
47    IFBUpdate::reset();
48    mDest = ovutils::OV_INVALID;
49}
50
51bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
52                             int fbZorder) {
53    if(!ctx->mMDP.hasOverlay) {
54        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
55                 __FUNCTION__);
56        return false;
57    }
58    mModeOn = configure(ctx, list, fbZorder);
59    return mModeOn;
60}
61
62// Configure
63bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
64                               int fbZorder) {
65    bool ret = false;
66    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
67    if (LIKELY(ctx->mOverlay)) {
68        overlay::Overlay& ov = *(ctx->mOverlay);
69        private_handle_t *hnd = (private_handle_t *)layer->handle;
70        ovutils::Whf info(hnd->width, hnd->height,
71                          ovutils::getMdpFormat(hnd->format), hnd->size);
72
73        //Request a pipe
74        ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
75        if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) {
76            //For 8x26 external always use DMA pipe
77            type = ovutils::OV_MDP_PIPE_DMA;
78        }
79        ovutils::eDest dest = ov.nextPipe(type, mDpy);
80        if(dest == ovutils::OV_INVALID) { //None available
81            ALOGE("%s: No pipes available to configure framebuffer",
82                __FUNCTION__);
83            return false;
84        }
85
86        mDest = dest;
87
88        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
89
90        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
91
92        //XXX: FB layer plane alpha is currently sent as zero from
93        //surfaceflinger
94        ovutils::PipeArgs parg(mdpFlags,
95                info,
96                zOrder,
97                ovutils::IS_FG_OFF,
98                ovutils::ROT_FLAGS_NONE,
99                ovutils::DEFAULT_PLANE_ALPHA,
100                (ovutils::eBlending) getBlending(layer->blending));
101        ov.setSource(parg, dest);
102
103        hwc_rect_t sourceCrop;
104        getNonWormholeRegion(list, sourceCrop);
105        // x,y,w,h
106        ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
107                           sourceCrop.right - sourceCrop.left,
108                           sourceCrop.bottom - sourceCrop.top);
109        ov.setCrop(dcrop, dest);
110
111        int transform = layer->transform;
112        ovutils::eTransform orient =
113            static_cast<ovutils::eTransform>(transform);
114        ov.setTransform(orient, dest);
115
116        if(!qdutils::MDPVersion::getInstance().is8x26()) {
117            getNonWormholeRegion(list, sourceCrop);
118        }
119
120        hwc_rect_t displayFrame = sourceCrop;
121        ovutils::Dim dpos(displayFrame.left,
122                          displayFrame.top,
123                          displayFrame.right - displayFrame.left,
124                          displayFrame.bottom - displayFrame.top);
125
126        if(mDpy && !qdutils::MDPVersion::getInstance().is8x26())
127            // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
128            getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
129        ov.setPosition(dpos, dest);
130
131        ret = true;
132        if (!ov.commit(dest)) {
133            ALOGE("%s: commit fails", __FUNCTION__);
134            ret = false;
135        }
136    }
137    return ret;
138}
139
140bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
141{
142    if(!mModeOn) {
143        return true;
144    }
145    bool ret = true;
146    overlay::Overlay& ov = *(ctx->mOverlay);
147    ovutils::eDest dest = mDest;
148    if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
149        ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
150        ret = false;
151    }
152    return ret;
153}
154
155//================= High res====================================
156FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
157
158inline void FBUpdateHighRes::reset() {
159    IFBUpdate::reset();
160    mDestLeft = ovutils::OV_INVALID;
161    mDestRight = ovutils::OV_INVALID;
162}
163
164bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
165                              int fbZorder) {
166    if(!ctx->mMDP.hasOverlay) {
167        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
168                 __FUNCTION__);
169        return false;
170    }
171    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
172    mModeOn = configure(ctx, list, fbZorder);
173    return mModeOn;
174}
175
176// Configure
177bool FBUpdateHighRes::configure(hwc_context_t *ctx,
178                                hwc_display_contents_1 *list, int fbZorder) {
179    bool ret = false;
180    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
181    if (LIKELY(ctx->mOverlay)) {
182        overlay::Overlay& ov = *(ctx->mOverlay);
183        private_handle_t *hnd = (private_handle_t *)layer->handle;
184        ovutils::Whf info(hnd->width, hnd->height,
185                          ovutils::getMdpFormat(hnd->format), hnd->size);
186
187        //Request left pipe
188        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
189        if(destL == ovutils::OV_INVALID) { //None available
190            ALOGE("%s: No pipes available to configure framebuffer",
191                __FUNCTION__);
192            return false;
193        }
194        //Request right pipe
195        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
196        if(destR == ovutils::OV_INVALID) { //None available
197            ALOGE("%s: No pipes available to configure framebuffer",
198                __FUNCTION__);
199            return false;
200        }
201
202        mDestLeft = destL;
203        mDestRight = destR;
204
205        ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT;
206
207        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
208
209        //XXX: FB layer plane alpha is currently sent as zero from
210        //surfaceflinger
211        ovutils::PipeArgs pargL(mdpFlagsL,
212                info,
213                zOrder,
214                ovutils::IS_FG_OFF,
215                ovutils::ROT_FLAGS_NONE,
216                ovutils::DEFAULT_PLANE_ALPHA,
217                (ovutils::eBlending) getBlending(layer->blending));
218        ov.setSource(pargL, destL);
219
220        ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
221        ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
222        ovutils::PipeArgs pargR(mdpFlagsR,
223                info,
224                zOrder,
225                ovutils::IS_FG_OFF,
226                ovutils::ROT_FLAGS_NONE,
227                ovutils::DEFAULT_PLANE_ALPHA,
228                (ovutils::eBlending) getBlending(layer->blending));
229        ov.setSource(pargR, destR);
230
231        hwc_rect_t sourceCrop;
232        getNonWormholeRegion(list, sourceCrop);
233        ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
234                            (sourceCrop.right - sourceCrop.left) / 2,
235                            sourceCrop.bottom - sourceCrop.top);
236        ovutils::Dim dcropR(
237            sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2,
238            sourceCrop.top,
239            (sourceCrop.right - sourceCrop.left) / 2,
240            sourceCrop.bottom - sourceCrop.top);
241        ov.setCrop(dcropL, destL);
242        ov.setCrop(dcropR, destR);
243
244        int transform = layer->transform;
245        ovutils::eTransform orient =
246            static_cast<ovutils::eTransform>(transform);
247        ov.setTransform(orient, destL);
248        ov.setTransform(orient, destR);
249
250        hwc_rect_t displayFrame = sourceCrop;
251        const int halfWidth = (displayFrame.right - displayFrame.left) / 2;
252        const int height = displayFrame.bottom - displayFrame.top;
253
254        const int halfDpy = ctx->dpyAttr[mDpy].xres / 2;
255        ovutils::Dim dposL(halfDpy - halfWidth,
256                           displayFrame.top,
257                           halfWidth,
258                           height);
259        ov.setPosition(dposL, destL);
260
261        ovutils::Dim dposR(0,
262                           displayFrame.top,
263                           halfWidth,
264                           height);
265        ov.setPosition(dposR, destR);
266
267        ret = true;
268        if (!ov.commit(destL)) {
269            ALOGE("%s: commit fails for left", __FUNCTION__);
270            ret = false;
271        }
272        if (!ov.commit(destR)) {
273            ALOGE("%s: commit fails for right", __FUNCTION__);
274            ret = false;
275        }
276    }
277    return ret;
278}
279
280bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
281{
282    if(!mModeOn) {
283        return true;
284    }
285    bool ret = true;
286    overlay::Overlay& ov = *(ctx->mOverlay);
287    ovutils::eDest destL = mDestLeft;
288    ovutils::eDest destR = mDestRight;
289    if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
290        ALOGE("%s: queue failed for left of dpy = %d",
291              __FUNCTION__, mDpy);
292        ret = false;
293    }
294    if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
295        ALOGE("%s: queue failed for right of dpy = %d",
296              __FUNCTION__, mDpy);
297        ret = false;
298    }
299    return ret;
300}
301
302//---------------------------------------------------------------------
303}; //namespace qhwc
304