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