blob: b974ffea5aed9bb861b5fbe21d5d85ef64e5b837 [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) {
Saurabh Shah86623d72012-09-25 19:39:17 -070068 newState = isExternalActive(ctx) ?
69 ovutils::OV_2D_VIDEO_ON_PANEL_TV : ovutils::OV_2D_VIDEO_ON_PANEL;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070070 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
Saurabh Shah86623d72012-09-25 19:39:17 -070071 newState = isExternalActive(ctx) ?
72 ovutils::OV_2D_VIDEO_ON_TV : ovutils::OV_CLOSED;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070073 }
74 }
75 break;
76 case HWC_DISPLAY_EXTERNAL:
77 //TODO needs overlay state change for UI also
78 newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
79 /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
80 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
81 switch(sState) { //set by primary chooseState
82 case ovutils::OV_2D_VIDEO_ON_PANEL:
83 //upgrade
84 sState = ovutils::OV_2D_VIDEO_PANEL_TV;
85 break;
86 case ovutils::OV_CLOSED:
87 sState = ovutils::OV_2D_VIDEO_ON_TV;
88 break;
89 }
90 }
91 }*/
92 break;
93 default:
94 break;
95 }
96
Naseer Ahmedf48aef62012-07-20 09:05:53 -070097 sState = newState;
98 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
99 ovutils::getStateString(sState));
100}
101
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700102void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
103 if(yuvLayer) {
104 yuvLayer->compositionType = HWC_OVERLAY;
105 yuvLayer->hints |= HWC_HINT_CLEAR_FB;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700106 }
107}
108
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700109/* Helpers */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700110bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700111 overlay::Overlay& ov = *(ctx->mOverlay);
112 private_handle_t *hnd = (private_handle_t *)layer->handle;
113 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700114
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700115 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700116 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700117 ovutils::setMdpFlags(mdpFlags,
118 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
119 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700120
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700121 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
122 if (ctx->numHwLayers == 1) {
123 isFgFlag = ovutils::IS_FG_SET;
124 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700125
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700126 ovutils::PipeArgs parg(mdpFlags,
127 info,
128 ovutils::ZORDER_0,
129 isFgFlag,
130 ovutils::ROT_FLAG_DISABLED);
131 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
132 ov.setSource(pargs, ovutils::OV_PIPE0);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700133
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700134 hwc_rect_t sourceCrop = layer->sourceCrop;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700135 hwc_rect_t displayFrame = layer->displayFrame;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700136
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700137 //Calculate the rect for primary based on whether the supplied position
138 //is within or outside bounds.
139 const int fbWidth =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700140 ovutils::FrameBufferInfo::getInstance()->getWidth();
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700141 const int fbHeight =
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700142 ovutils::FrameBufferInfo::getInstance()->getHeight();
143
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700144 if( displayFrame.left < 0 ||
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700145 displayFrame.top < 0 ||
146 displayFrame.right > fbWidth ||
147 displayFrame.bottom > fbHeight) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700148 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700149 }
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700150
Saurabh Shah1023ce22012-09-05 18:45:59 -0700151 // source crop x,y,w,h
152 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
153 sourceCrop.right - sourceCrop.left,
154 sourceCrop.bottom - sourceCrop.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700155 //Only for Primary
156 ov.setCrop(dcrop, ovutils::OV_PIPE0);
157
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700158 int transform = layer->transform;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700159 ovutils::eTransform orient =
160 static_cast<ovutils::eTransform>(transform);
161 ov.setTransform(orient, ovutils::OV_PIPE0);
162
Saurabh Shah1023ce22012-09-05 18:45:59 -0700163 // position x,y,w,h
164 ovutils::Dim dpos(displayFrame.left,
165 displayFrame.top,
166 displayFrame.right - displayFrame.left,
167 displayFrame.bottom - displayFrame.top);
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700168 ov.setPosition(dpos, ovutils::OV_PIPE0);
169
170 if (!ov.commit(ovutils::OV_PIPE0)) {
171 ALOGE("%s: commit fails", __FUNCTION__);
172 return false;
173 }
174 return true;
175}
176
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700177bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700178 overlay::Overlay& ov = *(ctx->mOverlay);
179 private_handle_t *hnd = (private_handle_t *)layer->handle;
180 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
181
182 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700183 if (isSecureBuffer(hnd)) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700184 ovutils::setMdpFlags(mdpFlags,
185 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
186 }
187
188 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
189 if (ctx->numHwLayers == 1) {
190 isFgFlag = ovutils::IS_FG_SET;
191 }
192
193 ovutils::PipeArgs parg(mdpFlags,
194 info,
195 ovutils::ZORDER_0,
196 isFgFlag,
Saurabh Shah8c8bfd22012-09-26 21:09:40 -0700197 ovutils::ROT_FLAG_ENABLED); //TODO remove this hack when sync for
198 //ext is done
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
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
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700231bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
232 hwc_layer_1_t *yuvLayer) {
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700233 bool ret = true;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700234 overlay::Overlay& ov = *(ctx->mOverlay);
235 switch(dpy) {
236 case HWC_DISPLAY_PRIMARY:
237 // Set overlay state
238 ov.setState(sState);
239 switch(sState) {
240 case ovutils::OV_2D_VIDEO_ON_PANEL:
241 ret &= configPrimVid(ctx, yuvLayer);
242 break;
Saurabh Shah86623d72012-09-25 19:39:17 -0700243 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
244 ret &= configPrimVid(ctx, yuvLayer);
245 ret &= configExtVid(ctx, yuvLayer);
246 break;
247 case ovutils::OV_2D_VIDEO_ON_TV:
248 ret &= configExtVid(ctx, yuvLayer);
249 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700250 default:
251 return false;
252 }
253 break;
254 case HWC_DISPLAY_EXTERNAL:
255 ov.setState(sState);
256 switch(sState) {
257 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
258 case ovutils::OV_2D_VIDEO_ON_TV:
259 ret = configExtVid(ctx, yuvLayer);
260 break;
261 default:
262 return false;
263 }
264 break;
Naseer Ahmed2cc53dd2012-07-31 19:11:48 -0700265 }
266 return ret;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700267}
268
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700269bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
270 int dpy)
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700271{
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700272 int yuvIndex = ctx->listStats[dpy].yuvIndex;
273 if(!sIsModeOn || yuvIndex == -1) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700274 return true;
275 }
276
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700277 private_handle_t *hnd = (private_handle_t *)
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700278 list->hwLayers[yuvIndex].handle;
Naseer Ahmed4c588a22012-07-31 19:12:17 -0700279
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700280 bool ret = true;
281 overlay::Overlay& ov = *(ctx->mOverlay);
282 ovutils::eOverlayState state = ov.getState();
283
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700284 switch(dpy) {
285 case HWC_DISPLAY_PRIMARY:
286 switch (state) {
287 case ovutils::OV_2D_VIDEO_ON_PANEL:
288 // Play primary
289 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
290 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
291 ret = false;
292 }
293 break;
Saurabh Shah86623d72012-09-25 19:39:17 -0700294 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
295 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
296 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
297 ret = false;
298 }
299 // 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 case ovutils::OV_2D_VIDEO_ON_TV:
306 // Play external
307 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
308 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
309 ret = false;
310 }
311 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700312 default:
313 ret = false;
314 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700315 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700316 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700317 case HWC_DISPLAY_EXTERNAL:
318 switch(state) {
319 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
320 case ovutils::OV_2D_VIDEO_ON_TV:
321 // Play external
322 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
323 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
324 ret = false;
325 }
326 break;
327 default:
328 ret = false;
329 break;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700330 }
331 break;
332 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700333 return ret;
334}
335
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700336}; //namespace qhwc