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