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