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 
Create(CoreInterface * core_intf,hwc_procs_t const ** hwc_procs,qService::QService * qservice,uint32_t panel_bpp,uint32_t pattern_type,HWCDisplay ** hwc_display)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 
Destroy(HWCDisplay * hwc_display)70 void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
71   static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
72 
73   delete hwc_display;
74 }
75 
HWCDisplayExternalTest(CoreInterface * core_intf,hwc_procs_t const ** hwc_procs,qService::QService * qservice,uint32_t panel_bpp,uint32_t pattern_type)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 
Init()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 
Deinit()116 int HWCDisplayExternalTest::Deinit() {
117   DestroyLayerStack();
118 
119   delete buffer_allocator_;
120   buffer_allocator_ = NULL;
121 
122   return HWCDisplay::Deinit();
123 }
124 
125 
Prepare(hwc_display_contents_1_t * content_list)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 
Commit(hwc_display_contents_1_t * content_list)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 
SetSecureDisplay(bool secure_display_active,bool force_flush)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 
Perform(uint32_t operation,...)215 int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
216   return 0;
217 }
218 
DumpInputBuffer()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 
CalcCRC(uint32_t color_val,std::bitset<16> * crc_data)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 
FillBuffer()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 
GetStride(LayerBufferFormat format,uint32_t width,uint32_t * stride)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 
PixelCopy(uint32_t red,uint32_t green,uint32_t blue,uint32_t alpha,uint8_t ** buffer)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 
GenerateColorRamp(uint8_t * buffer)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 
GenerateBWVertical(uint8_t * buffer)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 
GenerateColorSquare(uint8_t * buffer)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 
InitLayer(Layer * layer)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 
DeinitLayer(Layer * layer)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 
CreateLayerStack()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 
DestroyLayerStack()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 
PostCommit(hwc_display_contents_1_t * content_list)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