blob: c22c2fee92739864135c2c16baecbd70945a9aa0 [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
Sushil Chauhan69f2bb22013-02-13 10:50:47 -0800404 * 1. App layers > available pipes
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700405 * 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);
Sushil Chauhan69f2bb22013-02-13 10:50:47 -0800420 if (availablePipes > MAX_PIPES_PER_MIXER)
421 availablePipes = MAX_PIPES_PER_MIXER;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800422
423 if(numAppLayers < 1 || numAppLayers > (uint32_t)availablePipes) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700424 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
425 return false;
426 }
427
Amara Venkata Mastan Manoj Kumar75526f52012-12-27 18:27:01 -0800428 if(ctx->mExtDispConfiguring) {
429 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
430 __FUNCTION__);
431 return false;
432 }
433
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500434 if(isSecuring(ctx)) {
435 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
436 return false;
437 }
438
Naseer Ahmed76e313c2012-12-01 18:12:59 -0500439 if(ctx->mSecureMode)
440 return false;
441
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500442 //Check for skip layers
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800443 if(isSkipPresent(ctx, dpy)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500444 ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
Saurabh Shahb45b8812012-08-19 18:36:59 +0530445 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700446 }
447
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800448 if(ctx->listStats[dpy].needsAlphaScale) {
Naseer Ahmed018e5452012-12-03 14:46:15 -0500449 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
450 return false;
451 }
452
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700453 //FB composition on idle timeout
454 if(sIdleFallBack) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500455 sIdleFallBack = false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700456 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
457 return false;
458 }
459
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800460
Saurabh Shah09549f62012-10-04 13:25:44 -0700461 //MDP composition is not efficient if layer needs rotator.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700462 for(int i = 0; i < numAppLayers; ++i) {
Saurabh Shah09549f62012-10-04 13:25:44 -0700463 // As MDP h/w supports flip operation, use MDP comp only for
464 // 180 transforms. Fail for any transform involving 90 (90, 270).
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500465 hwc_layer_1_t* layer = &list->hwLayers[i];
466 private_handle_t *hnd = (private_handle_t *)layer->handle;
467 if((layer->transform & HWC_TRANSFORM_ROT_90) && !isYuvBuffer(hnd)) {
468 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
469 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700470 }
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800471
472 if(!isYuvBuffer(hnd) && !isWidthValid(ctx,layer))
473 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700474 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700475 return true;
476}
477
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800478int MDPCompLowRes::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
479 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500480 overlay::Overlay& ov = *ctx->mOverlay;
481 int mdp_pipe = -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700482
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500483 switch(type) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800484 case MDPCOMP_OV_ANY:
485 case MDPCOMP_OV_RGB:
486 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
487 if(mdp_pipe != ovutils::OV_INVALID) {
488 return mdp_pipe;
489 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700490
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800491 if(type == MDPCOMP_OV_RGB) {
492 //Requested only for RGB pipe
493 return -1;
494 }
495 case MDPCOMP_OV_VG:
496 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
497 if(mdp_pipe != ovutils::OV_INVALID) {
498 return mdp_pipe;
499 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500500 return -1;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800501 default:
502 ALOGE("%s: Invalid pipe type",__FUNCTION__);
503 return -1;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500504 };
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700505}
506
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800507bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700508 hwc_display_contents_1_t* list,
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500509 FrameInfo& currentFrame) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800510 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500511 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800512 int layer_count = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700513
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500514 currentFrame.count = layer_count;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500515 currentFrame.pipeLayer = (PipeLayerPair*)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800516 malloc(sizeof(PipeLayerPair) * currentFrame.count);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500517
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800518 if(isYuvPresent(ctx, dpy)) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800519 int nYuvCount = ctx->listStats[dpy].yuvCount;
520
521 for(int index = 0; index < nYuvCount; index ++) {
522 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
523 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
524 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
525 MdpPipeInfo& pipe_info = info.pipeIndex;
526 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
527 if(pipe_info.index < 0) {
528 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
529 __FUNCTION__);
530 return false;
531 }
532 pipe_info.zOrder = nYuvIndex;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500533 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500534 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700535
536 for(int index = 0 ; index < layer_count ; index++ ) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800537 hwc_layer_1_t* layer = &list->hwLayers[index];
538 private_handle_t *hnd = (private_handle_t *)layer->handle;
539
540 if(isYuvBuffer(hnd))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500541 continue;
542
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500543 PipeLayerPair& info = currentFrame.pipeLayer[index];
544 MdpPipeInfo& pipe_info = info.pipeIndex;
545 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY);
546 if(pipe_info.index < 0) {
547 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
548 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700549 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500550 pipe_info.zOrder = index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700551 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700552 return true;
553}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700554
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800555bool MDPCompLowRes::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
556 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700557 int nPipeIndex, vsync_wait, isFG;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800558 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700559
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800560 FrameInfo &currentFrame = mCurrentFrame;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500561 currentFrame.count = 0;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700562
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500563 if(currentFrame.pipeLayer) {
564 free(currentFrame.pipeLayer);
565 currentFrame.pipeLayer = NULL;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400566 }
567
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700568 if(!ctx) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800569 ALOGE("%s: invalid context", __FUNCTION__);
570 return -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700571 }
572
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500573 if(!allocLayerPipes(ctx, list, currentFrame)) {
574 //clean current frame data
575 currentFrame.count = 0;
576
577 if(currentFrame.pipeLayer) {
578 free(currentFrame.pipeLayer);
579 currentFrame.pipeLayer = NULL;
580 }
581
582 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
583 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700584 }
585
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500586 for (int index = 0 ; index < currentFrame.count; index++) {
587 hwc_layer_1_t* layer = &list->hwLayers[index];
588 MdpPipeInfo& cur_pipe = currentFrame.pipeLayer[index].pipeIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700589
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800590 if(configure(ctx, layer, cur_pipe) != 0 ) {
591 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
592 layer %d with pipe index:%d",__FUNCTION__,
593 index, cur_pipe.index);
594 return false;
595 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700596 }
597 return true;
598}
599
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800600bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700601
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500602 if(!isEnabled() || !isUsed()) {
603 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
604 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800605 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700606
607 if(!ctx || !list) {
608 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500609 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700610 }
611
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500612 /* reset Invalidator */
613 if(idleInvalidator)
614 idleInvalidator->markForSleep();
615
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800616 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500617 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800618 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700619
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800620 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700621 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700622 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700623 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700624
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500625 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700626 continue;
627 }
628
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500629 MdpPipeInfo& pipe_info =
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800630 mCurrentFrame.pipeLayer[i].pipeIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700631 int index = pipe_info.index;
632
633 if(index < 0) {
634 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500635 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700636 }
637
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500638 ovutils::eDest dest = (ovutils::eDest)index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700639
640 if (ctx ) {
641 private_handle_t *hnd = (private_handle_t *)layer->handle;
642 if(!hnd) {
643 ALOGE("%s handle null", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500644 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700645 }
646
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700647 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800648 using pipe: %d", __FUNCTION__, layer,
649 hnd, index );
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700650
651 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
652 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500653 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700654 }
655 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500656
657 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700658 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500659 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700660}
661
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800662bool MDPCompLowRes::prepare(hwc_context_t *ctx,
663 hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700664 if(!isEnabled()) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500665 ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700666 return false;
667 }
668
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500669 overlay::Overlay& ov = *ctx->mOverlay;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700670 bool isMDPCompUsed = true;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500671 bool doable = isDoable(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700672
673 if(doable) {
674 if(setup(ctx, list)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500675 setMDPCompLayerFlags(ctx, list);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700676 } else {
677 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
678 isMDPCompUsed = false;
679 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800680 } else {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700681 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800682 doable);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700683 isMDPCompUsed = false;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800684 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700685
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800686 //Reset states
687 if(!isMDPCompUsed) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700688 //Reset current frame
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800689 reset(ctx, list);
690 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700691
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800692 mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
693 return isMDPCompUsed;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700694}
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500695
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700696}; //namespace
697