blob: 2e4342a2456c7ab18e3187497706878b8acdf5d3 [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
28ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070029bool 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) {
34 int yuvIndex = ctx->listStats[dpy].yuvIndex;
35
Naseer Ahmed96c4c952012-07-25 18:27:14 -070036 if(!ctx->mMDP.hasOverlay) {
Naseer Ahmed31da0b12012-07-31 18:55:33 -070037 ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
38 return false;
39 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070040 if(yuvIndex == -1) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070041 return false;
42 }
Naseer Ahmed4c588a22012-07-31 19:12:17 -070043
Saurabh Shah3e858eb2012-09-17 16:53:21 -070044 //index guaranteed to be not -1 at this point
45 hwc_layer_1_t *yuvLayer = &list->hwLayers[yuvIndex];
Naseer Ahmed68b88cf2012-10-02 14:15:12 -040046
47 if(ctx->mSecureMode) {
48 private_handle_t *hnd = (private_handle_t *)yuvLayer->handle;
49 if (! isSecureBuffer(hnd)) {
50 ALOGD_IF(VIDEO_DEBUG, "%s: Handle non-secure video layer"
51 "during secure playback gracefully", __FUNCTION__);
52 return false;
53 }
54 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070055 chooseState(ctx, dpy, yuvLayer);
56 if(configure(ctx, dpy, yuvLayer)) {
57 markFlags(yuvLayer);
58 sIsModeOn = true;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070059 }
60
Naseer Ahmedf48aef62012-07-20 09:05:53 -070061 return sIsModeOn;
62}
63
Saurabh Shah3e858eb2012-09-17 16:53:21 -070064void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
65 hwc_layer_1_t *yuvLayer) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -070066 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
67 ovutils::getStateString(sState));
68
Saurabh Shah3e858eb2012-09-17 16:53:21 -070069 private_handle_t *hnd = NULL;
70 if(yuvLayer) {
71 hnd = (private_handle_t *)yuvLayer->handle;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070072 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070073 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
74 switch(dpy) {
75 case HWC_DISPLAY_PRIMARY:
76 if(ctx->listStats[dpy].yuvCount == 1) {
Saurabh Shah86623d72012-09-25 19:39:17 -070077 newState = isExternalActive(ctx) ?
78 ovutils::OV_2D_VIDEO_ON_PANEL_TV : ovutils::OV_2D_VIDEO_ON_PANEL;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070079 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
Saurabh Shah86623d72012-09-25 19:39:17 -070080 newState = isExternalActive(ctx) ?
81 ovutils::OV_2D_VIDEO_ON_TV : ovutils::OV_CLOSED;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070082 }
83 }
84 break;
85 case HWC_DISPLAY_EXTERNAL:
86 //TODO needs overlay state change for UI also
87 newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
88 /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
89 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
90 switch(sState) { //set by primary chooseState
91 case ovutils::OV_2D_VIDEO_ON_PANEL:
92 //upgrade
93 sState = ovutils::OV_2D_VIDEO_PANEL_TV;
94 break;
95 case ovutils::OV_CLOSED:
96 sState = ovutils::OV_2D_VIDEO_ON_TV;
97 break;
98 }
99 }
100 }*/
101 break;
102 default:
103 break;
104 }
105
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700106 sState = newState;
107 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
108 ovutils::getStateString(sState));
109}
110
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700111void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
112 if(yuvLayer) {
113 yuvLayer->compositionType = HWC_OVERLAY;
114 yuvLayer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700115 }
116}
117
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700118/* Helpers */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700119bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700120 overlay::Overlay& ov = *(ctx->mOverlay);
121 private_handle_t *hnd = (private_handle_t *)layer->handle;
122 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700123
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700124 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700125 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700126 ovutils::setMdpFlags(mdpFlags,
127 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
128 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700129
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700130 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
131 if (ctx->numHwLayers == 1) {
132 isFgFlag = ovutils::IS_FG_SET;
133 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700134
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700135 ovutils::PipeArgs parg(mdpFlags,
136 info,
137 ovutils::ZORDER_0,
138 isFgFlag,
139 ovutils::ROT_FLAG_DISABLED);
140 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
141 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700142
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700143 hwc_rect_t sourceCrop = layer->sourceCrop;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700144 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700145
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700146 //Calculate the rect for primary based on whether the supplied position
147 //is within or outside bounds.
148 const int fbWidth =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700149 ovutils::FrameBufferInfo::getInstance()->getWidth();
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700150 const int fbHeight =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700151 ovutils::FrameBufferInfo::getInstance()->getHeight();
152
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700153 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700154 displayFrame.top < 0 ||
155 displayFrame.right > fbWidth ||
156 displayFrame.bottom > fbHeight) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700157 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700158 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700159
Saurabh Shah1023ce22012-09-05 18:45:59 -0700160 // source crop x,y,w,h
161 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
162 sourceCrop.right - sourceCrop.left,
163 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700164 //Only for Primary
165 ov.setCrop(dcrop, ovutils::OV_PIPE0);
166
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700167 int transform = layer->transform;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700168 ovutils::eTransform orient =
169 static_cast<ovutils::eTransform>(transform);
170 ov.setTransform(orient, ovutils::OV_PIPE0);
171
Saurabh Shah1023ce22012-09-05 18:45:59 -0700172 // position x,y,w,h
173 ovutils::Dim dpos(displayFrame.left,
174 displayFrame.top,
175 displayFrame.right - displayFrame.left,
176 displayFrame.bottom - displayFrame.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700177 ov.setPosition(dpos, ovutils::OV_PIPE0);
178
179 if (!ov.commit(ovutils::OV_PIPE0)) {
180 ALOGE("%s: commit fails", __FUNCTION__);
181 return false;
182 }
183 return true;
184}
185
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700186bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700187 overlay::Overlay& ov = *(ctx->mOverlay);
188 private_handle_t *hnd = (private_handle_t *)layer->handle;
189 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
190
191 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700192 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700193 ovutils::setMdpFlags(mdpFlags,
194 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
195 }
196
197 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
198 if (ctx->numHwLayers == 1) {
199 isFgFlag = ovutils::IS_FG_SET;
200 }
201
202 ovutils::PipeArgs parg(mdpFlags,
203 info,
204 ovutils::ZORDER_0,
205 isFgFlag,
Saurabh Shah8c8bfd22012-09-26 21:09:40 -0700206 ovutils::ROT_FLAG_ENABLED); //TODO remove this hack when sync for
207 //ext is done
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700208 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
209 ov.setSource(pargs, ovutils::OV_PIPE1);
210
211 hwc_rect_t sourceCrop = layer->sourceCrop;
212 // x,y,w,h
213 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
214 sourceCrop.right - sourceCrop.left,
215 sourceCrop.bottom - sourceCrop.top);
216 //Only for External
217 ov.setCrop(dcrop, ovutils::OV_PIPE1);
218
219 // FIXME: Use source orientation for TV when source is portrait
220 //Only for External
221 ov.setTransform(0, ovutils::OV_PIPE1);
222
223 ovutils::Dim dpos;
224 hwc_rect_t displayFrame = layer->displayFrame;
225 dpos.x = displayFrame.left;
226 dpos.y = displayFrame.top;
227 dpos.w = (displayFrame.right - displayFrame.left);
228 dpos.h = (displayFrame.bottom - displayFrame.top);
229
230 //Only for External
231 ov.setPosition(dpos, ovutils::OV_PIPE1);
232
233 if (!ov.commit(ovutils::OV_PIPE1)) {
234 ALOGE("%s: commit fails", __FUNCTION__);
235 return false;
236 }
237 return true;
238}
239
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700240bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
241 hwc_layer_1_t *yuvLayer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700242 bool ret = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700243 overlay::Overlay& ov = *(ctx->mOverlay);
244 switch(dpy) {
245 case HWC_DISPLAY_PRIMARY:
246 // Set overlay state
247 ov.setState(sState);
248 switch(sState) {
249 case ovutils::OV_2D_VIDEO_ON_PANEL:
250 ret &= configPrimVid(ctx, yuvLayer);
251 break;
Saurabh Shah86623d72012-09-25 19:39:17 -0700252 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
253 ret &= configPrimVid(ctx, yuvLayer);
254 ret &= configExtVid(ctx, yuvLayer);
255 break;
256 case ovutils::OV_2D_VIDEO_ON_TV:
257 ret &= configExtVid(ctx, yuvLayer);
258 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700259 default:
260 return false;
261 }
262 break;
263 case HWC_DISPLAY_EXTERNAL:
264 ov.setState(sState);
265 switch(sState) {
266 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
267 case ovutils::OV_2D_VIDEO_ON_TV:
268 ret = configExtVid(ctx, yuvLayer);
269 break;
270 default:
271 return false;
272 }
273 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700274 }
275 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700276}
277
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700278bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
279 int dpy)
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700280{
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700281 int yuvIndex = ctx->listStats[dpy].yuvIndex;
282 if(!sIsModeOn || yuvIndex == -1) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700283 return true;
284 }
285
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700286 private_handle_t *hnd = (private_handle_t *)
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700287 list->hwLayers[yuvIndex].handle;
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700288
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700289 bool ret = true;
290 overlay::Overlay& ov = *(ctx->mOverlay);
291 ovutils::eOverlayState state = ov.getState();
292
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700293 switch(dpy) {
294 case HWC_DISPLAY_PRIMARY:
295 switch (state) {
296 case ovutils::OV_2D_VIDEO_ON_PANEL:
297 // Play primary
298 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
299 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
300 ret = false;
301 }
302 break;
Saurabh Shah86623d72012-09-25 19:39:17 -0700303 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
304 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
305 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
306 ret = false;
307 }
308 // Play external
309 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
310 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
311 ret = false;
312 }
313 break;
314 case ovutils::OV_2D_VIDEO_ON_TV:
315 // Play external
316 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
317 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
318 ret = false;
319 }
320 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700321 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) {
328 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
329 case ovutils::OV_2D_VIDEO_ON_TV:
330 // Play external
331 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
332 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
333 ret = false;
334 }
335 break;
336 default:
337 ret = false;
338 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700339 }
340 break;
341 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700342 return ret;
343}
344
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700345}; //namespace qhwc