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