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 if (error == kErrorShutDown) {
180 shutdown_pending_ = true;
181 status = HWC2::Error::Unsupported;
182 } else if (error == kErrorNotValidated) {
183 status = HWC2::Error::NotValidated;
184 } else if (error != kErrorPermission) {
185 DLOGE("Commit failed. Error = %d", error);
186 // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
187 // so that previous buffer and fences are released, and override the error.
188 flush_ = true;
189 }
190 }
191 PostCommit(out_retire_fence);
192 return status;
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, FLOAT(var_info.x_pixels),
629 FLOAT(var_info.y_pixels));
630 layer->dst_rect = layer->src_rect;
631 layer->frame_rate = var_info.fps;
632 layer->blending = kBlendingPremultiplied;
633
634 layer->input_buffer.unaligned_width = var_info.x_pixels;
635 layer->input_buffer.unaligned_height = var_info.y_pixels;
636 buffer_info_.buffer_config.format = kFormatRGBA8888;
637
638 if (layer->composition != kCompositionGPUTarget) {
639 buffer_info_.buffer_config.width = var_info.x_pixels;
640 buffer_info_.buffer_config.height = var_info.y_pixels;
641 switch (panel_bpp_) {
642 case kDisplayBpp18:
643 case kDisplayBpp24:
644 buffer_info_.buffer_config.format = kFormatRGB888;
645 break;
646 case kDisplayBpp30:
647 buffer_info_.buffer_config.format = kFormatRGBA1010102;
648 break;
649 default:
650 DLOGW("panel bpp not supported %d", panel_bpp_);
651 return -EINVAL;
652 }
653 buffer_info_.buffer_config.buffer_count = 1;
654
655 int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
656 if (ret != 0) {
657 DLOGE("Buffer allocation failed. ret: %d", ret);
658 return -ENOMEM;
659 }
660
661 ret = FillBuffer();
662 if (ret != 0) {
663 buffer_allocator_->FreeBuffer(&buffer_info_);
664 return ret;
665 }
666
667 layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
668 layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
669 layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
670 layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
671 layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
672 layer->input_buffer.format = buffer_info_.buffer_config.format;
673
674 DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
675 layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
676 layer->input_buffer.size, layer->input_buffer.planes[0].fd,
677 layer->input_buffer.planes[0].stride);
678 }
679
680 return 0;
681 }
682
DeinitLayer(Layer * layer)683 int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
684 if (layer->composition != kCompositionGPUTarget) {
685 int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
686 if (ret != 0) {
687 DLOGE("Buffer deallocation failed. ret: %d", ret);
688 return -ENOMEM;
689 }
690 }
691
692 return 0;
693 }
694
CreateLayerStack()695 int HWCDisplayExternalTest::CreateLayerStack() {
696 for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
697 Layer *layer = new Layer();
698
699 if (i == kTestLayerCnt) {
700 layer->composition = kCompositionGPUTarget;
701 }
702 DLOGE("External :: CreateLayerStack %d", i);
703 int ret = InitLayer(layer);
704 if (ret != 0) {
705 delete layer;
706 return ret;
707 }
708 layer_stack_.layers.push_back(layer);
709 }
710
711 return 0;
712 }
713
DestroyLayerStack()714 int HWCDisplayExternalTest::DestroyLayerStack() {
715 for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
716 Layer *layer = layer_stack_.layers.at(i);
717 int ret = DeinitLayer(layer);
718 if (ret != 0) {
719 return ret;
720 }
721 delete layer;
722 }
723 layer_stack_.layers = {};
724
725 return 0;
726 }
727
PostCommit(int32_t * out_retire_fence)728 HWC2::Error HWCDisplayExternalTest::PostCommit(int32_t *out_retire_fence) {
729 auto status = HWC2::Error::None;
730 // Do no call flush on errors, if a successful buffer is never submitted.
731 if (flush_ && flush_on_error_) {
732 display_intf_->Flush();
733 }
734 if (!flush_) {
735 for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
736 Layer *layer = layer_stack_.layers.at(i);
737 LayerBuffer &layer_buffer = layer->input_buffer;
738
739 close(layer_buffer.release_fence_fd);
740 layer_buffer.release_fence_fd = -1;
741 }
742 close(layer_stack_.retire_fence_fd);
743 layer_stack_.retire_fence_fd = -1;
744 *out_retire_fence = -1;
745 }
746 flush_ = false;
747
748 return status;
749 }
750
751 } // namespace sdm
752
753