1/*
2// Copyright (c) 2014 Intel Corporation 
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#include <HwcTrace.h>
17#include <tangier/TngPlaneManager.h>
18#include <tangier/TngPrimaryPlane.h>
19#include <tangier/TngSpritePlane.h>
20#include <tangier/TngOverlayPlane.h>
21#include <tangier/TngCursorPlane.h>
22
23namespace android {
24namespace intel {
25
26TngPlaneManager::TngPlaneManager()
27    : DisplayPlaneManager()
28{
29    memset(&mZorder, 0, sizeof(mZorder));
30}
31
32TngPlaneManager::~TngPlaneManager()
33{
34}
35
36bool TngPlaneManager::initialize()
37{
38    mSpritePlaneCount = 1;  // Sprite D
39    mOverlayPlaneCount = 2;  // Overlay A & C
40    mPrimaryPlaneCount = 3;  // Primary A, B, C
41    mCursorPlaneCount = 3;
42
43    return DisplayPlaneManager::initialize();
44}
45
46void TngPlaneManager::deinitialize()
47{
48    DisplayPlaneManager::deinitialize();
49}
50
51DisplayPlane* TngPlaneManager::allocPlane(int index, int type)
52{
53    DisplayPlane *plane = 0;
54
55    switch (type) {
56    case DisplayPlane::PLANE_PRIMARY:
57        plane = new TngPrimaryPlane(index, index);
58        break;
59    case DisplayPlane::PLANE_SPRITE:
60        plane = new TngSpritePlane(index, 0);
61        break;
62    case DisplayPlane::PLANE_OVERLAY:
63        plane = new TngOverlayPlane(index, 0);
64        break;
65    case DisplayPlane::PLANE_CURSOR:
66        plane = new TngCursorPlane(index, index /*disp */);
67        break;
68    default:
69        ETRACE("unsupported type %d", type);
70        break;
71    }
72    if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
73        ETRACE("failed to initialize plane.");
74        DEINIT_AND_DELETE_OBJ(plane);
75    }
76
77    return plane;
78}
79
80bool TngPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
81{
82    // check whether it's a supported z order config
83    int firstRGB = -1;
84    int lastRGB = -1;
85    int firstOverlay = -1;
86    int lastOverlay = -1;
87
88    for (int i = 0; i < (int)config.size(); i++) {
89        const ZOrderLayer *layer = config[i];
90        switch (layer->planeType) {
91        case DisplayPlane::PLANE_PRIMARY:
92        case DisplayPlane::PLANE_SPRITE:
93            if (firstRGB == -1) {
94                firstRGB = i;
95                lastRGB = i;
96            } else {
97                lastRGB = i;
98            }
99            break;
100        case DisplayPlane::PLANE_OVERLAY:
101        case DisplayPlane::PLANE_CURSOR:
102            if (firstOverlay == -1) {
103                firstOverlay = i;
104                lastOverlay = i;
105            } else {
106                lastOverlay = i;
107            }
108            break;
109        }
110    }
111
112    if ((lastRGB < firstOverlay) || (firstRGB > lastOverlay)) {
113        return true;
114    } else {
115        VTRACE("invalid z order config. rgb (%d, %d) yuv (%d, %d)",
116               firstRGB, lastRGB, firstOverlay, lastOverlay);
117        return false;
118    }
119}
120
121bool TngPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
122{
123    // probe if plane is available
124    int size = (int)config.size();
125    for (int i = 0; i < size; i++) {
126        const ZOrderLayer *layer = config.itemAt(i);
127        if (!getFreePlanes(dsp, layer->planeType)) {
128            DTRACE("no plane available for dsp %d, type %d", dsp, layer->planeType);
129            return false;
130        }
131    }
132
133    if (config.size() == 1 && config[0]->planeType == DisplayPlane::PLANE_SPRITE) {
134        config[0]->planeType == DisplayPlane::PLANE_PRIMARY;
135    }
136
137    // allocate planes
138    for (int i = 0; i < size; i++) {
139        ZOrderLayer *layer = config.itemAt(i);
140        layer->plane = getPlaneHelper(dsp, layer->planeType);
141        if (layer->plane == NULL) {
142            // should never happen!!
143            ETRACE("failed to assign plane for type %d", layer->planeType);
144            return false;
145        }
146        // sequence !!!!! enabling plane before setting zorder
147        // see TngSpritePlane::enablePlane implementation!!!!
148        layer->plane->enable();
149    }
150
151    // setup Z order
152    for (int i = 0; i < size; i++) {
153        ZOrderLayer *layer = config.itemAt(i);
154        layer->plane->setZOrderConfig(config, &mZorder);
155    }
156
157    return true;
158}
159
160void* TngPlaneManager::getZOrderConfig() const
161{
162    return (void*)&mZorder;
163}
164
165DisplayPlane* TngPlaneManager::getPlaneHelper(int dsp, int type)
166{
167    RETURN_NULL_IF_NOT_INIT();
168
169    if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
170        ETRACE("Invalid display device %d", dsp);
171        return 0;
172    }
173
174    int index = dsp == IDisplayDevice::DEVICE_PRIMARY ? 0 : 1;
175
176    if (type == DisplayPlane::PLANE_PRIMARY ||
177        type == DisplayPlane::PLANE_CURSOR) {
178        return getPlane(type, index);
179    } else if (type == DisplayPlane::PLANE_SPRITE) {
180        return getAnyPlane(type);
181    } else if (type == DisplayPlane::PLANE_OVERLAY) {
182        // use overlay A for pipe A and overlay C for pipe B if possible
183        DisplayPlane *plane = getPlane(type, index);
184        if (plane == NULL) {
185            plane = getPlane(type, !index);
186        }
187        return plane;
188    } else {
189        ETRACE("invalid plane type %d", type);
190        return 0;
191    }
192}
193
194} // namespace intel
195} // namespace android
196
197