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