1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 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 115 AnnPlaneManager::AnnPlaneManager() 116 : DisplayPlaneManager() 117 { 118 } 119 120 AnnPlaneManager::~AnnPlaneManager() 121 { 122 } 123 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 134 void AnnPlaneManager::deinitialize() 135 { 136 DisplayPlaneManager::deinitialize(); 137 } 138 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 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 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 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 387 void* AnnPlaneManager::getZOrderConfig() const 388 { 389 return NULL; 390 } 391 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