Home | History | Annotate | Download | only in anniedale
      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