blob: d3fd80aadc888dfff84f0fc883971a1617734ad3 [file] [log] [blame]
Iliyan Malchev202a77d2012-06-11 14:41:12 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2011-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
18#include "overlayLibUI.h"
19#include "gralloc_priv.h"
20#define LOG_TAG "OverlayUI"
21
22using android::sp;
23using gralloc::IMemAlloc;
24using gralloc::alloc_data;
25
26namespace {
27/* helper functions */
28void swapOVRotWidthHeight(msm_rotator_img_info& rotInfo,
29 mdp_overlay& ovInfo) {
30 int srcWidth = ovInfo.src.width;
31 ovInfo.src.width = ovInfo.src.height;
32 ovInfo.src.height = srcWidth;
33
34 int srcRectWidth = ovInfo.src_rect.w;
35 ovInfo.src_rect.w = ovInfo.src_rect.h;
36 ovInfo.src_rect.h = srcRectWidth;
37
38 int dstWidth = rotInfo.dst.width;
39 rotInfo.dst.width = rotInfo.dst.height;
40 rotInfo.dst.height = dstWidth;
41}
42
43bool isRGBType(int format) {
44 bool ret = false;
45 switch(format) {
46 case MDP_RGBA_8888:
47 case MDP_BGRA_8888:
48 case MDP_RGBX_8888:
49 case MDP_RGB_565:
50 ret = true;
51 break;
52 default:
53 ret = false;
54 break;
55 }
56 return ret;
57}
58
59int getRGBBpp(int format) {
60 int ret = -1;
61 switch(format) {
62 case MDP_RGBA_8888:
63 case MDP_BGRA_8888:
64 case MDP_RGBX_8888:
65 ret = 4;
66 break;
67 case MDP_RGB_565:
68 ret = 2;
69 break;
70 default:
71 ret = -1;
72 break;
73 }
74
75 return ret;
76}
77
78bool turnOFFVSync() {
79 static int swapIntervalPropVal = -1;
80 if (swapIntervalPropVal == -1) {
81 char pval[PROPERTY_VALUE_MAX];
82 property_get("debug.gr.swapinterval", pval, "1");
83 swapIntervalPropVal = atoi(pval);
84 }
85 return (swapIntervalPropVal == 0);
86}
87
88};
89
90namespace overlay {
91
92status_t Display::openDisplay(int fbnum) {
93 if (mFD != NO_INIT)
94 return NO_ERROR;
95
96 status_t ret = NO_INIT;
97 char dev_name[64];
98 snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
99
100 mFD = open(dev_name, O_RDWR, 0);
101 if (mFD < 0) {
102 LOGE("Failed to open FB %d", fbnum);
103 return ret;
104 }
105
106 fb_var_screeninfo vinfo;
107 if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo)) {
108 LOGE("FBIOGET_VSCREENINFO on failed on FB %d", fbnum);
109 close(mFD);
110 mFD = NO_INIT;
111 return ret;
112 }
113
114 mFBWidth = vinfo.xres;
115 mFBHeight = vinfo.yres;
116 mFBBpp = vinfo.bits_per_pixel;
117 ret = NO_ERROR;
118
119 return ret;
120}
121
122void Display::closeDisplay() {
123 close(mFD);
124 mFD = NO_INIT;
125}
126
127Rotator::Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(NO_INIT)
128{
129 mAlloc = gralloc::IAllocController::getInstance(false);
130}
131
132Rotator::~Rotator()
133{
134 closeRotSession();
135}
136
137status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
138 int size, int numBuffers) {
139 status_t ret = NO_ERROR;
140 if (mSessionID == NO_INIT && mFD == NO_INIT) {
141 mNumBuffers = numBuffers;
142 mFD = open("/dev/msm_rotator", O_RDWR, 0);
143 if (mFD < 0) {
144 LOGE("Couldnt open rotator device");
145 return NO_INIT;
146 }
147
148 if (ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
149 close(mFD);
150 mFD = NO_INIT;
151 return NO_INIT;
152 }
153
154 mSessionID = rotInfo.session_id;
155 alloc_data data;
156 data.base = 0;
157 data.fd = -1;
158 data.offset = 0;
159 data.size = mSize * mNumBuffers;
160 data.align = getpagesize();
161 data.uncached = true;
162
163 int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
164 GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |
165 GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
166 GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
167 GRALLOC_USAGE_PRIVATE_SMI_HEAP |
168 GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
169
170 int err = mAlloc->allocate(data, allocFlags, 0);
171
172 if(err) {
173 LOGE("%s: Can't allocate rotator memory", __func__);
174 closeRotSession();
175 return NO_INIT;
176 }
177 mPmemFD = data.fd;
178 mPmemAddr = data.base;
179 mBufferType = data.allocType;
180
181 mCurrentItem = 0;
182 for (int i = 0; i < mNumBuffers; i++)
183 mRotOffset[i] = i * mSize;
184 ret = NO_ERROR;
185 }
186 return ret;
187}
188
189status_t Rotator::closeRotSession() {
190 if (mSessionID != NO_INIT && mFD != NO_INIT) {
191 ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID);
192 close(mFD);
193 if (NO_INIT != mPmemFD) {
194 sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
195 memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
196 close(mPmemFD);
197 }
198 }
199
200 mFD = NO_INIT;
201 mSessionID = NO_INIT;
202 mPmemFD = NO_INIT;
203 mPmemAddr = MAP_FAILED;
204
205 return NO_ERROR;
206}
207
208status_t Rotator::rotateBuffer(msm_rotator_data_info& rotData) {
209 status_t ret = NO_INIT;
210 if (mSessionID != NO_INIT) {
211 rotData.dst.memory_id = mPmemFD;
212 rotData.dst.offset = mRotOffset[mCurrentItem];
213 rotData.session_id = mSessionID;
214 mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
215 if (ioctl(mFD, MSM_ROTATOR_IOCTL_ROTATE, &rotData)) {
216 LOGE("Rotator failed to rotate");
217 return BAD_VALUE;
218 }
219 return NO_ERROR;
220 }
221
222 return ret;
223}
224
225//===================== OverlayUI =================//
226
227OverlayUI::OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT),
228 mFBNum(NO_INIT), mZorder(NO_INIT), mWaitForVsync(false), mIsFg(false),
229 mSessionID(NO_INIT), mParamsChanged(false) {
230 memset(&mOvInfo, 0, sizeof(mOvInfo));
231 memset(&mRotInfo, 0, sizeof(mRotInfo));
232}
233
234OverlayUI::~OverlayUI() {
235 closeChannel();
236}
237
238void OverlayUI::setSource(const overlay_buffer_info& info, int orientation) {
239 status_t ret = NO_INIT;
240 int format3D = FORMAT_3D(info.format);
241 int colorFormat = COLOR_FORMAT(info.format);
242 int format = get_mdp_format(colorFormat);
243
244 if (format3D || !isRGBType(format)) {
245 LOGE("%s: Unsupported format", __func__);
246 return;
247 }
248
249 mParamsChanged |= (mSource.width ^ info.width) ||
250 (mSource.height ^ info.height) ||
251 (mSource.format ^ format) ||
252 (mSource.size ^ info.size) ||
253 (mOrientation ^ orientation);
254
255 mSource.width = info.width;
256 mSource.height = info.height;
257 mSource.format = format;
258 mSource.size = info.size;
259 mOrientation = orientation;
260 setupOvRotInfo();
261}
262
263void OverlayUI::setDisplayParams(int fbNum, bool waitForVsync, bool isFg, int
264 zorder, bool isVGPipe) {
265 int flags = 0;
266
267 if(false == waitForVsync)
268 flags |= MDP_OV_PLAY_NOWAIT;
269 else
270 flags &= ~MDP_OV_PLAY_NOWAIT;
271
272 if(isVGPipe)
273 flags |= MDP_OV_PIPE_SHARE;
274 else
275 flags &= ~MDP_OV_PIPE_SHARE;
276
277 if (turnOFFVSync())
278 flags |= MDP_OV_PLAY_NOWAIT;
279
280 mParamsChanged |= (mFBNum ^ fbNum) ||
281 (mOvInfo.is_fg ^ isFg) ||
282 (mOvInfo.flags ^ flags) ||
283 (mOvInfo.z_order ^ zorder);
284
285 mFBNum = fbNum;
286 mOvInfo.is_fg = isFg;
287 mOvInfo.flags = flags;
288 mOvInfo.z_order = zorder;
289
290 mobjDisplay.openDisplay(mFBNum);
291}
292
293void OverlayUI::setPosition(int x, int y, int w, int h) {
294 mParamsChanged |= (mOvInfo.dst_rect.x ^ x) ||
295 (mOvInfo.dst_rect.y ^ y) ||
296 (mOvInfo.dst_rect.w ^ w) ||
297 (mOvInfo.dst_rect.h ^ h);
298
299 mOvInfo.dst_rect.x = x;
300 mOvInfo.dst_rect.y = y;
301 mOvInfo.dst_rect.w = w;
302 mOvInfo.dst_rect.h = h;
303}
304
305void OverlayUI::setCrop(int x, int y, int w, int h) {
306 mParamsChanged |= (mOvInfo.src_rect.x ^ x) ||
307 (mOvInfo.src_rect.y ^ y) ||
308 (mOvInfo.src_rect.w ^ w) ||
309 (mOvInfo.src_rect.h ^ h);
310
311 mOvInfo.src_rect.x = x;
312 mOvInfo.src_rect.y = y;
313 mOvInfo.src_rect.w = w;
314 mOvInfo.src_rect.h = h;
315}
316
317void OverlayUI::setupOvRotInfo() {
318 int w = mSource.width;
319 int h = mSource.height;
320 int format = mSource.format;
321 int srcw = (w + 31) & ~31;
322 int srch = (h + 31) & ~31;
323 mOvInfo.src.width = srcw;
324 mOvInfo.src.height = srch;
325 mOvInfo.src.format = format;
326 mOvInfo.src_rect.w = w;
327 mOvInfo.src_rect.h = h;
328 mOvInfo.alpha = 0xff;
329 mOvInfo.transp_mask = 0xffffffff;
330 mRotInfo.src.format = format;
331 mRotInfo.dst.format = format;
332 mRotInfo.src.width = srcw;
333 mRotInfo.src.height = srch;
334 mRotInfo.src_rect.w = srcw;
335 mRotInfo.src_rect.h = srch;
336 mRotInfo.dst.width = srcw;
337 mRotInfo.dst.height = srch;
338
339 int rot = mOrientation;
340 switch(rot) {
341 case 0:
342 case HAL_TRANSFORM_FLIP_H:
343 case HAL_TRANSFORM_FLIP_V:
344 rot = 0;
345 break;
346 case HAL_TRANSFORM_ROT_90:
347 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
348 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): {
349 int tmp = mOvInfo.src_rect.x;
350 mOvInfo.src_rect.x = mOvInfo.src.height -
351 (mOvInfo.src_rect.y + mOvInfo.src_rect.h);
352 mOvInfo.src_rect.y = tmp;
353 swapOVRotWidthHeight(mRotInfo, mOvInfo);
354 rot = HAL_TRANSFORM_ROT_90;
355 break;
356 }
357 case HAL_TRANSFORM_ROT_180:
358 break;
359 case HAL_TRANSFORM_ROT_270: {
360 int tmp = mOvInfo.src_rect.y;
361 mOvInfo.src_rect.y = mOvInfo.src.width -
362 (mOvInfo.src_rect.x + mOvInfo.src_rect.w);
363 mOvInfo.src_rect.x = tmp;
364 swapOVRotWidthHeight(mRotInfo, mOvInfo);
365 break;
366 }
367 default:
368 break;
369 }
370 int mdp_rotation = overlay::get_mdp_orientation(rot);
371 if (mdp_rotation < 0)
372 mdp_rotation = 0;
373 mOvInfo.user_data[0] = mdp_rotation;
374 mRotInfo.rotations = mOvInfo.user_data[0];
375 if (mdp_rotation)
376 mRotInfo.enable = 1;
377}
378
379status_t OverlayUI::commit() {
380 status_t ret = BAD_VALUE;
381 if(mChannelState != UP)
382 mOvInfo.id = MSMFB_NEW_REQUEST;
383 ret = startOVSession();
384 if (ret == NO_ERROR && mOrientation) {
385 ret = mobjRotator.startRotSession(mRotInfo, mSource.size);
386 }
387 if (ret == NO_ERROR) {
388 mChannelState = UP;
389 } else {
390 LOGE("start channel failed.");
391 }
392 return ret;
393}
394
395status_t OverlayUI::closeChannel() {
396 if( mChannelState != UP ) {
397 return NO_ERROR;
398 }
399 if(NO_ERROR != closeOVSession()) {
400 LOGE("%s: closeOVSession() failed.", __FUNCTION__);
401 return BAD_VALUE;
402 }
403 if(NO_ERROR != mobjRotator.closeRotSession()) {
404 LOGE("%s: closeRotSession() failed.", __FUNCTION__);
405 return BAD_VALUE;
406 }
407 mChannelState = CLOSED;
408 mParamsChanged = false;
409 memset(&mOvInfo, 0, sizeof(mOvInfo));
410 memset(&mRotInfo, 0, sizeof(mRotInfo));
411 return NO_ERROR;
412}
413
414status_t OverlayUI::startOVSession() {
415 status_t ret = NO_INIT;
416 ret = mobjDisplay.openDisplay(mFBNum);
417
418 if (ret != NO_ERROR)
419 return ret;
420
421 if(mParamsChanged) {
422 mParamsChanged = false;
423 mdp_overlay ovInfo = mOvInfo;
424 if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
425 LOGE("Overlay set failed..");
426 ret = BAD_VALUE;
427 } else {
428 mSessionID = ovInfo.id;
429 mOvInfo = ovInfo;
430 ret = NO_ERROR;
431 }
432 }
433 return ret;
434}
435
436status_t OverlayUI::closeOVSession() {
437 status_t ret = NO_ERROR;
438 int err = 0;
439 if(err = ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID)) {
440 LOGE("%s: MSMFB_OVERLAY_UNSET failed. (%d)", __FUNCTION__, err);
441 ret = BAD_VALUE;
442 } else {
443 mobjDisplay.closeDisplay();
444 mSessionID = NO_INIT;
445 }
446 return ret;
447}
448
449status_t OverlayUI::queueBuffer(buffer_handle_t buffer) {
450 status_t ret = NO_INIT;
451
452 if (mChannelState != UP)
453 return ret;
454
455 msmfb_overlay_data ovData;
456 memset(&ovData, 0, sizeof(ovData));
457
458 private_handle_t const* hnd = reinterpret_cast
459 <private_handle_t const*>(buffer);
460 ovData.data.memory_id = hnd->fd;
461 ovData.data.offset = hnd->offset;
462 if (mOrientation) {
463 msm_rotator_data_info rotData;
464 memset(&rotData, 0, sizeof(rotData));
465 rotData.src.memory_id = hnd->fd;
466 rotData.src.offset = hnd->offset;
467 if (mobjRotator.rotateBuffer(rotData) != NO_ERROR) {
468 LOGE("Rotator failed.. ");
469 return BAD_VALUE;
470 }
471 ovData.data.memory_id = rotData.dst.memory_id;
472 ovData.data.offset = rotData.dst.offset;
473 }
474 ovData.id = mSessionID;
475 if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData)) {
476 LOGE("Queuebuffer failed ");
477 return BAD_VALUE;
478 }
479 return NO_ERROR;
480}
481
482};