hwc_fbupdate.cpp revision 3e858ebde3f2b4e762af8f7f2808d45ba59b890d
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
4 *
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
21#define HWC_UI_MIRROR 0
22#include <gralloc_priv.h>
23#include <fb_priv.h>
24#include "hwc_uimirror.h"
25#include "external.h"
26
27namespace qhwc {
28
29
30// 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;
49    }
50    return orientation;
51}
52
53//Static Members
54ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED;
55bool UIMirrorOverlay::sIsUiMirroringOn = false;
56
57void UIMirrorOverlay::reset() {
58    sIsUiMirroringOn = false;
59    sState = ovutils::OV_CLOSED;
60}
61
62//Prepare the overlay for the UI mirroring
63bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
64    sState = ovutils::OV_CLOSED;
65    sIsUiMirroringOn = false;
66
67    if(!ctx->mMDP.hasOverlay) {
68        ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
69                __FUNCTION__);
70       return false;
71    }
72    // If external display is active
73    if(isExternalActive(ctx)) {
74        sState = ovutils::OV_UI_MIRROR;
75        configure(ctx, fblayer);
76    }
77    return sIsUiMirroringOn;
78}
79
80// Configure
81bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
82{
83    if (LIKELY(ctx->mOverlay)) {
84        overlay::Overlay& ov = *(ctx->mOverlay);
85        // Set overlay state
86        ov.setState(sState);
87        framebuffer_device_t *fbDev = ctx->mFbDev;
88        if(fbDev) {
89            private_handle_t *hnd = (private_handle_t *)layer->handle;
90            ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
91            // Determine the RGB pipe for UI depending on the state
92            ovutils::eDest dest = ovutils::OV_PIPE_ALL;
93            if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
94                // True UI mirroring state: external RGB pipe is OV_PIPE2
95                dest = ovutils::OV_PIPE2;
96            } else if (sState == ovutils::OV_UI_MIRROR) {
97                // UI-only mirroring state: external RGB pipe is OV_PIPE0
98                dest = ovutils::OV_PIPE0;
99            }
100
101            ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
102            if(ctx->mSecureMode) {
103                ovutils::setMdpFlags(mdpFlags,
104                        ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
105            }
106
107            ovutils::PipeArgs parg(mdpFlags,
108                    info,
109                    ovutils::ZORDER_0,
110                    ovutils::IS_FG_OFF,
111                    ovutils::ROT_FLAG_ENABLED);
112            ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
113            ov.setSource(pargs, dest);
114
115            hwc_rect_t sourceCrop = layer->sourceCrop;
116            // x,y,w,h
117            ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
118                sourceCrop.right - sourceCrop.left,
119                sourceCrop.bottom - sourceCrop.top);
120            ov.setCrop(dcrop, dest);
121
122            //Get the current orientation on primary panel
123            int transform = getDeviceOrientation();
124            ovutils::eTransform orient =
125                    static_cast<ovutils::eTransform>(transform);
126            ov.setTransform(orient, dest);
127
128            hwc_rect_t displayFrame = layer->displayFrame;
129            ovutils::Dim dpos(displayFrame.left,
130                displayFrame.top,
131                displayFrame.right - displayFrame.left,
132                displayFrame.bottom - displayFrame.top);
133            ov.setPosition(dpos, dest);
134
135            if (!ov.commit(dest)) {
136                ALOGE("%s: commit fails", __FUNCTION__);
137                return false;
138            }
139            sIsUiMirroringOn = true;
140        }
141    }
142    return sIsUiMirroringOn;
143}
144
145bool UIMirrorOverlay::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
146{
147    if(!sIsUiMirroringOn) {
148        return true;
149    }
150    bool ret = true;
151    overlay::Overlay& ov = *(ctx->mOverlay);
152    ovutils::eOverlayState state = ov.getState();
153    ovutils::eDest dest = ovutils::OV_PIPE_ALL;
154    framebuffer_device_t *fbDev = ctx->mFbDev;
155    if(fbDev) {
156        private_module_t* m = reinterpret_cast<private_module_t*>(
157                              fbDev->common.module);
158        private_handle_t *hnd = (private_handle_t *)layer->handle;
159        switch (state) {
160            case ovutils::OV_UI_MIRROR:
161                //TODO why is this primary fd
162                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
163                            hnd->offset,  //div by line_length like in PAN?
164                            ovutils::OV_PIPE0)) {
165                    ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
166                    ret = false;
167                }
168                break;
169            case ovutils::OV_2D_TRUE_UI_MIRROR:
170                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
171                            hnd->offset,
172                            ovutils::OV_PIPE2)) {
173                    ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
174                    ret = false;
175                }
176                break;
177
178        default:
179            break;
180        }
181    }
182    return ret;
183}
184
185//---------------------------------------------------------------------
186}; //namespace qhwc
187