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