1 /*
2 * Copyright (c) 2014 - 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 <sync/sync.h>
32 #include <utils/constants.h>
33 #include <utils/debug.h>
34 #include <stdarg.h>
35 #include <sys/mman.h>
36
37 #include <map>
38 #include <string>
39 #include <vector>
40
41 #include "hwc_display_primary.h"
42 #include "hwc_debugger.h"
43
44 #define __CLASS__ "HWCDisplayPrimary"
45
46 namespace sdm {
47
Create(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,qService::QService * qservice,HWCDisplay ** hwc_display)48 int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
49 HWCCallbacks *callbacks, qService::QService *qservice,
50 HWCDisplay **hwc_display) {
51 int status = 0;
52 uint32_t primary_width = 0;
53 uint32_t primary_height = 0;
54
55 HWCDisplay *hwc_display_primary =
56 new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
57 status = hwc_display_primary->Init();
58 if (status) {
59 delete hwc_display_primary;
60 return status;
61 }
62
63 hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
64 int width = 0, height = 0;
65 HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
66 HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
67 if (width > 0 && height > 0) {
68 primary_width = UINT32(width);
69 primary_height = UINT32(height);
70 }
71
72 status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
73 if (status) {
74 Destroy(hwc_display_primary);
75 return status;
76 }
77
78 *hwc_display = hwc_display_primary;
79
80 return status;
81 }
82
Destroy(HWCDisplay * hwc_display)83 void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
84 hwc_display->Deinit();
85 delete hwc_display;
86 }
87
HWCDisplayPrimary(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,qService::QService * qservice)88 HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
89 HWCCallbacks *callbacks, qService::QService *qservice)
90 : HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
91 DISPLAY_CLASS_PRIMARY, buffer_allocator),
92 buffer_allocator_(buffer_allocator),
93 cpu_hint_(NULL) {
94 }
95
Init()96 int HWCDisplayPrimary::Init() {
97 cpu_hint_ = new CPUHint();
98 if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
99 delete cpu_hint_;
100 cpu_hint_ = NULL;
101 }
102
103 use_metadata_refresh_rate_ = true;
104 int disable_metadata_dynfps = 0;
105 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
106 if (disable_metadata_dynfps) {
107 use_metadata_refresh_rate_ = false;
108 }
109
110 int status = HWCDisplay::Init();
111 if (status) {
112 return status;
113 }
114 color_mode_ = new HWCColorMode(display_intf_);
115 color_mode_->Init();
116 HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE, &default_mode_status_);
117
118 return status;
119 }
120
ProcessBootAnimCompleted()121 void HWCDisplayPrimary::ProcessBootAnimCompleted() {
122 uint32_t numBootUpLayers = 0;
123 // TODO(user): Remove this hack
124
125 numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
126
127 if (numBootUpLayers == 0) {
128 numBootUpLayers = 2;
129 }
130 /* All other checks namely "init.svc.bootanim" or
131 * HWC_GEOMETRY_CHANGED fail in correctly identifying the
132 * exact bootup transition to homescreen
133 */
134 char property[PROPERTY_VALUE_MAX];
135 bool isEncrypted = false;
136 bool main_class_services_started = false;
137 property_get("ro.crypto.state", property, "unencrypted");
138 if (!strcmp(property, "encrypted")) {
139 property_get("ro.crypto.type", property, "block");
140 if (!strcmp(property, "block")) {
141 isEncrypted = true;
142 property_get("vold.decrypt", property, "");
143 if (!strcmp(property, "trigger_restart_framework")) {
144 main_class_services_started = true;
145 }
146 }
147 }
148
149 if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
150 (layer_set_.size() > numBootUpLayers)) {
151 DLOGI("Applying default mode");
152 boot_animation_completed_ = true;
153 // Applying default mode after bootanimation is finished And
154 // If Data is Encrypted, it is ready for access.
155 if (display_intf_) {
156 display_intf_->ApplyDefaultDisplayMode();
157 RestoreColorTransform();
158 }
159 }
160 }
161
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)162 HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
163 auto status = HWC2::Error::None;
164 DisplayError error = kErrorNone;
165
166 if (default_mode_status_ && !boot_animation_completed_) {
167 ProcessBootAnimCompleted();
168 }
169
170 if (display_paused_) {
171 MarkLayersForGPUBypass();
172 return status;
173 }
174
175
176 // Fill in the remaining blanks in the layers and add them to the SDM layerstack
177 BuildLayerStack();
178
179 if (color_tranform_failed_) {
180 // Must fall back to client composition
181 MarkLayersForClientComposition();
182 }
183
184 // Checks and replaces layer stack for solid fill
185 SolidFillPrepare();
186
187 bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
188
189 if (frame_capture_buffer_queued_ || pending_output_dump) {
190 // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
191 // here in a subsequent draw round.
192 layer_stack_.output_buffer = &output_buffer_;
193 layer_stack_.flags.post_processed_output = post_processed_output_;
194 }
195
196 uint32_t num_updating_layers = GetUpdatingLayersCount();
197 bool one_updating_layer = (num_updating_layers == 1);
198 if (num_updating_layers != 0) {
199 ToggleCPUHint(one_updating_layer);
200 }
201
202 uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
203 if (current_refresh_rate_ != refresh_rate || handle_idle_timeout_) {
204 error = display_intf_->SetRefreshRate(refresh_rate);
205 }
206
207 if (error == kErrorNone) {
208 // On success, set current refresh rate to new refresh rate
209 current_refresh_rate_ = refresh_rate;
210 }
211
212 if (handle_idle_timeout_) {
213 handle_idle_timeout_ = false;
214 }
215
216 if (layer_set_.empty()) {
217 // Avoid flush for Command mode panel.
218 DisplayConfigFixedInfo display_config;
219 display_intf_->GetConfig(&display_config);
220 flush_ = !display_config.is_cmdmode;
221 return status;
222 }
223
224 status = PrepareLayerStack(out_num_types, out_num_requests);
225 return status;
226 }
227
Present(int32_t * out_retire_fence)228 HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
229 auto status = HWC2::Error::None;
230 if (display_paused_) {
231 // TODO(user): From old HWC implementation
232 // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
233 // Revisit this when validating display_paused
234 DisplayError error = display_intf_->Flush();
235 if (error != kErrorNone) {
236 DLOGE("Flush failed. Error = %d", error);
237 }
238 } else {
239 status = HWCDisplay::CommitLayerStack();
240 if (status == HWC2::Error::None) {
241 HandleFrameOutput();
242 SolidFillCommit();
243 status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
244 }
245 }
246
247 CloseAcquireFds();
248 return status;
249 }
250
GetColorModes(uint32_t * out_num_modes,android_color_mode_t * out_modes)251 HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
252 android_color_mode_t *out_modes) {
253 if (out_modes == nullptr) {
254 *out_num_modes = color_mode_->GetColorModeCount();
255 } else {
256 color_mode_->GetColorModes(out_num_modes, out_modes);
257 }
258
259 return HWC2::Error::None;
260 }
261
SetColorMode(android_color_mode_t mode)262 HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
263 auto status = color_mode_->SetColorMode(mode);
264 if (status != HWC2::Error::None) {
265 DLOGE("failed for mode = %d", mode);
266 return status;
267 }
268
269 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
270 validated_.reset();
271
272 return status;
273 }
274
RestoreColorTransform()275 HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
276 auto status = color_mode_->RestoreColorTransform();
277 if (status != HWC2::Error::None) {
278 DLOGE("failed to RestoreColorTransform");
279 return status;
280 }
281
282 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
283
284 return status;
285 }
286
SetColorTransform(const float * matrix,android_color_transform_t hint)287 HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
288 android_color_transform_t hint) {
289 if (!matrix) {
290 return HWC2::Error::BadParameter;
291 }
292
293 auto status = color_mode_->SetColorTransform(matrix, hint);
294 if ((hint != HAL_COLOR_TRANSFORM_IDENTITY) && (status != HWC2::Error::None)) {
295 DLOGE("failed for hint = %d", hint);
296 color_tranform_failed_ = true;
297 return status;
298 }
299
300 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
301 color_tranform_failed_ = false;
302 validated_.reset();
303
304 return status;
305 }
306
Perform(uint32_t operation,...)307 int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
308 va_list args;
309 va_start(args, operation);
310 int val = 0;
311 LayerRect *rect = NULL;
312
313 switch (operation) {
314 case SET_METADATA_DYN_REFRESH_RATE:
315 val = va_arg(args, int32_t);
316 SetMetaDataRefreshRateFlag(val);
317 break;
318 case SET_BINDER_DYN_REFRESH_RATE:
319 val = va_arg(args, int32_t);
320 ForceRefreshRate(UINT32(val));
321 break;
322 case SET_DISPLAY_MODE:
323 val = va_arg(args, int32_t);
324 SetDisplayMode(UINT32(val));
325 break;
326 case SET_QDCM_SOLID_FILL_INFO:
327 val = va_arg(args, int32_t);
328 SetQDCMSolidFillInfo(true, UINT32(val));
329 break;
330 case UNSET_QDCM_SOLID_FILL_INFO:
331 val = va_arg(args, int32_t);
332 SetQDCMSolidFillInfo(false, UINT32(val));
333 break;
334 case SET_QDCM_SOLID_FILL_RECT:
335 rect = va_arg(args, LayerRect*);
336 solid_fill_rect_ = *rect;
337 break;
338 default:
339 DLOGW("Invalid operation %d", operation);
340 va_end(args);
341 return -EINVAL;
342 }
343 va_end(args);
344 validated_.reset();
345
346 return 0;
347 }
348
SetDisplayMode(uint32_t mode)349 DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
350 DisplayError error = kErrorNone;
351
352 if (display_intf_) {
353 error = display_intf_->SetDisplayMode(mode);
354 }
355
356 return error;
357 }
358
SetMetaDataRefreshRateFlag(bool enable)359 void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
360 int disable_metadata_dynfps = 0;
361
362 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
363 if (disable_metadata_dynfps) {
364 return;
365 }
366 use_metadata_refresh_rate_ = enable;
367 }
368
SetQDCMSolidFillInfo(bool enable,uint32_t color)369 void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
370 solid_fill_enable_ = enable;
371 solid_fill_color_ = color;
372 }
373
ToggleCPUHint(bool set)374 void HWCDisplayPrimary::ToggleCPUHint(bool set) {
375 if (!cpu_hint_) {
376 return;
377 }
378
379 if (set) {
380 cpu_hint_->Set();
381 } else {
382 cpu_hint_->Reset();
383 }
384 }
385
SetSecureDisplay(bool secure_display_active)386 void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
387 if (secure_display_active_ != secure_display_active) {
388 // Skip Prepare and call Flush for null commit
389 DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
390 secure_display_active);
391 secure_display_active_ = secure_display_active;
392
393 // Avoid flush for Command mode panel.
394 DisplayConfigFixedInfo display_config;
395 display_intf_->GetConfig(&display_config);
396 skip_prepare_ = !display_config.is_cmdmode;
397 }
398 }
399
ForceRefreshRate(uint32_t refresh_rate)400 void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
401 if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
402 force_refresh_rate_ == refresh_rate) {
403 // Cannot honor force refresh rate, as its beyond the range or new request is same
404 return;
405 }
406
407 force_refresh_rate_ = refresh_rate;
408
409 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
410
411 return;
412 }
413
GetOptimalRefreshRate(bool one_updating_layer)414 uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
415 if (force_refresh_rate_) {
416 return force_refresh_rate_;
417 } else if (handle_idle_timeout_) {
418 return min_refresh_rate_;
419 } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
420 return metadata_refresh_rate_;
421 }
422
423 return max_refresh_rate_;
424 }
425
Refresh()426 DisplayError HWCDisplayPrimary::Refresh() {
427 DisplayError error = kErrorNone;
428
429 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
430 handle_idle_timeout_ = true;
431
432 return error;
433 }
434
SetIdleTimeoutMs(uint32_t timeout_ms)435 void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
436 display_intf_->SetIdleTimeoutMs(timeout_ms);
437 validated_.reset();
438 }
439
SetLayerBuffer(const BufferInfo & output_buffer_info,LayerBuffer * output_buffer)440 static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
441 const BufferConfig& buffer_config = output_buffer_info.buffer_config;
442 const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
443
444 output_buffer->width = alloc_buffer_info.aligned_width;
445 output_buffer->height = alloc_buffer_info.aligned_height;
446 output_buffer->unaligned_width = buffer_config.width;
447 output_buffer->unaligned_height = buffer_config.height;
448 output_buffer->format = buffer_config.format;
449 output_buffer->planes[0].fd = alloc_buffer_info.fd;
450 output_buffer->planes[0].stride = alloc_buffer_info.stride;
451 }
452
HandleFrameOutput()453 void HWCDisplayPrimary::HandleFrameOutput() {
454 if (frame_capture_buffer_queued_) {
455 HandleFrameCapture();
456 } else if (dump_output_to_file_) {
457 HandleFrameDump();
458 }
459 }
460
HandleFrameCapture()461 void HWCDisplayPrimary::HandleFrameCapture() {
462 if (output_buffer_.release_fence_fd >= 0) {
463 frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
464 ::close(output_buffer_.release_fence_fd);
465 output_buffer_.release_fence_fd = -1;
466 }
467
468 frame_capture_buffer_queued_ = false;
469 post_processed_output_ = false;
470 output_buffer_ = {};
471 }
472
HandleFrameDump()473 void HWCDisplayPrimary::HandleFrameDump() {
474 if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
475 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
476 ::close(output_buffer_.release_fence_fd);
477 output_buffer_.release_fence_fd = -1;
478 if (ret < 0) {
479 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
480 } else {
481 DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
482 }
483 }
484
485 if (0 == dump_frame_count_) {
486 dump_output_to_file_ = false;
487 // Unmap and Free buffer
488 if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
489 DLOGE("unmap failed with err %d", errno);
490 }
491 if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
492 DLOGE("FreeBuffer failed");
493 }
494
495 post_processed_output_ = false;
496 output_buffer_ = {};
497 output_buffer_info_ = {};
498 output_buffer_base_ = nullptr;
499 }
500 }
501
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type)502 void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
503 HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
504 dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
505 DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
506
507 if (!count || !dump_output_to_file_) {
508 return;
509 }
510
511 // Allocate and map output buffer
512 output_buffer_info_ = {};
513 // Since we dump DSPP output use Panel resolution.
514 GetPanelResolution(&output_buffer_info_.buffer_config.width,
515 &output_buffer_info_.buffer_config.height);
516 output_buffer_info_.buffer_config.format = kFormatRGB888;
517 output_buffer_info_.buffer_config.buffer_count = 1;
518 if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
519 DLOGE("Buffer allocation failed");
520 output_buffer_info_ = {};
521 return;
522 }
523
524 void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
525 MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
526
527 if (buffer == MAP_FAILED) {
528 DLOGE("mmap failed with err %d", errno);
529 buffer_allocator_->FreeBuffer(&output_buffer_info_);
530 output_buffer_info_ = {};
531 return;
532 }
533
534 output_buffer_base_ = buffer;
535 post_processed_output_ = true;
536 DisablePartialUpdateOneFrame();
537 validated_.reset();
538 }
539
FrameCaptureAsync(const BufferInfo & output_buffer_info,bool post_processed_output)540 int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
541 bool post_processed_output) {
542 // Note: This function is called in context of a binder thread and a lock is already held
543 if (output_buffer_info.alloc_buffer_info.fd < 0) {
544 DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
545 return -1;
546 }
547
548 auto panel_width = 0u;
549 auto panel_height = 0u;
550 auto fb_width = 0u;
551 auto fb_height = 0u;
552
553 GetPanelResolution(&panel_width, &panel_height);
554 GetFrameBufferResolution(&fb_width, &fb_height);
555
556 if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
557 output_buffer_info.buffer_config.height < panel_height)) {
558 DLOGE("Buffer dimensions should not be less than panel resolution");
559 return -1;
560 } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
561 output_buffer_info.buffer_config.height < fb_height)) {
562 DLOGE("Buffer dimensions should not be less than FB resolution");
563 return -1;
564 }
565
566 SetLayerBuffer(output_buffer_info, &output_buffer_);
567 post_processed_output_ = post_processed_output;
568 frame_capture_buffer_queued_ = true;
569 // Status is only cleared on a new call to dump and remains valid otherwise
570 frame_capture_status_ = -EAGAIN;
571 DisablePartialUpdateOneFrame();
572
573 return 0;
574 }
575
SetDetailEnhancerConfig(const DisplayDetailEnhancerData & de_data)576 DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
577 (const DisplayDetailEnhancerData &de_data) {
578 DisplayError error = kErrorNotSupported;
579
580 if (display_intf_) {
581 error = display_intf_->SetDetailEnhancerData(de_data);
582 validated_.reset();
583 }
584 return error;
585 }
586
ControlPartialUpdate(bool enable,uint32_t * pending)587 DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
588 DisplayError error = kErrorNone;
589
590 if (display_intf_) {
591 error = display_intf_->ControlPartialUpdate(enable, pending);
592 validated_.reset();
593 }
594
595 return error;
596 }
597
DisablePartialUpdateOneFrame()598 DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
599 DisplayError error = kErrorNone;
600
601 if (display_intf_) {
602 error = display_intf_->DisablePartialUpdateOneFrame();
603 validated_.reset();
604 }
605
606 return error;
607 }
608
609
SetMixerResolution(uint32_t width,uint32_t height)610 DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
611 DisplayError error = display_intf_->SetMixerResolution(width, height);
612 validated_.reset();
613 return error;
614 }
615
GetMixerResolution(uint32_t * width,uint32_t * height)616 DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
617 return display_intf_->GetMixerResolution(width, height);
618 }
619
620 } // namespace sdm
621