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 <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 120 AnnPlaneManager::AnnPlaneManager() 121 : DisplayPlaneManager() 122 { 123 } 124 125 AnnPlaneManager::~AnnPlaneManager() 126 { 127 } 128 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 159 void AnnPlaneManager::deinitialize() 160 { 161 DisplayPlaneManager::deinitialize(); 162 } 163 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 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 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 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 424 void* AnnPlaneManager::getZOrderConfig() const 425 { 426 return NULL; 427 } 428 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