blob: c51a6aa300ad3f82052c329acb9fac3977a7992b [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Saurabh Shah56f610d2012-08-07 15:27:06 -07002 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
Naseer Ahmed7c958d42012-07-31 18:57:03 -07003 * Not a Contribution, Apache license notifications and license are retained
4 * for attribution purposes only.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "hwc_mdpcomp.h"
Naseer Ahmed54821fe2012-11-28 18:44:38 -050020#include <sys/ioctl.h>
Saurabh Shah56f610d2012-08-07 15:27:06 -070021#include "external.h"
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -080022#include "qdMetaData.h"
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -080023#include "mdp_version.h"
Naseer Ahmed7c958d42012-07-31 18:57:03 -070024
Naseer Ahmed7c958d42012-07-31 18:57:03 -070025namespace qhwc {
26
Naseer Ahmed54821fe2012-11-28 18:44:38 -050027namespace ovutils = overlay::utils;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070028
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080029//==============MDPComp========================================================
30
Naseer Ahmed7c958d42012-07-31 18:57:03 -070031IdleInvalidator *MDPComp::idleInvalidator = NULL;
32bool MDPComp::sIdleFallBack = false;
33bool MDPComp::sDebugLogs = false;
Naseer Ahmed54821fe2012-11-28 18:44:38 -050034bool MDPComp::sEnabled = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -070035
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080036MDPComp* MDPComp::getObject(const int& width) {
37 //For now. Later check for width > 2048
38 return new MDPCompLowRes();
39}
40
41void MDPComp::dump(android::String8& buf)
42{
43 dumpsys_log(buf, " MDP Composition: ");
44 dumpsys_log(buf, "MDPCompState=%d\n", mState);
45 //XXX: Log more info
46}
47
48bool MDPComp::init(hwc_context_t *ctx) {
49
50 if(!ctx) {
51 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
52 return false;
53 }
54
55 if(!setupBasePipe(ctx)) {
56 ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
57 return false;
58 }
59
60 char property[PROPERTY_VALUE_MAX];
61
62 sEnabled = false;
63 if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
64 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
65 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
66 sEnabled = true;
67 }
68
69 sDebugLogs = false;
70 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
71 if(atoi(property) != 0)
72 sDebugLogs = true;
73 }
74
75 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
76 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
77 if(atoi(property) != 0)
78 idle_timeout = atoi(property);
79 }
80
81 //create Idle Invalidator
82 idleInvalidator = IdleInvalidator::getInstance();
83
84 if(idleInvalidator == NULL) {
85 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
86 } else {
87 idleInvalidator->init(timeout_handler, ctx, idle_timeout);
88 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -070089 return true;
90}
91
92void MDPComp::timeout_handler(void *udata) {
93 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
94
95 if(!ctx) {
96 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
97 return;
98 }
99
Jesse Hall3be78d92012-08-21 15:12:23 -0700100 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700101 ALOGE("%s: HWC proc not registered", __FUNCTION__);
102 return;
103 }
104 sIdleFallBack = true;
105 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700106 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700107}
108
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800109void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
110 hwc_display_contents_1_t* list) {
111 const int dpy = HWC_DISPLAY_PRIMARY;
112 LayerProp *layerProp = ctx->layerProp[dpy];
113
114 for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
115 hwc_layer_1_t* layer = &(list->hwLayers[index]);
116 layerProp[index].mFlags |= HWC_MDPCOMP;
117 layer->compositionType = HWC_OVERLAY;
118 layer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400119 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700120}
121
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800122void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
123 hwc_display_contents_1_t* list) {
124 const int dpy = HWC_DISPLAY_PRIMARY;
125 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700126
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800127 for (int index = 0 ;
128 index < ctx->listStats[dpy].numAppLayers; index++) {
129 if(layerProp[index].mFlags & HWC_MDPCOMP) {
130 layerProp[index].mFlags &= ~HWC_MDPCOMP;
131 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700132
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800133 if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
134 list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
135 }
136 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700137}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500138
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800139/*
140 * Sets up BORDERFILL as default base pipe and detaches RGB0.
141 * Framebuffer is always updated using PLAY ioctl.
142 */
143bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
144 const int dpy = HWC_DISPLAY_PRIMARY;
145 int fb_stride = ctx->dpyAttr[dpy].stride;
146 int fb_width = ctx->dpyAttr[dpy].xres;
147 int fb_height = ctx->dpyAttr[dpy].yres;
148 int fb_fd = ctx->dpyAttr[dpy].fd;
149
150 mdp_overlay ovInfo;
151 msmfb_overlay_data ovData;
152 memset(&ovInfo, 0, sizeof(mdp_overlay));
153 memset(&ovData, 0, sizeof(msmfb_overlay_data));
154
155 ovInfo.src.format = MDP_RGB_BORDERFILL;
156 ovInfo.src.width = fb_width;
157 ovInfo.src.height = fb_height;
158 ovInfo.src_rect.w = fb_width;
159 ovInfo.src_rect.h = fb_height;
160 ovInfo.dst_rect.w = fb_width;
161 ovInfo.dst_rect.h = fb_height;
162 ovInfo.id = MSMFB_NEW_REQUEST;
163
164 if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
165 ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
166 strerror(errno));
167 return false;
168 }
169
170 ovData.id = ovInfo.id;
171 if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
172 ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
173 strerror(errno));
174 return false;
175 }
176 return true;
177}
178
179void MDPComp::printInfo(hwc_layer_1_t* layer) {
180 hwc_rect_t sourceCrop = layer->sourceCrop;
181 hwc_rect_t displayFrame = layer->displayFrame;
182
183 int s_l = sourceCrop.left;
184 int s_t = sourceCrop.top;
185 int s_r = sourceCrop.right;
186 int s_b = sourceCrop.bottom;
187
188 int d_l = displayFrame.left;
189 int d_t = displayFrame.top;
190 int d_r = displayFrame.right;
191 int d_b = displayFrame.bottom;
192
193 ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
194 dst:[%d,%d,%d,%d] (%d x %d)",
195 s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
196 d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
197}
198
199//=============MDPCompLowRes===================================================
200void MDPCompLowRes::reset(hwc_context_t *ctx,
201 hwc_display_contents_1_t* list ) {
202 //Reset flags and states
203 unsetMDPCompLayerFlags(ctx, list);
204 mCurrentFrame.count = 0;
205 if(mCurrentFrame.pipeLayer) {
206 free(mCurrentFrame.pipeLayer);
207 mCurrentFrame.pipeLayer = NULL;
208 }
209}
210
211void MDPCompLowRes::setVidInfo(hwc_layer_1_t *layer,
212 ovutils::eMdpFlags &mdpFlags) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500213 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -0800214 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500215
216 if(isSecureBuffer(hnd)) {
217 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500218 }
Ramkumar Radhakrishnan12b103b2013-01-09 17:47:56 -0800219 if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
220 metadata->interlaced) {
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -0800221 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
222 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500223}
224
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800225bool MDPCompLowRes::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
226
227 const int dpy = HWC_DISPLAY_PRIMARY;
228 private_handle_t *hnd = (private_handle_t *)layer->handle;
229
230 if(!hnd) {
231 ALOGE("%s: layer handle is NULL", __FUNCTION__);
232 return false;
233 }
234
235 int hw_w = ctx->dpyAttr[dpy].xres;
236 int hw_h = ctx->dpyAttr[dpy].yres;
237
238 hwc_rect_t sourceCrop = layer->sourceCrop;
239 hwc_rect_t displayFrame = layer->displayFrame;
240
241 hwc_rect_t crop = sourceCrop;
242 int crop_w = crop.right - crop.left;
243 int crop_h = crop.bottom - crop.top;
244
245 hwc_rect_t dst = displayFrame;
246 int dst_w = dst.right - dst.left;
247 int dst_h = dst.bottom - dst.top;
248
249 if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
250 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, layer->transform);
251 crop_w = crop.right - crop.left;
252 crop_h = crop.bottom - crop.top;
253 }
254
255 //Workaround for MDP HW limitation in DSI command mode panels where
256 //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
257
258 if(crop_w < 5)
259 return false;
260
261 return true;
262}
263
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700264/*
265 * Configures pipe(s) for MDP composition
266 */
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800267int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
268 MdpPipeInfo& mdp_info) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700269 int nPipeIndex = mdp_info.index;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800270 const int dpy = HWC_DISPLAY_PRIMARY;
271 private_handle_t *hnd = (private_handle_t *)layer->handle;
272 overlay::Overlay& ov = *ctx->mOverlay;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700273
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800274 if(!hnd) {
275 ALOGE("%s: layer handle is NULL", __FUNCTION__);
276 return -1;
277 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700278
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800279 int hw_w = ctx->dpyAttr[dpy].xres;
280 int hw_h = ctx->dpyAttr[dpy].yres;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700281
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800282 hwc_rect_t sourceCrop = layer->sourceCrop;
283 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700284
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800285 const int src_w = sourceCrop.right - sourceCrop.left;
286 const int src_h = sourceCrop.bottom - sourceCrop.top;
287
288 hwc_rect_t crop = sourceCrop;
289 int crop_w = crop.right - crop.left;
290 int crop_h = crop.bottom - crop.top;
291
292 hwc_rect_t dst = displayFrame;
293 int dst_w = dst.right - dst.left;
294 int dst_h = dst.bottom - dst.top;
295
296 if(dst.left < 0 || dst.top < 0 ||
297 dst.right > hw_w || dst.bottom > hw_h) {
298 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
299 __FUNCTION__);
Jeykumar Sankaran8f7a94f2013-01-29 18:06:44 -0800300 qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, layer->transform);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800301
302 //Update calulated width and height
303 crop_w = crop.right - crop.left;
304 crop_h = crop.bottom - crop.top;
305
306 dst_w = dst.right - dst.left;
307 dst_h = dst.bottom - dst.top;
308 }
309
310 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
311 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
312 printInfo(layer);
313 dst_w = hw_w;
314 dst_h = hw_h;
315 }
316
317 // Determine pipe to set based on pipe index
318 ovutils::eDest dest = (ovutils::eDest)mdp_info.index;
319
320 ovutils::eZorder zOrder = ovutils::ZORDER_0;
321
322 if(mdp_info.zOrder == 0 ) {
323 zOrder = ovutils::ZORDER_0;
324 } else if(mdp_info.zOrder == 1 ) {
325 zOrder = ovutils::ZORDER_1;
326 } else if(mdp_info.zOrder == 2 ) {
327 zOrder = ovutils::ZORDER_2;
328 } else if(mdp_info.zOrder == 3) {
329 zOrder = ovutils::ZORDER_3;
330 }
331
332 // Order order order
333 // setSource - just setting source
334 // setParameter - changes src w/h/f accordingly
335 // setCrop - ROI - src_rect
336 // setPosition - dst_rect
337 // commit - commit changes to mdp driver
338 // queueBuffer - not here, happens when draw is called
339
340 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
341
342 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
343
344 if(isYuvBuffer(hnd))
345 setVidInfo(layer, mdpFlags);
346
347 ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
348
349 if(layer->blending == HWC_BLENDING_PREMULT) {
350 ovutils::setMdpFlags(mdpFlags,
351 ovutils::OV_MDP_BLEND_FG_PREMULT);
352 }
353
354 ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
355
356 if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
357 if(layer->transform & HWC_TRANSFORM_FLIP_H) {
358 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700359 }
360
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800361 if(layer->transform & HWC_TRANSFORM_FLIP_V) {
362 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700363 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800364 } else {
365 orient = static_cast<ovutils::eTransform>(layer->transform);
366 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700367
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -0800368 ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE;
369 if(isYuvBuffer(hnd) && (ctx->mMDP.version >= qdutils::MDP_V4_2 &&
370 ctx->mMDP.version < qdutils::MDSS_V5)) {
371 rotFlags = ovutils::ROT_DOWNSCALE_ENABLED;
372 }
373
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800374 ovutils::PipeArgs parg(mdpFlags,
375 info,
376 zOrder,
377 ovutils::IS_FG_OFF,
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -0800378 rotFlags);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700379
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800380 ov.setSource(parg, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700381
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800382 ov.setTransform(orient, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700383
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800384 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
385 ov.setCrop(dcrop, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700386
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800387 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
388 ov.setPosition(dim, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700389
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800390 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
391 nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
392 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
393 mdp_info.index, mdp_info.zOrder);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500394
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800395 if (!ov.commit(dest)) {
396 ALOGE("%s: commit failed", __FUNCTION__);
397 return -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700398 }
399 return 0;
400}
401
402/*
403 * MDPComp not possible when
404 * 1. We have more than sMaxLayers
405 * 2. External display connected
406 * 3. Composition is triggered by
407 * Idle timer expiry
408 * 4. Rotation is needed
409 * 5. Overlay in use
410 */
411
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800412bool MDPCompLowRes::isDoable(hwc_context_t *ctx,
413 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700414 //Number of layers
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800415 const int dpy = HWC_DISPLAY_PRIMARY;
416 int numAppLayers = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500417
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800418 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaranccb44602013-01-03 12:48:22 -0800419 int availablePipes = ov.availablePipes(dpy);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800420
421 if(numAppLayers < 1 || numAppLayers > (uint32_t)availablePipes) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700422 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
423 return false;
424 }
425
Amara Venkata Mastan Manoj Kumar75526f52012-12-27 18:27:01 -0800426 if(ctx->mExtDispConfiguring) {
427 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
428 __FUNCTION__);
429 return false;
430 }
431
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500432 if(isSecuring(ctx)) {
433 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
434 return false;
435 }
436
Naseer Ahmed76e313c2012-12-01 18:12:59 -0500437 if(ctx->mSecureMode)
438 return false;
439
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500440 //Check for skip layers
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800441 if(isSkipPresent(ctx, dpy)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500442 ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530443 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700444 }
445
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800446 if(ctx->listStats[dpy].needsAlphaScale) {
Naseer Ahmed018e5452012-12-03 14:46:15 -0500447 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
448 return false;
449 }
450
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700451 //FB composition on idle timeout
452 if(sIdleFallBack) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500453 sIdleFallBack = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700454 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
455 return false;
456 }
457
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800458
Saurabh Shah09549f62012-10-04 13:25:44 -0700459 //MDP composition is not efficient if layer needs rotator.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700460 for(int i = 0; i < numAppLayers; ++i) {
Saurabh Shah09549f62012-10-04 13:25:44 -0700461 // As MDP h/w supports flip operation, use MDP comp only for
462 // 180 transforms. Fail for any transform involving 90 (90, 270).
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500463 hwc_layer_1_t* layer = &list->hwLayers[i];
464 private_handle_t *hnd = (private_handle_t *)layer->handle;
465 if((layer->transform & HWC_TRANSFORM_ROT_90) && !isYuvBuffer(hnd)) {
466 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
467 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700468 }
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800469
470 if(!isYuvBuffer(hnd) && !isWidthValid(ctx,layer))
471 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700472 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700473 return true;
474}
475
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800476int MDPCompLowRes::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
477 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500478 overlay::Overlay& ov = *ctx->mOverlay;
479 int mdp_pipe = -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700480
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500481 switch(type) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800482 case MDPCOMP_OV_ANY:
483 case MDPCOMP_OV_RGB:
484 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
485 if(mdp_pipe != ovutils::OV_INVALID) {
486 return mdp_pipe;
487 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700488
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800489 if(type == MDPCOMP_OV_RGB) {
490 //Requested only for RGB pipe
491 return -1;
492 }
493 case MDPCOMP_OV_VG:
494 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
495 if(mdp_pipe != ovutils::OV_INVALID) {
496 return mdp_pipe;
497 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500498 return -1;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800499 default:
500 ALOGE("%s: Invalid pipe type",__FUNCTION__);
501 return -1;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500502 };
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700503}
504
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800505bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700506 hwc_display_contents_1_t* list,
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500507 FrameInfo& currentFrame) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800508 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500509 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800510 int layer_count = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700511
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500512 currentFrame.count = layer_count;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500513 currentFrame.pipeLayer = (PipeLayerPair*)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800514 malloc(sizeof(PipeLayerPair) * currentFrame.count);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500515
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800516 if(isYuvPresent(ctx, dpy)) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800517 int nYuvCount = ctx->listStats[dpy].yuvCount;
518
519 for(int index = 0; index < nYuvCount; index ++) {
520 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
521 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
522 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
523 MdpPipeInfo& pipe_info = info.pipeIndex;
524 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
525 if(pipe_info.index < 0) {
526 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
527 __FUNCTION__);
528 return false;
529 }
530 pipe_info.zOrder = nYuvIndex;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500531 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500532 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700533
534 for(int index = 0 ; index < layer_count ; index++ ) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800535 hwc_layer_1_t* layer = &list->hwLayers[index];
536 private_handle_t *hnd = (private_handle_t *)layer->handle;
537
538 if(isYuvBuffer(hnd))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500539 continue;
540
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500541 PipeLayerPair& info = currentFrame.pipeLayer[index];
542 MdpPipeInfo& pipe_info = info.pipeIndex;
543 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY);
544 if(pipe_info.index < 0) {
545 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
546 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700547 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500548 pipe_info.zOrder = index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700549 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700550 return true;
551}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700552
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800553bool MDPCompLowRes::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
554 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700555 int nPipeIndex, vsync_wait, isFG;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800556 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700557
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800558 FrameInfo &currentFrame = mCurrentFrame;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500559 currentFrame.count = 0;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700560
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500561 if(currentFrame.pipeLayer) {
562 free(currentFrame.pipeLayer);
563 currentFrame.pipeLayer = NULL;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400564 }
565
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700566 if(!ctx) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800567 ALOGE("%s: invalid context", __FUNCTION__);
568 return -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700569 }
570
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500571 if(!allocLayerPipes(ctx, list, currentFrame)) {
572 //clean current frame data
573 currentFrame.count = 0;
574
575 if(currentFrame.pipeLayer) {
576 free(currentFrame.pipeLayer);
577 currentFrame.pipeLayer = NULL;
578 }
579
580 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
581 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700582 }
583
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500584 for (int index = 0 ; index < currentFrame.count; index++) {
585 hwc_layer_1_t* layer = &list->hwLayers[index];
586 MdpPipeInfo& cur_pipe = currentFrame.pipeLayer[index].pipeIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700587
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800588 if(configure(ctx, layer, cur_pipe) != 0 ) {
589 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
590 layer %d with pipe index:%d",__FUNCTION__,
591 index, cur_pipe.index);
592 return false;
593 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700594 }
595 return true;
596}
597
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800598bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700599
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500600 if(!isEnabled() || !isUsed()) {
601 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
602 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800603 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700604
605 if(!ctx || !list) {
606 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500607 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700608 }
609
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500610 /* reset Invalidator */
611 if(idleInvalidator)
612 idleInvalidator->markForSleep();
613
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800614 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500615 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800616 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700617
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800618 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700619 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700620 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700621 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700622
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500623 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700624 continue;
625 }
626
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500627 MdpPipeInfo& pipe_info =
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800628 mCurrentFrame.pipeLayer[i].pipeIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700629 int index = pipe_info.index;
630
631 if(index < 0) {
632 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500633 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700634 }
635
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500636 ovutils::eDest dest = (ovutils::eDest)index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700637
638 if (ctx ) {
639 private_handle_t *hnd = (private_handle_t *)layer->handle;
640 if(!hnd) {
641 ALOGE("%s handle null", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500642 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700643 }
644
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700645 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800646 using pipe: %d", __FUNCTION__, layer,
647 hnd, index );
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700648
649 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
650 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500651 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700652 }
653 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500654
655 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700656 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500657 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700658}
659
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800660bool MDPCompLowRes::prepare(hwc_context_t *ctx,
661 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700662 if(!isEnabled()) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500663 ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700664 return false;
665 }
666
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500667 overlay::Overlay& ov = *ctx->mOverlay;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700668 bool isMDPCompUsed = true;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500669 bool doable = isDoable(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700670
671 if(doable) {
672 if(setup(ctx, list)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500673 setMDPCompLayerFlags(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700674 } else {
675 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
676 isMDPCompUsed = false;
677 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800678 } else {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700679 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800680 doable);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700681 isMDPCompUsed = false;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800682 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700683
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800684 //Reset states
685 if(!isMDPCompUsed) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700686 //Reset current frame
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800687 reset(ctx, list);
688 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700689
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800690 mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
691 return isMDPCompUsed;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700692}
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500693
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700694}; //namespace
695