blob: aad29394a92adfde89d8bc5aaea94f352a2ace00 [file] [log] [blame]
Naseer Ahmedf48aef62012-07-20 09:05:53 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
Saurabh Shah56f610d2012-08-07 15:27:06 -07003 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
Naseer Ahmedf48aef62012-07-20 09:05:53 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Naseer Ahmed72cf9762012-07-21 12:17:13 -070018#define VIDEO_DEBUG 0
19#include <overlay.h>
Naseer Ahmedf48aef62012-07-20 09:05:53 -070020#include "hwc_video.h"
Saurabh Shah3e858eb2012-09-17 16:53:21 -070021#include "hwc_utils.h"
Naseer Ahmedf48aef62012-07-20 09:05:53 -070022
23namespace qhwc {
24
25#define FINAL_TRANSFORM_MASK 0x000F
Naseer Ahmedf48aef62012-07-20 09:05:53 -070026
27//Static Members
Saurabh Shahc4d034f2012-09-27 15:55:15 -070028ovutils::eOverlayState VideoOverlay::sState[] = {ovutils::OV_CLOSED};
29bool VideoOverlay::sIsModeOn[] = {false};
Naseer Ahmedf48aef62012-07-20 09:05:53 -070030
31//Cache stats, figure out the state, config overlay
Saurabh Shah3e858eb2012-09-17 16:53:21 -070032bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
33 int dpy) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070034
Saurabh Shah3e858eb2012-09-17 16:53:21 -070035 int yuvIndex = ctx->listStats[dpy].yuvIndex;
Saurabh Shahc4d034f2012-09-27 15:55:15 -070036 sIsModeOn[dpy] = false;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070037
Naseer Ahmed96c4c952012-07-25 18:27:14 -070038 if(!ctx->mMDP.hasOverlay) {
Naseer Ahmed31da0b12012-07-31 18:55:33 -070039 ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
40 return false;
41 }
Saurabh Shahc4d034f2012-09-27 15:55:15 -070042
43 if(yuvIndex == -1 || ctx->listStats[dpy].yuvCount != 1) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070044 return false;
45 }
Naseer Ahmed4c588a22012-07-31 19:12:17 -070046
Saurabh Shah3e858eb2012-09-17 16:53:21 -070047 //index guaranteed to be not -1 at this point
48 hwc_layer_1_t *yuvLayer = &list->hwLayers[yuvIndex];
Naseer Ahmed68b88cf2012-10-02 14:15:12 -040049
Naseer Ahmedcb5f25b2012-10-04 15:56:00 -040050 private_handle_t *hnd = (private_handle_t *)yuvLayer->handle;
Naseer Ahmed68b88cf2012-10-02 14:15:12 -040051 if(ctx->mSecureMode) {
Naseer Ahmed68b88cf2012-10-02 14:15:12 -040052 if (! isSecureBuffer(hnd)) {
53 ALOGD_IF(VIDEO_DEBUG, "%s: Handle non-secure video layer"
54 "during secure playback gracefully", __FUNCTION__);
55 return false;
56 }
Naseer Ahmedcb5f25b2012-10-04 15:56:00 -040057 } else {
58 if (isSecureBuffer(hnd)) {
59 ALOGD_IF(VIDEO_DEBUG, "%s: Handle secure video layer"
60 "during non-secure playback gracefully", __FUNCTION__);
61 return false;
62 }
Naseer Ahmed68b88cf2012-10-02 14:15:12 -040063 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070064 chooseState(ctx, dpy, yuvLayer);
65 if(configure(ctx, dpy, yuvLayer)) {
66 markFlags(yuvLayer);
Saurabh Shahc4d034f2012-09-27 15:55:15 -070067 sIsModeOn[dpy] = true;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070068 }
69
Saurabh Shahc4d034f2012-09-27 15:55:15 -070070 return sIsModeOn[dpy];
Naseer Ahmedf48aef62012-07-20 09:05:53 -070071}
72
Saurabh Shah3e858eb2012-09-17 16:53:21 -070073void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
74 hwc_layer_1_t *yuvLayer) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -070075 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
Saurabh Shahc4d034f2012-09-27 15:55:15 -070076 ovutils::getStateString(sState[dpy]));
Naseer Ahmedf48aef62012-07-20 09:05:53 -070077
Saurabh Shah3e858eb2012-09-17 16:53:21 -070078 private_handle_t *hnd = NULL;
79 if(yuvLayer) {
80 hnd = (private_handle_t *)yuvLayer->handle;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070081 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070082 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
83 switch(dpy) {
84 case HWC_DISPLAY_PRIMARY:
85 if(ctx->listStats[dpy].yuvCount == 1) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070086 newState = ovutils::OV_2D_VIDEO_ON_PANEL;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070087 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070088 newState = ovutils::OV_CLOSED;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070089 }
90 }
91 break;
92 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -070093 newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState(); //If we are here, external is active
94 if(ctx->listStats[dpy].yuvCount == 1) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -070095 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070096 newState = ovutils::OV_UI_VIDEO_TV;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070097 }
Saurabh Shahc4d034f2012-09-27 15:55:15 -070098 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070099 break;
100 default:
101 break;
102 }
103
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700104 sState[dpy] = newState;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700105 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700106 ovutils::getStateString(sState[dpy]));
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700107}
108
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700109void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
110 if(yuvLayer) {
111 yuvLayer->compositionType = HWC_OVERLAY;
112 yuvLayer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700113 }
114}
115
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700116/* Helpers */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700117bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700118 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700119 private_handle_t *hnd = (private_handle_t *)layer->handle;
120 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700121
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700122 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700123 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700124 ovutils::setMdpFlags(mdpFlags,
125 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
126 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700127
Saurabh Shah91a6a992012-08-20 15:25:28 -0700128 if(layer->blending == HWC_BLENDING_PREMULT) {
129 ovutils::setMdpFlags(mdpFlags,
130 ovutils::OV_MDP_BLEND_FG_PREMULT);
131 }
132
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700133 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
Saurabh Shah150806a2012-10-09 15:38:23 -0700134 if (ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers == 1) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700135 isFgFlag = ovutils::IS_FG_SET;
136 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700137
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700138 ovutils::PipeArgs parg(mdpFlags,
139 info,
140 ovutils::ZORDER_0,
141 isFgFlag,
142 ovutils::ROT_FLAG_DISABLED);
143 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
144 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700145
Saurabh Shah27c1d652012-08-14 19:30:28 -0700146 int transform = layer->transform & FINAL_TRANSFORM_MASK;
147 ovutils::eTransform orient =
148 static_cast<ovutils::eTransform>(transform);
149
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700150 hwc_rect_t sourceCrop = layer->sourceCrop;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700151 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700152
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700153 //Calculate the rect for primary based on whether the supplied position
154 //is within or outside bounds.
Saurabh Shah541b59d2012-10-11 11:08:12 -0700155 const int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
156 const int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700157
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700158 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700159 displayFrame.top < 0 ||
160 displayFrame.right > fbWidth ||
161 displayFrame.bottom > fbHeight) {
Saurabh Shah27c1d652012-08-14 19:30:28 -0700162 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight,
163 transform);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700164 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700165
Saurabh Shah1023ce22012-09-05 18:45:59 -0700166 // source crop x,y,w,h
167 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
168 sourceCrop.right - sourceCrop.left,
169 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700170 //Only for Primary
171 ov.setCrop(dcrop, ovutils::OV_PIPE0);
172
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700173 ov.setTransform(orient, ovutils::OV_PIPE0);
174
Saurabh Shah1023ce22012-09-05 18:45:59 -0700175 // position x,y,w,h
176 ovutils::Dim dpos(displayFrame.left,
177 displayFrame.top,
178 displayFrame.right - displayFrame.left,
179 displayFrame.bottom - displayFrame.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700180 ov.setPosition(dpos, ovutils::OV_PIPE0);
181
182 if (!ov.commit(ovutils::OV_PIPE0)) {
183 ALOGE("%s: commit fails", __FUNCTION__);
184 return false;
185 }
186 return true;
187}
188
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700189bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700190 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700191 private_handle_t *hnd = (private_handle_t *)layer->handle;
192 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
193
194 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700195 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700196 ovutils::setMdpFlags(mdpFlags,
197 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
198 }
199
Saurabh Shah91a6a992012-08-20 15:25:28 -0700200 if(layer->blending == HWC_BLENDING_PREMULT) {
201 ovutils::setMdpFlags(mdpFlags,
202 ovutils::OV_MDP_BLEND_FG_PREMULT);
203 }
204
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700205 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
Saurabh Shah150806a2012-10-09 15:38:23 -0700206 if (ctx->listStats[HWC_DISPLAY_EXTERNAL].numAppLayers == 1) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700207 isFgFlag = ovutils::IS_FG_SET;
208 }
209
210 ovutils::PipeArgs parg(mdpFlags,
211 info,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700212 ovutils::ZORDER_1,
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700213 isFgFlag,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700214 ovutils::ROT_FLAG_DISABLED);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700215 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
216 ov.setSource(pargs, ovutils::OV_PIPE1);
217
Saurabh Shah541b59d2012-10-11 11:08:12 -0700218 int transform = layer->transform;
219 ovutils::eTransform orient =
220 static_cast<ovutils::eTransform>(transform);
221
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700222 hwc_rect_t sourceCrop = layer->sourceCrop;
Saurabh Shah541b59d2012-10-11 11:08:12 -0700223 hwc_rect_t displayFrame = layer->displayFrame;
224
225 //Calculate the rect for primary based on whether the supplied position
226 //is within or outside bounds.
227 const int fbWidth = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres;
228 const int fbHeight = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].yres;
229
230 if( displayFrame.left < 0 ||
231 displayFrame.top < 0 ||
232 displayFrame.right > fbWidth ||
233 displayFrame.bottom > fbHeight) {
234 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight,
235 transform);
236 }
237
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700238 // x,y,w,h
239 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
240 sourceCrop.right - sourceCrop.left,
241 sourceCrop.bottom - sourceCrop.top);
242 //Only for External
243 ov.setCrop(dcrop, ovutils::OV_PIPE1);
244
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700245 ov.setTransform(orient, ovutils::OV_PIPE1);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700246
Saurabh Shah541b59d2012-10-11 11:08:12 -0700247 ovutils::Dim dpos(displayFrame.left,
248 displayFrame.top,
249 (displayFrame.right - displayFrame.left),
250 (displayFrame.bottom - displayFrame.top));
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700251
252 //Only for External
253 ov.setPosition(dpos, ovutils::OV_PIPE1);
254
255 if (!ov.commit(ovutils::OV_PIPE1)) {
256 ALOGE("%s: commit fails", __FUNCTION__);
257 return false;
258 }
259 return true;
260}
261
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700262bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
263 hwc_layer_1_t *yuvLayer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700264 bool ret = true;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700265 overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700266 switch(dpy) {
267 case HWC_DISPLAY_PRIMARY:
268 // Set overlay state
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700269 ov.setState(sState[dpy]);
270 switch(sState[dpy]) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700271 case ovutils::OV_2D_VIDEO_ON_PANEL:
272 ret &= configPrimVid(ctx, yuvLayer);
273 break;
274 default:
275 return false;
276 }
277 break;
278 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700279 ov.setState(sState[dpy]);
280 switch(sState[dpy]) {
281 case ovutils::OV_UI_VIDEO_TV:
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700282 ret = configExtVid(ctx, yuvLayer);
283 break;
284 default:
285 return false;
286 }
287 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700288 }
289 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700290}
291
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700292bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
293 int dpy)
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700294{
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700295 if(!sIsModeOn[dpy]) {
296 return true;
297 }
298
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700299 int yuvIndex = ctx->listStats[dpy].yuvIndex;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700300 if(yuvIndex == -1) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700301 return true;
302 }
303
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700304 private_handle_t *hnd = (private_handle_t *)
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700305 list->hwLayers[yuvIndex].handle;
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700306
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700307 bool ret = true;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700308 overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700309 ovutils::eOverlayState state = ov.getState();
310
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700311 switch(dpy) {
312 case HWC_DISPLAY_PRIMARY:
313 switch (state) {
314 case ovutils::OV_2D_VIDEO_ON_PANEL:
315 // Play primary
316 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
317 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
318 ret = false;
319 }
320 break;
321 default:
322 ret = false;
323 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700324 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700325 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700326 case HWC_DISPLAY_EXTERNAL:
327 switch(state) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700328 case ovutils::OV_UI_VIDEO_TV:
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700329 // Play external
330 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
331 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
332 ret = false;
333 }
334 break;
335 default:
336 ret = false;
337 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700338 }
339 break;
340 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700341 return ret;
342}
343
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700344}; //namespace qhwc