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 24namespace android { 25namespace intel { 26 27 28struct PlaneDescription { 29 char nickname; 30 int type; 31 int index; 32}; 33 34 35static 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 53struct 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 69static 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 96static 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 110static const int PIPE_A_ZORDER_COMBINATIONS = 111 sizeof(PIPE_A_ZORDER_DESC)/sizeof(ZOrderDescription); 112static const int PIPE_B_ZORDER_COMBINATIONS = 113 sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription); 114 115AnnPlaneManager::AnnPlaneManager() 116 : DisplayPlaneManager() 117{ 118} 119 120AnnPlaneManager::~AnnPlaneManager() 121{ 122} 123 124bool 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 134void AnnPlaneManager::deinitialize() 135{ 136 DisplayPlaneManager::deinitialize(); 137} 138 139DisplayPlane* 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 169bool 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 225bool 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 266bool 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 387void* AnnPlaneManager::getZOrderConfig() const 388{ 389 return NULL; 390} 391 392int 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