blob: f904d69509982ae20f85d54c7d9510faeae94062 [file] [log] [blame]
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -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 Ahmed0c8b7b52012-07-20 09:06:13 -07004 *
5 * Not a Contribution, Apache license notifications and license are
6 * retained for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
Naseer Ahmed72cf9762012-07-21 12:17:13 -070021#define HWC_UI_MIRROR 0
22#include <gralloc_priv.h>
23#include <fb_priv.h>
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070024#include "hwc_uimirror.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070025#include "external.h"
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070026
27namespace qhwc {
28
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070029
Naseer Ahmed51df92a2012-08-14 19:27:48 -070030// Function to get the orientation of UI on primary.
31// When external display is connected, the primary UI is
32// fixed to landscape by the phone window manager.
33// Return the landscape orientation based on w and hw of primary
34int getDeviceOrientation() {
35 int orientation = 0;
36 //Calculate the rect for primary based on whether the supplied
37 //position
38 //is within or outside bounds.
39 const int fbWidth =
40 ovutils::FrameBufferInfo::getInstance()->getWidth();
41 const int fbHeight =
42 ovutils::FrameBufferInfo::getInstance()->getHeight();
43 if(fbWidth >= fbHeight) {
44 // landscape panel
45 orientation = overlay::utils::OVERLAY_TRANSFORM_0;
46 } else {
47 // portrait panel
48 orientation = overlay::utils::OVERLAY_TRANSFORM_ROT_90;
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070049 }
50 return orientation;
51}
52
53//Static Members
54ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED;
55bool UIMirrorOverlay::sIsUiMirroringOn = false;
56
Saurabh Shah56f610d2012-08-07 15:27:06 -070057void UIMirrorOverlay::reset() {
58 sIsUiMirroringOn = false;
59 sState = ovutils::OV_CLOSED;
60}
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070061
62//Prepare the overlay for the UI mirroring
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070063bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070064 sState = ovutils::OV_CLOSED;
65 sIsUiMirroringOn = false;
Naseer Ahmedf8ec1622012-07-31 18:56:23 -070066
Naseer Ahmed96c4c952012-07-25 18:27:14 -070067 if(!ctx->mMDP.hasOverlay) {
Naseer Ahmedf8ec1622012-07-31 18:56:23 -070068 ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
69 __FUNCTION__);
70 return false;
71 }
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070072 // If external display is connected
Naseer Ahmed72cf9762012-07-21 12:17:13 -070073 if(ctx->mExtDisplay->getExternalDisplay()) {
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070074 sState = ovutils::OV_UI_MIRROR;
75 configure(ctx, list);
76 }
77 return sIsUiMirroringOn;
78}
79
80// Configure
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070081bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *list)
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070082{
83 if (LIKELY(ctx->mOverlay)) {
84 overlay::Overlay& ov = *(ctx->mOverlay);
85 // Set overlay state
86 ov.setState(sState);
Naseer Ahmed72cf9762012-07-21 12:17:13 -070087 framebuffer_device_t *fbDev = ctx->mFbDev;
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070088 if(fbDev) {
89 private_module_t* m = reinterpret_cast<private_module_t*>(
90 fbDev->common.module);
Naseer Ahmed31da0b12012-07-31 18:55:33 -070091 int alignedW = ALIGN_TO(m->info.xres, 32);
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -070092
93 private_handle_t const* hnd =
94 reinterpret_cast<private_handle_t const*>(m->framebuffer);
95 unsigned int size = hnd->size/m->numBuffers;
96 ovutils::Whf info(alignedW, hnd->height, hnd->format, size);
97 // Determine the RGB pipe for UI depending on the state
98 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
99 if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
100 // True UI mirroring state: external RGB pipe is OV_PIPE2
101 dest = ovutils::OV_PIPE2;
102 } else if (sState == ovutils::OV_UI_MIRROR) {
103 // UI-only mirroring state: external RGB pipe is OV_PIPE0
104 dest = ovutils::OV_PIPE0;
105 }
106
Naseer Ahmedf8ec1622012-07-31 18:56:23 -0700107 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
Saurabh Shah56f610d2012-08-07 15:27:06 -0700108 if(ctx->mSecureMode) {
109 ovutils::setMdpFlags(mdpFlags,
110 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
111 }
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700112
113 ovutils::PipeArgs parg(mdpFlags,
114 info,
115 ovutils::ZORDER_0,
116 ovutils::IS_FG_OFF,
117 ovutils::ROT_FLAG_ENABLED);
118 ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
119 ov.setSource(pargs, dest);
120
121 // x,y,w,h
122 ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
123 ov.setCrop(dcrop, dest);
124 //Get the current orientation on primary panel
Naseer Ahmed51df92a2012-08-14 19:27:48 -0700125 int transform = getDeviceOrientation();
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700126 ovutils::eTransform orient =
127 static_cast<ovutils::eTransform>(transform);
128 ov.setTransform(orient, dest);
129
130 ovutils::Dim dim;
131 dim.x = 0;
132 dim.y = 0;
133 dim.w = m->info.xres;
134 dim.h = m->info.yres;
135 ov.setPosition(dim, dest);
136 if (!ov.commit(dest)) {
137 ALOGE("%s: commit fails", __FUNCTION__);
138 return false;
139 }
140 sIsUiMirroringOn = true;
141 }
142 }
143 return sIsUiMirroringOn;
144}
145
146bool UIMirrorOverlay::draw(hwc_context_t *ctx)
147{
148 if(!sIsUiMirroringOn) {
149 return true;
150 }
151 bool ret = true;
152 overlay::Overlay& ov = *(ctx->mOverlay);
153 ovutils::eOverlayState state = ov.getState();
154 ovutils::eDest dest = ovutils::OV_PIPE_ALL;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700155 framebuffer_device_t *fbDev = ctx->mFbDev;
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700156 if(fbDev) {
157 private_module_t* m = reinterpret_cast<private_module_t*>(
158 fbDev->common.module);
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700159 switch (state) {
160 case ovutils::OV_UI_MIRROR:
161 if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
162 ovutils::OV_PIPE0)) {
163 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
Naseer Ahmedf8ec1622012-07-31 18:56:23 -0700164 ret = false;
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700165 }
166 break;
167 case ovutils::OV_2D_TRUE_UI_MIRROR:
168 if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
169 ovutils::OV_PIPE2)) {
170 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
Naseer Ahmedf8ec1622012-07-31 18:56:23 -0700171 ret = false;
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700172 }
173 break;
174
175 default:
176 break;
177 }
Naseer Ahmed0c8b7b52012-07-20 09:06:13 -0700178 }
179 return ret;
180}
181
182//---------------------------------------------------------------------
183}; //namespace qhwc