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