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