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