blob: fe5c3d3b680495daa080fad7276898de5529c59e [file] [log] [blame]
Iliyan Malchev202a77d2012-06-11 14:41:12 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2010-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 "overlayLib.h"
19#include "gralloc_priv.h"
20
21#define INTERLACE_MASK 0x80
22#define DEBUG_OVERLAY true
23/* Helper functions */
24static inline size_t ALIGN(size_t x, size_t align) {
25 return (x + align-1) & ~(align-1);
26}
27
28using namespace overlay;
29using android::sp;
30using gralloc::IMemAlloc;
31using gralloc::IonController;
32using gralloc::alloc_data;
33
34#ifdef HDMI_AS_PRIMARY
35bool Overlay::sHDMIAsPrimary = true;
36#else
37bool Overlay::sHDMIAsPrimary = false;
38#endif
39
40template <class Type>
41void swapWidthHeight(Type& width, Type& height) {
42 Type tmp = width;
43 width = height;
44 height = tmp;
45}
46
47int overlay::get_mdp_format(int format) {
48 switch (format) {
49 case HAL_PIXEL_FORMAT_RGBA_8888 :
50 return MDP_RGBA_8888;
51 case HAL_PIXEL_FORMAT_BGRA_8888:
52 return MDP_BGRA_8888;
53 case HAL_PIXEL_FORMAT_RGB_565:
54 return MDP_RGB_565;
55 case HAL_PIXEL_FORMAT_RGBX_8888:
56 return MDP_RGBX_8888;
57 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
58 return MDP_Y_CBCR_H2V1;
59 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
60 return MDP_Y_CRCB_H2V2;
61 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
62 return MDP_Y_CBCR_H2V2;
63 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
64 return MDP_Y_CRCB_H2V2_TILE;
65 case HAL_PIXEL_FORMAT_YV12:
66 return MDP_Y_CR_CB_GH2V2;
67 default:
68 LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format);
69 return -1;
70 }
71 return -1;
72}
73
74int overlay::get_mdp_orientation(int value) {
75 switch(value) {
76 case 0: return 0;
77 case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD;
78 case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR;
79 case HAL_TRANSFORM_ROT_90: return MDP_ROT_90;
80 case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V:
81 return MDP_ROT_90|MDP_FLIP_LR;
82 case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H:
83 return MDP_ROT_90|MDP_FLIP_UD;
84 case HAL_TRANSFORM_ROT_180: return MDP_ROT_180;
85 case HAL_TRANSFORM_ROT_270: return MDP_ROT_270;
86 default:
87 LOGE("%s: invalid rotation value (value = 0x%x",
88 __FUNCTION__, value);
89 return -1;
90 }
91 return -1;
92}
93
94// Rotator - input to output mapping
95int overlay::get_rot_output_format(int format) {
96 switch (format) {
97 case MDP_Y_CRCB_H2V2_TILE:
98 return MDP_Y_CRCB_H2V2;
99 case MDP_Y_CB_CR_H2V2:
100 return MDP_Y_CBCR_H2V2;
101 case MDP_Y_CR_CB_GH2V2:
102 return MDP_Y_CRCB_H2V2;
103 default:
104 return format;
105 }
106 return -1;
107}
108
109// This function normalizes the crop values to be all even
110void overlay::normalize_crop(uint32_t& xy, uint32_t& wh) {
111
112 if (xy & 0x0001) {
113 // x or y is odd, increment it's value
114 xy += 1;
115 // Since we've incremented x(y), we need to decrement
116 // w(h) accordingly
117 if (wh & 0x0001) {
118 // w or h is odd, decrement it by 1, to make it even
119 EVEN_OUT(wh);
120 } else {
121 // w(h) is already even, hence we decrement by 2
122 wh -=2;
123 }
124 } else {
125 EVEN_OUT(wh);
126 }
127}
128
129#define LOG_TAG "OverlayLIB"
130static void reportError(const char* message) {
131 LOGE( "%s", message);
132}
133
134void overlay::dump(mdp_overlay& mOVInfo) {
135 if (!DEBUG_OVERLAY)
136 return;
137 LOGE("mOVInfo:");
138 LOGE("src: width %d height %d format %s user_data[0] %d", mOVInfo.src.width,
139 mOVInfo.src.height, getFormatString(mOVInfo.src.format),
140 mOVInfo.user_data[0]);
141 LOGE("src_rect: x %d y %d w %d h %d", mOVInfo.src_rect.x,
142 mOVInfo.src_rect.y, mOVInfo.src_rect.w, mOVInfo.src_rect.h);
143 LOGE("dst_rect: x %d y %d w %d h %d", mOVInfo.dst_rect.x,
144 mOVInfo.dst_rect.y, mOVInfo.dst_rect.w, mOVInfo.dst_rect.h);
145 LOGE("z_order %d is_fg %d alpha %d transp_mask %d flags %x id %d",
146 mOVInfo.z_order, mOVInfo.is_fg, mOVInfo.alpha, mOVInfo.transp_mask,
147 mOVInfo.flags, mOVInfo.id);
148}
149
150void overlay::dump(msm_rotator_img_info& mRotInfo) {
151 if (!DEBUG_OVERLAY)
152 return;
153 LOGE("mRotInfo:");
154 LOGE("session_id %d dst_x %d dst_y %d rotations %d enable %d",
155 mRotInfo.session_id, mRotInfo.dst_x, mRotInfo.dst_y,
156 mRotInfo.rotations, mRotInfo.enable);
157 LOGE("src: width %d height %d format %s", mRotInfo.src.width,
158 mRotInfo.src.height, getFormatString(mRotInfo.src.format));
159 LOGE("dst: width %d height %d format %s", mRotInfo.dst.width,
160 mRotInfo.dst.height, getFormatString(mRotInfo.src.format));
161 LOGE("src_rect: x %d y %d w %d h %d", mRotInfo.src_rect.x,
162 mRotInfo.src_rect.y, mRotInfo.src_rect.w, mRotInfo.src_rect.h);
163}
164
165const char* overlay::getFormatString(int format){
166 static const char* formats[] = {
167 "MDP_RGB_565",
168 "MDP_XRGB_8888",
169 "MDP_Y_CBCR_H2V2",
170 "MDP_ARGB_8888",
171 "MDP_RGB_888",
172 "MDP_Y_CRCB_H2V2",
173 "MDP_YCRYCB_H2V1",
174 "MDP_Y_CRCB_H2V1",
175 "MDP_Y_CBCR_H2V1",
176 "MDP_RGBA_8888",
177 "MDP_BGRA_8888",
178 "MDP_RGBX_8888",
179 "MDP_Y_CRCB_H2V2_TILE",
180 "MDP_Y_CBCR_H2V2_TILE",
181 "MDP_Y_CR_CB_H2V2",
182 "MDP_Y_CR_CB_GH2V2",
183 "MDP_Y_CB_CR_H2V2",
184 "MDP_Y_CRCB_H1V1",
185 "MDP_Y_CBCR_H1V1",
186 "MDP_IMGTYPE_LIMIT",
187 "MDP_BGR_565",
188 "MDP_FB_FORMAT",
189 "MDP_IMGTYPE_LIMIT2"
190 };
191 return formats[format];
192}
193ZOrderManager* ZOrderManager::sInstance = 0;
194FrameBufferInfo* FrameBufferInfo::sFBInfoInstance = 0;
195
196int ZOrderManager::getZ(int fbnum){
197 int zorder = NO_PIPE;;
198 Mutex::Autolock objLock(mObjMutex);
199 if(mPipesInuse == mMaxPipes) {
200 LOGE("No free pipes available.. inUse = %d ", mPipesInuse);
201 return NO_PIPE;
202 }
203 switch(fbnum) {
204 case FRAMEBUFFER_0:
205 for (int i = 0;i < NUM_CHANNELS; i++) {
206 if(mFB0Pipes[i] == false) {
207 mFB0Pipes[i]= true;
208 zorder = i;
209 break;
210 }
211 }
212 break;
213 case FRAMEBUFFER_1:
214 case FRAMEBUFFER_2:
215 for (int i = 0;i < mMaxPipes; i++) {
216 if(mFB1Pipes[i] == false) {
217 mFB1Pipes[i]= true;
218 zorder = i;
219 break;
220 }
221 }
222 break;
223 default:
224 LOGE("getZ: Invalid framebuffer..");
225 break;
226 }
227 mPipesInuse++;
228 LOGE("getZ: return zorder = %d for fbdev = %d, pipesinUse = %d",
229 zorder, fbnum, mPipesInuse);
230 return zorder;
231}
232
233void ZOrderManager::decZ(int fbnum, int zorder){
234 Mutex::Autolock objLock(mObjMutex);
235 switch(fbnum) {
236 case FRAMEBUFFER_0:
237 LOG_ASSERT(!mFB0Pipes[zorder],"channel with ZOrder does not exist");
238 LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
239 mFB0Pipes[zorder] = false;
240 break;
241 case FRAMEBUFFER_1:
242 case FRAMEBUFFER_2:
243 LOG_ASSERT(!mFB1Pipes[zorder],"channel with ZOrder does not exist");
244 LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
245 mFB1Pipes[zorder] = false;
246 break;
247 default:
248 LOGE("decZ: Invalid framebuffer ");
249 break;
250 }
251 if(mPipesInuse > 0)
252 mPipesInuse--;
253 LOGE("decZ: Pipes in use = %d", mPipesInuse);
254}
255
256bool overlay::isHDMIConnected () {
257 char value[PROPERTY_VALUE_MAX];
258 property_get("hw.hdmiON", value, "0");
259 int isHDMI = atoi(value);
260 return isHDMI ? true : false;
261}
262
263bool overlay::is3DTV() {
264 char is3DTV = '0';
265 FILE *fp = fopen(EDID_3D_INFO_FILE, "r");
266 if (fp) {
267 fread(&is3DTV, 1, 1, fp);
268 fclose(fp);
269 }
270 LOGI("3DTV EDID flag: %c", is3DTV);
271 return (is3DTV == '0') ? false : true;
272}
273
274bool overlay::isPanel3D() {
275 int fd = open("/dev/graphics/fb0", O_RDWR, 0);
276 if (fd < 0) {
277 reportError("Can't open framebuffer 0");
278 return false;
279 }
280 fb_fix_screeninfo finfo;
281 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
282 reportError("FBIOGET_FSCREENINFO on fb0 failed");
283 close(fd);
284 fd = -1;
285 return false;
286 }
287 close(fd);
288 return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
289}
290
291bool overlay::usePanel3D() {
292 if (Overlay::sHDMIAsPrimary)
293 return is3DTV();
294
295 if(!isPanel3D())
296 return false;
297 char value[PROPERTY_VALUE_MAX];
298 property_get("persist.user.panel3D", value, "0");
299 int usePanel3D = atoi(value);
300 return usePanel3D ? true : false;
301}
302
303bool overlay::send3DInfoPacket (unsigned int format3D) {
304 FILE *fp = fopen(FORMAT_3D_FILE, "wb");
305 if (fp) {
306 fprintf(fp, "%d", format3D);
307 fclose(fp);
308 fp = NULL;
309 return true;
310 }
311 LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__);
312 return false;
313}
314
315bool overlay::enableBarrier (unsigned int orientation) {
316 FILE *fp = fopen(BARRIER_FILE, "wb");
317 if (fp) {
318 fprintf(fp, "%d", orientation);
319 fclose(fp);
320 fp = NULL;
321 return true;
322 }
323 LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__);
324 return false;
325}
326
327int overlay::getColorFormat(int format)
328{
329 if (format == HAL_PIXEL_FORMAT_YV12)
330 return format;
331 else if (format & INTERLACE_MASK)
332 return format ^ HAL_PIXEL_FORMAT_INTERLACE;
333 else
334 return COLOR_FORMAT(format);
335}
336
337bool overlay::isInterlacedContent(int format)
338{
339 if ((format != HAL_PIXEL_FORMAT_YV12) &&
340 (format & INTERLACE_MASK))
341 return true;
342
343 return false;
344}
345
346unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll,
347 bool isHDMI) {
348 bool isTV3D = false;
349 unsigned int curState = 0;
350 if (poll)
351 isHDMI = isHDMIConnected();
352 if (isHDMI) {
353 LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__);
354 if (format3D) {
355 if (is3DTV())
356 curState = OV_3D_VIDEO_3D_TV;
357 else
358 curState = OV_3D_VIDEO_2D_TV;
359 } else
360 curState = OV_2D_VIDEO_ON_TV;
361 } else {
362 LOGD("%s: HDMI not connected...", __FUNCTION__);
363 if(format3D) {
364 if (usePanel3D())
365 curState = OV_3D_VIDEO_3D_PANEL;
366 else
367 curState = OV_3D_VIDEO_2D_PANEL;
368 }
369 else
370 curState = OV_2D_VIDEO_ON_PANEL;
371 }
372 return curState;
373}
374
375/* clears any VG pipes allocated to the fb devices */
376int overlay::initOverlay() {
377 msmfb_mixer_info_req req;
378 mdp_mixer_info *minfo = NULL;
379 char name[64];
380 int fd = -1;
381 for(int i = 0; i < NUM_FB_DEVICES; i++) {
382 snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
383 LOGD("initoverlay:: opening the device:: %s", name);
384 fd = open(name, O_RDWR, 0);
385 if(fd < 0) {
386 LOGE("cannot open framebuffer(%d)", i);
387 return -1;
388 }
389 //Get the mixer configuration */
390 req.mixer_num = i;
391 if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
392 LOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
393 close(fd);
394 return -1;
395 }
396 minfo = req.info;
397 for (int j = 0; j < req.cnt; j++) {
398 LOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
399 minfo->z_order);
400 // except the RGB base layer with z_order of -1, clear any
401 // other pipes connected to mixer.
402 if((minfo->z_order) != -1) {
403 int index = minfo->pndx;
404 LOGD("Unset overlay with index: %d at mixer %d", index, i);
405 if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
406 LOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
407 close(fd);
408 return -1;
409 }
410 }
411 minfo++;
412 }
413 close(fd);
414 fd = -1;
415 }
416 return 0;
417}
418
419Overlay::Overlay() : mChannelUP(false), mExternalDisplay(false),
420 mS3DFormat(0), mCroppedSrcWidth(0),
421 mCroppedSrcHeight(0), mState(-1) {
422 mOVBufferInfo.width = mOVBufferInfo.height = 0;
423 mOVBufferInfo.format = mOVBufferInfo.size = 0;
424}
425
426Overlay::~Overlay() {
427 closeChannel();
428}
429
430int Overlay::getFBWidth(int channel) const {
431 return objOvCtrlChannel[channel].getFBWidth();
432}
433
434int Overlay::getFBHeight(int channel) const {
435 return objOvCtrlChannel[channel].getFBHeight();
436}
437
438bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum,
439 bool norot, bool uichannel,
440 unsigned int format3D, int channel,
441 int flags, int num_buffers) {
442 int zorder = 0;
443 mCroppedSrcWidth = info.width;
444 mCroppedSrcHeight = info.height;
445 if (format3D)
446 zorder = channel;
447 if (mState == -1)
448 mState = OV_UI_MIRROR_TV;
449
450 mChannelUP = objOvCtrlChannel[channel].startControlChannel(info, fbnum,
451 norot, uichannel,
452 format3D, zorder, flags);
453 if (!mChannelUP) {
454 LOGE("startChannel for fb%d failed", fbnum);
455 return mChannelUP;
456 }
457 bool secure = flags & SECURE_OVERLAY_SESSION;
458 objOvCtrlChannel[channel].setSize(info.size);
459 return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum,
460 norot, secure, uichannel, num_buffers);
461}
462
463bool Overlay::closeChannel() {
464
465 if (!mChannelUP)
466 return true;
467
468 if(mS3DFormat) {
469 if (mExternalDisplay)
470 overlay::send3DInfoPacket(0);
471 else if (mState == OV_3D_VIDEO_3D_PANEL) {
472 if (sHDMIAsPrimary)
473 overlay::send3DInfoPacket(0);
474 else
475 enableBarrier(0);
476 }
477 }
478 for (int i = 0; i < NUM_CHANNELS; i++) {
479 objOvCtrlChannel[i].closeControlChannel();
480 objOvDataChannel[i].closeDataChannel();
481 }
482 mChannelUP = false;
483 mS3DFormat = 0;
484 mOVBufferInfo.width = 0;
485 mOVBufferInfo.height = 0;
486 mOVBufferInfo.format = 0;
487 mOVBufferInfo.size = 0;
488 mState = -1;
489 return true;
490}
491
492void Overlay::closeExternalChannel() {
493 if (objOvCtrlChannel[VG1_PIPE].isChannelUP()) {
494 objOvCtrlChannel[VG1_PIPE].closeControlChannel();
495 objOvDataChannel[VG1_PIPE].closeDataChannel();
496 }
497}
498
499bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel) {
500 return objOvCtrlChannel[channel].getPosition(x, y, w, h);
501}
502
503bool Overlay::getOrientation(int& orientation, int channel) const {
504 return objOvCtrlChannel[channel].getOrientation(orientation);
505}
506
507bool Overlay::setDeviceOrientation(int orientation) {
508 // Use this to calculate the position on HDMI
509 mDevOrientation = orientation;
510 return true;
511}
512
513bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
514 bool ret = false;
515 overlay_rect secDest;
516 overlay_rect priDest;
517 int currX, currY;
518 uint32_t currW, currH;
519 // Set even destination co-ordinates
520 EVEN_OUT(x); EVEN_OUT(y);
521 EVEN_OUT(w); EVEN_OUT(h);
522 objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
523 priDest.x = x, priDest.y = y;
524 priDest.w = w, priDest.h = h;
525 if(x != currX || y != currY || w != currW || h != currH) {
526 switch (mState) {
527 case OV_UI_MIRROR_TV:
528 case OV_2D_VIDEO_ON_PANEL:
529 case OV_3D_VIDEO_2D_PANEL:
530 return setChannelPosition(x, y, w, h, VG0_PIPE);
531 break;
532 case OV_2D_VIDEO_ON_TV:
533 if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
534 objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
535 mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
536 &priDest, &secDest);
537 } else {
538 objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
539 mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
540 }
541 setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h,
542 VG1_PIPE);
543 return setChannelPosition(x, y, w, h, VG0_PIPE);
544 break;
545 case OV_3D_VIDEO_3D_PANEL:
546 for (int i = 0; i < NUM_CHANNELS; i++) {
547 if (sHDMIAsPrimary)
548 objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &secDest);
549 else {
550 if (!objOvCtrlChannel[i].useVirtualFB()) {
551 LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
552 return false;
553 }
554 objOvCtrlChannel[i].getPositionS3D(i, 0x1, &secDest);
555 }
556 if(!setChannelPosition(secDest.x, secDest.y, secDest.w,
557 secDest.h, i)) {
558 LOGE("%s: failed for channel %d", __FUNCTION__, i);
559 return false;
560 }
561 }
562 break;
563 case OV_3D_VIDEO_2D_TV:
564 case OV_3D_VIDEO_3D_TV:
565 for (int i = 0; i < NUM_CHANNELS; i++) {
566 ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat,
567 &secDest);
568 if (!ret)
569 ret = setChannelPosition(x, y, w, h, i);
570 else
571 ret = setChannelPosition(secDest.x, secDest.y, secDest.w,
572 secDest.h, i);
573 if (!ret) {
574 LOGE("%s: failed for channel %d", __FUNCTION__, i);
575 return ret;
576 }
577 }
578 break;
579 default:
580 LOGE("%s:Unknown state %d", __FUNCTION__, mState);
581 break;
582 }
583 }
584 return true;
585}
586
587bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) {
588 return objOvCtrlChannel[channel].setPosition(x, y, w, h);
589}
590
591bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation,
592 int flags) {
593 bool ret = false;
594 int currentFlags = 0;
595
596 bool needUpdateFlags = false;
597 if (objOvCtrlChannel[0].isChannelUP()) {
598 needUpdateFlags = objOvCtrlChannel[0].doFlagsNeedUpdate(flags);
599 }
600
601 bool geometryChanged = true;
602 if (info.width == mOVBufferInfo.width &&
603 info.height == mOVBufferInfo.height &&
604 info.format == mOVBufferInfo.format) {
605 geometryChanged = false;
606 }
607
608 if (sHDMIAsPrimary)
609 needUpdateFlags = false;
610
611 if ((false == needUpdateFlags) && (false == geometryChanged)) {
612 return true;
613 }
614
615 // Disable rotation for the HDMI channels
616 int orientHdmi = 0;
617 int orientPrimary = sHDMIAsPrimary ? 0 : orientation;
618 int orient[2] = {orientPrimary, orientHdmi};
619 // disable waitForVsync on HDMI, since we call the wait ioctl
620 int ovFlagsExternal = 0;
621 int ovFlagsPrimary = sHDMIAsPrimary ? (flags |= WAIT_FOR_VSYNC): flags;
622 int ovFlags[2] = {flags, ovFlagsExternal};
623 switch(mState) {
624 case OV_3D_VIDEO_3D_PANEL:
625 orient[1] = sHDMIAsPrimary ? 0 : orientation;
626 break;
627 case OV_3D_VIDEO_3D_TV:
628 orient[0] = 0;
629 break;
630 default:
631 break;
632 }
633
634 int numChannelsToUpdate = NUM_CHANNELS;
635 if (!geometryChanged) {
636 // Only update the primary channel - we only need to update the
637 // wait/no-wait flags
638 if (objOvCtrlChannel[0].isChannelUP()) {
639 return objOvCtrlChannel[0].updateOverlayFlags(flags);
640 }
641 }
642
643 // Set the overlay source info
644 for (int i = 0; i < NUM_CHANNELS; i++) {
645 if (objOvCtrlChannel[i].isChannelUP()) {
646 ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], ovFlags[i]);
647 if (!ret) {
648 LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i);
649 return false;
650 }
651 objOvCtrlChannel[i].setSize(info.size);
652 ret = objOvDataChannel[i].updateDataChannel(info.size);
653 }
654 }
655 if (ret) {
656 mOVBufferInfo = info;
657 } else
658 LOGE("update failed");
659 return ret;
660}
661
662bool Overlay::getAspectRatioPosition(int w, int h, overlay_rect *rect, int channel) {
663 return objOvCtrlChannel[channel].getAspectRatioPosition(w, h, rect);
664}
665
666int Overlay::getS3DFormat(int format) {
667 // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
668 // an explicit check for the format
669 if (format == HAL_PIXEL_FORMAT_YV12) {
670 return 0;
671 }
672 int format3D = FORMAT_3D(format);
673 int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format
674 int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format
675 format3D = fIn3D | fOut3D;
676 if (!fIn3D) {
677 format3D |= fOut3D << SHIFT_3D; //Set the input format
678 }
679 if (!fOut3D) {
680 format3D |= fIn3D >> SHIFT_3D; //Set the output format
681 }
682 return format3D;
683}
684
685bool Overlay::setSource(const overlay_buffer_info& info, int orientation,
686 int hdmiConnected, int flags, int num_buffers) {
687 // Separate the color format from the 3D format.
688 // If there is 3D content; the effective format passed by the client is:
689 // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat
690 int newState = mState;
691 bool stateChange = false, ret = true;
692 bool isHDMIStateChange = (mExternalDisplay != hdmiConnected) && (mState != -1);
693 unsigned int format3D = getS3DFormat(info.format);
694 int colorFormat = getColorFormat(info.format);
695 if (isHDMIStateChange || -1 == mState) {
696 // we were mirroring UI. Also HDMI state stored was stale
697 newState = getOverlayConfig (format3D, false, hdmiConnected);
698 stateChange = (mState == newState) ? false : true;
699 }
700
701 if (stateChange) {
702 mExternalDisplay = hdmiConnected;
703 mState = newState;
704 mS3DFormat = format3D;
705 if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) {
706 LOGI("3D content on 2D display: set the output format as monoscopic");
707 mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
708 }
709 // We always enable the rotator for the primary.
710 bool noRot = false;
711 bool uiChannel = false;
712 int fbnum = 0;
713 switch(mState) {
714 case OV_2D_VIDEO_ON_PANEL:
715 if(isHDMIStateChange) {
716 //close HDMI Only
717 closeExternalChannel();
718 break;
719 }
720 case OV_3D_VIDEO_2D_PANEL:
721 closeChannel();
722 return startChannel(info, FRAMEBUFFER_0, noRot, false,
723 mS3DFormat, VG0_PIPE, flags, num_buffers);
724 break;
725 case OV_3D_VIDEO_3D_PANEL:
726 closeChannel();
727 if (sHDMIAsPrimary) {
728 noRot = true;
729 flags |= WAIT_FOR_VSYNC;
730 send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
731 }
732 for (int i=0; i<NUM_CHANNELS; i++) {
733 if(!startChannel(info, FRAMEBUFFER_0, noRot, uiChannel,
734 mS3DFormat, i, flags, num_buffers)) {
735 LOGE("%s:failed to open channel %d", __FUNCTION__, i);
736 return false;
737 }
738 }
739 break;
740 case OV_2D_VIDEO_ON_TV:
741 if(isHDMIStateChange) {
742 //start only HDMI channel
743 noRot = true;
744 bool waitForVsync = true;
745 // External display connected, start corresponding channel
746 // mExternalDisplay will hold the fbnum
747 if(!startChannel(info, mExternalDisplay, noRot, false, mS3DFormat,
748 VG1_PIPE, waitForVsync, num_buffers)) {
749 LOGE("%s:failed to open channel %d", __func__, VG1_PIPE);
750 return false;
751 }
752 int currX, currY;
753 uint32_t currW, currH;
754 overlay_rect priDest;
755 overlay_rect secDest;
756 objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
757 priDest.x = currX, priDest.y = currY;
758 priDest.w = currW, priDest.h = currH;
759 if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
760 objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
761 mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
762 &priDest, &secDest);
763 } else {
764 objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
765 mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
766 }
767 return setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h, VG1_PIPE);
768 }
769 case OV_3D_VIDEO_2D_TV:
770 closeChannel();
771 for (int i=0; i<NUM_CHANNELS; i++) {
772 fbnum = i;
773 //start two channels for one for primary and external.
774 if (fbnum) {
775 // Disable rotation for external
776 noRot = true;
777 //set fbnum to hdmiConnected, which holds the ext display
778 fbnum = hdmiConnected;
779 flags &= ~WAIT_FOR_VSYNC;
780 }
781 if(!startChannel(info, fbnum, noRot, false, mS3DFormat,
782 i, flags, num_buffers)) {
783 LOGE("%s:failed to open channel %d", __FUNCTION__, i);
784 return false;
785 }
786 }
787 return true;
788 break;
789 case OV_3D_VIDEO_3D_TV:
790 closeChannel();
791 for (int i=0; i<NUM_CHANNELS; i++) {
792 if(!startChannel(info, FRAMEBUFFER_1, true, false,
793 mS3DFormat, i, flags, num_buffers)) {
794 LOGE("%s:failed to open channel %d", __FUNCTION__, i);
795 return false;
796 }
797 send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
798 }
799 break;
800 default:
801 LOGE("%s:Unknown state %d", __FUNCTION__, mState);
802 break;
803 }
804 } else {
805 ret = updateOverlaySource(info, orientation, flags);
806// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
807 return ret;
808// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
809 }
810 return true;
811}
812
813bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
814 if (!mChannelUP) {
815 LOGE("%s: channel not set", __FUNCTION__);
816 return false;
817 }
818 overlay_rect rect, inRect;
819 inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h;
820 mCroppedSrcWidth = w;
821 mCroppedSrcHeight = h;
822 switch (mState) {
823 case OV_UI_MIRROR_TV:
824 case OV_2D_VIDEO_ON_PANEL:
825 return setChannelCrop(x, y, w, h, VG0_PIPE);
826 break;
827 case OV_3D_VIDEO_2D_PANEL:
828 objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect);
829 return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE);
830 break;
831 case OV_2D_VIDEO_ON_TV:
832 for (int i=0; i<NUM_CHANNELS; i++) {
833 if(!setChannelCrop(x, y, w, h, i)) {
834 LOGE("%s: failed for pipe %d", __FUNCTION__, i);
835 return false;
836 }
837 }
838 break;
839 case OV_3D_VIDEO_3D_PANEL:
840 case OV_3D_VIDEO_2D_TV:
841 case OV_3D_VIDEO_3D_TV:
842 for (int i=0; i<NUM_CHANNELS; i++) {
843 objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect);
844 if(!setChannelCrop(rect.x, rect.y, rect.w, rect.h, i)) {
845 LOGE("%s: failed for pipe %d", __FUNCTION__, i);
846 return false;
847 }
848 }
849 break;
850 default:
851 LOGE("%s:Unknown state %d", __FUNCTION__, mState);
852 break;
853 }
854 return true;
855}
856
857bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel) {
858 return objOvDataChannel[channel].setCrop(x, y, w, h);
859}
860
861bool Overlay::updateOverlayFlags(int flags) {
862 return objOvCtrlChannel[VG0_PIPE].updateOverlayFlags(flags);
863}
864
865bool Overlay::setTransform(int value) {
866 int barrier = 0;
867 switch (mState) {
868 case OV_UI_MIRROR_TV:
869 case OV_2D_VIDEO_ON_PANEL:
870 case OV_3D_VIDEO_2D_PANEL:
871 return objOvCtrlChannel[VG0_PIPE].setTransform(value);
872 break;
873 case OV_2D_VIDEO_ON_TV:
874 case OV_3D_VIDEO_2D_TV:
875 case OV_3D_VIDEO_3D_TV:
876 for (int i=0; i<NUM_CHANNELS; i++) {
877 if(!objOvCtrlChannel[i].setTransform(value)) {
878 LOGE("%s:failed for channel %d", __FUNCTION__, i);
879 return false;
880 }
881 }
882 break;
883 case OV_3D_VIDEO_3D_PANEL:
884 switch (value) {
885 case HAL_TRANSFORM_ROT_90:
886 case HAL_TRANSFORM_ROT_270:
887 barrier = BARRIER_LANDSCAPE;
888 break;
889 default:
890 barrier = BARRIER_PORTRAIT;
891 break;
892 if(!enableBarrier(barrier))
893 LOGE("%s:failed to enable barriers for 3D video", __FUNCTION__);
894 }
895 for (int i=0; i<NUM_CHANNELS; i++) {
896 if(!objOvCtrlChannel[i].setTransform(value)) {
897 LOGE("%s:failed for channel %d", __FUNCTION__, i);
898 return false;
899 }
900 }
901 break;
902 default:
903 LOGE("%s:Unknown state %d", __FUNCTION__, mState);
904 break;
905 }
906 return true;
907}
908
909bool Overlay::setFd(int fd, int channel) {
910 return objOvDataChannel[channel].setFd(fd);
911}
912
913bool Overlay::queueBuffer(uint32_t offset, int channel) {
914 return objOvDataChannel[channel].queueBuffer(offset);
915}
916
917bool Overlay::waitForHdmiVsync(int channel) {
918 return objOvDataChannel[channel].waitForHdmiVsync();
919}
920
921bool Overlay::queueBuffer(buffer_handle_t buffer) {
922 private_handle_t const* hnd = reinterpret_cast
923 <private_handle_t const*>(buffer);
924 if (!hnd) {
925 LOGE("Overlay::queueBuffer invalid handle");
926 return false;
927 }
928 const size_t offset = hnd->offset;
929 const int fd = hnd->fd;
930 switch (mState) {
931 case OV_UI_MIRROR_TV:
932 case OV_2D_VIDEO_ON_PANEL:
933 case OV_3D_VIDEO_2D_PANEL:
934 if(!queueBuffer(fd, offset, VG0_PIPE)) {
935 LOGE("%s:failed for channel 0", __FUNCTION__);
936 return false;
937 }
938 break;
939 case OV_2D_VIDEO_ON_TV:
940 case OV_3D_VIDEO_3D_PANEL:
941 case OV_3D_VIDEO_2D_TV:
942 case OV_3D_VIDEO_3D_TV:
943 for (int i=NUM_CHANNELS-1; i>=0; i--) {
944 if(!queueBuffer(fd, offset, i)) {
945 LOGE("%s:failed for channel %d", __FUNCTION__, i);
946 return false;
947 }
948 }
949 //Wait for HDMI done..
950 if(!waitForHdmiVsync(VG1_PIPE)) {
951 LOGE("%s: waitforHdmiVsync failed", __FUNCTION__);
952 return false;
953 }
954 break;
955 default:
956 LOGE("%s:Unknown state %d", __FUNCTION__, mState);
957 break;
958 }
959 return true;
960}
961
962bool Overlay::queueBuffer(int fd, uint32_t offset, int channel) {
963 bool ret = false;
964 ret = setFd(fd, channel);
965 if(!ret) {
966 LOGE("Overlay::queueBuffer channel %d setFd failed", channel);
967 return false;
968 }
969 ret = queueBuffer(offset, channel);
970 if(!ret) {
971 LOGE("Overlay::queueBuffer channel %d queueBuffer failed", channel);
972 return false;
973 }
974 return ret;
975}
976
977OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
978 mFormat3D(0), mIsChannelUpdated(true) {
979 memset(&mOVInfo, 0, sizeof(mOVInfo));
980 memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
981 memset(&mRotInfo, 0, sizeof(mRotInfo));
982}
983
984
985OverlayControlChannel::~OverlayControlChannel() {
986 closeControlChannel();
987}
988
989bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *rect)
990{
991 int width = w, height = h, x, y;
992 int fbWidth = getFBWidth();
993 int fbHeight = getFBHeight();
994 // width and height for YUV TILE format
995 int tempWidth = w, tempHeight = h;
996 /* Calculate the width and height if it is YUV TILE format*/
997 if(getFormat() == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
998 tempWidth = w - ( (((w-1)/64 +1)*64) - w);
999 tempHeight = h - ((((h-1)/32 +1)*32) - h);
1000 }
1001 if (width * fbHeight > fbWidth * height) {
1002 height = fbWidth * height / width;
1003 EVEN_OUT(height);
1004 width = fbWidth;
1005 } else if (width * fbHeight < fbWidth * height) {
1006 width = fbHeight * width / height;
1007 EVEN_OUT(width);
1008 height = fbHeight;
1009 } else {
1010 width = fbWidth;
1011 height = fbHeight;
1012 }
1013 /* Scaling of upto a max of 8 times supported */
1014 if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){
1015 width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth;
1016 }
1017 if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) {
1018 height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight;
1019 }
1020 if (width > fbWidth) width = fbWidth;
1021 if (height > fbHeight) height = fbHeight;
1022
1023 char value[PROPERTY_VALUE_MAX];
1024 property_get("hw.actionsafe.width", value, "0");
1025 float asWidth = atof(value);
1026 property_get("hw.actionsafe.height", value, "0");
1027 float asHeight = atof(value);
1028 width = width * (1.0f - asWidth / 100.0f);
1029 height = height * (1.0f - asHeight / 100.0f);
1030
1031 x = (fbWidth - width) / 2;
1032 y = (fbHeight - height) / 2;
1033 rect->x = x;
1034 rect->y = y;
1035 rect->w = width;
1036 rect->h = height;
1037 return true;
1038}
1039
1040
1041// This function gets the destination position for Seconday display
1042// based on the position and aspect ratio of the primary
1043bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int orientation,
1044 overlay_rect *inRect, overlay_rect *outRect) {
1045 float priWidth = FrameBufferInfo::getInstance()->getWidth();
1046 float priHeight = FrameBufferInfo::getInstance()->getHeight();
1047 float fbWidth = getFBWidth();
1048 float fbHeight = getFBHeight();
1049 float wRatio = 1.0;
1050 float hRatio = 1.0;
1051 float xRatio = 1.0;
1052 float yRatio = 1.0;
1053
1054 int xPos = 0;
1055 int yPos = 0;
1056 int tmp = 0;
1057 overlay_rect rect;
1058 switch(orientation) {
1059 case MDP_ROT_NOP:
1060 case MDP_ROT_180:
1061 getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
1062 xPos = rect.x;
1063 yPos = rect.y;
1064 fbWidth = rect.w;
1065 fbHeight = rect.h;
1066
1067 if(orientation == MDP_ROT_180) {
1068 inRect->x = priWidth - (inRect->x + inRect->w);
1069 inRect->y = priHeight - (inRect->y + inRect->h);
1070 }
1071 break;
1072 case MDP_ROT_90:
1073 case MDP_ROT_270:
1074 if(orientation == MDP_ROT_90) {
1075 tmp = inRect->y;
1076 inRect->y = priWidth - (inRect->x + inRect->w);
1077 inRect->x = tmp;
1078 }
1079 else if(orientation == MDP_ROT_270) {
1080 tmp = inRect->x;
1081 inRect->x = priHeight - (inRect->y + inRect->h);
1082 inRect->y = tmp;
1083 }
1084 //Swap the destination width/height
1085 swapWidthHeight(inRect->w, inRect->h);
1086 // Swap width/height for primary
1087 swapWidthHeight(priWidth, priHeight);
1088 getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
1089 xPos = rect.x;
1090 yPos = rect.y;
1091 fbWidth = rect.w;
1092 fbHeight = rect.h;
1093 break;
1094 default:
1095 LOGE("In %s: Unknown Orientation", __FUNCTION__);
1096 break;
1097 }
1098 //Calculate the position...
1099 xRatio = inRect->x/priWidth;
1100 yRatio = inRect->y/priHeight;
1101
1102 wRatio = inRect->w/priWidth;
1103 hRatio = inRect->h/priHeight;
1104 outRect->x = (xRatio * fbWidth) + xPos;
1105 outRect->y = (yRatio * fbHeight) + yPos;
1106
1107 outRect->w = (wRatio * fbWidth);
1108 outRect->h = hRatio * fbHeight;
1109 LOGD("Calculated AS Position for HDMI: X= %d, y = %d w = %d h = %d",
1110 outRect->x, outRect->y,outRect->w, outRect->h);
1111 return true;
1112}
1113
1114
1115bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) {
1116 int wDisp = getFBWidth();
1117 int hDisp = getFBHeight();
1118 switch (format & OUTPUT_MASK_3D) {
1119 case HAL_3D_OUT_SIDE_BY_SIDE_MASK:
1120 if (channel == VG0_PIPE) {
1121 rect->x = 0;
1122 rect->y = 0;
1123 rect->w = wDisp/2;
1124 rect->h = hDisp;
1125 } else {
1126 rect->x = wDisp/2;
1127 rect->y = 0;
1128 rect->w = wDisp/2;
1129 rect->h = hDisp;
1130 }
1131 break;
1132 case HAL_3D_OUT_TOP_BOTTOM_MASK:
1133 if (channel == VG0_PIPE) {
1134 rect->x = 0;
1135 rect->y = 0;
1136 rect->w = wDisp;
1137 rect->h = hDisp/2;
1138 } else {
1139 rect->x = 0;
1140 rect->y = hDisp/2;
1141 rect->w = wDisp;
1142 rect->h = hDisp/2;
1143 }
1144 break;
1145 case HAL_3D_OUT_MONOSCOPIC_MASK:
1146 if (channel == VG1_PIPE) {
1147 rect->x = 0;
1148 rect->y = 0;
1149 rect->w = wDisp;
1150 rect->h = hDisp;
1151 }
1152 else
1153 return false;
1154 break;
1155 case HAL_3D_OUT_INTERLEAVE_MASK:
1156 break;
1157 default:
1158 reportError("Unsupported 3D output format");
1159 break;
1160 }
1161 return true;
1162}
1163
1164bool OverlayControlChannel::openDevices(int fbnum) {
1165 if (fbnum < 0)
1166 return false;
1167
1168 char dev_name[64];
1169 snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
1170 mFD = open(dev_name, O_RDWR, 0);
1171 if (mFD < 0) {
1172 reportError("Cant open framebuffer ");
1173 return false;
1174 }
1175
1176 fb_fix_screeninfo finfo;
1177 if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) {
1178 reportError("FBIOGET_FSCREENINFO on fb1 failed");
1179 close(mFD);
1180 mFD = -1;
1181 return false;
1182 }
1183
1184 fb_var_screeninfo vinfo;
1185 if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) {
1186 reportError("FBIOGET_VSCREENINFO on fb1 failed");
1187 close(mFD);
1188 mFD = -1;
1189 return false;
1190 }
1191 mFBWidth = vinfo.xres;
1192 mFBHeight = vinfo.yres;
1193 mFBbpp = vinfo.bits_per_pixel;
1194 mFBystride = finfo.line_length;
1195
1196 if (!mNoRot) {
1197 mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
1198 if (mRotFD < 0) {
1199 reportError("Cant open rotator device");
1200 close(mFD);
1201 mFD = -1;
1202 return false;
1203 }
1204 }
1205
1206 return true;
1207}
1208
1209bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& info,
1210 int zorder, int flags, int requestType) {
1211 int w = info.width;
1212 int h = info.height;
1213 int format = info.format;
1214
1215 mOVInfo.src.width = w;
1216 mOVInfo.src.height = h;
1217 mOVInfo.src_rect.x = 0;
1218 mOVInfo.src_rect.y = 0;
1219 mOVInfo.dst_rect.x = 0;
1220 mOVInfo.dst_rect.y = 0;
1221 mOVInfo.dst_rect.w = w;
1222 mOVInfo.dst_rect.h = h;
1223 if(format == MDP_Y_CRCB_H2V2_TILE) {
1224 if (mNoRot) {
1225 mOVInfo.src_rect.w = w - ((((w-1)/64 +1)*64) - w);
1226 mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
1227 } else {
1228 mOVInfo.src_rect.w = w;
1229 mOVInfo.src_rect.h = h;
1230 mOVInfo.src.width = (((w-1)/64 +1)*64);
1231 mOVInfo.src.height = (((h-1)/32 +1)*32);
1232 mOVInfo.src_rect.x = mOVInfo.src.width - w;
1233 mOVInfo.src_rect.y = mOVInfo.src.height - h;
1234 }
1235 } else {
1236 mOVInfo.src_rect.w = w;
1237 mOVInfo.src_rect.h = h;
1238 }
1239
1240 mOVInfo.src.format = format;
1241 int dst_w = w;
1242 int dst_h = h;
1243
1244 if (dst_w > mFBWidth) {
1245 dst_w = mFBWidth;
1246 dst_h = dst_h * mFBWidth / w;
1247 }
1248 if (dst_h > mFBHeight) {
1249 dst_h = mFBHeight;
1250 dst_w = dst_w * mFBHeight / h;
1251 }
1252 mOVInfo.dst_rect.w = dst_w;
1253 mOVInfo.dst_rect.h = dst_h;
1254 mOVInfo.user_data[0] = 0;
1255 if (requestType == NEW_REQUEST) {
1256 mOVInfo.id = MSMFB_NEW_REQUEST;
1257 mOVInfo.z_order = zorder;
1258 mOVInfo.alpha = 0xff;
1259 mOVInfo.transp_mask = 0xffffffff;
1260 }
1261 mOVInfo.flags = 0;
1262 setInformationFromFlags(flags, mOVInfo);
1263 mOVInfo.dpp.sharp_strength = 0;
1264 return true;
1265}
1266
1267void OverlayControlChannel::setInformationFromFlags(int flags, mdp_overlay& ov)
1268{
1269 if (flags & INTERLACED_CONTENT) {
1270 mOVInfo.flags |= MDP_DEINTERLACE;
1271 } else {
1272 mOVInfo.flags &= ~MDP_DEINTERLACE;
1273 }
1274
1275 if ((flags & WAIT_FOR_VSYNC) == 0)
1276 mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
1277 else
1278 mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
1279
1280 if(flags & SECURE_OVERLAY_SESSION)
1281 mOVInfo.flags |= MDP_SECURE_OVERLAY_SESSION;
1282 else
1283 mOVInfo.flags &= ~MDP_SECURE_OVERLAY_SESSION;
1284
1285 //set the default sharpening settings
1286 mOVInfo.flags |= MDP_SHARPENING;
1287
1288 if (flags & DISABLE_FRAMEBUFFER_FETCH)
1289 mOVInfo.is_fg = 1;
1290 else
1291 mOVInfo.is_fg = 0;
1292
1293 if (flags & OVERLAY_PIPE_SHARE) {
1294 mOVInfo.flags |= MDP_OV_PIPE_SHARE;
1295 } else {
1296 mOVInfo.flags &= ~MDP_OV_PIPE_SHARE;
1297 }
1298 mOVInfo.dpp.sharp_strength = 0;
1299
1300}
1301
1302bool OverlayControlChannel::doFlagsNeedUpdate(int flags) {
1303 bool needUpdate = false;
1304
1305 if ((flags & WAIT_FOR_VSYNC) == 0) {
1306 if (!(mOVInfo.flags & MDP_OV_PLAY_NOWAIT)) {
1307 needUpdate = true;
1308 }
1309 }
1310 if (flags & WAIT_FOR_VSYNC) {
1311 if (mOVInfo.flags & MDP_OV_PLAY_NOWAIT) {
1312 needUpdate = true;
1313 }
1314 }
1315
1316 if ((flags & DISABLE_FRAMEBUFFER_FETCH) == 0) {
1317 if (mOVInfo.is_fg == 1) {
1318 needUpdate = true;
1319 }
1320 }
1321 if (flags & DISABLE_FRAMEBUFFER_FETCH) {
1322 if (mOVInfo.is_fg == 0) {
1323 needUpdate = true;
1324 }
1325 }
1326 return needUpdate;
1327}
1328
1329bool OverlayControlChannel::startOVRotatorSessions(
1330 const overlay_buffer_info& info,
1331 int requestType) {
1332 bool ret = true;
1333 int w = info.width;
1334 int h = info.height;
1335 int format = info.format;
1336
1337 if (!mNoRot) {
1338 mRotInfo.src.format = format;
1339 mRotInfo.src.width = w;
1340 mRotInfo.src.height = h;
1341 mRotInfo.src_rect.w = w;
1342 mRotInfo.src_rect.h = h;
1343 mRotInfo.dst.width = w;
1344 mRotInfo.dst.height = h;
1345 if(format == MDP_Y_CRCB_H2V2_TILE) {
1346 mRotInfo.src.width = (((w-1)/64 +1)*64);
1347 mRotInfo.src.height = (((h-1)/32 +1)*32);
1348 mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
1349 mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
1350 mRotInfo.dst.width = (((w-1)/64 +1)*64);
1351 mRotInfo.dst.height = (((h-1)/32 +1)*32);
1352 mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
1353 }
1354 mRotInfo.dst.format = get_rot_output_format(format);
1355 mRotInfo.dst_x = 0;
1356 mRotInfo.dst_y = 0;
1357 mRotInfo.src_rect.x = 0;
1358 mRotInfo.src_rect.y = 0;
1359 mRotInfo.rotations = 0;
1360
1361 if (requestType == NEW_REQUEST) {
1362 mRotInfo.enable = 0;
1363 if(mUIChannel)
1364 mRotInfo.enable = 1;
1365 mRotInfo.session_id = 0;
1366 } else
1367 mRotInfo.enable = 1;
1368
1369 int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo);
1370 if (result) {
1371 reportError("Rotator session failed");
1372 dump(mRotInfo);
1373 ret = false;
1374 }
1375 }
1376
1377 if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
1378 reportError("startOVRotatorSessions, Overlay set failed");
1379 dump(mOVInfo);
1380 ret = false;
1381 }
1382
1383 if (!ret)
1384 closeControlChannel();
1385 else
1386 mIsChannelUpdated = true;
1387 return ret;
1388}
1389
1390bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info,
1391 int orientation, int flags)
1392{
1393 int colorFormat = getColorFormat(info.format);
1394 int hw_format = get_mdp_format(colorFormat);
1395 overlay_buffer_info ovBufInfo;
1396 ovBufInfo.width = info.width;
1397 ovBufInfo.height = info.height;
1398 ovBufInfo.format = hw_format;
1399
1400 if (isInterlacedContent(info.format)) {
1401 flags |= INTERLACED_CONTENT;
1402 }
1403 if (!setOverlayInformation(ovBufInfo, 0, flags,
1404 UPDATE_REQUEST))
1405 return false;
1406
1407 return startOVRotatorSessions(ovBufInfo, UPDATE_REQUEST);
1408}
1409
1410bool OverlayControlChannel::startControlChannel(const overlay_buffer_info& info,
1411 int fbnum, bool norot,
1412 bool uichannel,
1413 unsigned int format3D, int zorder,
1414 int flags) {
1415 int colorFormat = getColorFormat(info.format);
1416 mNoRot = norot;
1417 mFormat = colorFormat;
1418 mUIChannel = uichannel;
1419 mFBNum = fbnum;
1420 fb_fix_screeninfo finfo;
1421 fb_var_screeninfo vinfo;
1422 int hw_format;
1423
1424 // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add
1425 // an explicit check for the format
1426 if (isInterlacedContent(colorFormat)) {
1427 flags |= MDP_DEINTERLACE;
1428
1429 // Get the actual format
1430 colorFormat = colorFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
1431 }
1432 hw_format = get_mdp_format(colorFormat);
1433 if (hw_format < 0) {
1434 reportError("Unsupported format");
1435 return false;
1436 }
1437
1438 mFormat3D = format3D;
1439 if ( !mFormat3D || (mFormat3D & HAL_3D_OUT_MONOSCOPIC_MASK) ) {
1440 // Set the share bit for sharing the VG pipe
1441 flags |= OVERLAY_PIPE_SHARE;
1442 }
1443 //do not set the PIPE SHARE bit for true mirroring
1444 if(uichannel && FrameBufferInfo::getInstance()->canSupportTrueMirroring())
1445 flags &= ~OVERLAY_PIPE_SHARE;
1446 if (!openDevices(fbnum))
1447 return false;
1448
1449 //get Z order
1450 zorder = ZOrderManager::getInstance()->getZ(fbnum);
1451 if (zorder == NO_PIPE)
1452 return false;
1453
1454 overlay_buffer_info ovBufInfo;
1455 ovBufInfo.width = info.width;
1456 ovBufInfo.height = info.height;
1457 ovBufInfo.format = hw_format;
1458 if (!setOverlayInformation(ovBufInfo, zorder, flags, NEW_REQUEST))
1459 return false;
1460
1461 return startOVRotatorSessions(ovBufInfo, NEW_REQUEST);
1462}
1463
1464bool OverlayControlChannel::closeControlChannel() {
1465 if (!isChannelUP())
1466 return true;
1467
1468 if (!mNoRot && mRotFD > 0) {
1469 ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id));
1470 close(mRotFD);
1471 mRotFD = -1;
1472 }
1473
1474 int ovid = mOVInfo.id;
1475 ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid);
1476 if (m3DOVInfo.is_3d) {
1477 m3DOVInfo.is_3d = 0;
1478 ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo);
1479 }
1480
1481 close(mFD);
1482
1483 if(NO_PIPE != mOVInfo.z_order){
1484 ZOrderManager::getInstance()->decZ(mFBNum, mOVInfo.z_order);
1485 }
1486 memset(&mOVInfo, 0, sizeof(mOVInfo));
1487 memset(&mRotInfo, 0, sizeof(mRotInfo));
1488 memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
1489
1490 mOVInfo.z_order = NO_PIPE;
1491 mFD = -1;
1492
1493 return true;
1494}
1495
1496bool OverlayControlChannel::updateOverlayFlags(int flags) {
1497 if ((flags & WAIT_FOR_VSYNC) == 0)
1498 mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
1499 else
1500 mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
1501
1502 if (flags & DISABLE_FRAMEBUFFER_FETCH)
1503 mOVInfo.is_fg = 1;
1504 else
1505 mOVInfo.is_fg = 0;
1506
1507 if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
1508 LOGE("%s: OVERLAY_SET failed", __FUNCTION__);
1509 dump(mOVInfo);
1510 return false;
1511 }
1512 return true;
1513}
1514
1515bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
1516
1517 if (!isChannelUP() ||
1518 (x < 0) || (y < 0) || ((x + w) > mFBWidth) ||
1519 ((y + h) > mFBHeight)) {
1520 reportError("setPosition failed");
1521 LOGW("x %d y %d (x+w) %d (y+h) %d FBWidth %d FBHeight %d", x, y, x+w, y+h,
1522 mFBWidth,mFBHeight);
1523 return false;
1524 }
1525 if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y ||
1526 w != mOVInfo.dst_rect.w || h != mOVInfo.dst_rect.h ) {
1527 mdp_overlay ov;
1528 ov.id = mOVInfo.id;
1529 if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
1530 reportError("setPosition, overlay GET failed");
1531 return false;
1532 }
1533
1534// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
1535 // can not scale-up 8 times over original source
1536 // return false to compose with GPU
1537#if 1
1538 if(w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
1539 LOGE("[TJ] setPosition : too big width, back to GPU comp %d => %d", ov.src_rect.w, w);
1540 return false;
1541 }
1542 if(h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
1543 LOGE("[TJ] setPosition : too big height, back to GPU comp %d => %d", ov.src_rect.h, h);
1544 return false;
1545 }
1546#else
1547// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
1548
1549 /* Scaling of upto a max of 8 times supported */
1550 if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
1551 w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
1552 x = (mFBWidth - w) / 2;
1553 }
1554 if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
1555 h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
1556 y = (mFBHeight - h) / 2;
1557 }
1558// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
1559#endif
1560// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
1561
1562 ov.dst_rect.x = x;
1563 ov.dst_rect.y = y;
1564 ov.dst_rect.w = w;
1565 ov.dst_rect.h = h;
1566 if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
1567 reportError("setPosition, Overlay SET failed");
1568 dump(ov);
1569 return false;
1570 }
1571 mOVInfo = ov;
1572// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
1573 LOGE("setPosition");
1574 dump(ov);
1575// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
1576 }
1577 return true;
1578}
1579
1580void OverlayControlChannel::swapOVRotWidthHeight() {
1581 int tmp = mOVInfo.src.width;
1582 mOVInfo.src.width = mOVInfo.src.height;
1583 mOVInfo.src.height = tmp;
1584
1585 tmp = mOVInfo.src_rect.h;
1586 mOVInfo.src_rect.h = mOVInfo.src_rect.w;
1587 mOVInfo.src_rect.w = tmp;
1588
1589 tmp = mRotInfo.dst.width;
1590 mRotInfo.dst.width = mRotInfo.dst.height;
1591 mRotInfo.dst.height = tmp;
1592}
1593
1594bool OverlayControlChannel::useVirtualFB() {
1595 if(!m3DOVInfo.is_3d) {
1596 m3DOVInfo.is_3d = 1;
1597 mFBWidth *= 2;
1598 mFBHeight /= 2;
1599 m3DOVInfo.width = mFBWidth;
1600 m3DOVInfo.height = mFBHeight;
1601 return ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo) ? false : true;
1602 }
1603 return true;
1604}
1605
1606bool OverlayControlChannel::setTransform(int value, bool fetch) {
1607 if (!isChannelUP()) {
1608 LOGE("%s: channel is not up", __FUNCTION__);
1609 return false;
1610 }
1611
1612 mdp_overlay ov = mOVInfo;
1613 if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
1614 reportError("setParameter, overlay GET failed");
1615 return false;
1616 }
1617 mOVInfo = ov;
1618 if (!mIsChannelUpdated) {
1619 int orientation = get_mdp_orientation(value);
1620 if (orientation == mOVInfo.user_data[0]) {
1621 return true;
1622 }
1623 }
1624 mIsChannelUpdated = false;
1625
1626 int val = mOVInfo.user_data[0];
1627 if (mNoRot)
1628 return true;
1629
1630 int rot = value;
1631
1632 switch(rot) {
1633 case 0:
1634 case HAL_TRANSFORM_FLIP_H:
1635 case HAL_TRANSFORM_FLIP_V:
1636 {
1637 if (val == MDP_ROT_90) {
1638 int tmp = mOVInfo.src_rect.y;
1639 mOVInfo.src_rect.y = mOVInfo.src.width -
1640 (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
1641 mOVInfo.src_rect.x = tmp;
1642 swapOVRotWidthHeight();
1643 }
1644 else if (val == MDP_ROT_270) {
1645 int tmp = mOVInfo.src_rect.x;
1646 mOVInfo.src_rect.x = mOVInfo.src.height - (
1647 mOVInfo.src_rect.y + mOVInfo.src_rect.h);
1648 mOVInfo.src_rect.y = tmp;
1649 swapOVRotWidthHeight();
1650 }
1651 break;
1652 }
1653 case HAL_TRANSFORM_ROT_90:
1654 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
1655 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
1656 {
1657 if (val == MDP_ROT_270) {
1658 mOVInfo.src_rect.x = mOVInfo.src.width - (
1659 mOVInfo.src_rect.x + mOVInfo.src_rect.w);
1660 mOVInfo.src_rect.y = mOVInfo.src.height - (
1661 mOVInfo.src_rect.y + mOVInfo.src_rect.h);
1662 }
1663 else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
1664 int tmp = mOVInfo.src_rect.x;
1665 mOVInfo.src_rect.x = mOVInfo.src.height -
1666 (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
1667 mOVInfo.src_rect.y = tmp;
1668 swapOVRotWidthHeight();
1669 }
1670 break;
1671 }
1672 case HAL_TRANSFORM_ROT_180:
1673 {
1674 if (val == MDP_ROT_270) {
1675 int tmp = mOVInfo.src_rect.y;
1676 mOVInfo.src_rect.y = mOVInfo.src.width -
1677 (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
1678 mOVInfo.src_rect.x = tmp;
1679 swapOVRotWidthHeight();
1680 }
1681 else if (val == MDP_ROT_90) {
1682 int tmp = mOVInfo.src_rect.x;
1683 mOVInfo.src_rect.x = mOVInfo.src.height - (
1684 mOVInfo.src_rect.y + mOVInfo.src_rect.h);
1685 mOVInfo.src_rect.y = tmp;
1686 swapOVRotWidthHeight();
1687 }
1688 break;
1689 }
1690 case HAL_TRANSFORM_ROT_270:
1691 {
1692 if (val == MDP_ROT_90) {
1693 mOVInfo.src_rect.y = mOVInfo.src.height -
1694 (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
1695 mOVInfo.src_rect.x = mOVInfo.src.width -
1696 (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
1697 }
1698 else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
1699 int tmp = mOVInfo.src_rect.y;
1700 mOVInfo.src_rect.y = mOVInfo.src.width - (
1701 mOVInfo.src_rect.x + mOVInfo.src_rect.w);
1702 mOVInfo.src_rect.x = tmp;
1703 swapOVRotWidthHeight();
1704 }
1705 break;
1706 }
1707 default: return false;
1708 }
1709
1710 int mdp_rotation = get_mdp_orientation(rot);
1711 if (mdp_rotation == -1)
1712 return false;
1713
1714 mOVInfo.user_data[0] = mdp_rotation;
1715 mRotInfo.rotations = mOVInfo.user_data[0];
1716
1717 /* Rotator always outputs non-tiled formats.
1718 If rotator is used, set Overlay input to non-tiled
1719 Else, overlay input remains tiled */
1720 if (mOVInfo.user_data[0]) {
1721 mOVInfo.src.format = get_rot_output_format(mRotInfo.src.format);
1722 mRotInfo.enable = 1;
1723 }
1724 else {
1725 //We can switch between rotator ON and OFF. Reset overlay
1726 //i/p format whenever this happens
1727 if(mRotInfo.dst.format == mOVInfo.src.format)
1728 mOVInfo.src.format = mRotInfo.src.format;
1729 mRotInfo.enable = 0;
1730 //Always enable rotation for UI mirror usecase
1731 if(mUIChannel)
1732 mRotInfo.enable = 1;
1733 }
1734
1735// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
1736 // can not scale-up 8 times over original source
1737 // return false to compose with GPU
1738#if 1
1739 if(mOVInfo.dst_rect.w > (mOVInfo.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
1740 LOGE("[TJ] setTransform : too big width, back to GPU comp %d => %d", mOVInfo.src_rect.w, mOVInfo.dst_rect.w);
1741 return false;
1742 }
1743 if(mOVInfo.dst_rect.h > (mOVInfo.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
1744 LOGE("[TJ] setTransform : too big height, back to GPU comp %d => %d", mOVInfo.src_rect.h, mOVInfo.dst_rect.h);
1745 return false;
1746 }
1747#endif
1748// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
1749
1750 //dump(mRotInfo); // TJ
1751 if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
1752 reportError("setTransform, rotator start failed");
1753 dump(mRotInfo);
1754 return false;
1755 }
1756
1757 if ((mOVInfo.user_data[0] == MDP_ROT_90) ||
1758 (mOVInfo.user_data[0] == MDP_ROT_270))
1759 mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
1760 else
1761 mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
1762
1763// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
1764 LOGE("setTransform"); // TJ
1765 dump(mOVInfo); // TJ
1766// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
1767
1768 if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
1769 reportError("setTransform, overlay set failed");
1770 dump(mOVInfo);
1771 return false;
1772 }
1773
1774 return true;
1775}
1776
1777bool OverlayControlChannel::getPosition(int& x, int& y,
1778 uint32_t& w, uint32_t& h) {
1779 if (!isChannelUP())
1780 return false;
1781 //mOVInfo has the current Overlay Position
1782 x = mOVInfo.dst_rect.x;
1783 y = mOVInfo.dst_rect.y;
1784 w = mOVInfo.dst_rect.w;
1785 h = mOVInfo.dst_rect.h;
1786
1787 return true;
1788}
1789
1790bool OverlayControlChannel::getOrientation(int& orientation) const {
1791 if (!isChannelUP())
1792 return false;
1793 // mOVInfo has the current orientation
1794 orientation = mOVInfo.user_data[0];
1795 return true;
1796}
1797bool OverlayControlChannel::getOvSessionID(int& sessionID) const {
1798 if (!isChannelUP())
1799 return false;
1800 sessionID = mOVInfo.id;
1801 return true;
1802}
1803
1804bool OverlayControlChannel::getRotSessionID(int& sessionID) const {
1805 if (!isChannelUP())
1806 return false;
1807 sessionID = mRotInfo.session_id;
1808 return true;
1809}
1810
1811bool OverlayControlChannel::getSize(int& size) const {
1812 if (!isChannelUP())
1813 return false;
1814 size = mSize;
1815 return true;
1816}
1817
1818OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
1819 mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(false)
1820{
1821 //XXX: getInstance(false) implies that it should only
1822 // use the kernel allocator. Change it to something
1823 // more descriptive later.
1824 mAlloc = gralloc::IAllocController::getInstance(false);
1825}
1826
1827OverlayDataChannel::~OverlayDataChannel() {
1828 closeDataChannel();
1829}
1830
1831bool OverlayDataChannel::startDataChannel(
1832 const OverlayControlChannel& objOvCtrlChannel,
1833 int fbnum, bool norot, bool secure, bool uichannel,
1834 int num_buffers) {
1835 int ovid, rotid, size;
1836 mNoRot = norot;
1837 mSecure = secure;
1838 memset(&mOvData, 0, sizeof(mOvData));
1839 memset(&mOvDataRot, 0, sizeof(mOvDataRot));
1840 memset(&mRotData, 0, sizeof(mRotData));
1841 if (objOvCtrlChannel.getOvSessionID(ovid) &&
1842 objOvCtrlChannel.getRotSessionID(rotid) &&
1843 objOvCtrlChannel.getSize(size)) {
1844 return startDataChannel(ovid, rotid, size, fbnum,
1845 norot, uichannel, num_buffers);
1846 }
1847 else
1848 return false;
1849}
1850
1851bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) {
1852 if (fbnum < 0)
1853 return false;
1854 char dev_name[64];
1855 snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
1856
1857 mFD = open(dev_name, O_RDWR, 0);
1858 if (mFD < 0) {
1859 reportError("Cant open framebuffer ");
1860 return false;
1861 }
1862 if (!mNoRot) {
1863 mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
1864 if (mRotFD < 0) {
1865 reportError("Cant open rotator device");
1866 close(mFD);
1867 mFD = -1;
1868 return false;
1869 }
1870
1871 return mapRotatorMemory(num_buffers, uichannel, NEW_REQUEST);
1872 }
1873 return true;
1874}
1875
1876bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int requestType)
1877{
1878 mPmemAddr = MAP_FAILED;
1879
1880 alloc_data data;
1881 data.base = 0;
1882 data.fd = -1;
1883 data.offset = 0;
1884 data.size = mPmemOffset * num_buffers;
1885 data.align = getpagesize();
1886 data.uncached = true;
1887
1888 int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
1889 GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP|
1890 GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
1891
1892 if(mSecure) {
1893 allocFlags |= GRALLOC_USAGE_PROTECTED;
1894 } else {
1895 allocFlags |= GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
1896 GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
1897 if((requestType == NEW_REQUEST) && !uiChannel)
1898 allocFlags |= GRALLOC_USAGE_PRIVATE_SMI_HEAP;
1899 }
1900
1901 int err = mAlloc->allocate(data, allocFlags, 0);
1902 if(err) {
1903 reportError("Cant allocate rotatory memory");
1904 close(mFD);
1905 mFD = -1;
1906 close(mRotFD);
1907 mRotFD = -1;
1908 return false;
1909 }
1910 mPmemFD = data.fd;
1911 mPmemAddr = data.base;
1912 mBufferType = data.allocType;
1913
1914 // Set this flag if source memory is fb
1915 if(uiChannel)
1916 mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB;
1917
1918 mOvDataRot.data.memory_id = mPmemFD;
1919 mRotData.dst.memory_id = mPmemFD;
1920 mRotData.dst.offset = 0;
1921 mNumBuffers = num_buffers;
1922 mCurrentItem = 0;
1923 for (int i = 0; i < num_buffers; i++)
1924 mRotOffset[i] = i * mPmemOffset;
1925
1926 return true;
1927}
1928
1929bool OverlayDataChannel::updateDataChannel(int size) {
1930 mUpdateDataChannel = true;
1931 mNewPmemOffset = size;
1932 return true;
1933}
1934
1935bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size,
1936 int fbnum, bool norot,
1937 bool uichannel, int num_buffers) {
1938 memset(&mOvData, 0, sizeof(mOvData));
1939 memset(&mOvDataRot, 0, sizeof(mOvDataRot));
1940 memset(&mRotData, 0, sizeof(mRotData));
1941 mNoRot = norot;
1942 mOvData.data.memory_id = -1;
1943 mOvData.id = ovid;
1944 mOvDataRot = mOvData;
1945 mPmemOffset = size;
1946 mRotData.session_id = rotid;
1947 mNumBuffers = 0;
1948 mCurrentItem = 0;
1949
1950 return openDevices(fbnum, uichannel, num_buffers);
1951}
1952
1953bool OverlayDataChannel::closeDataChannel() {
1954 if (!isChannelUP())
1955 return true;
1956
1957 if (!mNoRot && mRotFD > 0) {
1958 sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
1959 memalloc->free_buffer(mPmemAddr, mPmemOffset * mNumBuffers, 0, mPmemFD);
1960 close(mPmemFD);
1961 mPmemFD = -1;
1962 close(mRotFD);
1963 mRotFD = -1;
1964 }
1965 close(mFD);
1966 mFD = -1;
1967 memset(&mOvData, 0, sizeof(mOvData));
1968 memset(&mOvDataRot, 0, sizeof(mOvDataRot));
1969 memset(&mRotData, 0, sizeof(mRotData));
1970
1971 mNumBuffers = 0;
1972 mCurrentItem = 0;
1973
1974 return true;
1975}
1976
1977bool OverlayDataChannel::setFd(int fd) {
1978 mOvData.data.memory_id = fd;
1979 return true;
1980}
1981
1982bool OverlayDataChannel::queueBuffer(uint32_t offset) {
1983 if ((!isChannelUP()) || mOvData.data.memory_id < 0) {
1984 reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from");
1985 return false;
1986 }
1987
1988 int oldPmemFD = -1;
1989 void* oldPmemAddr = MAP_FAILED;
1990 uint32_t oldPmemOffset = -1;
1991 bool result;
1992 if (!mNoRot) {
1993 if (mUpdateDataChannel) {
1994 oldPmemFD = mPmemFD;
1995 oldPmemAddr = mPmemAddr;
1996 oldPmemOffset = mPmemOffset;
1997 mPmemOffset = mNewPmemOffset;
1998 mNewPmemOffset = -1;
1999 // Map the new PMEM memory
2000 result = mapRotatorMemory(mNumBuffers, 0, UPDATE_REQUEST);
2001 if (!result) {
2002 LOGE("queueBuffer: mapRotatorMemory failed");
2003 return false;
2004 }
2005 mUpdateDataChannel = false;
2006 }
2007 }
2008
2009 result = queue(offset);
2010
2011 // Unmap the old PMEM memory after the queueBuffer has returned
2012 if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) {
2013 sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
2014 memalloc->free_buffer(oldPmemAddr, oldPmemOffset * mNumBuffers, 0, oldPmemFD);
2015 oldPmemFD = -1;
2016 }
2017 return result;
2018}
2019
2020bool OverlayDataChannel::queue(uint32_t offset) {
2021 msmfb_overlay_data *odPtr;
2022 mOvData.data.offset = offset;
2023 odPtr = &mOvData;
2024 if (!mNoRot) {
2025 mRotData.src.memory_id = mOvData.data.memory_id;
2026 mRotData.src.offset = offset;
2027 mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset;
2028 mRotData.dst.offset = mRotOffset[mCurrentItem];
2029 mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
2030
2031 int result = ioctl(mRotFD,
2032 MSM_ROTATOR_IOCTL_ROTATE, &mRotData);
2033
2034 if (!result) {
2035 mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset;
2036 odPtr = &mOvDataRot;
2037 }
2038 }
2039
2040 if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) {
2041 reportError("overlay play failed.");
2042 return false;
2043 }
2044
2045 return true;
2046}
2047
2048bool OverlayDataChannel::waitForHdmiVsync() {
2049 if (!isChannelUP()) {
2050 LOGE("%s: channel not up", __FUNCTION__);
2051 return false;
2052 }
2053 if (ioctl(mFD, MSMFB_OVERLAY_PLAY_WAIT, &mOvData)) {
2054 LOGE("%s: MSMFB_OVERLAY_PLAY_WAIT failed", __FUNCTION__);
2055 return false;
2056 }
2057 return true;
2058}
2059
2060bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format,
2061 overlay_rect *rect) {
2062 // for the 3D usecase extract channels from a frame
2063 switch (format & INPUT_MASK_3D) {
2064 case HAL_3D_IN_SIDE_BY_SIDE_L_R:
2065 if(channel == 0) {
2066 rect->x = 0;
2067 rect->y = 0;
2068 rect->w = inRect->w/2;
2069 rect->h = inRect->h;
2070 } else {
2071 rect->x = inRect->w/2;
2072 rect->y = 0;
2073 rect->w = inRect->w/2;
2074 rect->h = inRect->h;
2075 }
2076 break;
2077 case HAL_3D_IN_SIDE_BY_SIDE_R_L:
2078 if(channel == 1) {
2079 rect->x = 0;
2080 rect->y = 0;
2081 rect->w = inRect->w/2;
2082 rect->h = inRect->h;
2083 } else {
2084 rect->x = inRect->w/2;
2085 rect->y = 0;
2086 rect->w = inRect->w/2;
2087 rect->h = inRect->h;
2088 }
2089 break;
2090 case HAL_3D_IN_TOP_BOTTOM:
2091 if(channel == 0) {
2092 rect->x = 0;
2093 rect->y = 0;
2094 rect->w = inRect->w;
2095 rect->h = inRect->h/2;
2096 } else {
2097 rect->x = 0;
2098 rect->y = inRect->h/2;
2099 rect->w = inRect->w;
2100 rect->h = inRect->h/2;
2101 }
2102 break;
2103 case HAL_3D_IN_INTERLEAVE:
2104 break;
2105 default:
2106 reportError("Unsupported 3D format...");
2107 break;
2108 }
2109 return true;
2110}
2111
2112bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
2113 if (!isChannelUP()) {
2114 reportError("Channel not set");
2115 return false;
2116 }
2117
2118 mdp_overlay ov;
2119 ov.id = mOvData.id;
2120 if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
2121 reportError("setCrop, overlay GET failed");
2122 return false;
2123 }
2124
2125 if ((ov.user_data[0] == MDP_ROT_90) ||
2126 (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_UD)) ||
2127 (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_LR))){
2128 if (ov.src.width < (y + h))
2129 return false;
2130
2131 uint32_t tmp = x;
2132 x = ov.src.width - (y + h);
2133 y = tmp;
2134
2135 tmp = w;
2136 w = h;
2137 h = tmp;
2138 }
2139 else if (ov.user_data[0] == MDP_ROT_270) {
2140 if (ov.src.height < (x + w))
2141 return false;
2142
2143 uint32_t tmp = y;
2144 y = ov.src.height - (x + w);
2145 x = tmp;
2146
2147 tmp = w;
2148 w = h;
2149 h = tmp;
2150 }
2151 else if(ov.user_data[0] == MDP_ROT_180) {
2152 if ((ov.src.height < (y + h)) || (ov.src.width < ( x + w)))
2153 return false;
2154
2155 x = ov.src.width - (x + w);
2156 y = ov.src.height - (y + h);
2157 }
2158
2159
2160 normalize_crop(x, w);
2161 normalize_crop(y, h);
2162
2163 if ((ov.src_rect.x == x) &&
2164 (ov.src_rect.y == y) &&
2165 (ov.src_rect.w == w) &&
2166 (ov.src_rect.h == h))
2167 return true;
2168
2169 ov.src_rect.x = x;
2170 ov.src_rect.y = y;
2171 ov.src_rect.w = w;
2172 ov.src_rect.h = h;
2173
2174// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
2175 // can not scale-up 8 times over original source
2176 // return false to compose with GPU
2177#if 1
2178 if(ov.dst_rect.w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
2179 LOGE("[TJ] setCrop : too big width, back to GPU comp %d => %d", ov.src_rect.w, ov.dst_rect.w);
2180 return false;
2181 }
2182 if(ov.dst_rect.h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
2183 LOGE("[TJ] setCrop : too big height, back to GPU comp %d => %d", ov.src_rect.h, ov.dst_rect.h);
2184 return false;
2185 }
2186#else
2187// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
2188
2189 /* Scaling of upto a max of 8 times supported */
2190 if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
2191 ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
2192 }
2193 if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
2194 ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
2195 }
2196// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
2197#endif
2198
2199 LOGE("setCrop");
2200 dump(ov);
2201// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
2202
2203 if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
2204 reportError("setCrop, overlay set error");
2205 dump(ov);
2206 return false;
2207 }
2208
2209 return true;
2210}
2211
2212/* setVisualParam can be called to set the configuration value of a post
2213 * processing feature (HUE,SATURATION,BRIGHTNESS,CONTRAST,SMOOTHING/SHARPENING)
2214 * for the first 4, the setting will stay set until the parameter is changed
2215 * by another call to setVisualParam with that same paramType */
2216void Overlay::setVisualParam(int8_t paramType, float paramValue) {
2217 switch (mState) {
2218 case OV_UI_MIRROR_TV:
2219 case OV_2D_VIDEO_ON_PANEL:
2220 case OV_3D_VIDEO_2D_PANEL:
2221 // set the parameter value for the given parameter type.
2222 if(!objOvCtrlChannel[VG0_PIPE].setVisualParam(paramType, paramValue)) {
2223 LOGE("Failed to set param %d for value %f", paramType, paramValue);
2224 }
2225 break;
2226 case OV_2D_VIDEO_ON_TV:
2227 case OV_3D_VIDEO_3D_PANEL:
2228 case OV_3D_VIDEO_2D_TV:
2229 case OV_3D_VIDEO_3D_TV:
2230 for (int i=0; i<NUM_CHANNELS; i++) {
2231 //setting the value for the given parameter on each pipe (i.e. for
2232 //both video pipes)
2233 if(!objOvCtrlChannel[i].setVisualParam(paramType, paramValue)) {
2234 LOGE("Failed to set param %d for value %f", paramType, paramValue);
2235 }
2236 }
2237 break;
2238 default:
2239 break;
2240 }
2241}
2242
2243/* Finalizes the parameter value in the hsic_cfg structure*/
2244int OverlayControlChannel::commitVisualParam(int8_t paramType, float paramValue) {
2245#ifdef USES_POST_PROCESSING
2246 switch(paramType) {
2247 case SET_HUE:
2248 //API expects param within range -180 - 180
2249 CAP_RANGE(paramValue, HUE_RANGE, -HUE_RANGE);
2250 hsic_cfg.hue = (int32_t) paramValue;
2251 break;
2252 case SET_BRIGHTNESS:
2253 //API expects param within range -255 - 255
2254 CAP_RANGE(paramValue, BRIGHTNESS_RANGE, -BRIGHTNESS_RANGE);
2255 hsic_cfg.intensity = (int32_t) paramValue;
2256 break;
2257 case SET_SATURATION:
2258 //API expects param within range -1 - 1
2259 CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
2260 hsic_cfg.sat = paramValue;
2261 break;
2262 case SET_CONTRAST:
2263 //API expects param within range -1 - 1
2264 CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
2265 hsic_cfg.contrast = paramValue;
2266 break;
2267 default:
2268 return -1;
2269 }
2270 return 0;
2271#endif
2272 return -1;
2273}
2274
2275/* Converts paramValue to the expected range for each paramType, */
2276bool OverlayControlChannel::setVisualParam(int8_t paramType, float paramValue)
2277{
2278 if (!isChannelUP()) {
2279 LOGE("%s: Channel not set", __FUNCTION__);
2280 return false;
2281 }
2282
2283 bool setFlag = false;
2284
2285 //Sharpness values range from -128 to 127
2286 //Integer values must be converted accordingly
2287
2288 int8_t value;
2289 if (paramType == SET_SHARPNESS) {
2290 //binding paramValue to the limits of its range.
2291 CAP_RANGE(paramValue, SHARPNESS_RANGE, -SHARPNESS_RANGE);
2292 value = paramValue * NUM_SHARPNESS_VALS - (NUM_SHARPNESS_VALS / 2);
2293 }
2294
2295 uint32_t block = MDP_BLOCK_MAX;
2296
2297 //tranlate mOVInfo.id into block type for pp_conv
2298 switch(mOVInfo.id) {
2299 case 3:
2300 // 3 is the pipe_ndx given when OVERLAY_PIPE_VG1 is used
2301 block = MDP_BLOCK_VG_1;
2302 break;
2303 case 4:
2304 // 4 is the pipe_ndx given when OVERLAY_PIPE_VG2 is used
2305 block = MDP_BLOCK_VG_2;
2306 break;
2307 default:
2308 LOGE("%s: Invalid HSIC overlay id",__FUNCTION__);
2309 }
2310
2311 //save the paramValue to hsic_cfg
2312 commitVisualParam(paramType, paramValue);
2313#ifdef USES_POST_PROCESSING
2314 //calling our user space library to configure the post processing color
2315 //conversion (does Hue, Saturation, Brightness, and Contrast adjustment)
2316 display_pp_conv_set_cfg(block, &hsic_cfg);
2317#endif
2318 mdp_overlay overlay;
2319
2320 switch(paramType) {
2321 case SET_NONE:
2322 return true;
2323 case SET_SHARPNESS:
2324 if (ioctl(mFD, MSMFB_OVERLAY_GET, &overlay)) {
2325 reportError("setVisualParam, overlay GET failed");
2326 return false;
2327 }
2328 if (overlay.dpp.sharp_strength != value) {
2329 mOVInfo.flags |= MDP_SHARPENING;
2330 mOVInfo.dpp.sharp_strength = value;
2331 setFlag = true;
2332 }
2333 break;
2334 case RESET_ALL:
2335 //set all visual params to a default value
2336 //passed in from the app
2337 mOVInfo.flags |= MDP_SHARPENING;
2338 mOVInfo.dpp.sharp_strength = value;
2339 setFlag = true;
2340 break;
2341 default:
2342 return false;
2343 }
2344 if (setFlag) {
2345 if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
2346 reportError("setVisualParam, overlay set failed");
2347 dump(mOVInfo);
2348 return false;
2349 }
2350 }
2351 return true;
2352}