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 <common/utils/HwcTrace.h>
17 #include <utils/String8.h>
18 #include <ips/anniedale/AnnPlaneManager.h>
19 #include <ips/anniedale/AnnRGBPlane.h>
20 #include <ips/anniedale/AnnOverlayPlane.h>
21 #include <ips/anniedale/AnnCursorPlane.h>
22 #include <PlaneCapabilities.h>
23
24 namespace android {
25 namespace intel {
26
27
28 struct PlaneDescription {
29 char nickname;
30 int type;
31 int index;
32 };
33
34
35 static PlaneDescription PLANE_DESC[] =
36 {
37 // nickname must be continous and start with 'A',
38 // it is used to fast locate plane index and type
39 {'A', DisplayPlane::PLANE_PRIMARY, 0},
40 {'B', DisplayPlane::PLANE_PRIMARY, 1},
41 {'C', DisplayPlane::PLANE_PRIMARY, 2},
42 {'D', DisplayPlane::PLANE_SPRITE, 0},
43 {'E', DisplayPlane::PLANE_SPRITE, 1},
44 {'F', DisplayPlane::PLANE_SPRITE, 2},
45 {'G', DisplayPlane::PLANE_OVERLAY, 0}, // nickname for Overlay A
46 {'H', DisplayPlane::PLANE_OVERLAY, 1}, // nickname for Overlay C
47 {'I', DisplayPlane::PLANE_CURSOR, 0}, // nickname for cursor A
48 {'J', DisplayPlane::PLANE_CURSOR, 1}, // nickname for cursor B
49 {'K', DisplayPlane::PLANE_CURSOR, 2} // nickname for cursor C
50 };
51
52
53 struct ZOrderDescription {
54 int index; // based on overlay position
55 const char *zorder;
56 };
57
58 // If overlay is in the bottom of Z order, two legitimate combinations are Oa, D, E, F
59 // and Oc, D, E, F. However, plane A has to be part of the blending chain as it can't
60 // be disabled [HW bug]. The only legitimate combinations including overlay and plane A is:
61 // A, Oa, E, F
62 // A, Oc, E, F
63 #define OVERLAY_HW_WORKAROUND
64
65
66 // Cursor plane can be placed on top of any plane below and is intentionally ignored
67 // in the zorder table.
68
69 static ZOrderDescription PIPE_A_ZORDER_DESC[] =
70 {
71 {0, "ADEF"}, // no overlay
72 #ifndef OVERLAY_HW_WORKAROUND
73 {1, "GDEF"}, // overlay A at bottom (1 << 0)
74 {1, "HDEF"}, // overlay C at bottom (1 << 0)
75 #else
76 {1, "GEF"}, // overlay A at bottom (1 << 0)
77 {1, "HEF"}, // overlay C at bottom (1 << 0)
78 #endif
79 {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
80 {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
81 #ifndef OVERLAY_HW_WORKAROUND
82 {3, "GHEF"}, // overlay A, C at bottom
83 #else
84 {3, "GHF"}, // overlay A, C at bottom
85 #endif
86 {4, "ADGF"}, // overlay A at next to top (1 << 2)
87 {4, "ADHF"}, // overlay C at next to top (1 << 2)
88 {6, "AGHF"}, // overlay A, C in between
89 {8, "ADEG"}, // overlay A at top (1 << 3)
90 {8, "ADEH"}, // overlay C at top (1 <<3)
91 {12, "ADGH"} // overlay A, C at top
92 };
93
94 // use overlay C over overlay A if possible on pipe B
95 // workaround: use only overlay C on pipe B
96 static ZOrderDescription PIPE_B_ZORDER_DESC[] =
97 {
98 {0, "BD"}, // no overlay
99 {1, "GBD"}, // overlay A at bottom (1 << 0)
100 {1, "HBD"}, // overlay C at bottom (1 << 0)
101 {2, "BGD"}, // overlay A at middle (1 << 1)
102 {2, "BHD"}, // overlay C at middle (1 << 1)
103 {3, "GHBD"}, // overlay A and C at bottom ( 1 << 0 + 1 << 1)
104 {4, "BDG"}, // overlay A at top (1 << 2)
105 {4, "BDH"}, // overlay C at top (1 << 2)
106 {6, "BGHD"}, // overlay A/C at middle 1 << 1 + 1 << 2)
107 {12, "BDGH"} // overlay A/C at top (1 << 2 + 1 << 3)
108 };
109
110 static const int PIPE_A_ZORDER_COMBINATIONS =
111 sizeof(PIPE_A_ZORDER_DESC)/sizeof(ZOrderDescription);
112 static const int PIPE_B_ZORDER_COMBINATIONS =
113 sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
114
AnnPlaneManager()115 AnnPlaneManager::AnnPlaneManager()
116 : DisplayPlaneManager()
117 {
118 }
119
~AnnPlaneManager()120 AnnPlaneManager::~AnnPlaneManager()
121 {
122 }
123
initialize()124 bool AnnPlaneManager::initialize()
125 {
126 mSpritePlaneCount = 3; // Sprite D, E, F
127 mOverlayPlaneCount = 2; // Overlay A, C
128 mPrimaryPlaneCount = 3; // Primary A, B, C
129 mCursorPlaneCount = 3;
130
131 return DisplayPlaneManager::initialize();
132 }
133
deinitialize()134 void AnnPlaneManager::deinitialize()
135 {
136 DisplayPlaneManager::deinitialize();
137 }
138
allocPlane(int index,int type)139 DisplayPlane* AnnPlaneManager::allocPlane(int index, int type)
140 {
141 DisplayPlane *plane = NULL;
142
143 switch (type) {
144 case DisplayPlane::PLANE_PRIMARY:
145 plane = new AnnRGBPlane(index, DisplayPlane::PLANE_PRIMARY, index/*disp*/);
146 break;
147 case DisplayPlane::PLANE_SPRITE:
148 plane = new AnnRGBPlane(index, DisplayPlane::PLANE_SPRITE, 0/*disp*/);
149 break;
150 case DisplayPlane::PLANE_OVERLAY:
151 plane = new AnnOverlayPlane(index, 0/*disp*/);
152 break;
153 case DisplayPlane::PLANE_CURSOR:
154 plane = new AnnCursorPlane(index, index /*disp */);
155 break;
156 default:
157 ELOGTRACE("unsupported type %d", type);
158 break;
159 }
160
161 if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
162 ELOGTRACE("failed to initialize plane.");
163 DEINIT_AND_DELETE_OBJ(plane);
164 }
165
166 return plane;
167 }
168
isValidZOrder(int dsp,ZOrderConfig & config)169 bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
170 {
171 int size = (int)config.size();
172
173 if (size == 0 || size > 5) {
174 VLOGTRACE("invalid z order config size %d", size);
175 return false;
176 }
177
178 if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
179 int firstOverlay = -1;
180 for (int i = 0; i < size; i++) {
181 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
182 firstOverlay = i;
183 break;
184 }
185 }
186
187 int sprites = 0;
188 for (int i = 0; i < size; i++) {
189 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
190 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
191 sprites++;
192 }
193 }
194
195 if (firstOverlay < 0 && sprites > 4) {
196 VLOGTRACE("not capable to support more than 4 sprite layers");
197 return false;
198 }
199
200 #ifdef OVERLAY_HW_WORKAROUND
201 if (firstOverlay == 0 && sprites > 2) {
202 VLOGTRACE("not capable to support 3 sprite layers on top of overlay");
203 return false;
204 }
205 #endif
206 } else if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
207 int sprites = 0;
208 for (int i = 0; i < size; i++) {
209 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
210 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
211 sprites++;
212 }
213 }
214 if (sprites > 2) {
215 ELOGTRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
216 return false;
217 }
218 } else {
219 ELOGTRACE("invalid display device %d", dsp);
220 return false;
221 }
222 return true;
223 }
224
assignPlanes(int dsp,ZOrderConfig & config)225 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
226 {
227 if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
228 ELOGTRACE("invalid display device %d", dsp);
229 return false;
230 }
231
232 int size = (int)config.size();
233
234 // calculate index based on overlay Z order position
235 int index = 0;
236 for (int i = 0; i < size; i++) {
237 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
238 index += (1 << i);
239 }
240 }
241
242 int combinations = 0;
243 if (dsp == IDisplayDevice::DEVICE_PRIMARY)
244 combinations = PIPE_A_ZORDER_COMBINATIONS;
245 else
246 combinations = PIPE_B_ZORDER_COMBINATIONS;
247
248 ZOrderDescription *zorderDesc = NULL;
249 for (int i = 0; i < combinations; i++) {
250 if (dsp == IDisplayDevice::DEVICE_PRIMARY)
251 zorderDesc = &PIPE_A_ZORDER_DESC[i];
252 else
253 zorderDesc = &PIPE_B_ZORDER_DESC[i];
254
255 if (zorderDesc->index != index)
256 continue;
257
258 if (assignPlanes(dsp, config, zorderDesc->zorder)) {
259 VLOGTRACE("zorder assigned %s", zorderDesc->zorder);
260 return true;
261 }
262 }
263 return false;
264 }
265
assignPlanes(int dsp,ZOrderConfig & config,const char * zorder)266 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config, const char *zorder)
267 {
268 // zorder string does not include cursor plane, therefore cursor layer needs to be handled
269 // in a special way. Cursor layer must be on top of zorder and no more than one cursor layer.
270
271 int size = (int)config.size();
272
273 if (zorder == NULL || size == 0) {
274 //DLOGTRACE("invalid zorder or ZOrder config.");
275 return false;
276 }
277
278 int zorderLen = (int)strlen(zorder);
279
280 // test if plane is available
281 for (int i = 0; i < size; i++) {
282 if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
283 if (i != size - 1) {
284 ELOGTRACE("invalid zorder of cursor layer");
285 return false;
286 }
287 PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
288 if (!isFreePlane(desc.type, desc.index)) {
289 ELOGTRACE("cursor plane is not available");
290 return false;
291 }
292 continue;
293 }
294 if (i >= zorderLen) {
295 DLOGTRACE("index of ZOrderConfig is out of bound");
296 return false;
297 }
298 char id = *(zorder + i);
299 PlaneDescription& desc = PLANE_DESC[id - 'A'];
300 if (!isFreePlane(desc.type, desc.index)) {
301 DLOGTRACE("plane type %d index %d is not available", desc.type, desc.index);
302 return false;
303 }
304
305 #if 0
306 // plane type check
307 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY &&
308 desc.type != DisplayPlane::PLANE_OVERLAY) {
309 ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
310 return false;
311 }
312
313 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY) {
314 if (config[i]->planeType != DisplayPlane::PLANE_PRIMARY &&
315 config[i]->planeType != DisplayPlane::PLANE_SPRITE) {
316 ELOGTRACE("invalid plane type %d,", config[i]->planeType);
317 return false;
318 }
319 if (desc.type != DisplayPlane::PLANE_PRIMARY &&
320 desc.type != DisplayPlane::PLANE_SPRITE) {
321 ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
322 return false;
323 }
324 }
325 #endif
326
327 if (desc.type == DisplayPlane::PLANE_OVERLAY && desc.index == 1 &&
328 config[i]->hwcLayer->getTransform() != 0) {
329 DLOGTRACE("overlay C does not support transform");
330 return false;
331 }
332 }
333
334 bool primaryPlaneActive = false;
335 // allocate planes
336 for (int i = 0; i < size; i++) {
337 if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
338 PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
339 ZOrderLayer *zLayer = config.itemAt(i);
340 zLayer->plane = getPlane(desc.type, desc.index);
341 if (zLayer->plane == NULL) {
342 ELOGTRACE("failed to get cursor plane, should never happen!");
343 }
344 continue;
345 }
346 char id = *(zorder + i);
347 PlaneDescription& desc = PLANE_DESC[id - 'A'];
348 ZOrderLayer *zLayer = config.itemAt(i);
349 zLayer->plane = getPlane(desc.type, desc.index);
350 if (zLayer->plane == NULL) {
351 ELOGTRACE("failed to get plane, should never happen!");
352 }
353 // override type
354 zLayer->planeType = desc.type;
355 if (desc.type == DisplayPlane::PLANE_PRIMARY) {
356 primaryPlaneActive = true;
357 }
358 }
359
360 // setup Z order
361 int slot = 0;
362 for (int i = 0; i < size; i++) {
363 slot = i;
364
365 #ifdef OVERLAY_HW_WORKAROUND
366 if (!primaryPlaneActive && config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
367 slot += 1;
368 }
369 #endif
370
371 config[i]->plane->setZOrderConfig(config, (void *)slot);
372 config[i]->plane->enable();
373 }
374
375 #if 0
376 DLOGTRACE("config size %d, zorder %s", size, zorder);
377 for (int i = 0; i < size; i++) {
378 const ZOrderLayer *l = config.itemAt(i);
379 ILOGTRACE("%d: plane type %d, index %d, zorder %d",
380 i, l->planeType, l->plane->getIndex(), l->zorder);
381 }
382 #endif
383
384 return true;
385 }
386
getZOrderConfig() const387 void* AnnPlaneManager::getZOrderConfig() const
388 {
389 return NULL;
390 }
391
getFreePlanes(int dsp,int type)392 int AnnPlaneManager::getFreePlanes(int dsp, int type)
393 {
394 RETURN_NULL_IF_NOT_INIT();
395
396 if (type != DisplayPlane::PLANE_SPRITE) {
397 return DisplayPlaneManager::getFreePlanes(dsp, type);
398 }
399
400 if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
401 ELOGTRACE("invalid display device %d", dsp);
402 return 0;
403 }
404
405 uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
406 int start = 0;
407 int stop = mSpritePlaneCount;
408 if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
409 // only Sprite D (index 0) can be assigned to pipe 1
410 // Sprites E/F (index 1, 2) are fixed on pipe 0
411 stop = 1;
412 }
413 int count = 0;
414 for (int i = start; i < stop; i++) {
415 if ((1 << i) & freePlanes) {
416 count++;
417 }
418 }
419 return count;
420 }
421
422 } // namespace intel
423 } // namespace android
424
425