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