blob: 7bbfaf9a658b58d7c5544f815a72ce930b7ba105 [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
50 if(ctx->mSecureMode) {
51 private_handle_t *hnd = (private_handle_t *)yuvLayer->handle;
52 if (! isSecureBuffer(hnd)) {
53 ALOGD_IF(VIDEO_DEBUG, "%s: Handle non-secure video layer"
54 "during secure playback gracefully", __FUNCTION__);
55 return false;
56 }
57 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070058 chooseState(ctx, dpy, yuvLayer);
59 if(configure(ctx, dpy, yuvLayer)) {
60 markFlags(yuvLayer);
Saurabh Shahc4d034f2012-09-27 15:55:15 -070061 sIsModeOn[dpy] = true;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070062 }
63
Saurabh Shahc4d034f2012-09-27 15:55:15 -070064 return sIsModeOn[dpy];
Naseer Ahmedf48aef62012-07-20 09:05:53 -070065}
66
Saurabh Shah3e858eb2012-09-17 16:53:21 -070067void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
68 hwc_layer_1_t *yuvLayer) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -070069 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
Saurabh Shahc4d034f2012-09-27 15:55:15 -070070 ovutils::getStateString(sState[dpy]));
Naseer Ahmedf48aef62012-07-20 09:05:53 -070071
Saurabh Shah3e858eb2012-09-17 16:53:21 -070072 private_handle_t *hnd = NULL;
73 if(yuvLayer) {
74 hnd = (private_handle_t *)yuvLayer->handle;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070075 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070076 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
77 switch(dpy) {
78 case HWC_DISPLAY_PRIMARY:
79 if(ctx->listStats[dpy].yuvCount == 1) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070080 newState = ovutils::OV_2D_VIDEO_ON_PANEL;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070081 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070082 newState = ovutils::OV_CLOSED;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070083 }
84 }
85 break;
86 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -070087 newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState(); //If we are here, external is active
88 if(ctx->listStats[dpy].yuvCount == 1) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -070089 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -070090 newState = ovutils::OV_UI_VIDEO_TV;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070091 }
Saurabh Shahc4d034f2012-09-27 15:55:15 -070092 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070093 break;
94 default:
95 break;
96 }
97
Saurabh Shahc4d034f2012-09-27 15:55:15 -070098 sState[dpy] = newState;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070099 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700100 ovutils::getStateString(sState[dpy]));
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700101}
102
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700103void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
104 if(yuvLayer) {
105 yuvLayer->compositionType = HWC_OVERLAY;
106 yuvLayer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700107 }
108}
109
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700110/* Helpers */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700111bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700112 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700113 private_handle_t *hnd = (private_handle_t *)layer->handle;
114 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700115
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700116 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700117 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700118 ovutils::setMdpFlags(mdpFlags,
119 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
120 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700121
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700122 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
123 if (ctx->numHwLayers == 1) {
124 isFgFlag = ovutils::IS_FG_SET;
125 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700126
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700127 ovutils::PipeArgs parg(mdpFlags,
128 info,
129 ovutils::ZORDER_0,
130 isFgFlag,
131 ovutils::ROT_FLAG_DISABLED);
132 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
133 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700134
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700135 hwc_rect_t sourceCrop = layer->sourceCrop;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700136 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700137
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700138 //Calculate the rect for primary based on whether the supplied position
139 //is within or outside bounds.
140 const int fbWidth =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700141 ovutils::FrameBufferInfo::getInstance()->getWidth();
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700142 const int fbHeight =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700143 ovutils::FrameBufferInfo::getInstance()->getHeight();
144
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700145 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700146 displayFrame.top < 0 ||
147 displayFrame.right > fbWidth ||
148 displayFrame.bottom > fbHeight) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700149 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700150 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700151
Saurabh Shah1023ce22012-09-05 18:45:59 -0700152 // source crop x,y,w,h
153 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
154 sourceCrop.right - sourceCrop.left,
155 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700156 //Only for Primary
157 ov.setCrop(dcrop, ovutils::OV_PIPE0);
158
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700159 int transform = layer->transform;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700160 ovutils::eTransform orient =
161 static_cast<ovutils::eTransform>(transform);
162 ov.setTransform(orient, ovutils::OV_PIPE0);
163
Saurabh Shah1023ce22012-09-05 18:45:59 -0700164 // position x,y,w,h
165 ovutils::Dim dpos(displayFrame.left,
166 displayFrame.top,
167 displayFrame.right - displayFrame.left,
168 displayFrame.bottom - displayFrame.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700169 ov.setPosition(dpos, ovutils::OV_PIPE0);
170
171 if (!ov.commit(ovutils::OV_PIPE0)) {
172 ALOGE("%s: commit fails", __FUNCTION__);
173 return false;
174 }
175 return true;
176}
177
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700178bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700179 overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700180 private_handle_t *hnd = (private_handle_t *)layer->handle;
181 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
182
183 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700184 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700185 ovutils::setMdpFlags(mdpFlags,
186 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
187 }
188
189 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
190 if (ctx->numHwLayers == 1) {
191 isFgFlag = ovutils::IS_FG_SET;
192 }
193
194 ovutils::PipeArgs parg(mdpFlags,
195 info,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700196 ovutils::ZORDER_1,
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700197 isFgFlag,
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700198 ovutils::ROT_FLAG_DISABLED);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700199 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
200 ov.setSource(pargs, ovutils::OV_PIPE1);
201
202 hwc_rect_t sourceCrop = layer->sourceCrop;
203 // x,y,w,h
204 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
205 sourceCrop.right - sourceCrop.left,
206 sourceCrop.bottom - sourceCrop.top);
207 //Only for External
208 ov.setCrop(dcrop, ovutils::OV_PIPE1);
209
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700210 int transform = layer->transform;
211 ovutils::eTransform orient =
212 static_cast<ovutils::eTransform>(transform);
213 ov.setTransform(orient, ovutils::OV_PIPE1);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700214
215 ovutils::Dim dpos;
216 hwc_rect_t displayFrame = layer->displayFrame;
217 dpos.x = displayFrame.left;
218 dpos.y = displayFrame.top;
219 dpos.w = (displayFrame.right - displayFrame.left);
220 dpos.h = (displayFrame.bottom - displayFrame.top);
221
222 //Only for External
223 ov.setPosition(dpos, ovutils::OV_PIPE1);
224
225 if (!ov.commit(ovutils::OV_PIPE1)) {
226 ALOGE("%s: commit fails", __FUNCTION__);
227 return false;
228 }
229 return true;
230}
231
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700232bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
233 hwc_layer_1_t *yuvLayer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700234 bool ret = true;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700235 overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700236 switch(dpy) {
237 case HWC_DISPLAY_PRIMARY:
238 // Set overlay state
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700239 ov.setState(sState[dpy]);
240 switch(sState[dpy]) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700241 case ovutils::OV_2D_VIDEO_ON_PANEL:
242 ret &= configPrimVid(ctx, yuvLayer);
243 break;
244 default:
245 return false;
246 }
247 break;
248 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700249 ov.setState(sState[dpy]);
250 switch(sState[dpy]) {
251 case ovutils::OV_UI_VIDEO_TV:
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700252 ret = configExtVid(ctx, yuvLayer);
253 break;
254 default:
255 return false;
256 }
257 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700258 }
259 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700260}
261
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700262bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
263 int dpy)
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700264{
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700265 if(!sIsModeOn[dpy]) {
266 return true;
267 }
268
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700269 int yuvIndex = ctx->listStats[dpy].yuvIndex;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700270 if(yuvIndex == -1) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700271 return true;
272 }
273
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700274 private_handle_t *hnd = (private_handle_t *)
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700275 list->hwLayers[yuvIndex].handle;
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700276
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700277 bool ret = true;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700278 overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700279 ovutils::eOverlayState state = ov.getState();
280
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700281 switch(dpy) {
282 case HWC_DISPLAY_PRIMARY:
283 switch (state) {
284 case ovutils::OV_2D_VIDEO_ON_PANEL:
285 // Play primary
286 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
287 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
288 ret = false;
289 }
290 break;
291 default:
292 ret = false;
293 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700294 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700295 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700296 case HWC_DISPLAY_EXTERNAL:
297 switch(state) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700298 case ovutils::OV_UI_VIDEO_TV:
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700299 // Play external
300 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
301 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
302 ret = false;
303 }
304 break;
305 default:
306 ret = false;
307 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700308 }
309 break;
310 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700311 return ret;
312}
313
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700314}; //namespace qhwc