Home | History | Annotate | Download | only in hwc
      1 /*
      2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *     * Redistributions of source code must retain the above copyright
      8 *       notice, this list of conditions and the following disclaimer.
      9 *     * Redistributions in binary form must reproduce the above
     10 *       copyright notice, this list of conditions and the following
     11 *       disclaimer in the documentation and/or other materials provided
     12 *       with the distribution.
     13 *     * Neither the name of The Linux Foundation nor the names of its
     14 *       contributors may be used to endorse or promote products derived
     15 *       from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <cutils/properties.h>
     31 #include <sys/mman.h>
     32 #include <utils/constants.h>
     33 #include <utils/debug.h>
     34 #include <utils/formats.h>
     35 #include <algorithm>
     36 #include <array>
     37 #include <sstream>
     38 #include <string>
     39 #include <fstream>
     40 #include <sys/stat.h>
     41 
     42 #include "hwc_display_external_test.h"
     43 #include "hwc_debugger.h"
     44 
     45 #define __CLASS__ "HWCDisplayExternalTest"
     46 
     47 namespace sdm {
     48 
     49 using std::array;
     50 
     51 int HWCDisplayExternalTest::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
     52                                    qService::QService *qservice, uint32_t panel_bpp,
     53                                    uint32_t pattern_type, HWCDisplay **hwc_display) {
     54   HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, hwc_procs, qservice,
     55                                                              panel_bpp, pattern_type);
     56 
     57   int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
     58   if (status) {
     59     delete hwc_external_test;
     60     return status;
     61   }
     62 
     63   *hwc_display = hwc_external_test;
     64 
     65   DLOGI("panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
     66 
     67   return status;
     68 }
     69 
     70 void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
     71   static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
     72 
     73   delete hwc_display;
     74 }
     75 
     76 HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
     77                                                hwc_procs_t const **hwc_procs,
     78                                                qService::QService *qservice, uint32_t panel_bpp,
     79                                                uint32_t pattern_type)
     80   : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
     81                DISPLAY_CLASS_EXTERNAL), panel_bpp_(panel_bpp), pattern_type_(pattern_type) {
     82 }
     83 
     84 int HWCDisplayExternalTest::Init() {
     85   uint32_t external_width = 0;
     86   uint32_t external_height = 0;
     87 
     88   int status = HWCDisplay::Init();
     89   if (status) {
     90     return status;
     91   }
     92 
     93   buffer_allocator_ = new HWCBufferAllocator();
     94 
     95   status = CreateLayerStack();
     96   if (status) {
     97     Deinit();
     98     return status;
     99   }
    100 
    101   DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
    102   if (error != kErrorNone) {
    103     Deinit();
    104     return -EINVAL;
    105   }
    106 
    107   status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
    108   if (status) {
    109     Deinit();
    110     return status;
    111   }
    112 
    113   return status;
    114 }
    115 
    116 int HWCDisplayExternalTest::Deinit() {
    117   DestroyLayerStack();
    118 
    119   delete buffer_allocator_;
    120   buffer_allocator_ = NULL;
    121 
    122   return HWCDisplay::Deinit();
    123 }
    124 
    125 
    126 int HWCDisplayExternalTest::Prepare(hwc_display_contents_1_t *content_list) {
    127   int status = 0;
    128 
    129   if (secure_display_active_) {
    130     MarkLayersForGPUBypass(content_list);
    131     return status;
    132   }
    133 
    134   if (!content_list || !content_list->numHwLayers) {
    135     DLOGW("Invalid content list");
    136     return -EINVAL;
    137   }
    138 
    139   if (shutdown_pending_) {
    140     return 0;
    141   }
    142 
    143   DisplayError error = display_intf_->Prepare(&layer_stack_);
    144   if (error != kErrorNone) {
    145     if (error == kErrorShutDown) {
    146       shutdown_pending_ = true;
    147     } else if (error != kErrorPermission) {
    148       DLOGE("Prepare failed. Error = %d", error);
    149       // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
    150       // so that previous buffer and fences are released, and override the error.
    151       flush_ = true;
    152     }
    153   }
    154 
    155   MarkLayersForGPUBypass(content_list);
    156 
    157   return 0;
    158 }
    159 
    160 int HWCDisplayExternalTest::Commit(hwc_display_contents_1_t *content_list) {
    161   int status = 0;
    162 
    163   if (secure_display_active_) {
    164     return status;
    165   }
    166 
    167   if (!content_list || !content_list->numHwLayers) {
    168     DLOGW("Invalid content list");
    169     return -EINVAL;
    170   }
    171 
    172   if (shutdown_pending_) {
    173     return 0;
    174   }
    175 
    176   DumpInputBuffer();
    177 
    178   if (!flush_) {
    179     DisplayError error = kErrorUndefined;
    180 
    181     error = display_intf_->Commit(&layer_stack_);
    182     if (error == kErrorNone) {
    183       // A commit is successfully submitted, start flushing on failure now onwards.
    184       flush_on_error_ = true;
    185     } else {
    186       if (error == kErrorShutDown) {
    187         shutdown_pending_ = true;
    188         return status;
    189       } else if (error != kErrorPermission) {
    190         DLOGE("Commit failed. Error = %d", error);
    191         // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
    192         // so that previous buffer and fences are released, and override the error.
    193         flush_ = true;
    194       }
    195     }
    196   }
    197 
    198   return PostCommit(content_list);
    199 }
    200 
    201 void HWCDisplayExternalTest::SetSecureDisplay(bool secure_display_active, bool force_flush) {
    202   if (secure_display_active_ != secure_display_active) {
    203     secure_display_active_ = secure_display_active;
    204 
    205     if (secure_display_active_) {
    206       DisplayError error = display_intf_->Flush();
    207       if (error != kErrorNone) {
    208         DLOGE("Flush failed. Error = %d", error);
    209       }
    210     }
    211   }
    212   return;
    213 }
    214 
    215 int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
    216   return 0;
    217 }
    218 
    219 void HWCDisplayExternalTest::DumpInputBuffer() {
    220   if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
    221     return;
    222   }
    223 
    224   const char *dir_path = "/data/misc/display/frame_dump_external";
    225   uint32_t width = buffer_info_.alloc_buffer_info.aligned_width;
    226   uint32_t height = buffer_info_.alloc_buffer_info.aligned_height;
    227   string format_str = GetFormatString(buffer_info_.buffer_config.format);
    228 
    229   char *buffer = reinterpret_cast<char *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
    230                                                 PROT_READ|PROT_WRITE, MAP_SHARED,
    231                                                 buffer_info_.alloc_buffer_info.fd, 0));
    232   if (buffer == MAP_FAILED) {
    233     DLOGW("mmap failed. err = %d", errno);
    234     return;
    235   }
    236 
    237   if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
    238     DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
    239     return;
    240   }
    241 
    242   // if directory exists already, need to explicitly change the permission.
    243   if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
    244     DLOGW("Failed to change permissions on %s directory", dir_path);
    245     return;
    246   }
    247 
    248   if (buffer) {
    249     std::stringstream dump_file_name(dir_path);
    250     dump_file_name << "/input_layer_" << width << "x" << height << "_" << format_str << ".raw";
    251 
    252     std::fstream fs(dump_file_name.str().c_str());
    253     if (!fs.is_open()) {
    254       DLOGI("File open failed", dump_file_name.str().c_str());
    255       return;
    256     }
    257 
    258     fs.write(buffer, (std::streamsize)buffer_info_.alloc_buffer_info.size);
    259     fs.close();
    260 
    261     DLOGI("Frame Dump %s: is successful", dump_file_name.str().c_str());
    262   }
    263 
    264   // Dump only once as the content is going to be same for all draw cycles
    265   if (dump_frame_count_) {
    266     dump_frame_count_ = 0;
    267   }
    268 
    269   if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
    270     DLOGW("munmap failed. err = %d", errno);
    271     return;
    272   }
    273 }
    274 
    275 void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
    276   std::bitset<16> color = {};
    277   std::bitset<16> temp_crc = {};
    278 
    279   switch (panel_bpp_) {
    280     case kDisplayBpp18:
    281       color = (color_val & 0xFC) << 8;
    282       break;
    283     case kDisplayBpp24:
    284       color = color_val << 8;
    285       break;
    286     case kDisplayBpp30:
    287       color = color_val << 6;
    288       break;
    289     default:
    290       return;
    291   }
    292 
    293   temp_crc[15] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^
    294                  (*crc_data)[4] ^ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^
    295                  (*crc_data)[8] ^ (*crc_data)[9] ^ (*crc_data)[10] ^ (*crc_data)[11] ^
    296                  (*crc_data)[12] ^ (*crc_data)[14] ^ (*crc_data)[15] ^ color[0] ^ color[1] ^
    297                  color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^ color[7] ^ color[8] ^
    298                  color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[14] ^ color[15];
    299 
    300   temp_crc[14] = (*crc_data)[12] ^ (*crc_data)[13] ^ color[12] ^ color[13];
    301   temp_crc[13] = (*crc_data)[11] ^ (*crc_data)[12] ^ color[11] ^ color[12];
    302   temp_crc[12] = (*crc_data)[10] ^ (*crc_data)[11] ^ color[10] ^ color[11];
    303   temp_crc[11] = (*crc_data)[9] ^ (*crc_data)[10] ^ color[9] ^ color[10];
    304   temp_crc[10] = (*crc_data)[8] ^ (*crc_data)[9] ^ color[8] ^ color[9];
    305   temp_crc[9] = (*crc_data)[7] ^ (*crc_data)[8] ^ color[7] ^ color[8];
    306   temp_crc[8] = (*crc_data)[6] ^ (*crc_data)[7] ^ color[6] ^ color[7];
    307   temp_crc[7] = (*crc_data)[5] ^ (*crc_data)[6] ^ color[5] ^ color[6];
    308   temp_crc[6] = (*crc_data)[4] ^ (*crc_data)[5] ^ color[4] ^ color[5];
    309   temp_crc[5] = (*crc_data)[3] ^ (*crc_data)[4] ^ color[3] ^ color[4];
    310   temp_crc[4] = (*crc_data)[2] ^ (*crc_data)[3] ^ color[2] ^ color[3];
    311   temp_crc[3] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[15] ^ color[1] ^ color[2] ^ color[15];
    312   temp_crc[2] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[14] ^ color[0] ^ color[1] ^ color[14];
    313 
    314   temp_crc[1] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^ (*crc_data)[5] ^
    315                 (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
    316                 (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
    317                 (*crc_data)[14] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^
    318                 color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[13] ^
    319                 color[14];
    320 
    321   temp_crc[0] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^
    322                 (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
    323                 (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
    324                 (*crc_data)[15] ^ color[0] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^
    325                 color[6] ^ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^
    326                 color[13] ^ color[15];
    327 
    328   (*crc_data) = temp_crc;
    329 }
    330 
    331 int HWCDisplayExternalTest::FillBuffer() {
    332   uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
    333                                                 PROT_READ|PROT_WRITE, MAP_SHARED,
    334                                                 buffer_info_.alloc_buffer_info.fd, 0));
    335   if (buffer == MAP_FAILED) {
    336     DLOGE("mmap failed. err = %d", errno);
    337     return -EFAULT;
    338   }
    339 
    340   switch (pattern_type_) {
    341     case kPatternColorRamp:
    342       GenerateColorRamp(buffer);
    343       break;
    344     case kPatternBWVertical:
    345       GenerateBWVertical(buffer);
    346       break;
    347     case kPatternColorSquare:
    348       GenerateColorSquare(buffer);
    349       break;
    350     default:
    351       DLOGW("Invalid Pattern type %d", pattern_type_);
    352       return -EINVAL;
    353   }
    354 
    355   if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
    356     DLOGE("munmap failed. err = %d", errno);
    357     return -EFAULT;
    358   }
    359 
    360   return 0;
    361 }
    362 
    363 int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
    364   switch (format) {
    365   case kFormatRGBA8888:
    366   case kFormatRGBA1010102:
    367     *stride = width * 4;
    368     break;
    369   case kFormatRGB888:
    370     *stride = width * 3;
    371     break;
    372   default:
    373     DLOGE("Unsupported format type %d", format);
    374     return -EINVAL;
    375   }
    376 
    377   return 0;
    378 }
    379 
    380 void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
    381                                        uint8_t **buffer) {
    382   LayerBufferFormat format = buffer_info_.buffer_config.format;
    383 
    384   switch (format) {
    385     case kFormatRGBA8888:
    386       *(*buffer)++ = UINT8(red & 0xFF);
    387       *(*buffer)++ = UINT8(green & 0xFF);
    388       *(*buffer)++ = UINT8(blue & 0xFF);
    389       *(*buffer)++ = UINT8(alpha & 0xFF);
    390       break;
    391     case kFormatRGB888:
    392       *(*buffer)++ = UINT8(red & 0xFF);
    393       *(*buffer)++ = UINT8(green & 0xFF);
    394       *(*buffer)++ = UINT8(blue & 0xFF);
    395       break;
    396     case kFormatRGBA1010102:
    397       // Lower 8 bits of red
    398       *(*buffer)++ = UINT8(red & 0xFF);
    399 
    400       // Upper 2 bits of Red + Lower 6 bits of green
    401       *(*buffer)++ = UINT8(((green & 0x3F) << 2) | ((red >> 0x8) & 0x3));
    402 
    403       // Upper 4 bits of green + Lower 4 bits of blue
    404       *(*buffer)++ = UINT8(((blue & 0xF) << 4) | ((green >> 6) & 0xF));
    405 
    406       // Upper 6 bits of blue + Lower 2 bits of alpha
    407       *(*buffer)++ = UINT8(((alpha & 0x3) << 6) | ((blue >> 4) & 0x3F));
    408       break;
    409     default:
    410       DLOGW("format not supported format = %d", format);
    411       break;
    412   }
    413 }
    414 
    415 void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
    416   uint32_t width = buffer_info_.buffer_config.width;
    417   uint32_t height = buffer_info_.buffer_config.height;
    418   LayerBufferFormat format = buffer_info_.buffer_config.format;
    419   uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
    420   uint32_t buffer_stride = 0;
    421 
    422   uint32_t color_ramp = 0;
    423   uint32_t start_color_val = 0;
    424   uint32_t step_size = 1;
    425   uint32_t ramp_width = 0;
    426   uint32_t ramp_height = 0;
    427   uint32_t shift_by = 0;
    428 
    429   std::bitset<16> crc_red = {};
    430   std::bitset<16> crc_green = {};
    431   std::bitset<16> crc_blue = {};
    432 
    433   switch (panel_bpp_) {
    434     case kDisplayBpp18:
    435       ramp_height = 64;
    436       ramp_width = 64;
    437       shift_by = 2;
    438       break;
    439     case kDisplayBpp24:
    440       ramp_height = 64;
    441       ramp_width = 256;
    442       break;
    443     case kDisplayBpp30:
    444       ramp_height = 32;
    445       ramp_width = 256;
    446       start_color_val = 0x180;
    447       break;
    448     default:
    449       return;
    450   }
    451 
    452   GetStride(format, aligned_width, &buffer_stride);
    453 
    454   for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
    455     uint32_t color_value = start_color_val;
    456     uint8_t *temp = buffer + (loop_height * buffer_stride);
    457 
    458     for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
    459       if (color_ramp == kColorRedRamp) {
    460         PixelCopy(color_value, 0, 0, 0, &temp);
    461         CalcCRC(color_value, &crc_red);
    462         CalcCRC(0, &crc_green);
    463         CalcCRC(0, &crc_blue);
    464       }
    465       if (color_ramp == kColorGreenRamp) {
    466         PixelCopy(0, color_value, 0, 0, &temp);
    467         CalcCRC(0, &crc_red);
    468         CalcCRC(color_value, &crc_green);
    469         CalcCRC(0, &crc_blue);
    470       }
    471       if (color_ramp == kColorBlueRamp) {
    472         PixelCopy(0, 0, color_value, 0, &temp);
    473         CalcCRC(0, &crc_red);
    474         CalcCRC(0, &crc_green);
    475         CalcCRC(color_value, &crc_blue);
    476       }
    477       if (color_ramp == kColorWhiteRamp) {
    478         PixelCopy(color_value, color_value, color_value, 0, &temp);
    479         CalcCRC(color_value, &crc_red);
    480         CalcCRC(color_value, &crc_green);
    481         CalcCRC(color_value, &crc_blue);
    482       }
    483 
    484       color_value = (start_color_val + (((loop_width + 1) % ramp_width) * step_size)) << shift_by;
    485     }
    486 
    487     if (panel_bpp_ == kDisplayBpp30 && ((loop_height + 1) % ramp_height) == 0) {
    488       if (start_color_val == 0x180) {
    489         start_color_val = 0;
    490         step_size = 4;
    491       } else {
    492         start_color_val = 0x180;
    493         step_size = 1;
    494         color_ramp = (color_ramp + 1) % 4;
    495       }
    496       continue;
    497     }
    498 
    499     if (((loop_height + 1) % ramp_height) == 0) {
    500       color_ramp = (color_ramp + 1) % 4;
    501     }
    502   }
    503 
    504   DLOGI("CRC red %x", crc_red.to_ulong());
    505   DLOGI("CRC green %x", crc_green.to_ulong());
    506   DLOGI("CRC blue %x", crc_blue.to_ulong());
    507 }
    508 
    509 void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
    510   uint32_t width = buffer_info_.buffer_config.width;
    511   uint32_t height = buffer_info_.buffer_config.height;
    512   LayerBufferFormat format = buffer_info_.buffer_config.format;
    513   uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
    514   uint32_t buffer_stride = 0;
    515   uint32_t bits_per_component = panel_bpp_ / 3;
    516   uint32_t max_color_val = (1 << bits_per_component) - 1;
    517 
    518   std::bitset<16> crc_red = {};
    519   std::bitset<16> crc_green = {};
    520   std::bitset<16> crc_blue = {};
    521 
    522   if (panel_bpp_ == kDisplayBpp18) {
    523     max_color_val <<= 2;
    524   }
    525 
    526   GetStride(format, aligned_width, &buffer_stride);
    527 
    528   for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
    529     uint32_t color = 0;
    530     uint8_t *temp = buffer + (loop_height * buffer_stride);
    531 
    532     for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
    533       if (color == kColorBlack) {
    534         PixelCopy(0, 0, 0, 0, &temp);
    535         CalcCRC(0, &crc_red);
    536         CalcCRC(0, &crc_green);
    537         CalcCRC(0, &crc_blue);
    538       }
    539       if (color == kColorWhite) {
    540         PixelCopy(max_color_val, max_color_val, max_color_val, 0, &temp);
    541         CalcCRC(max_color_val, &crc_red);
    542         CalcCRC(max_color_val, &crc_green);
    543         CalcCRC(max_color_val, &crc_blue);
    544       }
    545 
    546       color = (color + 1) % 2;
    547     }
    548   }
    549 
    550   DLOGI("CRC red %x", crc_red.to_ulong());
    551   DLOGI("CRC green %x", crc_green.to_ulong());
    552   DLOGI("CRC blue %x", crc_blue.to_ulong());
    553 }
    554 
    555 void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
    556   uint32_t width = buffer_info_.buffer_config.width;
    557   uint32_t height = buffer_info_.buffer_config.height;
    558   LayerBufferFormat format = buffer_info_.buffer_config.format;
    559   uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
    560   uint32_t buffer_stride = 0;
    561   uint32_t max_color_val = 0;
    562   uint32_t min_color_val = 0;
    563 
    564   std::bitset<16> crc_red = {};
    565   std::bitset<16> crc_green = {};
    566   std::bitset<16> crc_blue = {};
    567 
    568   switch (panel_bpp_) {
    569     case kDisplayBpp18:
    570       max_color_val = 63 << 2;  // CEA Dynamic range for 18bpp 0 - 63
    571       min_color_val = 0;
    572       break;
    573     case kDisplayBpp24:
    574       max_color_val = 235;  // CEA Dynamic range for 24bpp 16 - 235
    575       min_color_val = 16;
    576       break;
    577     case kDisplayBpp30:
    578       max_color_val = 940;  // CEA Dynamic range for 30bpp 64 - 940
    579       min_color_val = 64;
    580       break;
    581     default:
    582       return;
    583   }
    584 
    585   array<array<uint32_t, 3>, 8> colors = {{
    586     {{max_color_val, max_color_val, max_color_val}},  // White Color
    587     {{max_color_val, max_color_val, min_color_val}},  // Yellow Color
    588     {{min_color_val, max_color_val, max_color_val}},  // Cyan Color
    589     {{min_color_val, max_color_val, min_color_val}},  // Green Color
    590     {{max_color_val, min_color_val, max_color_val}},  // Megenta Color
    591     {{max_color_val, min_color_val, min_color_val}},  // Red Color
    592     {{min_color_val, min_color_val, max_color_val}},  // Blue Color
    593     {{min_color_val, min_color_val, min_color_val}},  // Black Color
    594   }};
    595 
    596   GetStride(format, aligned_width, &buffer_stride);
    597 
    598   for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
    599     uint32_t color = 0;
    600     uint8_t *temp = buffer + (loop_height * buffer_stride);
    601 
    602     for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
    603       PixelCopy(colors[color][0], colors[color][1], colors[color][2], 0, &temp);
    604       CalcCRC(colors[color][0], &crc_red);
    605       CalcCRC(colors[color][1], &crc_green);
    606       CalcCRC(colors[color][2], &crc_blue);
    607 
    608       if (((loop_width + 1) % 64) == 0) {
    609         color = (color + 1) % colors.size();
    610       }
    611     }
    612 
    613     if (((loop_height + 1) % 64) == 0) {
    614       std::reverse(colors.begin(), (colors.end() - 1));
    615     }
    616   }
    617 
    618   DLOGI("CRC red %x", crc_red.to_ulong());
    619   DLOGI("CRC green %x", crc_green.to_ulong());
    620   DLOGI("CRC blue %x", crc_blue.to_ulong());
    621 }
    622 
    623 int HWCDisplayExternalTest::InitLayer(Layer *layer) {
    624   uint32_t active_config = 0;
    625   DisplayConfigVariableInfo var_info = {};
    626 
    627   GetActiveDisplayConfig(&active_config);
    628 
    629   GetDisplayAttributesForConfig(INT32(active_config), &var_info);
    630 
    631   layer->flags.updating = 1;
    632   layer->src_rect = LayerRect(0, 0, var_info.x_pixels, var_info.y_pixels);
    633   layer->dst_rect = layer->src_rect;
    634   layer->frame_rate = var_info.fps;
    635   layer->blending = kBlendingPremultiplied;
    636 
    637   layer->input_buffer.unaligned_width = var_info.x_pixels;
    638   layer->input_buffer.unaligned_height = var_info.y_pixels;
    639   buffer_info_.buffer_config.format = kFormatRGBA8888;
    640 
    641   if (layer->composition != kCompositionGPUTarget) {
    642     buffer_info_.buffer_config.width = var_info.x_pixels;
    643     buffer_info_.buffer_config.height = var_info.y_pixels;
    644     switch (panel_bpp_) {
    645       case kDisplayBpp18:
    646       case kDisplayBpp24:
    647         buffer_info_.buffer_config.format = kFormatRGB888;
    648         break;
    649       case kDisplayBpp30:
    650         buffer_info_.buffer_config.format = kFormatRGBA1010102;
    651         break;
    652       default:
    653         DLOGW("panel bpp not supported %d", panel_bpp_);
    654         return -EINVAL;
    655     }
    656     buffer_info_.buffer_config.buffer_count = 1;
    657 
    658     int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
    659     if (ret != 0) {
    660       DLOGE("Buffer allocation failed. ret: %d", ret);
    661       return -ENOMEM;
    662     }
    663 
    664     ret = FillBuffer();
    665     if (ret != 0) {
    666       buffer_allocator_->FreeBuffer(&buffer_info_);
    667       return ret;
    668     }
    669 
    670     layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
    671     layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
    672     layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
    673     layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
    674     layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
    675     layer->input_buffer.format = buffer_info_.buffer_config.format;
    676 
    677     DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
    678           layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
    679           layer->input_buffer.size, layer->input_buffer.planes[0].fd,
    680           layer->input_buffer.planes[0].stride);
    681   }
    682 
    683   return 0;
    684 }
    685 
    686 int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
    687   if (layer->composition != kCompositionGPUTarget) {
    688     int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
    689     if (ret != 0) {
    690       DLOGE("Buffer deallocation failed. ret: %d", ret);
    691       return -ENOMEM;
    692     }
    693   }
    694 
    695   return 0;
    696 }
    697 
    698 int HWCDisplayExternalTest::CreateLayerStack() {
    699   for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
    700     Layer *layer = new Layer();
    701 
    702     if (i == kTestLayerCnt) {
    703       layer->composition = kCompositionGPUTarget;
    704     }
    705 
    706     int ret = InitLayer(layer);
    707     if (ret != 0) {
    708       delete layer;
    709       return ret;
    710     }
    711     layer_stack_.layers.push_back(layer);
    712   }
    713 
    714   return 0;
    715 }
    716 
    717 int HWCDisplayExternalTest::DestroyLayerStack() {
    718   for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
    719     Layer *layer = layer_stack_.layers.at(i);
    720     int ret = DeinitLayer(layer);
    721     if (ret != 0) {
    722       return ret;
    723     }
    724 
    725     delete layer;
    726   }
    727 
    728   layer_stack_.layers = {};
    729 
    730   return 0;
    731 }
    732 
    733 int HWCDisplayExternalTest::PostCommit(hwc_display_contents_1_t *content_list) {
    734   int status = 0;
    735 
    736   // Do no call flush on errors, if a successful buffer is never submitted.
    737   if (flush_ && flush_on_error_) {
    738     display_intf_->Flush();
    739   }
    740 
    741   if (!flush_) {
    742     for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
    743       Layer *layer = layer_stack_.layers.at(i);
    744       LayerBuffer &layer_buffer = layer->input_buffer;
    745 
    746       close(layer_buffer.release_fence_fd);
    747       layer_buffer.release_fence_fd = -1;
    748     }
    749 
    750     close(layer_stack_.retire_fence_fd);
    751     layer_stack_.retire_fence_fd = -1;
    752     content_list->retireFenceFd = -1;
    753   }
    754 
    755   flush_ = false;
    756 
    757   return status;
    758 }
    759 
    760 }  // namespace sdm
    761 
    762