blob: 3aa7e7a1870e037b44d9890c5a0515538cfaf7a2 [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];
46 chooseState(ctx, dpy, yuvLayer);
47 if(configure(ctx, dpy, yuvLayer)) {
48 markFlags(yuvLayer);
49 sIsModeOn = true;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070050 }
51
Naseer Ahmedf48aef62012-07-20 09:05:53 -070052 return sIsModeOn;
53}
54
Saurabh Shah3e858eb2012-09-17 16:53:21 -070055void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
56 hwc_layer_1_t *yuvLayer) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -070057 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
58 ovutils::getStateString(sState));
59
Saurabh Shah3e858eb2012-09-17 16:53:21 -070060 private_handle_t *hnd = NULL;
61 if(yuvLayer) {
62 hnd = (private_handle_t *)yuvLayer->handle;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070063 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -070064 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
65 switch(dpy) {
66 case HWC_DISPLAY_PRIMARY:
67 if(ctx->listStats[dpy].yuvCount == 1) {
68 newState = ovutils::OV_2D_VIDEO_ON_PANEL;
69 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
70 newState = ovutils::OV_CLOSED;
71 }
72 }
73 break;
74 case HWC_DISPLAY_EXTERNAL:
75 //TODO needs overlay state change for UI also
76 newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
77 /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
78 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
79 switch(sState) { //set by primary chooseState
80 case ovutils::OV_2D_VIDEO_ON_PANEL:
81 //upgrade
82 sState = ovutils::OV_2D_VIDEO_PANEL_TV;
83 break;
84 case ovutils::OV_CLOSED:
85 sState = ovutils::OV_2D_VIDEO_ON_TV;
86 break;
87 }
88 }
89 }*/
90 break;
91 default:
92 break;
93 }
94
Naseer Ahmedf48aef62012-07-20 09:05:53 -070095 sState = newState;
96 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
97 ovutils::getStateString(sState));
98}
99
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700100void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
101 if(yuvLayer) {
102 yuvLayer->compositionType = HWC_OVERLAY;
103 yuvLayer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700104 }
105}
106
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700107/* Helpers */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700108bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700109 overlay::Overlay& ov = *(ctx->mOverlay);
110 private_handle_t *hnd = (private_handle_t *)layer->handle;
111 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700112
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700113 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700114 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700115 ovutils::setMdpFlags(mdpFlags,
116 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
117 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700118
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700119 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
120 if (ctx->numHwLayers == 1) {
121 isFgFlag = ovutils::IS_FG_SET;
122 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700123
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700124 ovutils::PipeArgs parg(mdpFlags,
125 info,
126 ovutils::ZORDER_0,
127 isFgFlag,
128 ovutils::ROT_FLAG_DISABLED);
129 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
130 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700131
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700132 hwc_rect_t sourceCrop = layer->sourceCrop;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700133 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700134
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700135 //Calculate the rect for primary based on whether the supplied position
136 //is within or outside bounds.
137 const int fbWidth =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700138 ovutils::FrameBufferInfo::getInstance()->getWidth();
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700139 const int fbHeight =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700140 ovutils::FrameBufferInfo::getInstance()->getHeight();
141
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700142 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700143 displayFrame.top < 0 ||
144 displayFrame.right > fbWidth ||
145 displayFrame.bottom > fbHeight) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700146 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700147 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700148
Saurabh Shah1023ce22012-09-05 18:45:59 -0700149 // source crop x,y,w,h
150 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
151 sourceCrop.right - sourceCrop.left,
152 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700153 //Only for Primary
154 ov.setCrop(dcrop, ovutils::OV_PIPE0);
155
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700156 int transform = layer->transform;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700157 ovutils::eTransform orient =
158 static_cast<ovutils::eTransform>(transform);
159 ov.setTransform(orient, ovutils::OV_PIPE0);
160
Saurabh Shah1023ce22012-09-05 18:45:59 -0700161 // position x,y,w,h
162 ovutils::Dim dpos(displayFrame.left,
163 displayFrame.top,
164 displayFrame.right - displayFrame.left,
165 displayFrame.bottom - displayFrame.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700166 ov.setPosition(dpos, ovutils::OV_PIPE0);
167
168 if (!ov.commit(ovutils::OV_PIPE0)) {
169 ALOGE("%s: commit fails", __FUNCTION__);
170 return false;
171 }
172 return true;
173}
174
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700175bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700176 overlay::Overlay& ov = *(ctx->mOverlay);
177 private_handle_t *hnd = (private_handle_t *)layer->handle;
178 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
179
180 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700181 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700182 ovutils::setMdpFlags(mdpFlags,
183 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
184 }
185
186 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
187 if (ctx->numHwLayers == 1) {
188 isFgFlag = ovutils::IS_FG_SET;
189 }
190
191 ovutils::PipeArgs parg(mdpFlags,
192 info,
193 ovutils::ZORDER_0,
194 isFgFlag,
195 ovutils::ROT_FLAG_DISABLED);
196 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
197 ov.setSource(pargs, ovutils::OV_PIPE1);
198
199 hwc_rect_t sourceCrop = layer->sourceCrop;
200 // x,y,w,h
201 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
202 sourceCrop.right - sourceCrop.left,
203 sourceCrop.bottom - sourceCrop.top);
204 //Only for External
205 ov.setCrop(dcrop, ovutils::OV_PIPE1);
206
207 // FIXME: Use source orientation for TV when source is portrait
208 //Only for External
209 ov.setTransform(0, ovutils::OV_PIPE1);
210
211 ovutils::Dim dpos;
212 hwc_rect_t displayFrame = layer->displayFrame;
213 dpos.x = displayFrame.left;
214 dpos.y = displayFrame.top;
215 dpos.w = (displayFrame.right - displayFrame.left);
216 dpos.h = (displayFrame.bottom - displayFrame.top);
217
218 //Only for External
219 ov.setPosition(dpos, ovutils::OV_PIPE1);
220
221 if (!ov.commit(ovutils::OV_PIPE1)) {
222 ALOGE("%s: commit fails", __FUNCTION__);
223 return false;
224 }
225 return true;
226}
227
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700228bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
229 hwc_layer_1_t *yuvLayer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700230 bool ret = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700231 overlay::Overlay& ov = *(ctx->mOverlay);
232 switch(dpy) {
233 case HWC_DISPLAY_PRIMARY:
234 // Set overlay state
235 ov.setState(sState);
236 switch(sState) {
237 case ovutils::OV_2D_VIDEO_ON_PANEL:
238 ret &= configPrimVid(ctx, yuvLayer);
239 break;
240 default:
241 return false;
242 }
243 break;
244 case HWC_DISPLAY_EXTERNAL:
245 ov.setState(sState);
246 switch(sState) {
247 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
248 case ovutils::OV_2D_VIDEO_ON_TV:
249 ret = configExtVid(ctx, yuvLayer);
250 break;
251 default:
252 return false;
253 }
254 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700255 }
256 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700257}
258
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700259bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
260 int dpy)
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700261{
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700262 int yuvIndex = ctx->listStats[dpy].yuvIndex;
263 if(!sIsModeOn || yuvIndex == -1) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700264 return true;
265 }
266
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700267 private_handle_t *hnd = (private_handle_t *)
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700268 list->hwLayers[yuvIndex].handle;
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700269
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700270 bool ret = true;
271 overlay::Overlay& ov = *(ctx->mOverlay);
272 ovutils::eOverlayState state = ov.getState();
273
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700274 switch(dpy) {
275 case HWC_DISPLAY_PRIMARY:
276 switch (state) {
277 case ovutils::OV_2D_VIDEO_ON_PANEL:
278 // Play primary
279 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
280 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
281 ret = false;
282 }
283 break;
284 default:
285 ret = false;
286 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700287 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700288 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700289 case HWC_DISPLAY_EXTERNAL:
290 switch(state) {
291 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
292 case ovutils::OV_2D_VIDEO_ON_TV:
293 // Play external
294 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
295 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
296 ret = false;
297 }
298 break;
299 default:
300 ret = false;
301 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700302 }
303 break;
304 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700305 return ret;
306}
307
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700308}; //namespace qhwc