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 <utils/String8.h>
18 #include <anniedale/AnnPlaneManager.h>
19 #include <anniedale/AnnRGBPlane.h>
20 #include <anniedale/AnnOverlayPlane.h>
21 #include <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 // Cursor plane can be placed on top of any plane below and is intentionally ignored
64 // in the zorder table.
65
66 // video mode panel doesn't need the primay plane A always on hack
67 static ZOrderDescription PIPE_A_ZORDER_DESC_VID[] =
68 {
69 {0, "ADEF"}, // no overlay
70 {1, "GDEF"}, // overlay A at bottom (1 << 0)
71 {1, "HDEF"}, // overlay C at bottom (1 << 0)
72 {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
73 {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
74 {3, "GHEF"}, // overlay A, C at bottom
75 {4, "ADGF"}, // overlay A at next to top (1 << 2)
76 {4, "ADHF"}, // overlay C at next to top (1 << 2)
77 {6, "AGHF"}, // overlay A, C in between
78 {8, "ADEG"}, // overlay A at top (1 << 3)
79 {8, "ADEH"}, // overlay C at top (1 <<3)
80 {12, "ADGH"} // overlay A, C at top
81 };
82
83 static ZOrderDescription PIPE_A_ZORDER_DESC_CMD[] =
84 {
85 {0, "ADEF"}, // no overlay
86 {1, "GEF"}, // overlay A at bottom (1 << 0)
87 {1, "HEF"}, // overlay C at bottom (1 << 0)
88 {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
89 {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
90 {3, "GHF"}, // overlay A, C at bottom
91 {4, "ADGF"}, // overlay A at next to top (1 << 2)
92 {4, "ADHF"}, // overlay C at next to top (1 << 2)
93 {6, "AGHF"}, // overlay A, C in between
94 {8, "ADEG"}, // overlay A at top (1 << 3)
95 {8, "ADEH"}, // overlay C at top (1 <<3)
96 {12, "ADGH"} // overlay A, C at top
97 };
98
99 // use overlay C over overlay A if possible on pipe B
100 static ZOrderDescription PIPE_B_ZORDER_DESC[] =
101 {
102 {0, "BD"}, // no overlay
103 {1, "HBD"}, // overlay C at bottom (1 << 0)
104 // {1, "GBD"}, // overlay A at bottom (1 << 0), overlay A don`t switch to pipeB and only overlay C on pipeB
105 {2, "BHD"}, // overlay C at middle (1 << 1)
106 // {2, "BGD"}, // overlay A at middle (1 << 1), overlay A don`t switch to pipeB and only overaly C on pipeB
107 {3, "GHBD"}, // overlay A and C at bottom ( 1 << 0 + 1 << 1)
108 {4, "BDH"}, // overlay C at top (1 << 2)
109 {4, "BDG"}, // overlay A at top (1 << 2)
110 {6, "BGHD"}, // overlay A/C at middle 1 << 1 + 1 << 2)
111 {12, "BDGH"} // overlay A/C at top (1 << 2 + 1 << 3)
112 };
113
114 static ZOrderDescription *PIPE_A_ZORDER_TBL;
115 static int PIPE_A_ZORDER_COMBINATIONS;
116 static ZOrderDescription *PIPE_B_ZORDER_TBL;
117 static int PIPE_B_ZORDER_COMBINATIONS;
118 static bool OVERLAY_HW_WORKAROUND;
119
AnnPlaneManager()120 AnnPlaneManager::AnnPlaneManager()
121 : DisplayPlaneManager()
122 {
123 }
124
~AnnPlaneManager()125 AnnPlaneManager::~AnnPlaneManager()
126 {
127 }
128
initialize()129 bool AnnPlaneManager::initialize()
130 {
131 mSpritePlaneCount = 3; // Sprite D, E, F
132 mOverlayPlaneCount = 2; // Overlay A, C
133 mPrimaryPlaneCount = 3; // Primary A, B, C
134 mCursorPlaneCount = 3;
135
136 uint32_t videoMode = 0;
137 Drm *drm = Hwcomposer::getInstance().getDrm();
138 drm->readIoctl(DRM_PSB_PANEL_QUERY, &videoMode, sizeof(uint32_t));
139 if (videoMode == 1) {
140 DTRACE("video mode panel, no primay A always on hack");
141 PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_VID;
142 PIPE_A_ZORDER_COMBINATIONS =
143 sizeof(PIPE_A_ZORDER_DESC_VID)/sizeof(ZOrderDescription);
144 } else {
145 DTRACE("command mode panel, need primay A always on hack");
146 PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_CMD;
147 PIPE_A_ZORDER_COMBINATIONS =
148 sizeof(PIPE_A_ZORDER_DESC_CMD)/sizeof(ZOrderDescription);
149 OVERLAY_HW_WORKAROUND = true;
150 }
151
152 PIPE_B_ZORDER_TBL = PIPE_B_ZORDER_DESC;
153 PIPE_B_ZORDER_COMBINATIONS =
154 sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
155
156 return DisplayPlaneManager::initialize();
157 }
158
deinitialize()159 void AnnPlaneManager::deinitialize()
160 {
161 DisplayPlaneManager::deinitialize();
162 }
163
allocPlane(int index,int type)164 DisplayPlane* AnnPlaneManager::allocPlane(int index, int type)
165 {
166 DisplayPlane *plane = NULL;
167
168 switch (type) {
169 case DisplayPlane::PLANE_PRIMARY:
170 plane = new AnnRGBPlane(index, DisplayPlane::PLANE_PRIMARY, index/*disp*/);
171 break;
172 case DisplayPlane::PLANE_SPRITE:
173 plane = new AnnRGBPlane(index, DisplayPlane::PLANE_SPRITE, 0/*disp*/);
174 break;
175 case DisplayPlane::PLANE_OVERLAY:
176 plane = new AnnOverlayPlane(index, 0/*disp*/);
177 break;
178 case DisplayPlane::PLANE_CURSOR:
179 plane = new AnnCursorPlane(index, index /*disp */);
180 break;
181 default:
182 ETRACE("unsupported type %d", type);
183 break;
184 }
185
186 if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
187 ETRACE("failed to initialize plane.");
188 DEINIT_AND_DELETE_OBJ(plane);
189 }
190
191 return plane;
192 }
193
isValidZOrder(int dsp,ZOrderConfig & config)194 bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
195 {
196 int size = (int)config.size();
197 bool hasCursor = false;
198
199 for (int i = 0; i < size; i++) {
200 if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
201 hasCursor = true;
202 break;
203 }
204 }
205
206 if (size <= 0 ||
207 (hasCursor && size > 5) ||
208 (!hasCursor && size > 4)) {
209 VTRACE("invalid z order config size %d", size);
210 return false;
211 }
212
213 if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
214 int firstOverlay = -1;
215 for (int i = 0; i < size; i++) {
216 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
217 firstOverlay = i;
218 break;
219 }
220 }
221
222 int sprites = 0;
223 for (int i = 0; i < size; i++) {
224 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
225 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
226 sprites++;
227 }
228 }
229
230 if (firstOverlay < 0 && sprites > 4) {
231 VTRACE("not capable to support more than 4 sprite layers");
232 return false;
233 }
234
235 if (OVERLAY_HW_WORKAROUND) {
236 if (firstOverlay == 0 && size > 2) {
237 VTRACE("can not support 3 sprite layers on top of overlay");
238 return false;
239 }
240 }
241 } else if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
242 int sprites = 0;
243 for (int i = 0; i < size; i++) {
244 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
245 config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
246 sprites++;
247 }
248 }
249 if (sprites > 2) {
250 ETRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
251 return false;
252 }
253 } else {
254 ETRACE("invalid display device %d", dsp);
255 return false;
256 }
257 return true;
258 }
259
assignPlanes(int dsp,ZOrderConfig & config)260 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
261 {
262 if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
263 ETRACE("invalid display device %d", dsp);
264 return false;
265 }
266
267 int size = (int)config.size();
268
269 // calculate index based on overlay Z order position
270 int index = 0;
271 for (int i = 0; i < size; i++) {
272 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
273 index += (1 << i);
274 }
275 }
276
277 int combinations;
278 ZOrderDescription *table;
279 if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
280 combinations = PIPE_A_ZORDER_COMBINATIONS;
281 table = PIPE_A_ZORDER_TBL;
282 } else {
283 combinations = PIPE_B_ZORDER_COMBINATIONS;
284 table = PIPE_B_ZORDER_TBL;
285 }
286
287 for (int i = 0; i < combinations; i++) {
288 ZOrderDescription *zorderDesc = table + i;
289
290 if (zorderDesc->index != index)
291 continue;
292
293 if (assignPlanes(dsp, config, zorderDesc->zorder)) {
294 VTRACE("zorder assigned %s", zorderDesc->zorder);
295 return true;
296 }
297 }
298 return false;
299 }
300
assignPlanes(int dsp,ZOrderConfig & config,const char * zorder)301 bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config, const char *zorder)
302 {
303 // zorder string does not include cursor plane, therefore cursor layer needs to be handled
304 // in a special way. Cursor layer must be on top of zorder and no more than one cursor layer.
305
306 int size = (int)config.size();
307 if (zorder == NULL || size == 0) {
308 //DTRACE("invalid zorder or ZOrder config.");
309 return false;
310 }
311
312 int zorderLen = (int)strlen(zorder);
313
314 // test if plane is avalable
315 for (int i = 0; i < size; i++) {
316 if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
317 if (i != size - 1) {
318 ETRACE("invalid zorder of cursor layer");
319 return false;
320 }
321 PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
322 if (!isFreePlane(desc.type, desc.index)) {
323 ETRACE("cursor plane is not available");
324 return false;
325 }
326 continue;
327 }
328 if (i >= zorderLen) {
329 DTRACE("index of ZOrderConfig is out of bound");
330 return false;
331 }
332
333 char id = *(zorder + i);
334 PlaneDescription& desc = PLANE_DESC[id - 'A'];
335 if (!isFreePlane(desc.type, desc.index)) {
336 DTRACE("plane type %d index %d is not available", desc.type, desc.index);
337 return false;
338 }
339
340 #if 0
341 // plane type check
342 if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY &&
343 desc.type != DisplayPlane::PLANE_OVERLAY) {
344 ETRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
345 return false;
346 }
347
348 if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY) {
349 if (config[i]->planeType != DisplayPlane::PLANE_PRIMARY &&
350 config[i]->planeType != DisplayPlane::PLANE_SPRITE) {
351 ETRACE("invalid plane type %d,", config[i]->planeType);
352 return false;
353 }
354 if (desc.type != DisplayPlane::PLANE_PRIMARY &&
355 desc.type != DisplayPlane::PLANE_SPRITE) {
356 ETRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
357 return false;
358 }
359 }
360 #endif
361
362 if (desc.type == DisplayPlane::PLANE_OVERLAY && desc.index == 1 &&
363 config[i]->hwcLayer->getTransform() != 0) {
364 DTRACE("overlay C does not support transform");
365 return false;
366 }
367 }
368
369 bool primaryPlaneActive = false;
370 // allocate planes
371 for (int i = 0; i < size; i++) {
372 if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
373 PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
374 ZOrderLayer *zLayer = config.itemAt(i);
375 zLayer->plane = getPlane(desc.type, desc.index);
376 if (zLayer->plane == NULL) {
377 ETRACE("failed to get cursor plane, should never happen!");
378 }
379 continue;
380 }
381
382 char id = *(zorder + i);
383 PlaneDescription& desc = PLANE_DESC[id - 'A'];
384 ZOrderLayer *zLayer = config.itemAt(i);
385 zLayer->plane = getPlane(desc.type, desc.index);
386 if (zLayer->plane == NULL) {
387 ETRACE("failed to get plane, should never happen!");
388 }
389 // override type
390 zLayer->planeType = desc.type;
391 if (desc.type == DisplayPlane::PLANE_PRIMARY) {
392 primaryPlaneActive = true;
393 }
394 }
395
396 // setup Z order
397 int slot = 0;
398 for (int i = 0; i < size; i++) {
399 slot = i;
400
401 if (OVERLAY_HW_WORKAROUND) {
402 if (!primaryPlaneActive &&
403 config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
404 slot += 1;
405 }
406 }
407
408 config[i]->plane->setZOrderConfig(config, (void *)(unsigned long)slot);
409 config[i]->plane->enable();
410 }
411
412 #if 0
413 DTRACE("config size %d, zorder %s", size, zorder);
414 for (int i = 0; i < size; i++) {
415 const ZOrderLayer *l = config.itemAt(i);
416 ITRACE("%d: plane type %d, index %d, zorder %d",
417 i, l->planeType, l->plane->getIndex(), l->zorder);
418 }
419 #endif
420
421 return true;
422 }
423
getZOrderConfig() const424 void* AnnPlaneManager::getZOrderConfig() const
425 {
426 return NULL;
427 }
428
getFreePlanes(int dsp,int type)429 int AnnPlaneManager::getFreePlanes(int dsp, int type)
430 {
431 RETURN_NULL_IF_NOT_INIT();
432
433 if (type != DisplayPlane::PLANE_SPRITE) {
434 return DisplayPlaneManager::getFreePlanes(dsp, type);
435 }
436
437 if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
438 ETRACE("invalid display device %d", dsp);
439 return 0;
440 }
441
442 uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
443 int start = 0;
444 int stop = mSpritePlaneCount;
445 if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
446 // only Sprite D (index 0) can be assigned to pipe 1
447 // Sprites E/F (index 1, 2) are fixed on pipe 0
448 stop = 1;
449 }
450 int count = 0;
451 for (int i = start; i < stop; i++) {
452 if ((1 << i) & freePlanes) {
453 count++;
454 }
455 }
456 return count;
457 }
458
459 } // namespace intel
460 } // namespace android
461
462