blob: 190e31b05a7d79074541e0b1249ceba0caa2d787 [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 Ahmed31da0b12012-07-31 18:55:33 -070038 if(!ctx->hasOverlay) {
39 ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
40 return false;
41 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -070042 chooseState(ctx);
43 //if the state chosen above is CLOSED, skip this block.
44 if(sState != ovutils::OV_CLOSED) {
45 if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) {
46 markFlags(&list->hwLayers[sYuvLayerIndex]);
47 }
48 }
49
50 ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
51 "IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount,
52 sYuvLayerIndex, sIsModeOn, sIsLayerSkip);
53
54 return sIsModeOn;
55}
56
57void VideoOverlay::chooseState(hwc_context_t *ctx) {
58 ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
59 ovutils::getStateString(sState));
60
61 ovutils::eOverlayState newState = ovutils::OV_CLOSED;
62 //TODO check if device supports overlay and hdmi
63
64 //Support 1 video layer
65 if(sYuvCount == 1) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070066 //Skip on primary, display on ext.
Naseer Ahmed72cf9762012-07-21 12:17:13 -070067 if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
Naseer Ahmedf48aef62012-07-20 09:05:53 -070068 //TODO
69 //VIDEO_ON_TV_ONLY
70 } else if(sIsLayerSkip) { //skip on primary, no ext
71 newState = ovutils::OV_CLOSED;
Naseer Ahmed72cf9762012-07-21 12:17:13 -070072 } else if(ctx->mExtDisplay->getExternalDisplay()) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070073 //display on both
Naseer Ahmedf48aef62012-07-20 09:05:53 -070074 newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
75 } else { //display on primary only
76 newState = ovutils::OV_2D_VIDEO_ON_PANEL;
77 }
78 }
79 sState = newState;
80 ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
81 ovutils::getStateString(sState));
82}
83
84void VideoOverlay::markFlags(hwc_layer_t *layer) {
85 switch(sState) {
86 case ovutils::OV_2D_VIDEO_ON_PANEL:
87 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
88 layer->compositionType = HWC_OVERLAY;
89 layer->hints |= HWC_HINT_CLEAR_FB;
90 break;
91 //TODO
92 //case ovutils::OV_2D_VIDEO_ON_TV:
93 //just break, dont update flags.
94 default:
95 break;
96 }
97}
98
99bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *layer)
100{
101 if (LIKELY(ctx->mOverlay)) {
102
103 overlay::Overlay& ov = *(ctx->mOverlay);
104 // Set overlay state
105 ov.setState(sState);
106
107 private_handle_t *hnd = (private_handle_t *)layer->handle;
108 ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
109
110 //TODO change this based on state.
111 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
112
113 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
114 if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
115 ovutils::setMdpFlags(mdpFlags,
116 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
117 }
118
119 ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
120 if (ctx->numHwLayers == 1) {
121 isFgFlag = ovutils::IS_FG_SET;
122 }
123
124 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, dest);
131
132 hwc_rect_t sourceCrop = layer->sourceCrop;
133 // x,y,w,h
134 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
135 sourceCrop.right - sourceCrop.left,
136 sourceCrop.bottom - sourceCrop.top);
137 //Only for External
138 ov.setCrop(dcrop, ovutils::OV_PIPE1);
139
140 // FIXME: Use source orientation for TV when source is portrait
141 //Only for External
142 ov.setTransform(0, dest);
143
144 ovutils::Dim dpos;
145 hwc_rect_t displayFrame = layer->displayFrame;
146 dpos.x = displayFrame.left;
147 dpos.y = displayFrame.top;
148 dpos.w = (displayFrame.right - displayFrame.left);
149 dpos.h = (displayFrame.bottom - displayFrame.top);
150
151 //Only for External
152 ov.setPosition(dpos, ovutils::OV_PIPE1);
153
154 //Calculate the rect for primary based on whether the supplied position
155 //is within or outside bounds.
156 const int fbWidth =
157 ovutils::FrameBufferInfo::getInstance()->getWidth();
158 const int fbHeight =
159 ovutils::FrameBufferInfo::getInstance()->getHeight();
160
161 if( displayFrame.left < 0 ||
162 displayFrame.top < 0 ||
163 displayFrame.right > fbWidth ||
164 displayFrame.bottom > fbHeight) {
165
166 calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
167
168 //Update calculated width and height
169 dcrop.w = sourceCrop.right - sourceCrop.left;
170 dcrop.h = sourceCrop.bottom - sourceCrop.top;
171
172 dpos.w = displayFrame.right - displayFrame.left;
173 dpos.h = displayFrame.bottom - displayFrame.top;
174 }
175
176 //Only for Primary
177 ov.setCrop(dcrop, ovutils::OV_PIPE0);
178
179 int transform = layer->transform & FINAL_TRANSFORM_MASK;
180 ovutils::eTransform orient =
181 static_cast<ovutils::eTransform>(transform);
182 ov.setTransform(orient, ovutils::OV_PIPE0);
183
184 ov.setPosition(dpos, ovutils::OV_PIPE0);
185
186 //Both prim and external
187 if (!ov.commit(dest)) {
188 ALOGE("%s: commit fails", __FUNCTION__);
189 return false;
190 }
191
192 sIsModeOn = true;
193 }
194 return sIsModeOn;
195}
196
197bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
198{
199 if(!sIsModeOn || sYuvLayerIndex == -1) {
200 return true;
201 }
202
203 private_handle_t *hnd =
204 (private_handle_t *)list->hwLayers[sYuvLayerIndex].handle;
205
206 // Lock this buffer for read.
207 ctx->qbuf->lockAndAdd(hnd);
208 bool ret = true;
209 overlay::Overlay& ov = *(ctx->mOverlay);
210 ovutils::eOverlayState state = ov.getState();
211
212 switch (state) {
213 case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
214 case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
215 // Play external
216 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
217 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
218 ret = false;
219 }
220
221 // Play primary
222 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
223 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
224 ret = false;
225 }
226
227 // Wait for external vsync to be done
228 if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
229 ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
230 ret = false;
231 }
232 break;
233 default:
234 // In most cases, displaying only to one (primary or external)
235 // so use OV_PIPE_ALL since overlay will ignore NullPipes
236 if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE_ALL)) {
237 ALOGE("%s: queueBuffer failed", __FUNCTION__);
238 ret = false;
239 }
240 break;
241 }
242
243 return ret;
244}
245
246
247}; //namespace qhwc