1/*
2 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#include <cutils/properties.h>
21#include <errno.h>
22#include <math.h>
23#include <sync/sync.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <utils/constants.h>
27#include <utils/debug.h>
28#include <utils/formats.h>
29#include <utils/rect.h>
30#include <qd_utils.h>
31
32#include <algorithm>
33#include <iomanip>
34#include <map>
35#include <sstream>
36#include <string>
37#include <utility>
38#include <vector>
39
40#include "hwc_display.h"
41#include "hwc_debugger.h"
42#include "blit_engine_c2d.h"
43#include "hwc_tonemapper.h"
44
45#ifndef USE_GRALLOC1
46#include <gr.h>
47#endif
48
49#ifdef QTI_BSP
50#include <hardware/display_defs.h>
51#endif
52
53#define __CLASS__ "HWCDisplay"
54
55namespace sdm {
56
57// This weight function is needed because the color primaries are not sorted by gamut size
58static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
59  int weight = 10;
60  int lp1 = p1, lp2 = p2;
61  // TODO(user) add weight to other wide gamut primaries
62  if (lp1 == ColorPrimaries_BT2020) {
63    lp1 *= weight;
64  }
65  if (lp1 == ColorPrimaries_BT2020) {
66    lp2 *= weight;
67  }
68  if (lp1 >= lp2) {
69    return p1;
70  } else {
71    return p2;
72  }
73}
74
75HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
76
77HWC2::Error HWCColorMode::Init() {
78  PopulateColorModes();
79  return ApplyDefaultColorMode();
80}
81
82HWC2::Error HWCColorMode::DeInit() {
83  color_mode_transform_map_.clear();
84  return HWC2::Error::None;
85}
86
87uint32_t HWCColorMode::GetColorModeCount() {
88  uint32_t count = UINT32(color_mode_transform_map_.size());
89  DLOGI("Supported color mode count = %d", count);
90
91  return std::max(1U, count);
92}
93
94HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
95                                        android_color_mode_t *out_modes) {
96  auto it = color_mode_transform_map_.begin();
97  for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
98    out_modes[i] = it->first;
99    DLOGI("Supports color mode[%d] = %d", i, it->first);
100  }
101  *out_num_modes = UINT32(color_mode_transform_map_.size());
102  return HWC2::Error::None;
103}
104
105HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
106  // first mode in 2D matrix is the mode (identity)
107  if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
108    DLOGE("Could not find mode: %d", mode);
109    return HWC2::Error::BadParameter;
110  }
111  auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
112  if (status != HWC2::Error::None) {
113    DLOGE("failed for mode = %d", mode);
114  }
115
116  return status;
117}
118
119HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
120  DLOGI("Applying mode: %d", color_mode_id);
121  DisplayError error = display_intf_->SetColorModeById(color_mode_id);
122  if (error != kErrorNone) {
123    return HWC2::Error::BadParameter;
124  }
125  return HWC2::Error::None;
126}
127
128HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
129  if (!matrix) {
130    return HWC2::Error::BadParameter;
131  }
132
133  double color_matrix[kColorTransformMatrixCount] = {0};
134  CopyColorTransformMatrix(matrix, color_matrix);
135
136  auto status = HandleColorModeTransform(current_color_mode_, hint, color_matrix);
137  if (status != HWC2::Error::None) {
138    DLOGE("failed for hint = %d", hint);
139  }
140
141  return status;
142}
143
144HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
145                                                   android_color_transform_t hint,
146                                                   const double *matrix) {
147  android_color_transform_t transform_hint = hint;
148  std::string color_mode_transform;
149  bool use_matrix = false;
150  if (hint != HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) {
151    // if the mode + transfrom request from HWC matches one mode in SDM, set that
152    if (color_mode_transform.empty()) {
153      transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
154      use_matrix = true;
155    } else {
156      color_mode_transform = color_mode_transform_map_[mode][hint];
157    }
158  } else {
159    use_matrix = true;
160    transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
161  }
162
163  // if the mode count is 1, then only native mode is supported, so just apply matrix w/o
164  // setting mode
165  if (color_mode_transform_map_.size() > 1U) {
166    color_mode_transform = color_mode_transform_map_[mode][transform_hint];
167    DisplayError error = display_intf_->SetColorMode(color_mode_transform);
168    if (error != kErrorNone) {
169      DLOGE("Failed to set color_mode  = %d transform_hint = %d", mode, hint);
170      // failure to force client composition
171      return HWC2::Error::Unsupported;
172    }
173  }
174
175  if (use_matrix) {
176    DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, matrix);
177    if (error != kErrorNone) {
178      DLOGE("Failed to set Color Transform Matrix");
179      // failure to force client composition
180      return HWC2::Error::Unsupported;
181    }
182  }
183
184  current_color_mode_ = mode;
185  current_color_transform_ = hint;
186  CopyColorTransformMatrix(matrix, color_matrix_);
187  DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
188
189  return HWC2::Error::None;
190}
191
192void HWCColorMode::PopulateColorModes() {
193  uint32_t color_mode_count = 0;
194  // SDM returns modes which is string combination of mode + transform.
195  DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
196  if (error != kErrorNone || (color_mode_count == 0)) {
197    DLOGW("GetColorModeCount failed, use native color mode");
198    PopulateTransform(HAL_COLOR_MODE_NATIVE, "native", "identity");
199    return;
200  }
201
202  DLOGV_IF(kTagQDCM, "Color Modes supported count = %d", color_mode_count);
203
204  const std::string color_transform = "identity";
205  std::vector<std::string> color_modes(color_mode_count);
206  error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
207  for (uint32_t i = 0; i < color_mode_count; i++) {
208    std::string &mode_string = color_modes.at(i);
209    DLOGV_IF(kTagQDCM, "Color Mode[%d] = %s", i, mode_string.c_str());
210    AttrVal attr;
211    error = display_intf_->GetColorModeAttr(mode_string, &attr);
212    if (!attr.empty()) {
213      std::string color_gamut, dynamic_range, pic_quality;
214      for (auto &it : attr) {
215        if (it.first.find(kColorGamutAttribute) != std::string::npos) {
216          color_gamut = it.second;
217        } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
218          dynamic_range = it.second;
219        } else if (it.first.find(kPictureQualityAttribute) != std::string::npos) {
220          pic_quality = it.second;
221        }
222      }
223      if (dynamic_range == kHdr) {
224        continue;
225      }
226      if ((color_gamut == kNative) &&
227          (pic_quality.empty() || pic_quality == kStandard)) {
228        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, color_transform);
229      } else if ((color_gamut == kSrgb) &&
230                 (pic_quality.empty() || pic_quality == kStandard)) {
231        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, color_transform);
232      } else if ((color_gamut == kDcip3) &&
233                 (pic_quality.empty() || pic_quality == kStandard)) {
234        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, color_transform);
235      } else if ((color_gamut == kDisplayP3) &&
236                 (pic_quality.empty() || pic_quality == kStandard)) {
237        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
238      }
239    } else {
240      if (mode_string.find("hal_native") != std::string::npos) {
241        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, mode_string);
242      } else if (mode_string.find("hal_srgb") != std::string::npos) {
243        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, mode_string);
244      } else if (mode_string.find("hal_adobe") != std::string::npos) {
245        PopulateTransform(HAL_COLOR_MODE_ADOBE_RGB, mode_string, mode_string);
246      } else if (mode_string.find("hal_dci_p3") != std::string::npos) {
247        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, mode_string);
248      } else if (mode_string.find("hal_display_p3") != std::string::npos) {
249        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, mode_string);
250      }
251    }
252  }
253}
254
255void HWCColorMode::PopulateTransform(const android_color_mode_t &mode,
256                                     const std::string &color_mode,
257                                     const std::string &color_transform) {
258  // TODO(user): Check the substring from QDCM
259  if (color_transform.find("identity") != std::string::npos) {
260    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
261  } else if (color_transform.find("arbitrary") != std::string::npos) {
262    // no color mode for arbitrary
263  } else if (color_transform.find("inverse") != std::string::npos) {
264    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_VALUE_INVERSE] = color_mode;
265  } else if (color_transform.find("grayscale") != std::string::npos) {
266    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_GRAYSCALE] = color_mode;
267  } else if (color_transform.find("correct_protonopia") != std::string::npos) {
268    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA] = color_mode;
269  } else if (color_transform.find("correct_deuteranopia") != std::string::npos) {
270    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA] = color_mode;
271  } else if (color_transform.find("correct_tritanopia") != std::string::npos) {
272    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA] = color_mode;
273  } else {
274    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
275  }
276}
277
278HWC2::Error HWCColorMode::ApplyDefaultColorMode() {
279  android_color_mode_t color_mode = HAL_COLOR_MODE_NATIVE;
280  if (color_mode_transform_map_.size() == 1U) {
281    color_mode = color_mode_transform_map_.begin()->first;
282  } else if (color_mode_transform_map_.size() > 1U) {
283    std::string default_color_mode;
284    bool found = false;
285    DisplayError error = display_intf_->GetDefaultColorMode(&default_color_mode);
286    if (error == kErrorNone) {
287      // get the default mode corresponding android_color_mode_t
288      for (auto &it_mode : color_mode_transform_map_) {
289        for (auto &it : it_mode.second) {
290          if (it.second == default_color_mode) {
291            found = true;
292            break;
293          }
294        }
295        if (found) {
296          color_mode = it_mode.first;
297          break;
298        }
299      }
300    }
301
302    // return the first andrid_color_mode_t when we encouter if not found
303    if (!found) {
304      color_mode = color_mode_transform_map_.begin()->first;
305    }
306  }
307  return SetColorMode(color_mode);
308}
309
310void HWCColorMode::Dump(std::ostringstream* os) {
311  *os << "color modes supported: ";
312  for (auto it : color_mode_transform_map_) {
313    *os << it.first <<" ";
314  }
315  *os << "current mode: " << current_color_mode_ << std::endl;
316  *os << "current transform: ";
317  for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
318    if (i % 4 == 0) {
319     *os << std::endl;
320    }
321    *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
322        << color_matrix_[i] << " ";
323  }
324  *os << std::endl;
325}
326
327HWCDisplay::HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type,
328                       hwc2_display_t id, bool needs_blit, qService::QService *qservice,
329                       DisplayClass display_class, BufferAllocator *buffer_allocator)
330    : core_intf_(core_intf),
331      callbacks_(callbacks),
332      type_(type),
333      id_(id),
334      needs_blit_(needs_blit),
335      qservice_(qservice),
336      display_class_(display_class) {
337  buffer_allocator_ = static_cast<HWCBufferAllocator *>(buffer_allocator);
338}
339
340int HWCDisplay::Init() {
341  DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
342  if (error != kErrorNone) {
343    DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p", error,
344          type_, this, &display_intf_);
345    return -EINVAL;
346  }
347
348  HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
349  if (disable_hdr_handling_) {
350    DLOGI("HDR Handling disabled");
351  }
352
353  int property_swap_interval = 1;
354  HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
355  if (property_swap_interval == 0) {
356    swap_interval_zero_ = true;
357  }
358
359  client_target_ = new HWCLayer(id_, buffer_allocator_);
360
361  int blit_enabled = 0;
362  HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
363  if (needs_blit_ && blit_enabled) {
364    // TODO(user): Add blit engine when needed
365  }
366
367  tone_mapper_ = new HWCToneMapper(buffer_allocator_);
368
369  display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
370  current_refresh_rate_ = max_refresh_rate_;
371  DLOGI("Display created with id: %d", id_);
372  return 0;
373}
374
375int HWCDisplay::Deinit() {
376  DisplayError error = core_intf_->DestroyDisplay(display_intf_);
377  if (error != kErrorNone) {
378    DLOGE("Display destroy failed. Error = %d", error);
379    return -EINVAL;
380  }
381
382  delete client_target_;
383
384  if (color_mode_) {
385    color_mode_->DeInit();
386    delete color_mode_;
387  }
388
389  delete tone_mapper_;
390  tone_mapper_ = nullptr;
391
392  return 0;
393}
394
395// LayerStack operations
396HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
397  HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
398  layer_map_.emplace(std::make_pair(layer->GetId(), layer));
399  *out_layer_id = layer->GetId();
400  validated_ = false;
401  geometry_changes_ |= GeometryChanges::kAdded;
402  return HWC2::Error::None;
403}
404
405HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
406  const auto map_layer = layer_map_.find(layer_id);
407  if (map_layer == layer_map_.end()) {
408    DLOGE("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
409    return nullptr;
410  } else {
411    return map_layer->second;
412  }
413}
414
415HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
416  const auto map_layer = layer_map_.find(layer_id);
417  if (map_layer == layer_map_.end()) {
418    DLOGE("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
419    return HWC2::Error::BadLayer;
420  }
421  const auto layer = map_layer->second;
422  layer_map_.erase(map_layer);
423  const auto z_range = layer_set_.equal_range(layer);
424  for (auto current = z_range.first; current != z_range.second; ++current) {
425    if (*current == layer) {
426      current = layer_set_.erase(current);
427      delete layer;
428      break;
429    }
430  }
431  validated_ = false;
432
433  geometry_changes_ |= GeometryChanges::kRemoved;
434  return HWC2::Error::None;
435}
436
437
438void HWCDisplay::BuildLayerStack() {
439  layer_stack_ = LayerStack();
440  display_rect_ = LayerRect();
441  metadata_refresh_rate_ = 0;
442  auto working_primaries = ColorPrimaries_BT709_5;
443
444  // Add one layer for fb target
445  // TODO(user): Add blit target layers
446  for (auto hwc_layer : layer_set_) {
447    // Reset layer data which SDM may change
448    hwc_layer->ResetPerFrameData();
449
450    Layer *layer = hwc_layer->GetSDMLayer();
451    layer->flags = {};   // Reset earlier flags
452    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
453      layer->flags.skip = true;
454    } else if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::SolidColor) {
455      layer->flags.solid_fill = true;
456    }
457
458#ifdef FEATURE_WIDE_COLOR
459    if (!hwc_layer->SupportedDataspace()) {
460        layer->flags.skip = true;
461        DLOGW_IF(kTagStrategy, "Unsupported dataspace: 0x%x", hwc_layer->GetLayerDataspace());
462    }
463#endif
464
465    working_primaries = WidestPrimaries(working_primaries,
466                                        layer->input_buffer.color_metadata.colorPrimaries);
467
468    // set default composition as GPU for SDM
469    layer->composition = kCompositionGPU;
470
471    if (swap_interval_zero_) {
472      if (layer->input_buffer.acquire_fence_fd >= 0) {
473        close(layer->input_buffer.acquire_fence_fd);
474        layer->input_buffer.acquire_fence_fd = -1;
475      }
476    }
477
478    const private_handle_t *handle =
479        reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
480    if (handle) {
481#ifdef USE_GRALLOC1
482      if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
483#else
484      if (handle->bufferType == BUFFER_TYPE_VIDEO) {
485#endif
486        layer_stack_.flags.video_present = true;
487      }
488      // TZ Protected Buffer - L1
489      if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
490        layer_stack_.flags.secure_present = true;
491      }
492      // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
493      if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
494        layer_stack_.flags.secure_present = true;
495      }
496    }
497
498    if (layer->flags.skip) {
499      layer_stack_.flags.skip_present = true;
500    }
501
502    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
503      // Currently we support only one HWCursor & only at top most z-order
504      if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
505        layer->flags.cursor = true;
506        layer_stack_.flags.cursor_present = true;
507      }
508    }
509
510    bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
511                     (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
512                     layer->input_buffer.color_metadata.transfer == Transfer_HLG);
513    if (hdr_layer && !disable_hdr_handling_) {
514      // dont honor HDR when its handling is disabled
515      layer->input_buffer.flags.hdr = true;
516      layer_stack_.flags.hdr_present = true;
517    }
518
519    // TODO(user): Move to a getter if this is needed at other places
520    hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
521                                       INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
522    ApplyScanAdjustment(&scaled_display_frame);
523    hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
524    // SDM requires these details even for solid fill
525    if (layer->flags.solid_fill) {
526      LayerBuffer *layer_buffer = &layer->input_buffer;
527      layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
528      layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
529      layer_buffer->unaligned_width = layer_buffer->width;
530      layer_buffer->unaligned_height = layer_buffer->height;
531      layer_buffer->acquire_fence_fd = -1;
532      layer_buffer->release_fence_fd = -1;
533      layer->src_rect.left = 0;
534      layer->src_rect.top = 0;
535      layer->src_rect.right = layer_buffer->width;
536      layer->src_rect.bottom = layer_buffer->height;
537    }
538
539    if (layer->frame_rate > metadata_refresh_rate_) {
540      metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
541    } else {
542      layer->frame_rate = current_refresh_rate_;
543    }
544    display_rect_ = Union(display_rect_, layer->dst_rect);
545    geometry_changes_ |= hwc_layer->GetGeometryChanges();
546
547    layer->flags.updating = true;
548    if (layer_set_.size() <= kMaxLayerCount) {
549      layer->flags.updating = IsLayerUpdating(layer);
550    }
551
552    layer_stack_.layers.push_back(layer);
553  }
554
555
556#ifdef FEATURE_WIDE_COLOR
557  for (auto hwc_layer : layer_set_) {
558    auto layer = hwc_layer->GetSDMLayer();
559    if (layer->input_buffer.color_metadata.colorPrimaries != working_primaries &&
560        !hwc_layer->SupportLocalConversion(working_primaries)) {
561      layer->flags.skip = true;
562    }
563    if (layer->flags.skip) {
564      layer_stack_.flags.skip_present = true;
565    }
566  }
567#endif
568
569  // TODO(user): Set correctly when SDM supports geometry_changes as bitmask
570  layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
571  // Append client target to the layer stack
572  layer_stack_.layers.push_back(client_target_->GetSDMLayer());
573}
574
575void HWCDisplay::BuildSolidFillStack() {
576  layer_stack_ = LayerStack();
577  display_rect_ = LayerRect();
578
579  layer_stack_.layers.push_back(solid_fill_layer_);
580  layer_stack_.flags.geometry_changed = 1U;
581  // Append client target to the layer stack
582  layer_stack_.layers.push_back(client_target_->GetSDMLayer());
583}
584
585HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
586  const auto map_layer = layer_map_.find(layer_id);
587  if (map_layer == layer_map_.end()) {
588    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
589    return HWC2::Error::BadLayer;
590  }
591  validated_ = false;
592
593  const auto layer = map_layer->second;
594  const auto z_range = layer_set_.equal_range(layer);
595  bool layer_on_display = false;
596  for (auto current = z_range.first; current != z_range.second; ++current) {
597    if (*current == layer) {
598      if ((*current)->GetZ() == z) {
599        // Don't change anything if the Z hasn't changed
600        return HWC2::Error::None;
601      }
602      current = layer_set_.erase(current);
603      layer_on_display = true;
604      break;
605    }
606  }
607
608  if (!layer_on_display) {
609    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", id_);
610    return HWC2::Error::BadLayer;
611  }
612
613  layer->SetLayerZOrder(z);
614  layer_set_.emplace(layer);
615  return HWC2::Error::None;
616}
617
618HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
619  DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
620  DisplayError error = kErrorNone;
621
622  if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
623    return HWC2::Error::None;
624  }
625
626  bool state;
627  if (enabled == HWC2::Vsync::Enable)
628    state = true;
629  else if (enabled == HWC2::Vsync::Disable)
630    state = false;
631  else
632    return HWC2::Error::BadParameter;
633
634  error = display_intf_->SetVSyncState(state);
635
636  if (error != kErrorNone) {
637    if (error == kErrorShutDown) {
638      shutdown_pending_ = true;
639      return HWC2::Error::None;
640    }
641    DLOGE("Failed. enabled = %s, error = %d", to_string(enabled).c_str(), error);
642    return HWC2::Error::BadDisplay;
643  }
644
645  return HWC2::Error::None;
646}
647
648HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
649  DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
650  DisplayState state = kStateOff;
651  bool flush_on_error = flush_on_error_;
652
653  if (shutdown_pending_) {
654    return HWC2::Error::None;
655  }
656
657  switch (mode) {
658    case HWC2::PowerMode::Off:
659      // During power off, all of the buffers are released.
660      // Do not flush until a buffer is successfully submitted again.
661      flush_on_error = false;
662      state = kStateOff;
663      if (tone_mapper_) {
664        tone_mapper_->Terminate();
665      }
666      break;
667    case HWC2::PowerMode::On:
668      state = kStateOn;
669      last_power_mode_ = HWC2::PowerMode::On;
670      break;
671    case HWC2::PowerMode::Doze:
672      state = kStateDoze;
673      last_power_mode_ = HWC2::PowerMode::Doze;
674      break;
675    case HWC2::PowerMode::DozeSuspend:
676      state = kStateDozeSuspend;
677      last_power_mode_ = HWC2::PowerMode::DozeSuspend;
678      break;
679    default:
680      return HWC2::Error::BadParameter;
681  }
682
683  DisplayError error = display_intf_->SetDisplayState(state);
684  if (error == kErrorNone) {
685    flush_on_error_ = flush_on_error;
686  } else {
687    if (error == kErrorShutDown) {
688      shutdown_pending_ = true;
689      return HWC2::Error::None;
690    }
691    DLOGE("Set state failed. Error = %d", error);
692    return HWC2::Error::BadParameter;
693  }
694
695  return HWC2::Error::None;
696}
697
698HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
699                                               int32_t dataspace) {
700  DisplayConfigVariableInfo variable_config;
701  display_intf_->GetFrameBufferConfig(&variable_config);
702  // TODO(user): Support scaled configurations, other formats and other dataspaces
703  if (format != HAL_PIXEL_FORMAT_RGBA_8888 || dataspace != HAL_DATASPACE_UNKNOWN ||
704      width != variable_config.x_pixels || height != variable_config.y_pixels) {
705    return HWC2::Error::Unsupported;
706  } else {
707    return HWC2::Error::None;
708  }
709}
710
711HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
712  if (out_modes) {
713    out_modes[0] = HAL_COLOR_MODE_NATIVE;
714  }
715  *out_num_modes = 1;
716
717  return HWC2::Error::None;
718}
719
720HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
721  // TODO(user): Actually handle multiple configs
722  if (out_configs == nullptr) {
723    *out_num_configs = 1;
724  } else {
725    *out_num_configs = 1;
726    out_configs[0] = 0;
727  }
728
729  return HWC2::Error::None;
730}
731
732HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
733                                            int32_t *out_value) {
734  DisplayConfigVariableInfo variable_config;
735  DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
736  if (error != kErrorNone) {
737    DLOGV("Get variable config failed. Error = %d", error);
738    return HWC2::Error::BadDisplay;
739  }
740
741  if (config != 0) {  // We only use config[0] - see TODO above
742      return HWC2::Error::BadConfig;
743  }
744
745  switch (attribute) {
746    case HWC2::Attribute::VsyncPeriod:
747      *out_value = INT32(variable_config.vsync_period_ns);
748      break;
749    case HWC2::Attribute::Width:
750      *out_value = INT32(variable_config.x_pixels);
751      break;
752    case HWC2::Attribute::Height:
753      *out_value = INT32(variable_config.y_pixels);
754      break;
755    case HWC2::Attribute::DpiX:
756      *out_value = INT32(variable_config.x_dpi * 1000.0f);
757      break;
758    case HWC2::Attribute::DpiY:
759      *out_value = INT32(variable_config.y_dpi * 1000.0f);
760      break;
761    default:
762      DLOGW("Spurious attribute type = %s", to_string(attribute).c_str());
763      *out_value = -1;
764      return HWC2::Error::BadConfig;
765  }
766
767  return HWC2::Error::None;
768}
769
770HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
771  // TODO(user): Get panel name and EDID name and populate it here
772  if (out_name == nullptr) {
773    *out_size = 32;
774  } else {
775    std::string name;
776    switch (id_) {
777      case HWC_DISPLAY_PRIMARY:
778        name = "Primary Display";
779        break;
780      case HWC_DISPLAY_EXTERNAL:
781        name = "External Display";
782        break;
783      case HWC_DISPLAY_VIRTUAL:
784        name = "Virtual Display";
785        break;
786      default:
787        name = "Unknown";
788        break;
789    }
790    std::strncpy(out_name, name.c_str(), name.size());
791    *out_size = UINT32(name.size());
792  }
793  return HWC2::Error::None;
794}
795
796HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
797  if (out_type != nullptr) {
798    if (id_ == HWC_DISPLAY_VIRTUAL) {
799      *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
800    } else {
801      *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
802    }
803    return HWC2::Error::None;
804  } else {
805    return HWC2::Error::BadParameter;
806  }
807}
808
809// TODO(user): Store configurations and hook them up here
810HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
811  if (out_config != nullptr) {
812    *out_config = 0;
813    return HWC2::Error::None;
814  } else {
815    return HWC2::Error::BadParameter;
816  }
817}
818
819HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
820                                        int32_t dataspace, hwc_region_t damage) {
821  // TODO(user): SurfaceFlinger gives us a null pointer here when doing full SDE composition
822  // The error is problematic for layer caching as it would overwrite our cached client target.
823  // Reported bug 28569722 to resolve this.
824  // For now, continue to use the last valid buffer reported to us for layer caching.
825  if (target == nullptr) {
826    return HWC2::Error::None;
827  }
828
829  if (acquire_fence == 0) {
830    DLOGE("acquire_fence is zero");
831    return HWC2::Error::BadParameter;
832  }
833
834  client_target_->SetLayerBuffer(target, acquire_fence);
835  client_target_->SetLayerSurfaceDamage(damage);
836  // Ignoring dataspace for now
837  return HWC2::Error::None;
838}
839
840HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
841  if (config != 0) {
842    return HWC2::Error::BadConfig;
843  }
844  // We have only one config right now - do nothing
845  return HWC2::Error::None;
846}
847
848DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
849  return kErrorNotSupported;
850}
851
852void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
853  dump_frame_count_ = count;
854  dump_frame_index_ = 0;
855  dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
856
857  if (tone_mapper_) {
858    tone_mapper_->SetFrameDumpConfig(count);
859  }
860
861  DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
862}
863
864HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
865  return last_power_mode_;
866}
867
868DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
869  callbacks_->Vsync(id_, vsync.timestamp);
870  return kErrorNone;
871}
872
873DisplayError HWCDisplay::Refresh() {
874  return kErrorNotSupported;
875}
876
877DisplayError HWCDisplay::CECMessage(char *message) {
878  if (qservice_) {
879    qservice_->onCECMessageReceived(message, 0);
880  } else {
881    DLOGW("Qservice instance not available.");
882  }
883
884  return kErrorNone;
885}
886
887HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
888  layer_changes_.clear();
889  layer_requests_.clear();
890  if (shutdown_pending_) {
891    return HWC2::Error::BadDisplay;
892  }
893
894  if (!skip_prepare_) {
895    DisplayError error = display_intf_->Prepare(&layer_stack_);
896    if (error != kErrorNone) {
897      if (error == kErrorShutDown) {
898        shutdown_pending_ = true;
899      } else if (error != kErrorPermission) {
900        DLOGE("Prepare failed. Error = %d", error);
901        // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
902        // so that previous buffer and fences are released, and override the error.
903        flush_ = true;
904      }
905      return HWC2::Error::BadDisplay;
906    }
907  } else {
908    // Skip is not set
909    MarkLayersForGPUBypass();
910    skip_prepare_ = false;
911    DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush",
912          secure_display_active_ ? "Starting" : "Stopping");
913    flush_ = true;
914  }
915
916  for (auto hwc_layer : layer_set_) {
917    Layer *layer = hwc_layer->GetSDMLayer();
918    LayerComposition &composition = layer->composition;
919
920    if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
921        (composition == kCompositionBlit)) {
922      layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
923    }
924
925    HWC2::Composition requested_composition = hwc_layer->GetClientRequestedCompositionType();
926    // Set SDM composition to HWC2 type in HWCLayer
927    hwc_layer->SetComposition(composition);
928    HWC2::Composition device_composition  = hwc_layer->GetDeviceSelectedCompositionType();
929    // Update the changes list only if the requested composition is different from SDM comp type
930    // TODO(user): Take Care of other comptypes(BLIT)
931    if (requested_composition != device_composition) {
932      layer_changes_[hwc_layer->GetId()] = device_composition;
933    }
934  }
935  *out_num_types = UINT32(layer_changes_.size());
936  *out_num_requests = UINT32(layer_requests_.size());
937  validated_ = true;
938  if (*out_num_types > 0) {
939    return HWC2::Error::HasChanges;
940  } else {
941    return HWC2::Error::None;
942  }
943}
944
945HWC2::Error HWCDisplay::AcceptDisplayChanges() {
946  if (layer_set_.empty()) {
947    return HWC2::Error::None;
948  }
949
950  if (!validated_) {
951    return HWC2::Error::NotValidated;
952  }
953
954  for (const auto& change : layer_changes_) {
955    auto hwc_layer = layer_map_[change.first];
956    auto composition = change.second;
957    if (hwc_layer != nullptr) {
958      hwc_layer->UpdateClientCompositionType(composition);
959    } else {
960      DLOGW("Invalid layer: %" PRIu64, change.first);
961    }
962  }
963  return HWC2::Error::None;
964}
965
966HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
967                                                   hwc2_layer_t *out_layers, int32_t *out_types) {
968  if (layer_set_.empty()) {
969    return HWC2::Error::None;
970  }
971
972  if (!validated_) {
973    DLOGW("Display is not validated");
974    return HWC2::Error::NotValidated;
975  }
976  *out_num_elements = UINT32(layer_changes_.size());
977  if (out_layers != nullptr && out_types != nullptr) {
978    int i = 0;
979    for (auto change : layer_changes_) {
980      out_layers[i] = change.first;
981      out_types[i] = INT32(change.second);
982      i++;
983    }
984  }
985  return HWC2::Error::None;
986}
987
988HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
989                                         int32_t *out_fences) {
990  if (out_layers != nullptr && out_fences != nullptr) {
991    int i = 0;
992    for (auto hwc_layer : layer_set_) {
993      out_layers[i] = hwc_layer->GetId();
994      out_fences[i] = hwc_layer->PopReleaseFence();
995      i++;
996    }
997  }
998  *out_num_elements = UINT32(layer_set_.size());
999  return HWC2::Error::None;
1000}
1001
1002HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
1003                                           uint32_t *out_num_elements, hwc2_layer_t *out_layers,
1004                                           int32_t *out_layer_requests) {
1005  // No display requests for now
1006  // Use for sharing blit buffers and
1007  // writing wfd buffer directly to output if there is full GPU composition
1008  // and no color conversion needed
1009  if (layer_set_.empty()) {
1010    return HWC2::Error::None;
1011  }
1012
1013  if (!validated_) {
1014    DLOGW("Display is not validated");
1015    return HWC2::Error::NotValidated;
1016  }
1017  *out_display_requests = 0;
1018  *out_num_elements = UINT32(layer_requests_.size());
1019  if (out_layers != nullptr && out_layer_requests != nullptr) {
1020    int i = 0;
1021    for (auto &request : layer_requests_) {
1022      out_layers[i] = request.first;
1023      out_layer_requests[i] = INT32(request.second);
1024      i++;
1025    }
1026  }
1027
1028  auto client_target_layer = client_target_->GetSDMLayer();
1029  if (client_target_layer->request.flags.flip_buffer) {
1030    *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
1031  }
1032
1033  return HWC2::Error::None;
1034}
1035
1036HWC2::Error HWCDisplay::GetHdrCapabilities(uint32_t *out_num_types, int32_t *out_types,
1037                                           float *out_max_luminance,
1038                                           float *out_max_average_luminance,
1039                                           float *out_min_luminance) {
1040  DisplayConfigFixedInfo fixed_info = {};
1041  display_intf_->GetConfig(&fixed_info);
1042
1043  if (!fixed_info.hdr_supported) {
1044    *out_num_types = 0;
1045    DLOGI("HDR is not supported");
1046    return HWC2::Error::None;
1047  }
1048
1049  if (out_types == nullptr) {
1050    // 1(now) - because we support only HDR10, change when HLG & DOLBY vision are supported
1051    *out_num_types  = 1;
1052  } else {
1053    // Only HDR10 supported
1054    *out_types = HAL_HDR_HDR10;
1055    static const float kLuminanceFactor = 10000.0;
1056    // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
1057    *out_max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
1058    *out_max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
1059    *out_min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
1060  }
1061
1062  return HWC2::Error::None;
1063}
1064
1065
1066HWC2::Error HWCDisplay::CommitLayerStack(void) {
1067  if (shutdown_pending_ || layer_set_.empty()) {
1068    return HWC2::Error::None;
1069  }
1070
1071  if (!validated_) {
1072    DLOGW("Display is not validated");
1073    return HWC2::Error::NotValidated;
1074  }
1075
1076  DumpInputBuffers();
1077
1078  if (!flush_) {
1079    DisplayError error = kErrorUndefined;
1080    int status = 0;
1081    if (tone_mapper_) {
1082      if (layer_stack_.flags.hdr_present) {
1083        status = tone_mapper_->HandleToneMap(&layer_stack_);
1084        if (status != 0) {
1085          DLOGE("Error handling HDR in ToneMapper");
1086        }
1087      } else {
1088        tone_mapper_->Terminate();
1089      }
1090    }
1091    error = display_intf_->Commit(&layer_stack_);
1092    validated_ = false;
1093
1094    if (error == kErrorNone) {
1095      // A commit is successfully submitted, start flushing on failure now onwards.
1096      flush_on_error_ = true;
1097    } else {
1098      if (error == kErrorShutDown) {
1099        shutdown_pending_ = true;
1100        return HWC2::Error::Unsupported;
1101      } else if (error != kErrorPermission) {
1102        DLOGE("Commit failed. Error = %d", error);
1103        // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
1104        // so that previous buffer and fences are released, and override the error.
1105        flush_ = true;
1106      }
1107    }
1108  }
1109
1110  return HWC2::Error::None;
1111}
1112
1113HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
1114  auto status = HWC2::Error::None;
1115
1116  // Do no call flush on errors, if a successful buffer is never submitted.
1117  if (flush_ && flush_on_error_) {
1118    display_intf_->Flush();
1119  }
1120
1121  if (tone_mapper_ && tone_mapper_->IsActive()) {
1122     tone_mapper_->PostCommit(&layer_stack_);
1123  }
1124
1125  // TODO(user): No way to set the client target release fence on SF
1126  int32_t &client_target_release_fence =
1127      client_target_->GetSDMLayer()->input_buffer.release_fence_fd;
1128  if (client_target_release_fence >= 0) {
1129    close(client_target_release_fence);
1130    client_target_release_fence = -1;
1131  }
1132
1133  for (auto hwc_layer : layer_set_) {
1134    hwc_layer->ResetGeometryChanges();
1135    Layer *layer = hwc_layer->GetSDMLayer();
1136    LayerBuffer *layer_buffer = &layer->input_buffer;
1137
1138    if (!flush_) {
1139      // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
1140      // release fences and discard fences from driver
1141      if (swap_interval_zero_ || layer->flags.single_buffer) {
1142        close(layer_buffer->release_fence_fd);
1143        layer_buffer->release_fence_fd = -1;
1144      } else if (layer->composition != kCompositionGPU) {
1145        hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
1146        layer_buffer->release_fence_fd = -1;
1147      } else {
1148        hwc_layer->PushReleaseFence(-1);
1149      }
1150    }
1151
1152    if (layer_buffer->acquire_fence_fd >= 0) {
1153      close(layer_buffer->acquire_fence_fd);
1154      layer_buffer->acquire_fence_fd = -1;
1155    }
1156  }
1157
1158  *out_retire_fence = -1;
1159  if (!flush_) {
1160    // if swapinterval property is set to 0 then close and reset the list retire fence
1161    if (swap_interval_zero_) {
1162      close(layer_stack_.retire_fence_fd);
1163      layer_stack_.retire_fence_fd = -1;
1164    }
1165    *out_retire_fence = layer_stack_.retire_fence_fd;
1166
1167    if (dump_frame_count_) {
1168      dump_frame_count_--;
1169      dump_frame_index_++;
1170    }
1171  }
1172
1173  geometry_changes_ = GeometryChanges::kNone;
1174  flush_ = false;
1175
1176  ClearRequestFlags();
1177
1178  return status;
1179}
1180
1181void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
1182  return;
1183}
1184
1185DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
1186  DisplayError error = kErrorNone;
1187
1188  if (display_intf_) {
1189    error = display_intf_->SetMaxMixerStages(max_mixer_stages);
1190  }
1191
1192  return error;
1193}
1194
1195LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
1196  LayerBufferFormat format = kFormatInvalid;
1197  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
1198    switch (source) {
1199      case HAL_PIXEL_FORMAT_RGBA_8888:
1200        format = kFormatRGBA8888Ubwc;
1201        break;
1202      case HAL_PIXEL_FORMAT_RGBX_8888:
1203        format = kFormatRGBX8888Ubwc;
1204        break;
1205      case HAL_PIXEL_FORMAT_BGR_565:
1206        format = kFormatBGR565Ubwc;
1207        break;
1208      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
1209      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
1210      case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1211        format = kFormatYCbCr420SPVenusUbwc;
1212        break;
1213      case HAL_PIXEL_FORMAT_RGBA_1010102:
1214        format = kFormatRGBA1010102Ubwc;
1215        break;
1216      case HAL_PIXEL_FORMAT_RGBX_1010102:
1217        format = kFormatRGBX1010102Ubwc;
1218        break;
1219      case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
1220        format = kFormatYCbCr420TP10Ubwc;
1221        break;
1222      case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
1223        format = kFormatYCbCr420P010Ubwc;
1224        break;
1225      default:
1226        DLOGE("Unsupported format type for UBWC %d", source);
1227        return kFormatInvalid;
1228    }
1229    return format;
1230  }
1231
1232  switch (source) {
1233    case HAL_PIXEL_FORMAT_RGBA_8888:
1234      format = kFormatRGBA8888;
1235      break;
1236    case HAL_PIXEL_FORMAT_RGBA_5551:
1237      format = kFormatRGBA5551;
1238      break;
1239    case HAL_PIXEL_FORMAT_RGBA_4444:
1240      format = kFormatRGBA4444;
1241      break;
1242    case HAL_PIXEL_FORMAT_BGRA_8888:
1243      format = kFormatBGRA8888;
1244      break;
1245    case HAL_PIXEL_FORMAT_RGBX_8888:
1246      format = kFormatRGBX8888;
1247      break;
1248    case HAL_PIXEL_FORMAT_BGRX_8888:
1249      format = kFormatBGRX8888;
1250      break;
1251    case HAL_PIXEL_FORMAT_RGB_888:
1252      format = kFormatRGB888;
1253      break;
1254    case HAL_PIXEL_FORMAT_RGB_565:
1255      format = kFormatRGB565;
1256      break;
1257    case HAL_PIXEL_FORMAT_BGR_565:
1258      format = kFormatBGR565;
1259      break;
1260    case HAL_PIXEL_FORMAT_BGR_888:
1261      format = kFormatBGR888;
1262      break;
1263    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1264    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
1265      format = kFormatYCbCr420SemiPlanarVenus;
1266      break;
1267    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
1268      format = kFormatYCrCb420SemiPlanarVenus;
1269      break;
1270    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
1271      format = kFormatYCbCr420SPVenusUbwc;
1272      break;
1273    case HAL_PIXEL_FORMAT_YV12:
1274      format = kFormatYCrCb420PlanarStride16;
1275      break;
1276    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1277      format = kFormatYCrCb420SemiPlanar;
1278      break;
1279    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1280      format = kFormatYCbCr420SemiPlanar;
1281      break;
1282    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1283      format = kFormatYCbCr422H2V1SemiPlanar;
1284      break;
1285    case HAL_PIXEL_FORMAT_YCbCr_422_I:
1286      format = kFormatYCbCr422H2V1Packed;
1287      break;
1288    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
1289      format = kFormatCbYCrY422H2V1Packed;
1290      break;
1291    case HAL_PIXEL_FORMAT_RGBA_1010102:
1292      format = kFormatRGBA1010102;
1293      break;
1294    case HAL_PIXEL_FORMAT_ARGB_2101010:
1295      format = kFormatARGB2101010;
1296      break;
1297    case HAL_PIXEL_FORMAT_RGBX_1010102:
1298      format = kFormatRGBX1010102;
1299      break;
1300    case HAL_PIXEL_FORMAT_XRGB_2101010:
1301      format = kFormatXRGB2101010;
1302      break;
1303    case HAL_PIXEL_FORMAT_BGRA_1010102:
1304      format = kFormatBGRA1010102;
1305      break;
1306    case HAL_PIXEL_FORMAT_ABGR_2101010:
1307      format = kFormatABGR2101010;
1308      break;
1309    case HAL_PIXEL_FORMAT_BGRX_1010102:
1310      format = kFormatBGRX1010102;
1311      break;
1312    case HAL_PIXEL_FORMAT_XBGR_2101010:
1313      format = kFormatXBGR2101010;
1314      break;
1315    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
1316      format = kFormatYCbCr420P010;
1317      break;
1318    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
1319      format = kFormatYCbCr420TP10Ubwc;
1320      break;
1321    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
1322      format = kFormatYCbCr420P010Ubwc;
1323      break;
1324    default:
1325      DLOGW("Unsupported format type = %d", source);
1326      return kFormatInvalid;
1327  }
1328
1329  return format;
1330}
1331
1332void HWCDisplay::DumpInputBuffers() {
1333  char dir_path[PATH_MAX];
1334
1335  if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
1336    return;
1337  }
1338
1339  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
1340
1341  if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
1342    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1343    return;
1344  }
1345
1346  // if directory exists already, need to explicitly change the permission.
1347  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
1348    DLOGW("Failed to change permissions on %s directory", dir_path);
1349    return;
1350  }
1351
1352  for (uint32_t i = 0; i < layer_stack_.layers.size(); i++) {
1353    auto layer = layer_stack_.layers.at(i);
1354    const private_handle_t *pvt_handle =
1355        reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
1356    auto acquire_fence_fd = layer->input_buffer.acquire_fence_fd;
1357
1358    if (acquire_fence_fd >= 0) {
1359      int error = sync_wait(acquire_fence_fd, 1000);
1360      if (error < 0) {
1361        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1362        return;
1363      }
1364    }
1365
1366    if (pvt_handle && pvt_handle->base) {
1367      char dump_file_name[PATH_MAX];
1368      size_t result = 0;
1369
1370      snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
1371               dir_path, i, pvt_handle->width, pvt_handle->height,
1372               qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
1373
1374      FILE *fp = fopen(dump_file_name, "w+");
1375      if (fp) {
1376        result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
1377        fclose(fp);
1378      }
1379
1380      DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
1381    }
1382  }
1383}
1384
1385void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence) {
1386  char dir_path[PATH_MAX];
1387
1388  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
1389
1390  if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
1391    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1392    return;
1393  }
1394
1395  // if directory exists already, need to explicitly change the permission.
1396  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
1397    DLOGW("Failed to change permissions on %s directory", dir_path);
1398    return;
1399  }
1400
1401  if (base) {
1402    char dump_file_name[PATH_MAX];
1403    size_t result = 0;
1404
1405    if (fence >= 0) {
1406      int error = sync_wait(fence, 1000);
1407      if (error < 0) {
1408        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1409        return;
1410      }
1411    }
1412
1413    snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
1414             dir_path, buffer_info.buffer_config.width, buffer_info.buffer_config.height,
1415             GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
1416
1417    FILE *fp = fopen(dump_file_name, "w+");
1418    if (fp) {
1419      result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
1420      fclose(fp);
1421    }
1422
1423    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
1424  }
1425}
1426
1427const char *HWCDisplay::GetDisplayString() {
1428  switch (type_) {
1429    case kPrimary:
1430      return "primary";
1431    case kHDMI:
1432      return "hdmi";
1433    case kVirtual:
1434      return "virtual";
1435    default:
1436      return "invalid";
1437  }
1438}
1439
1440int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
1441  if (x_pixels <= 0 || y_pixels <= 0) {
1442    DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
1443    return -EINVAL;
1444  }
1445
1446  DisplayConfigVariableInfo fb_config;
1447  DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
1448  if (error != kErrorNone) {
1449    DLOGV("Get frame buffer config failed. Error = %d", error);
1450    return -EINVAL;
1451  }
1452
1453  fb_config.x_pixels = x_pixels;
1454  fb_config.y_pixels = y_pixels;
1455
1456  error = display_intf_->SetFrameBufferConfig(fb_config);
1457  if (error != kErrorNone) {
1458    DLOGV("Set frame buffer config failed. Error = %d", error);
1459    return -EINVAL;
1460  }
1461
1462  // Create rects to represent the new source and destination crops
1463  LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
1464  LayerRect dst = LayerRect(0, 0, FLOAT(fb_config.x_pixels), FLOAT(fb_config.y_pixels));
1465  auto client_target_layer = client_target_->GetSDMLayer();
1466  client_target_layer->src_rect = crop;
1467  client_target_layer->dst_rect = dst;
1468
1469  int aligned_width;
1470  int aligned_height;
1471  uint32_t usage = GRALLOC_USAGE_HW_FB;
1472  int format = HAL_PIXEL_FORMAT_RGBA_8888;
1473  int ubwc_enabled = 0;
1474  int flags = 0;
1475  HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
1476  if (ubwc_enabled == 1) {
1477    usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
1478    flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
1479  }
1480
1481#ifdef USE_GRALLOC1
1482  buffer_allocator_->GetAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format, usage,
1483                                              &aligned_width, &aligned_height);
1484#else
1485  AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format,
1486                                                        INT(usage), aligned_width, aligned_height);
1487#endif
1488
1489  // TODO(user): How does the dirty region get set on the client target? File bug on Google
1490  client_target_layer->composition = kCompositionGPUTarget;
1491  client_target_layer->input_buffer.format = GetSDMFormat(format, flags);
1492  client_target_layer->input_buffer.width = UINT32(aligned_width);
1493  client_target_layer->input_buffer.height = UINT32(aligned_height);
1494  client_target_layer->input_buffer.unaligned_width = x_pixels;
1495  client_target_layer->input_buffer.unaligned_height = y_pixels;
1496  client_target_layer->plane_alpha = 255;
1497
1498  DLOGI("New framebuffer resolution (%dx%d)", fb_config.x_pixels, fb_config.y_pixels);
1499
1500  return 0;
1501}
1502
1503void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
1504  DisplayConfigVariableInfo fb_config;
1505  display_intf_->GetFrameBufferConfig(&fb_config);
1506
1507  *x_pixels = fb_config.x_pixels;
1508  *y_pixels = fb_config.y_pixels;
1509}
1510
1511DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
1512  return display_intf_->GetMixerResolution(x_pixels, y_pixels);
1513}
1514
1515void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
1516  DisplayConfigVariableInfo display_config;
1517  uint32_t active_index = 0;
1518
1519  display_intf_->GetActiveConfig(&active_index);
1520  display_intf_->GetConfig(active_index, &display_config);
1521
1522  *x_pixels = display_config.x_pixels;
1523  *y_pixels = display_config.y_pixels;
1524}
1525
1526int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
1527  int status = 0;
1528
1529  switch (display_status) {
1530    case kDisplayStatusResume:
1531      display_paused_ = false;
1532    case kDisplayStatusOnline:
1533      status = INT32(SetPowerMode(HWC2::PowerMode::On));
1534      break;
1535    case kDisplayStatusPause:
1536      display_paused_ = true;
1537    case kDisplayStatusOffline:
1538      status = INT32(SetPowerMode(HWC2::PowerMode::Off));
1539      break;
1540    default:
1541      DLOGW("Invalid display status %d", display_status);
1542      return -EINVAL;
1543  }
1544
1545  if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
1546    callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
1547  }
1548
1549  return status;
1550}
1551
1552HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
1553  if (shutdown_pending_) {
1554    return HWC2::Error::None;
1555  }
1556
1557  if (GetHWCLayer(layer) == nullptr) {
1558    return HWC2::Error::BadLayer;
1559  }
1560
1561  DisplayState state;
1562  if (display_intf_->GetDisplayState(&state) == kErrorNone) {
1563    if (state != kStateOn) {
1564      return HWC2::Error::None;
1565    }
1566  }
1567
1568  if (!validated_) {
1569    return HWC2::Error::NotValidated;
1570  }
1571
1572  auto error = display_intf_->SetCursorPosition(x, y);
1573  if (error != kErrorNone) {
1574    if (error == kErrorShutDown) {
1575      shutdown_pending_ = true;
1576      return HWC2::Error::None;
1577    }
1578
1579    DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
1580    return HWC2::Error::BadDisplay;
1581  }
1582
1583  return HWC2::Error::None;
1584}
1585
1586int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
1587  DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
1588  if (error != kErrorNone) {
1589    DLOGE("Failed. Error = %d", error);
1590    return -1;
1591  }
1592
1593  return 0;
1594}
1595
1596void HWCDisplay::MarkLayersForGPUBypass() {
1597  for (auto hwc_layer : layer_set_) {
1598    auto layer = hwc_layer->GetSDMLayer();
1599    layer->composition = kCompositionSDE;
1600  }
1601}
1602
1603void HWCDisplay::MarkLayersForClientComposition() {
1604  // ClientComposition - GPU comp, to acheive this, set skip flag so that
1605  // SDM does not handle this layer and hwc_layer composition will be
1606  // set correctly at the end of Prepare.
1607  for (auto hwc_layer : layer_set_) {
1608    Layer *layer = hwc_layer->GetSDMLayer();
1609    layer->flags.skip = true;
1610  }
1611}
1612
1613void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
1614}
1615
1616int HWCDisplay::SetPanelBrightness(int level) {
1617  int ret = 0;
1618  if (display_intf_)
1619    ret = display_intf_->SetPanelBrightness(level);
1620  else
1621    ret = -EINVAL;
1622
1623  return ret;
1624}
1625
1626int HWCDisplay::GetPanelBrightness(int *level) {
1627  return display_intf_->GetPanelBrightness(level);
1628}
1629
1630int HWCDisplay::ToggleScreenUpdates(bool enable) {
1631  display_paused_ = enable ? false : true;
1632  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
1633  return 0;
1634}
1635
1636int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
1637                                     PPDisplayAPIPayload *out_payload,
1638                                     PPPendingParams *pending_action) {
1639  int ret = 0;
1640
1641  if (display_intf_)
1642    ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
1643  else
1644    ret = -EINVAL;
1645
1646  return ret;
1647}
1648
1649void HWCDisplay::SolidFillPrepare() {
1650  if (solid_fill_enable_) {
1651    if (solid_fill_layer_ == NULL) {
1652      // Create a dummy layer here
1653      solid_fill_layer_ = new Layer();
1654    }
1655    uint32_t primary_width = 0, primary_height = 0;
1656    GetMixerResolution(&primary_width, &primary_height);
1657
1658    LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
1659    layer_buffer->width = primary_width;
1660    layer_buffer->height = primary_height;
1661    layer_buffer->unaligned_width = primary_width;
1662    layer_buffer->unaligned_height = primary_height;
1663    layer_buffer->acquire_fence_fd = -1;
1664    layer_buffer->release_fence_fd = -1;
1665
1666    LayerRect rect;
1667    rect.top = 0; rect.left = 0;
1668    rect.right = primary_width;
1669    rect.bottom = primary_height;
1670
1671    solid_fill_layer_->composition = kCompositionGPU;
1672    solid_fill_layer_->src_rect = rect;
1673    solid_fill_layer_->dst_rect = rect;
1674
1675    solid_fill_layer_->blending = kBlendingPremultiplied;
1676    solid_fill_layer_->solid_fill_color = solid_fill_color_;
1677    solid_fill_layer_->frame_rate = 60;
1678    solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
1679    solid_fill_layer_->flags.updating = 1;
1680    solid_fill_layer_->flags.solid_fill = true;
1681  } else {
1682    // delete the dummy layer
1683    delete solid_fill_layer_;
1684    solid_fill_layer_ = NULL;
1685  }
1686
1687  if (solid_fill_enable_ && solid_fill_layer_) {
1688    BuildSolidFillStack();
1689    MarkLayersForGPUBypass();
1690  }
1691
1692  return;
1693}
1694
1695void HWCDisplay::SolidFillCommit() {
1696  if (solid_fill_enable_ && solid_fill_layer_) {
1697    LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
1698    if (layer_buffer->release_fence_fd > 0) {
1699      close(layer_buffer->release_fence_fd);
1700      layer_buffer->release_fence_fd = -1;
1701    }
1702    if (layer_stack_.retire_fence_fd > 0) {
1703      close(layer_stack_.retire_fence_fd);
1704      layer_stack_.retire_fence_fd = -1;
1705    }
1706  }
1707}
1708
1709int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
1710  if (!IsValid(display_rect_)) {
1711    return -EINVAL;
1712  }
1713
1714  visible_rect->left = INT(display_rect_.left);
1715  visible_rect->top = INT(display_rect_.top);
1716  visible_rect->right = INT(display_rect_.right);
1717  visible_rect->bottom = INT(display_rect_.bottom);
1718  DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
1719        visible_rect->right, visible_rect->bottom);
1720
1721  return 0;
1722}
1723
1724void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
1725  secure_display_active_ = secure_display_active;
1726  return;
1727}
1728
1729int HWCDisplay::SetActiveDisplayConfig(int config) {
1730  return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1;
1731}
1732
1733int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
1734  return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
1735}
1736
1737int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
1738  return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
1739}
1740
1741int HWCDisplay::GetDisplayAttributesForConfig(int config,
1742                                            DisplayConfigVariableInfo *display_attributes) {
1743  return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
1744}
1745
1746bool HWCDisplay::SingleLayerUpdating(void) {
1747  uint32_t updating_count = 0;
1748
1749  for (uint i = 0; i < layer_stack_.layers.size(); i++) {
1750    auto layer = layer_stack_.layers.at(i);
1751    if (layer->flags.updating) {
1752      updating_count++;
1753    }
1754  }
1755
1756  return (updating_count == 1);
1757}
1758
1759bool HWCDisplay::IsLayerUpdating(const Layer *layer) {
1760  // Layer should be considered updating if
1761  //   a) layer is in single buffer mode, or
1762  //   b) valid dirty_regions(android specific hint for updating status), or
1763  //   c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
1764  //      geometry_changed as bit fields).
1765  return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
1766          geometry_changes_);
1767}
1768
1769bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
1770  // based on dirty_regions determine if its updating
1771  // dirty_rect count = 0 - whole layer - updating.
1772  // dirty_rect count = 1 or more valid rects - updating.
1773  // dirty_rect count = 1 with (0,0,0,0) - not updating.
1774  return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
1775}
1776
1777uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
1778  uint32_t refresh_rate = req_refresh_rate;
1779
1780  if (refresh_rate < min_refresh_rate_) {
1781    // Pick the next multiple of request which is within the range
1782    refresh_rate =
1783        (((min_refresh_rate_ / refresh_rate) + ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) *
1784         refresh_rate);
1785  }
1786
1787  if (refresh_rate > max_refresh_rate_) {
1788    refresh_rate = max_refresh_rate_;
1789  }
1790
1791  return refresh_rate;
1792}
1793
1794DisplayClass HWCDisplay::GetDisplayClass() {
1795  return display_class_;
1796}
1797
1798void HWCDisplay::CloseAcquireFds() {
1799  for (auto hwc_layer : layer_set_) {
1800    auto layer = hwc_layer->GetSDMLayer();
1801    if (layer->input_buffer.acquire_fence_fd >= 0) {
1802      close(layer->input_buffer.acquire_fence_fd);
1803      layer->input_buffer.acquire_fence_fd = -1;
1804    }
1805  }
1806  int32_t &client_target_acquire_fence =
1807      client_target_->GetSDMLayer()->input_buffer.acquire_fence_fd;
1808  if (client_target_acquire_fence >= 0) {
1809    close(client_target_acquire_fence);
1810    client_target_acquire_fence = -1;
1811  }
1812}
1813
1814void HWCDisplay::ClearRequestFlags() {
1815  for (Layer *layer : layer_stack_.layers) {
1816    layer->request.flags = {};
1817  }
1818}
1819
1820std::string HWCDisplay::Dump() {
1821  std::ostringstream os;
1822  os << "-------------------------------" << std::endl;
1823  os << "HWC2 display_id: " << id_ << std::endl;
1824  for (auto layer : layer_set_) {
1825    auto sdm_layer = layer->GetSDMLayer();
1826    auto transform = sdm_layer->transform;
1827    os << "layer: " << std::setw(4) << layer->GetId();
1828    os << " z: " << layer->GetZ();
1829    os << " compositon: " <<
1830          to_string(layer->GetClientRequestedCompositionType()).c_str();
1831    os << "/" <<
1832          to_string(layer->GetDeviceSelectedCompositionType()).c_str();
1833    os << " alpha: " << std::to_string(sdm_layer->plane_alpha).c_str();
1834    os << " format: " << std::setw(22) << GetFormatString(sdm_layer->input_buffer.format);
1835    os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
1836       << layer->GetLayerDataspace() << std::dec << std::setfill(' ');
1837    os << " transform: " << transform.rotation << "/" << transform.flip_horizontal <<
1838          "/"<< transform.flip_vertical;
1839    os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec
1840       << std::endl;
1841  }
1842  if (color_mode_) {
1843    color_mode_->Dump(&os);
1844  }
1845  os << "-------------------------------" << std::endl;
1846  return os.str();
1847}
1848}  // namespace sdm
1849