blob: a0ae3315cd1f65ef02e9ea3dc993a7fcd75b64af [file] [log] [blame]
Naseer Ahmedf48aef62012-07-20 09:05:53 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
4 *
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>
20#include "hwc_qbuf.h"
Naseer Ahmedf48aef62012-07-20 09:05:53 -070021#include "hwc_video.h"
Naseer Ahmed72cf9762012-07-21 12:17:13 -070022#include "hwc_external.h"
Naseer Ahmedf48aef62012-07-20 09:05:53 -070023
24namespace qhwc {
25
26#define FINAL_TRANSFORM_MASK 0x000F
Naseer Ahmedf48aef62012-07-20 09:05:53 -070027
28//Static Members
29ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
30int VideoOverlay::sYuvCount = 0;
31int VideoOverlay::sYuvLayerIndex = -1;
32bool VideoOverlay::sIsModeOn = false;
33bool VideoOverlay::sIsLayerSkip = false;
34
35//Cache stats, figure out the state, config overlay
36bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
37 sIsModeOn = false;
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 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070042 if(sYuvLayerIndex == -1) {
43 return false;
44 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -070045 chooseState(ctx);
46 //if the state chosen above is CLOSED, skip this block.
47 if(sState != ovutils::OV_CLOSED) {
48 if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) {
49 markFlags(&list->hwLayers[sYuvLayerIndex]);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070050 sIsModeOn = true;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070051 }
52 }
53
54 ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
55 "IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount,
56 sYuvLayerIndex, sIsModeOn, sIsLayerSkip);
57
58 return sIsModeOn;
59}
60
61void VideoOverlay::chooseState(hwc_context_t *ctx) {
62 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
63 ovutils::getStateString(sState));
64
65 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
66 //TODO check if device supports overlay and hdmi
67
68 //Support 1 video layer
69 if(sYuvCount == 1) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070070 //Skip on primary, display on ext.
Naseer Ahmed72cf9762012-07-21 12:17:13 -070071 if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070072 newState = ovutils::OV_2D_VIDEO_ON_TV;
Naseer Ahmedf48aef62012-07-20 09:05:53 -070073 } else if(sIsLayerSkip) { //skip on primary, no ext
74 newState = ovutils::OV_CLOSED;
Naseer Ahmed72cf9762012-07-21 12:17:13 -070075 } else if(ctx->mExtDisplay->getExternalDisplay()) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070076 //display on both
Naseer Ahmedf48aef62012-07-20 09:05:53 -070077 newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
78 } else { //display on primary only
79 newState = ovutils::OV_2D_VIDEO_ON_PANEL;
80 }
81 }
82 sState = newState;
83 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
84 ovutils::getStateString(sState));
85}
86
87void VideoOverlay::markFlags(hwc_layer_t *layer) {
88 switch(sState) {
89 case ovutils::OV_2D_VIDEO_ON_PANEL:
90 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
91 layer->compositionType = HWC_OVERLAY;
92 layer->hints |= HWC_HINT_CLEAR_FB;
93 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -070094 case ovutils::OV_2D_VIDEO_ON_TV:
95 break; //dont update flags.
Naseer Ahmedf48aef62012-07-20 09:05:53 -070096 default:
97 break;
98 }
99}
100
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700101/* Helpers */
102bool configPrimVid(hwc_context_t *ctx, hwc_layer_t *layer) {
103 overlay::Overlay& ov = *(ctx->mOverlay);
104 private_handle_t *hnd = (private_handle_t *)layer->handle;
105 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700106
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700107 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
108 if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
109 ovutils::setMdpFlags(mdpFlags,
110 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
111 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700112
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700113 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
114 if (ctx->numHwLayers == 1) {
115 isFgFlag = ovutils::IS_FG_SET;
116 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700117
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700118 ovutils::PipeArgs parg(mdpFlags,
119 info,
120 ovutils::ZORDER_0,
121 isFgFlag,
122 ovutils::ROT_FLAG_DISABLED);
123 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
124 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700125
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700126 hwc_rect_t sourceCrop = layer->sourceCrop;
127 // x,y,w,h
128 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
129 sourceCrop.right - sourceCrop.left,
130 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700131
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700132 ovutils::Dim dpos;
133 hwc_rect_t displayFrame = layer->displayFrame;
134 dpos.x = displayFrame.left;
135 dpos.y = displayFrame.top;
136 dpos.w = (displayFrame.right - displayFrame.left);
137 dpos.h = (displayFrame.bottom - displayFrame.top);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700138
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700139 //Calculate the rect for primary based on whether the supplied position
140 //is within or outside bounds.
141 const int fbWidth =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700142 ovutils::FrameBufferInfo::getInstance()->getWidth();
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700143 const int fbHeight =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700144 ovutils::FrameBufferInfo::getInstance()->getHeight();
145
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700146 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700147 displayFrame.top < 0 ||
148 displayFrame.right > fbWidth ||
149 displayFrame.bottom > fbHeight) {
150
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700151 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700152
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700153 //Update calculated width and height
154 dcrop.w = sourceCrop.right - sourceCrop.left;
155 dcrop.h = sourceCrop.bottom - sourceCrop.top;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700156
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700157 dpos.w = displayFrame.right - displayFrame.left;
158 dpos.h = displayFrame.bottom - displayFrame.top;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700159 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700160
161 //Only for Primary
162 ov.setCrop(dcrop, ovutils::OV_PIPE0);
163
164 int transform = layer->transform & FINAL_TRANSFORM_MASK;
165 ovutils::eTransform orient =
166 static_cast<ovutils::eTransform>(transform);
167 ov.setTransform(orient, ovutils::OV_PIPE0);
168
169 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
178bool configExtVid(hwc_context_t *ctx, hwc_layer_t *layer) {
179 overlay::Overlay& ov = *(ctx->mOverlay);
180 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;
184 if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
185 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,
196 ovutils::ZORDER_0,
197 isFgFlag,
198 ovutils::ROT_FLAG_DISABLED);
199 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
210 // FIXME: Use source orientation for TV when source is portrait
211 //Only for External
212 ov.setTransform(0, ovutils::OV_PIPE1);
213
214 ovutils::Dim dpos;
215 hwc_rect_t displayFrame = layer->displayFrame;
216 dpos.x = displayFrame.left;
217 dpos.y = displayFrame.top;
218 dpos.w = (displayFrame.right - displayFrame.left);
219 dpos.h = (displayFrame.bottom - displayFrame.top);
220
221 //Only for External
222 ov.setPosition(dpos, ovutils::OV_PIPE1);
223
224 if (!ov.commit(ovutils::OV_PIPE1)) {
225 ALOGE("%s: commit fails", __FUNCTION__);
226 return false;
227 }
228 return true;
229}
230
231bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer)
232{
233 bool ret = true;
234 if (LIKELY(ctx->mOverlay)) {
235 overlay::Overlay& ov = *(ctx->mOverlay);
236 // Set overlay state
237 ov.setState(sState);
238 switch(sState) {
239 case ovutils::OV_2D_VIDEO_ON_PANEL:
240 ret &= configPrimVid(ctx, yuvLayer);
241 break;
242 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
243 ret &= configExtVid(ctx, yuvLayer);
244 ret &= configPrimVid(ctx, yuvLayer);
245 break;
246 case ovutils::OV_2D_VIDEO_ON_TV:
247 ret &= configExtVid(ctx, yuvLayer);
248 break;
249 default:
250 return false;
251 }
252 } else {
253 //Ov null
254 return false;
255 }
256 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700257}
258
259bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
260{
261 if(!sIsModeOn || sYuvLayerIndex == -1) {
262 return true;
263 }
264
265 private_handle_t *hnd =
266 (private_handle_t *)list->hwLayers[sYuvLayerIndex].handle;
267
268 // Lock this buffer for read.
269 ctx->qbuf->lockAndAdd(hnd);
270 bool ret = true;
271 overlay::Overlay& ov = *(ctx->mOverlay);
272 ovutils::eOverlayState state = ov.getState();
273
274 switch (state) {
275 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700276 // Play external
277 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
278 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
279 ret = false;
280 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700281 // Play primary
282 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
283 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
284 ret = false;
285 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700286 // Wait for external vsync to be done
287 if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
288 ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
289 ret = false;
290 }
291 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700292 case ovutils::OV_2D_VIDEO_ON_PANEL:
293 // Play primary
294 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
295 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700296 ret = false;
297 }
298 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700299 case ovutils::OV_2D_VIDEO_ON_TV:
300 // Play external
301 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
302 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
303 ret = false;
304 }
305 // Wait for external vsync to be done
306 if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
307 ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
308 ret = false;
309 }
310 default:
311 ALOGE("%s Unused state %s", __FUNCTION__,
312 ovutils::getStateString(state));
313 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700314 }
315
316 return ret;
317}
318
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700319}; //namespace qhwc