blob: 4bdc3e9e0c3c3511716af15e4911bfbb1f0417b8 [file] [log] [blame]
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001/*
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08002 * Copyright (C) 2012-2013, 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) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -080037 if(width <= MAX_DISPLAY_DIM) {
38 return new MDPCompLowRes();
39 } else {
40 return new MDPCompHighRes();
41 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -080042}
43
44void MDPComp::dump(android::String8& buf)
45{
46 dumpsys_log(buf, " MDP Composition: ");
47 dumpsys_log(buf, "MDPCompState=%d\n", mState);
48 //XXX: Log more info
49}
50
51bool MDPComp::init(hwc_context_t *ctx) {
52
53 if(!ctx) {
54 ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
55 return false;
56 }
57
58 if(!setupBasePipe(ctx)) {
59 ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
60 return false;
61 }
62
63 char property[PROPERTY_VALUE_MAX];
64
65 sEnabled = false;
66 if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
67 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
68 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
69 sEnabled = true;
70 }
71
72 sDebugLogs = false;
73 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
74 if(atoi(property) != 0)
75 sDebugLogs = true;
76 }
77
78 unsigned long idle_timeout = DEFAULT_IDLE_TIME;
79 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
80 if(atoi(property) != 0)
81 idle_timeout = atoi(property);
82 }
83
84 //create Idle Invalidator
85 idleInvalidator = IdleInvalidator::getInstance();
86
87 if(idleInvalidator == NULL) {
88 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
89 } else {
90 idleInvalidator->init(timeout_handler, ctx, idle_timeout);
91 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -070092 return true;
93}
94
95void MDPComp::timeout_handler(void *udata) {
96 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
97
98 if(!ctx) {
99 ALOGE("%s: received empty data in timer callback", __FUNCTION__);
100 return;
101 }
102
Jesse Hall3be78d92012-08-21 15:12:23 -0700103 if(!ctx->proc) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700104 ALOGE("%s: HWC proc not registered", __FUNCTION__);
105 return;
106 }
107 sIdleFallBack = true;
108 /* Trigger SF to redraw the current frame */
Jesse Hall3be78d92012-08-21 15:12:23 -0700109 ctx->proc->invalidate(ctx->proc);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700110}
111
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800112void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
113 hwc_display_contents_1_t* list) {
114 const int dpy = HWC_DISPLAY_PRIMARY;
115 LayerProp *layerProp = ctx->layerProp[dpy];
116
117 for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
118 hwc_layer_1_t* layer = &(list->hwLayers[index]);
119 layerProp[index].mFlags |= HWC_MDPCOMP;
120 layer->compositionType = HWC_OVERLAY;
121 layer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmed52ca6d22012-10-08 14:03:01 -0400122 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700123}
124
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800125void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
126 hwc_display_contents_1_t* list) {
127 const int dpy = HWC_DISPLAY_PRIMARY;
128 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700129
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800130 for (int index = 0 ;
131 index < ctx->listStats[dpy].numAppLayers; index++) {
132 if(layerProp[index].mFlags & HWC_MDPCOMP) {
133 layerProp[index].mFlags &= ~HWC_MDPCOMP;
134 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700135
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800136 if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
137 list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
138 }
139 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700140}
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500141
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800142/*
143 * Sets up BORDERFILL as default base pipe and detaches RGB0.
144 * Framebuffer is always updated using PLAY ioctl.
145 */
146bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
147 const int dpy = HWC_DISPLAY_PRIMARY;
148 int fb_stride = ctx->dpyAttr[dpy].stride;
149 int fb_width = ctx->dpyAttr[dpy].xres;
150 int fb_height = ctx->dpyAttr[dpy].yres;
151 int fb_fd = ctx->dpyAttr[dpy].fd;
152
153 mdp_overlay ovInfo;
154 msmfb_overlay_data ovData;
155 memset(&ovInfo, 0, sizeof(mdp_overlay));
156 memset(&ovData, 0, sizeof(msmfb_overlay_data));
157
158 ovInfo.src.format = MDP_RGB_BORDERFILL;
159 ovInfo.src.width = fb_width;
160 ovInfo.src.height = fb_height;
161 ovInfo.src_rect.w = fb_width;
162 ovInfo.src_rect.h = fb_height;
163 ovInfo.dst_rect.w = fb_width;
164 ovInfo.dst_rect.h = fb_height;
165 ovInfo.id = MSMFB_NEW_REQUEST;
166
167 if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
168 ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
169 strerror(errno));
170 return false;
171 }
172
173 ovData.id = ovInfo.id;
174 if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
175 ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
176 strerror(errno));
177 return false;
178 }
179 return true;
180}
181
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800182void MDPComp::reset(hwc_context_t *ctx,
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800183 hwc_display_contents_1_t* list ) {
184 //Reset flags and states
185 unsetMDPCompLayerFlags(ctx, list);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800186 if(mCurrentFrame.pipeLayer) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800187 for(int i = 0 ; i < mCurrentFrame.count; i++ ) {
188 if(mCurrentFrame.pipeLayer[i].pipeInfo) {
189 delete mCurrentFrame.pipeLayer[i].pipeInfo;
190 mCurrentFrame.pipeLayer[i].pipeInfo = NULL;
191 }
192 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800193 free(mCurrentFrame.pipeLayer);
194 mCurrentFrame.pipeLayer = NULL;
195 }
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800196 mCurrentFrame.count = 0;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800197}
198
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800199void MDPComp::setVidInfo(hwc_layer_1_t *layer,
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800200 ovutils::eMdpFlags &mdpFlags) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500201 private_handle_t *hnd = (private_handle_t *)layer->handle;
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -0800202 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500203
204 if(isSecureBuffer(hnd)) {
205 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500206 }
Ramkumar Radhakrishnan12b103b2013-01-09 17:47:56 -0800207 if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
208 metadata->interlaced) {
Ramkumar Radhakrishnan47573e22012-11-07 11:36:41 -0800209 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
210 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500211}
212
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800213bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800214
215 const int dpy = HWC_DISPLAY_PRIMARY;
216 private_handle_t *hnd = (private_handle_t *)layer->handle;
217
218 if(!hnd) {
219 ALOGE("%s: layer handle is NULL", __FUNCTION__);
220 return false;
221 }
222
223 int hw_w = ctx->dpyAttr[dpy].xres;
224 int hw_h = ctx->dpyAttr[dpy].yres;
225
226 hwc_rect_t sourceCrop = layer->sourceCrop;
227 hwc_rect_t displayFrame = layer->displayFrame;
228
229 hwc_rect_t crop = sourceCrop;
230 int crop_w = crop.right - crop.left;
231 int crop_h = crop.bottom - crop.top;
232
233 hwc_rect_t dst = displayFrame;
234 int dst_w = dst.right - dst.left;
235 int dst_h = dst.bottom - dst.top;
236
237 if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800238 hwc_rect_t scissor = {0, 0, hw_w, hw_h };
239 qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
Jeykumar Sankaranc18dbc22013-02-08 14:29:44 -0800240 crop_w = crop.right - crop.left;
241 crop_h = crop.bottom - crop.top;
242 }
243
244 //Workaround for MDP HW limitation in DSI command mode panels where
245 //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
246
247 if(crop_w < 5)
248 return false;
249
250 return true;
251}
252
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800253ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
254 const int dpy = HWC_DISPLAY_PRIMARY;
255 overlay::Overlay& ov = *ctx->mOverlay;
256 ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
257
258 switch(type) {
259 case MDPCOMP_OV_DMA:
260 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, dpy);
261 if(mdp_pipe != ovutils::OV_INVALID) {
262 return mdp_pipe;
263 }
264 case MDPCOMP_OV_ANY:
265 case MDPCOMP_OV_RGB:
266 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
267 if(mdp_pipe != ovutils::OV_INVALID) {
268 return mdp_pipe;
269 }
270
271 if(type == MDPCOMP_OV_RGB) {
272 //Requested only for RGB pipe
273 break;
274 }
275 case MDPCOMP_OV_VG:
276 return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
277 default:
278 ALOGE("%s: Invalid pipe type",__FUNCTION__);
279 return ovutils::OV_INVALID;
280 };
281 return ovutils::OV_INVALID;
282}
283
284bool MDPComp::isDoable(hwc_context_t *ctx,
285 hwc_display_contents_1_t* list) {
286 //Number of layers
287 const int dpy = HWC_DISPLAY_PRIMARY;
288 int numAppLayers = ctx->listStats[dpy].numAppLayers;
289
290 overlay::Overlay& ov = *ctx->mOverlay;
291 int availablePipes = ov.availablePipes(dpy);
292
293 if(numAppLayers < 1 || numAppLayers > MAX_PIPES_PER_MIXER ||
294 pipesNeeded(ctx, list) > availablePipes) {
295 ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
296 return false;
297 }
298
299 if(ctx->mExtDispConfiguring) {
300 ALOGD_IF( isDebug(),"%s: External Display connection is pending",
301 __FUNCTION__);
302 return false;
303 }
304
305 if(isSecuring(ctx)) {
306 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
307 return false;
308 }
309
310 if(ctx->mSecureMode)
311 return false;
312
313 //Check for skip layers
314 if(isSkipPresent(ctx, dpy)) {
315 ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
316 return false;
317 }
318
319 if(ctx->listStats[dpy].needsAlphaScale
320 && ctx->mMDP.version < qdutils::MDSS_V5) {
321 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
322 return false;
323 }
324
325 //FB composition on idle timeout
326 if(sIdleFallBack) {
327 sIdleFallBack = false;
328 ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
329 return false;
330 }
331
332 //MDP composition is not efficient if layer needs rotator.
333 for(int i = 0; i < numAppLayers; ++i) {
334 // As MDP h/w supports flip operation, use MDP comp only for
335 // 180 transforms. Fail for any transform involving 90 (90, 270).
336 hwc_layer_1_t* layer = &list->hwLayers[i];
337 private_handle_t *hnd = (private_handle_t *)layer->handle;
338 if((layer->transform & HWC_TRANSFORM_ROT_90) && (!isYuvBuffer(hnd)
339 || !canRotate())) {
340 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
341 return false;
342 }
343
344 if(!isYuvBuffer(hnd) && !isWidthValid(ctx,layer)) {
345 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",__FUNCTION__);
346 return false;
347 }
348 }
349 return true;
350}
351
352bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
353 const int dpy = HWC_DISPLAY_PRIMARY;
354 if(!ctx) {
355 ALOGE("%s: invalid context", __FUNCTION__);
356 return -1;
357 }
358
359 if(!allocLayerPipes(ctx, list, mCurrentFrame)) {
360 ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
361 return false;
362 }
363
364 for (int index = 0 ; index < mCurrentFrame.count; index++) {
365 hwc_layer_1_t* layer = &list->hwLayers[index];
366 MdpPipeInfo* cur_pipe = mCurrentFrame.pipeLayer[index].pipeInfo;
367
368 if(configure(ctx, layer, cur_pipe) != 0 ) {
369 ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
370 layer %d",__FUNCTION__, index);
371 return false;
372 }
373 }
374 return true;
375}
376
377bool MDPComp::prepare(hwc_context_t *ctx,
378 hwc_display_contents_1_t* list) {
379 if(!isEnabled()) {
380 ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
381 return false;
382 }
383
384 overlay::Overlay& ov = *ctx->mOverlay;
385 bool isMDPCompUsed = true;
386
387 //reset old data
388 reset(ctx, list);
389
390 bool doable = isDoable(ctx, list);
391 if(doable) {
392 if(setup(ctx, list)) {
393 setMDPCompLayerFlags(ctx, list);
394 } else {
395 ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
396 isMDPCompUsed = false;
397 }
398 } else {
399 ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
400 doable);
401 isMDPCompUsed = false;
402 }
403
404 //Reset states
405 if(!isMDPCompUsed) {
406 //Reset current frame
407 reset(ctx, list);
408 }
409
410 mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
411 return isMDPCompUsed;
412}
413
414//=============MDPCompLowRes===================================================
415
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700416/*
417 * Configures pipe(s) for MDP composition
418 */
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800419int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800420 MdpPipeInfo* mdpInfo) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800421 const int dpy = HWC_DISPLAY_PRIMARY;
422 private_handle_t *hnd = (private_handle_t *)layer->handle;
423 overlay::Overlay& ov = *ctx->mOverlay;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700424
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800425 if(!hnd) {
426 ALOGE("%s: layer handle is NULL", __FUNCTION__);
427 return -1;
428 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700429
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800430 MdpPipeInfoLowRes& mdp_info = *(MdpPipeInfoLowRes*)mdpInfo;
431
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800432 int hw_w = ctx->dpyAttr[dpy].xres;
433 int hw_h = ctx->dpyAttr[dpy].yres;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700434
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800435 hwc_rect_t crop = layer->sourceCrop;
436 hwc_rect_t dst = layer->displayFrame;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700437
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800438 int crop_w = crop.right - crop.left;
439 int crop_h = crop.bottom - crop.top;
440
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800441 int dst_w = dst.right - dst.left;
442 int dst_h = dst.bottom - dst.top;
443
444 if(dst.left < 0 || dst.top < 0 ||
445 dst.right > hw_w || dst.bottom > hw_h) {
446 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
447 __FUNCTION__);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800448 hwc_rect_t scissor = {0, 0, hw_w, hw_h };
449 qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800450
451 //Update calulated width and height
452 crop_w = crop.right - crop.left;
453 crop_h = crop.bottom - crop.top;
454
455 dst_w = dst.right - dst.left;
456 dst_h = dst.bottom - dst.top;
457 }
458
459 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
460 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800461 dst_w = hw_w;
462 dst_h = hw_h;
463 }
464
465 // Determine pipe to set based on pipe index
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800466 ovutils::eDest dest = mdp_info.index;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800467
468 ovutils::eZorder zOrder = ovutils::ZORDER_0;
469
470 if(mdp_info.zOrder == 0 ) {
471 zOrder = ovutils::ZORDER_0;
472 } else if(mdp_info.zOrder == 1 ) {
473 zOrder = ovutils::ZORDER_1;
474 } else if(mdp_info.zOrder == 2 ) {
475 zOrder = ovutils::ZORDER_2;
476 } else if(mdp_info.zOrder == 3) {
477 zOrder = ovutils::ZORDER_3;
478 }
479
480 // Order order order
481 // setSource - just setting source
482 // setParameter - changes src w/h/f accordingly
483 // setCrop - ROI - src_rect
484 // setPosition - dst_rect
485 // commit - commit changes to mdp driver
486 // queueBuffer - not here, happens when draw is called
487
488 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
489
490 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
491
492 if(isYuvBuffer(hnd))
493 setVidInfo(layer, mdpFlags);
494
495 ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
496
497 if(layer->blending == HWC_BLENDING_PREMULT) {
498 ovutils::setMdpFlags(mdpFlags,
499 ovutils::OV_MDP_BLEND_FG_PREMULT);
500 }
501
502 ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
503
504 if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
505 if(layer->transform & HWC_TRANSFORM_FLIP_H) {
506 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700507 }
508
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800509 if(layer->transform & HWC_TRANSFORM_FLIP_V) {
510 ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700511 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800512 } else {
513 orient = static_cast<ovutils::eTransform>(layer->transform);
514 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700515
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -0800516 ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE;
517 if(isYuvBuffer(hnd) && (ctx->mMDP.version >= qdutils::MDP_V4_2 &&
518 ctx->mMDP.version < qdutils::MDSS_V5)) {
519 rotFlags = ovutils::ROT_DOWNSCALE_ENABLED;
520 }
521
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800522 ovutils::PipeArgs parg(mdpFlags,
523 info,
524 zOrder,
525 ovutils::IS_FG_OFF,
Ramkumar Radhakrishnan288f8c72013-01-15 11:37:54 -0800526 rotFlags);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700527
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800528 ov.setSource(parg, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700529
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800530 ov.setTransform(orient, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700531
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800532 ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
533 ov.setCrop(dcrop, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700534
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800535 ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
536 ov.setPosition(dim, dest);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700537
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800538 ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
539 nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
540 dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
541 mdp_info.index, mdp_info.zOrder);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500542
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800543 if (!ov.commit(dest)) {
544 ALOGE("%s: commit failed", __FUNCTION__);
545 return -1;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700546 }
547 return 0;
548}
549
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800550int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
551 hwc_display_contents_1_t* list) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800552 const int dpy = HWC_DISPLAY_PRIMARY;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800553 return ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700554}
555
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800556bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700557 hwc_display_contents_1_t* list,
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500558 FrameInfo& currentFrame) {
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800559 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500560 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800561 int layer_count = ctx->listStats[dpy].numAppLayers;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700562
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500563 currentFrame.count = layer_count;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500564 currentFrame.pipeLayer = (PipeLayerPair*)
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800565 malloc(sizeof(PipeLayerPair) * currentFrame.count);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500566
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800567 if(isYuvPresent(ctx, dpy)) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800568 int nYuvCount = ctx->listStats[dpy].yuvCount;
569
570 for(int index = 0; index < nYuvCount; index ++) {
571 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
572 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
573 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800574 info.pipeInfo = new MdpPipeInfoLowRes;
575 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800576 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800577 if(pipe_info.index == ovutils::OV_INVALID) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800578 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
579 __FUNCTION__);
580 return false;
581 }
582 pipe_info.zOrder = nYuvIndex;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500583 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500584 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700585
586 for(int index = 0 ; index < layer_count ; index++ ) {
Jeykumar Sankarancf537002013-01-21 21:19:15 -0800587 hwc_layer_1_t* layer = &list->hwLayers[index];
588 private_handle_t *hnd = (private_handle_t *)layer->handle;
589
590 if(isYuvBuffer(hnd))
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500591 continue;
592
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500593 PipeLayerPair& info = currentFrame.pipeLayer[index];
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800594 info.pipeInfo = new MdpPipeInfoLowRes;
595 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
596
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500597 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY);
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800598 if(pipe_info.index == ovutils::OV_INVALID) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500599 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
600 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700601 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500602 pipe_info.zOrder = index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700603 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700604 return true;
605}
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700606
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800607bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700608
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500609 if(!isEnabled() || !isUsed()) {
610 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
611 return true;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800612 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700613
614 if(!ctx || !list) {
615 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500616 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700617 }
618
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500619 /* reset Invalidator */
620 if(idleInvalidator)
621 idleInvalidator->markForSleep();
622
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800623 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500624 overlay::Overlay& ov = *ctx->mOverlay;
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800625 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700626
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800627 int numHwLayers = ctx->listStats[dpy].numAppLayers;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700628 for(int i = 0; i < numHwLayers; i++ )
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700629 {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700630 hwc_layer_1_t *layer = &list->hwLayers[i];
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700631
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500632 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700633 continue;
634 }
635
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800636 MdpPipeInfoLowRes& pipe_info =
637 *(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
638 ovutils::eDest dest = pipe_info.index;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700639
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800640 if(dest == ovutils::OV_INVALID) {
641 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
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 if (ctx ) {
646 private_handle_t *hnd = (private_handle_t *)layer->handle;
647 if(!hnd) {
648 ALOGE("%s handle null", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500649 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700650 }
651
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700652 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800653 using pipe: %d", __FUNCTION__, layer,
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800654 hnd, dest );
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700655
656 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
657 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500658 return false;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700659 }
660 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500661
662 layerProp[i].mFlags &= ~HWC_MDPCOMP;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700663 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500664 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700665}
666
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800667//=============MDPCompHighRes===================================================
668
669int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
670 hwc_display_contents_1_t* list) {
671 const int dpy = HWC_DISPLAY_PRIMARY;
672 int numAppLayers = ctx->listStats[dpy].numAppLayers;
673 int pipesNeeded = 0;
674
675 int hw_w = ctx->dpyAttr[dpy].xres;
676
677 for(int i = 0; i < numAppLayers; ++i) {
678 hwc_layer_1_t* layer = &list->hwLayers[i];
679 hwc_rect_t dst = layer->displayFrame;
680 if(dst.left > hw_w/2) {
681 pipesNeeded++;
682 } else if(dst.right <= hw_w/2) {
683 pipesNeeded++;
684 } else {
685 pipesNeeded += 2;
686 }
687 }
688 return pipesNeeded;
689}
690
691bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
692 MdpPipeInfoHighRes& pipe_info, ePipeType type) {
693 const int dpy = HWC_DISPLAY_PRIMARY;
694 int hw_w = ctx->dpyAttr[dpy].xres;
695
696 hwc_rect_t dst = layer->displayFrame;
697 if(dst.left > hw_w/2) {
698 pipe_info.lIndex = ovutils::OV_INVALID;
699 pipe_info.rIndex = getMdpPipe(ctx, type);
700 if(pipe_info.rIndex == ovutils::OV_INVALID)
701 return false;
702 } else if (dst.right <= hw_w/2) {
703 pipe_info.rIndex = ovutils::OV_INVALID;
704 pipe_info.lIndex = getMdpPipe(ctx, type);
705 if(pipe_info.lIndex == ovutils::OV_INVALID)
706 return false;
707 } else {
708 pipe_info.rIndex = getMdpPipe(ctx, type);
709 pipe_info.lIndex = getMdpPipe(ctx, type);
710 if(pipe_info.rIndex == ovutils::OV_INVALID ||
711 pipe_info.lIndex == ovutils::OV_INVALID)
712 return false;
713 }
714 return true;
715}
716
717bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
718 hwc_display_contents_1_t* list,
719 FrameInfo& currentFrame) {
720 const int dpy = HWC_DISPLAY_PRIMARY;
721 overlay::Overlay& ov = *ctx->mOverlay;
722 int layer_count = ctx->listStats[dpy].numAppLayers;
723
724 currentFrame.count = layer_count;
725 currentFrame.pipeLayer = (PipeLayerPair*)
726 malloc(sizeof(PipeLayerPair) * currentFrame.count);
727
728 if(isYuvPresent(ctx, dpy)) {
729 int nYuvCount = ctx->listStats[dpy].yuvCount;
730
731 for(int index = 0; index < nYuvCount; index ++) {
732 int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
733 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
734 PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
735 info.pipeInfo = new MdpPipeInfoHighRes;
736 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
737 if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
738 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
739 __FUNCTION__);
740 //TODO: windback pipebook data on fail
741 return false;
742 }
743 pipe_info.zOrder = nYuvIndex;
744 }
745 }
746
747 for(int index = 0 ; index < layer_count ; index++ ) {
748 hwc_layer_1_t* layer = &list->hwLayers[index];
749 private_handle_t *hnd = (private_handle_t *)layer->handle;
750
751 if(isYuvBuffer(hnd))
752 continue;
753
754 PipeLayerPair& info = currentFrame.pipeLayer[index];
755 info.pipeInfo = new MdpPipeInfoHighRes;
756 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
757
758 ePipeType type = MDPCOMP_OV_ANY;
759
760 if(!qhwc::needsScaling(layer) && !ctx->mDMAInUse
761 && ctx->mMDP.version >= qdutils::MDSS_V5)
762 type = MDPCOMP_OV_DMA;
763
764 if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
765 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
766 //TODO: windback pipebook data on fail
767 return false;
768 }
769 pipe_info.zOrder = index;
770 }
771 return true;
772}
773/*
774 * Configures pipe(s) for MDP composition
775 */
776int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
777 MdpPipeInfo* mdpInfo) {
778 const int dpy = HWC_DISPLAY_PRIMARY;
779 private_handle_t *hnd = (private_handle_t *)layer->handle;
780 overlay::Overlay& ov = *ctx->mOverlay;
781
782 if(!hnd) {
783 ALOGE("%s: layer handle is NULL", __FUNCTION__);
784 return -1;
785 }
786
787 MdpPipeInfoHighRes& mdp_info = *(MdpPipeInfoHighRes*)mdpInfo;
788
789 int hw_w = ctx->dpyAttr[dpy].xres;
790 int hw_h = ctx->dpyAttr[dpy].yres;
791
792 hwc_rect_t crop = layer->sourceCrop;
793 hwc_rect_t dst = layer->displayFrame;
794
795 int crop_w = crop.right - crop.left;
796 int crop_h = crop.bottom - crop.top;
797
798 int dst_w = dst.right - dst.left;
799 int dst_h = dst.bottom - dst.top;
800
801 if(dst.left < 0 || dst.top < 0 ||
802 dst.right > hw_w || dst.bottom > hw_h) {
803 ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
804 __FUNCTION__);
805 hwc_rect_t scissor = {0, 0, hw_w, hw_h };
806 qhwc::calculate_crop_rects(crop, dst, scissor, 0);
807
808 //Update calulated width and height
809 crop_w = crop.right - crop.left;
810 crop_h = crop.bottom - crop.top;
811
812 dst_w = dst.right - dst.left;
813 dst_h = dst.bottom - dst.top;
814 }
815
816 if( (dst_w > hw_w)|| (dst_h > hw_h)) {
817 ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
818 dst_w = hw_w;
819 dst_h = hw_h;
820 }
821
822 // Determine pipe to set based on pipe index
823 ovutils::eDest l_dest = mdp_info.lIndex;
824 ovutils::eDest r_dest = mdp_info.rIndex;
825
826 ovutils::eZorder zOrder = ovutils::ZORDER_0;
827
828 if(mdp_info.zOrder == 0 ) {
829 zOrder = ovutils::ZORDER_0;
830 } else if(mdp_info.zOrder == 1 ) {
831 zOrder = ovutils::ZORDER_1;
832 } else if(mdp_info.zOrder == 2 ) {
833 zOrder = ovutils::ZORDER_2;
834 } else if(mdp_info.zOrder == 3) {
835 zOrder = ovutils::ZORDER_3;
836 }
837
838 // Order order order
839 // setSource - just setting source
840 // setParameter - changes src w/h/f accordingly
841 // setCrop - ROI - src_rect
842 // setPosition - dst_rect
843 // commit - commit changes to mdp driver
844 // queueBuffer - not here, happens when draw is called
845
846 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
847
848 ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
849
850 if(isYuvBuffer(hnd))
851 setVidInfo(layer, mdpFlagsL);
852
853 ovutils::setMdpFlags(mdpFlagsL,ovutils::OV_MDP_BACKEND_COMPOSITION);
854
855 if(layer->blending == HWC_BLENDING_PREMULT) {
856 ovutils::setMdpFlags(mdpFlagsL,
857 ovutils::OV_MDP_BLEND_FG_PREMULT);
858 }
859
860 ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
861
862 if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
863 if(layer->transform & HWC_TRANSFORM_FLIP_H) {
864 ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_H);
865 }
866
867 if(layer->transform & HWC_TRANSFORM_FLIP_V) {
868 ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_V);
869 }
870 } else {
871 orient = static_cast<ovutils::eTransform>(layer->transform);
872 }
873
874 ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
875 ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
876
877 hwc_rect_t tmp_cropL, tmp_dstL;
878 hwc_rect_t tmp_cropR, tmp_dstR;
879
880 if(l_dest != ovutils::OV_INVALID) {
881 tmp_cropL = crop;
882 tmp_dstL = dst;
883 hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
884 qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
885 }
886 if(r_dest != ovutils::OV_INVALID) {
887 tmp_cropR = crop;
888 tmp_dstR = dst;
889 hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
890 qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
891 }
892
893 //When buffer is flipped, contents of mixer config also needs to swapped.
894 //Not needed if the layer is confined to one half of the screen.
895 if(layer->transform & HWC_TRANSFORM_FLIP_V &&
896 l_dest != ovutils::OV_INVALID && r_dest != ovutils::OV_INVALID ) {
897 hwc_rect_t new_cropR;
898 new_cropR.left = tmp_cropL.left;
899 new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
900
901 hwc_rect_t new_cropL;
902 new_cropL.left = new_cropR.right;
903 new_cropL.right = tmp_cropR.right;
904
905 tmp_cropL.left = new_cropL.left;
906 tmp_cropL.right = new_cropL.right;
907
908 tmp_cropR.left = new_cropR.left;
909 tmp_cropR.right = new_cropR.right;
910
911 ALOGD_IF(isDebug(),"rects on V flip: \
912 cropL(%d,%d,%d,%d) dstL(%d,%d,%d,%d) \
913 cropR(%d,%d,%d,%d) dstR(%d,%d,%d,%d)",
914 tmp_cropL.left, tmp_cropL.top, tmp_cropL.right, tmp_cropL.bottom,
915 tmp_dstL.left, tmp_dstL.top, tmp_dstL.right, tmp_dstL.bottom,
916 tmp_cropR.left, tmp_cropR.top, tmp_cropR.right, tmp_cropR.bottom,
917 tmp_dstR.left, tmp_dstR.top, tmp_dstR.right, tmp_dstR.bottom);
918 }
919
920 //**** configure left mixer ****
921 if(l_dest != ovutils::OV_INVALID) {
922 ovutils::PipeArgs pargL(mdpFlagsL,
923 info,
924 zOrder,
925 ovutils::IS_FG_OFF,
926 ovutils::ROT_FLAGS_NONE);
927
928 ov.setSource(pargL, l_dest);
929 ov.setTransform(orient, l_dest);
930 ovutils::Dim dcropL(tmp_cropL.left, tmp_cropL.top,
931 tmp_cropL.right - tmp_cropL.left,
932 tmp_cropL.bottom - tmp_cropL.top);
933 ov.setCrop(dcropL, l_dest);
934 ovutils::Dim dimL(tmp_dstL.left , tmp_dstL.top,
935 tmp_dstL.right - tmp_dstL.left,
936 tmp_dstL.bottom - tmp_dstL.top);
937 ov.setPosition(dimL, l_dest);
938
939 ALOGD_IF(isDebug(),"%s: MDP set: LEFT: \
940 crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexL: %d zorder: %d",
941 __FUNCTION__, dcropL.x, dcropL.y,dcropL.w, dcropL.h,
942 dimL.x, dimL.y, dimL.w, dimL.h,
943 mdp_info.lIndex, mdp_info.zOrder);
944
945 if (!ov.commit(l_dest)) {
946 ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
947 return -1;
948 }
949 }
950
951 //**** configure right mixer ****
952 if(r_dest != ovutils::OV_INVALID) {
953 ovutils::PipeArgs pargR(mdpFlagsR,
954 info,
955 zOrder,
956 ovutils::IS_FG_OFF,
957 ovutils::ROT_FLAGS_NONE);
958
959 ov.setSource(pargR, r_dest);
960 ov.setTransform(orient, r_dest);
961 ovutils::Dim dcropR(tmp_cropR.left, tmp_cropR.top,
962 tmp_cropR.right - tmp_cropR.left,
963 tmp_cropR.bottom - tmp_cropR.top);
964 ov.setCrop(dcropR, r_dest);
965 ovutils::Dim dimR(tmp_dstR.left - hw_w/2, tmp_dstR.top,
966 tmp_dstR.right - tmp_dstR.left,
967 tmp_dstR.bottom - tmp_dstR.top);
968 ov.setPosition(dimR, r_dest);
969
970 ALOGD_IF(isDebug(),"%s: MDP set: RIGHT: \
971 crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexR: %d zorder: %d",
972 __FUNCTION__, dcropR.x, dcropR.y,dcropR.w, dcropR.h,
973 dimR.x, dimR.y, dimR.w, dimR.h,
974 mdp_info.rIndex, mdp_info.zOrder);
975
976 if (!ov.commit(r_dest)) {
977 ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
978 return -1;
979 }
980 }
981
982 return 0;
983}
984
985bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
986
987 if(!isEnabled() || !isUsed()) {
988 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
989 return true;
990 }
991
992 if(!ctx || !list) {
993 ALOGE("%s: invalid contxt or list",__FUNCTION__);
Naseer Ahmed7c958d42012-07-31 18:57:03 -0700994 return false;
995 }
996
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -0800997 /* reset Invalidator */
998 if(idleInvalidator)
999 idleInvalidator->markForSleep();
1000
1001 const int dpy = HWC_DISPLAY_PRIMARY;
Naseer Ahmed54821fe2012-11-28 18:44:38 -05001002 overlay::Overlay& ov = *ctx->mOverlay;
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001003 LayerProp *layerProp = ctx->layerProp[dpy];
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001004
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001005 int numHwLayers = ctx->listStats[dpy].numAppLayers;
1006 for(int i = 0; i < numHwLayers; i++ )
1007 {
1008 hwc_layer_1_t *layer = &list->hwLayers[i];
1009
1010 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
1011 continue;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001012 }
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001013
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001014 MdpPipeInfoHighRes& pipe_info =
1015 *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
1016 ovutils::eDest indexL = pipe_info.lIndex;
1017 ovutils::eDest indexR = pipe_info.rIndex;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001018
Jeykumar Sankaranb551ce42013-01-10 16:26:48 -08001019 //************* play left mixer **********
1020 if(indexL != ovutils::OV_INVALID) {
1021 ovutils::eDest destL = (ovutils::eDest)indexL;
1022 if (ctx ) {
1023 private_handle_t *hnd = (private_handle_t *)layer->handle;
1024 if(!hnd) {
1025 ALOGE("%s handle null", __FUNCTION__);
1026 return false;
1027 }
1028
1029 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1030 using pipe: %d", __FUNCTION__, layer, hnd, indexL );
1031
1032 if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
1033 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
1034 return false;
1035 }
1036 }
1037 }
1038
1039 //************* play right mixer **********
1040 if(indexR != ovutils::OV_INVALID) {
1041 ovutils::eDest destR = (ovutils::eDest)indexR;
1042 if (ctx ) {
1043 private_handle_t *hnd = (private_handle_t *)layer->handle;
1044 if(!hnd) {
1045 ALOGE("%s handle null", __FUNCTION__);
1046 return false;
1047 }
1048
1049 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1050 using pipe: %d", __FUNCTION__, layer, hnd, indexR );
1051
1052 if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
1053 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
1054 return false;
1055 }
1056 }
1057 }
1058 layerProp[i].mFlags &= ~HWC_MDPCOMP;
1059 }
1060 return true;
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001061}
Naseer Ahmed7c958d42012-07-31 18:57:03 -07001062}; //namespace
1063