1 /* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #ifndef __COLOR_PARAMS_H__ 31 #define __COLOR_PARAMS_H__ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <display_color_processing.h> 36 #include <dpps_control_interface.h> 37 #include <utils/locker.h> 38 #include <utils/constants.h> 39 #include <core/sdm_types.h> 40 #include <core/display_interface.h> 41 42 #include <string> 43 44 #include "hw_info_types.h" 45 46 namespace sdm { 47 48 /* max customer extended render intent */ 49 #define MAX_EXTENDED_RENDER_INTENT 0x1ff 50 51 // Bitmap Pending action to indicate to the caller what's pending to be taken care of. 52 enum PendingAction { 53 kInvalidating = BITMAP(0), 54 kApplySolidFill = BITMAP(1), 55 kDisableSolidFill = BITMAP(2), 56 kEnterQDCMMode = BITMAP(3), 57 kExitQDCMMode = BITMAP(4), 58 kSetPanelBrightness = BITMAP(5), 59 kEnableFrameCapture = BITMAP(6), 60 kDisableFrameCapture = BITMAP(7), 61 kConfigureDetailedEnhancer = BITMAP(8), 62 kModeSet = BITMAP(10), 63 kMultiDispProc = BITMAP(11), 64 kMultiDispGetId = BITMAP(12), 65 kSetModeFromClient = BITMAP(13), 66 kGetDetailedEnhancerData = BITMAP(21), 67 kNoAction = BITMAP(31), 68 }; 69 70 static const uint32_t kOpsEnable = BITMAP(0); 71 static const uint32_t kOpsRead = BITMAP(1); 72 static const uint32_t kOpsWrite = BITMAP(2); 73 static const uint32_t kOpsDisable = BITMAP(3); 74 75 static const uint32_t kOpsGc8BitRoundEnable = BITMAP(4); 76 77 static const uint32_t kPaHueEnable = BITMAP(4); 78 static const uint32_t kPaSatEnable = BITMAP(5); 79 static const uint32_t kPaValEnable = BITMAP(6); 80 static const uint32_t kPaContEnable = BITMAP(7); 81 82 static const uint32_t kPaSixZoneEnable = BITMAP(8); 83 static const uint32_t kPaSkinEnable = BITMAP(9); 84 static const uint32_t kPaSkyEnable = BITMAP(10); 85 static const uint32_t kPaFoliageEnable = BITMAP(11); 86 87 static const uint32_t kLeftSplitMode = BITMAP(28); // 0x10000000 88 static const uint32_t kRightSplitMode = BITMAP(29); // 0x20000000 89 90 static const int32_t kInvalidModeId = -1; 91 92 static const std::string kDynamicRangeAttribute = "DynamicRange"; 93 static const std::string kColorGamutAttribute = "ColorGamut"; 94 static const std::string kPictureQualityAttribute = "PictureQuality"; 95 static const std::string kGammaTransferAttribute = "GammaTransfer"; 96 static const std::string kRenderIntentAttribute = "RenderIntent"; 97 98 static const std::string kHdr = "hdr"; 99 static const std::string kSdr = "sdr"; 100 101 static const std::string kNative = "native"; 102 static const std::string kDcip3 = "dcip3"; 103 static const std::string kSrgb = "srgb"; 104 static const std::string kDisplayP3 = "display_p3"; 105 static const std::string kBt2020 = "bt2020"; 106 107 static const std::string kHlg = "hlg"; 108 static const std::string kSt2084 = "st2084"; 109 static const std::string kGamma2_2 = "gamma2_2"; 110 111 static const std::string kVivid = "vivid"; 112 static const std::string kSharp = "sharp"; 113 static const std::string kStandard = "standard"; 114 static const std::string kAmazon = "amazon"; 115 static const std::string kNetflix = "netflix"; 116 static const std::string kEnhanced = "enhanced"; 117 118 // Enum to identify type of dynamic range of color mode. 119 enum DynamicRangeType { 120 kSdrType, 121 kHdrType, 122 }; 123 124 // ENUM to identify different Postprocessing feature block to program. 125 // Note: For each new entry added here, also need update hw_interface::GetPPFeaturesVersion<> 126 // AND HWPrimary::SetPPFeatures<>. 127 enum PPGlobalColorFeatureID { 128 kGlobalColorFeaturePcc, 129 kGlobalColorFeatureIgc, 130 kGlobalColorFeaturePgc, 131 kMixerColorFeatureGc, 132 kGlobalColorFeaturePaV2, 133 kGlobalColorFeatureDither, 134 kGlobalColorFeatureGamut, 135 kGlobalColorFeaturePADither, 136 kMaxNumPPFeatures, 137 }; 138 139 enum PPSourceColorFeatureID { 140 kSourceColorFeatureIgc = kMaxNumPPFeatures + 1, 141 kSourceColorFeatureGc, 142 kSourceColorFeatureGamut, 143 kMaxNumSourcePPFeatures, 144 }; 145 146 struct PPPendingParams { 147 int32_t action = kNoAction; 148 void *params = NULL; 149 }; 150 151 struct PPColorInfo { 152 uint32_t r_bitdepth = 0; 153 uint32_t r = 0; 154 uint32_t g_bitdepth = 0; 155 uint32_t g = 0; 156 uint32_t b_bitdepth = 0; 157 uint32_t b = 0; 158 }; 159 160 struct PPColorFillParams { 161 uint32_t flags = 0; 162 struct { 163 uint32_t width = 0; 164 uint32_t height = 0; 165 int32_t x = 0; 166 int32_t y = 0; 167 } rect; 168 169 PPColorInfo color; 170 }; 171 172 struct PPFeatureVersion { 173 // SDE ASIC versioning its PP block at each specific feature level. 174 static const uint32_t kSDEPpVersionInvalid = 0; 175 static const uint32_t kSDEIgcV17 = 1; 176 static const uint32_t kSDEPgcV17 = 5; 177 static const uint32_t kSDEDitherV17 = 7; 178 static const uint32_t kSDEGamutV17 = 9; 179 static const uint32_t kSDEPaV17 = 11; 180 static const uint32_t kSDEPccV17 = 13; 181 static const uint32_t kSDELegacyPP = 15; 182 static const uint32_t kSDEPADitherV17 = 16; 183 static const uint32_t kSDEIgcV30 = 17; 184 static const uint32_t kSDEGamutV4 = 18; 185 static const uint32_t kSDEPccV4 = 19; 186 187 uint32_t version[kMaxNumPPFeatures]; PPFeatureVersionPPFeatureVersion188 PPFeatureVersion() { memset(version, 0, sizeof(version)); } 189 }; 190 191 struct PPHWAttributes : HWResourceInfo, HWPanelInfo, DisplayConfigVariableInfo { 192 char panel_name[256] = "generic_panel"; 193 PPFeatureVersion version; 194 DppsControlInterface *dpps_intf = NULL; 195 196 void Set(const HWResourceInfo &hw_res, const HWPanelInfo &panel_info, 197 const DisplayConfigVariableInfo &attr, const PPFeatureVersion &feature_ver, 198 DppsControlInterface *dpps_intf); 199 }; 200 201 struct PPDisplayAPIPayload { 202 bool own_payload = false; // to indicate if *payload is owned by this or just a reference. 203 uint32_t size = 0; 204 uint8_t *payload = NULL; 205 int fd = -1; 206 207 PPDisplayAPIPayload() = default; PPDisplayAPIPayloadPPDisplayAPIPayload208 PPDisplayAPIPayload(uint32_t size, uint8_t *param) 209 : size(size), payload(param) {} 210 211 template <typename T> CreatePayloadPPDisplayAPIPayload212 DisplayError CreatePayload(T *&output) { 213 DisplayError ret = kErrorNone; 214 215 payload = new uint8_t[sizeof(T)](); 216 if (!payload) { 217 ret = kErrorMemory; 218 output = NULL; 219 } else { 220 this->size = sizeof(T); 221 output = reinterpret_cast<T *>(payload); 222 own_payload = true; 223 } 224 return ret; 225 } 226 CreatePayloadBytesPPDisplayAPIPayload227 DisplayError CreatePayloadBytes(uint32_t size_in_bytes, uint8_t **output) { 228 DisplayError ret = kErrorNone; 229 230 payload = new uint8_t[size_in_bytes](); 231 if (!payload) { 232 ret = kErrorMemory; 233 *output = NULL; 234 } else { 235 this->size = size_in_bytes; 236 *output = payload; 237 own_payload = true; 238 } 239 return ret; 240 } 241 DestroyPayloadPPDisplayAPIPayload242 inline void DestroyPayload() { 243 if (payload && own_payload) { 244 delete[] payload; 245 payload = NULL; 246 size = 0; 247 } else { 248 payload = NULL; 249 size = 0; 250 } 251 } 252 }; 253 254 struct PPRectInfo { 255 uint32_t width; 256 uint32_t height; 257 int32_t x; 258 int32_t y; 259 }; 260 261 typedef enum { 262 PP_PIXEL_FORMAT_NONE = 0, 263 PP_PIXEL_FORMAT_RGB_888, 264 PP_PIXEL_FORMAT_RGB_2101010, 265 PP_PIXEL_FORMAT_MAX, 266 PP_PIXEL_FORMAT_FORCE32BIT = 0x7FFFFFFF, 267 } PPPixelFormats; 268 269 struct PPFrameCaptureInputParams { 270 PPRectInfo rect; 271 PPPixelFormats out_pix_format; 272 uint32_t flags; 273 }; 274 275 struct PPFrameCaptureData { 276 PPFrameCaptureInputParams input_params; 277 uint8_t *buffer; 278 uint32_t buffer_stride; 279 uint32_t buffer_size; 280 }; 281 282 struct SDEGamutCfg { 283 static const int kGamutTableNum = 4; 284 static const int kGamutScaleoffTableNum = 3; 285 static const int kGamutTableSize = 1229; 286 static const int kGamutTableCoarse13Size = 550; 287 static const int kGamutTableCoarseSize = 32; 288 static const int kGamutScaleoffSize = 16; 289 uint32_t mode; 290 uint32_t map_en; 291 uint32_t tbl_size[kGamutTableNum]; 292 uint32_t *c0_data[kGamutTableNum]; 293 uint32_t *c1_c2_data[kGamutTableNum]; 294 uint32_t tbl_scale_off_sz[kGamutScaleoffTableNum]; 295 uint32_t *scale_off_data[kGamutScaleoffTableNum]; 296 }; 297 298 struct SDEPccCoeff { 299 uint32_t c = 0; 300 uint32_t r = 0; 301 uint32_t g = 0; 302 uint32_t b = 0; 303 uint32_t rg = 0; 304 uint32_t gb = 0; 305 uint32_t rb = 0; 306 uint32_t rgb = 0; 307 }; 308 309 struct SDEPccCfg { 310 SDEPccCoeff red; 311 SDEPccCoeff green; 312 SDEPccCoeff blue; 313 314 static SDEPccCfg *Init(uint32_t arg __attribute__((__unused__))); GetConfigSDEPccCfg315 SDEPccCfg *GetConfig() { return this; } 316 }; 317 318 struct SDEPccV4Coeff { 319 uint32_t c = 0; 320 uint32_t r = 0; 321 uint32_t g = 0; 322 uint32_t b = 0; 323 uint32_t rg = 0; 324 uint32_t gb = 0; 325 uint32_t rb = 0; 326 uint32_t rgb = 0; 327 uint32_t rr = 0; 328 uint32_t gg = 0; 329 uint32_t bb = 0; 330 }; 331 332 struct SDEPccV4Cfg { 333 SDEPccV4Coeff red; 334 SDEPccV4Coeff green; 335 SDEPccV4Coeff blue; 336 337 static SDEPccV4Cfg *Init(uint32_t arg __attribute__((__unused__))); GetConfigSDEPccV4Cfg338 SDEPccV4Cfg *GetConfig() { return this; } 339 }; 340 341 struct SDEDitherCfg { 342 uint32_t g_y_depth; 343 uint32_t r_cr_depth; 344 uint32_t b_cb_depth; 345 uint32_t length; 346 uint32_t dither_matrix[16]; 347 uint32_t temporal_en; 348 349 static SDEDitherCfg *Init(uint32_t arg __attribute__((__unused__))); GetConfigSDEDitherCfg350 SDEDitherCfg *GetConfig() { return this; } 351 }; 352 353 struct SDEPADitherData { 354 uint64_t data_flags; 355 uint32_t matrix_size; 356 uint64_t matrix_data_addr; 357 uint32_t strength; 358 uint32_t offset_en; 359 }; 360 361 class SDEPADitherWrapper : private SDEPADitherData { 362 public: 363 static SDEPADitherWrapper *Init(uint32_t arg __attribute__((__unused__))); ~SDEPADitherWrapper()364 ~SDEPADitherWrapper() { 365 if (buffer_) 366 delete[] buffer_; 367 } GetConfig(void)368 inline SDEPADitherData *GetConfig(void) { return this; } 369 370 private: SDEPADitherWrapper()371 SDEPADitherWrapper() {} 372 uint32_t *buffer_ = NULL; 373 }; 374 375 struct SDEPaMemColorData { 376 uint32_t adjust_p0 = 0; 377 uint32_t adjust_p1 = 0; 378 uint32_t adjust_p2 = 0; 379 uint32_t blend_gain = 0; 380 uint8_t sat_hold = 0; 381 uint8_t val_hold = 0; 382 uint32_t hue_region = 0; 383 uint32_t sat_region = 0; 384 uint32_t val_region = 0; 385 }; 386 387 struct SDEPaData { 388 static const int kSixZoneLUTSize = 384; 389 uint32_t mode = 0; 390 uint32_t hue_adj = 0; 391 uint32_t sat_adj = 0; 392 uint32_t val_adj = 0; 393 uint32_t cont_adj; 394 SDEPaMemColorData skin; 395 SDEPaMemColorData sky; 396 SDEPaMemColorData foliage; 397 uint32_t six_zone_thresh = 0; 398 uint32_t six_zone_adj_p0 = 0; 399 uint32_t six_zone_adj_p1 = 0; 400 uint8_t six_zone_sat_hold = 0; 401 uint8_t six_zone_val_hold = 0; 402 uint32_t six_zone_len = 0; 403 uint32_t *six_zone_curve_p0 = NULL; 404 uint32_t *six_zone_curve_p1 = NULL; 405 }; 406 407 struct SDEIgcLUTData { 408 static const int kMaxIgcLUTEntries = 256; 409 uint32_t table_fmt = 0; 410 uint32_t len = 0; 411 uint32_t *c0_c1_data = NULL; 412 uint32_t *c2_data = NULL; 413 }; 414 415 struct SDEIgcV30LUTData { 416 static const int kMaxIgcLUTEntries = 256; 417 uint32_t table_fmt = 0; 418 uint32_t len = 0; 419 uint64_t c0_c1_data = 0; 420 uint64_t c2_data = 0; 421 uint32_t strength = 0; 422 }; 423 424 struct SDEPgcLUTData { 425 static const int kPgcLUTEntries = 1024; 426 uint32_t len = 0; 427 uint32_t *c0_data = NULL; 428 uint32_t *c1_data = NULL; 429 uint32_t *c2_data = NULL; 430 }; 431 432 struct SDEDisplayMode { 433 static const int kMaxModeNameSize = 256; 434 int32_t id = -1; 435 uint32_t type = 0; 436 char name[kMaxModeNameSize] = {0}; 437 }; 438 439 // Wrapper on HW block config data structure to encapsulate the details of allocating 440 // and destroying from the caller. 441 class SDEGamutCfgWrapper : private SDEGamutCfg { 442 public: 443 enum GamutMode { 444 GAMUT_FINE_MODE = 0x01, 445 GAMUT_COARSE_MODE, 446 GAMUT_COARSE_MODE_13, 447 }; 448 449 // This factory method will be used by libsdm-color.so data producer to be populated with 450 // converted config values for SDE feature blocks. 451 static SDEGamutCfgWrapper *Init(uint32_t arg); 452 453 // Data consumer<Commit thread> will be responsible to destroy it once the feature is commited. ~SDEGamutCfgWrapper()454 ~SDEGamutCfgWrapper() { 455 if (buffer_) 456 delete[] buffer_; 457 } 458 459 // Data consumer will use this method to retrieve contained feature configuration. GetConfig(void)460 inline SDEGamutCfg *GetConfig(void) { return this; } 461 462 private: SDEGamutCfgWrapper()463 SDEGamutCfgWrapper() {} 464 uint32_t *buffer_ = NULL; 465 }; 466 467 class SDEPaCfgWrapper : private SDEPaData { 468 public: 469 static SDEPaCfgWrapper *Init(uint32_t arg = 0); ~SDEPaCfgWrapper()470 ~SDEPaCfgWrapper() { 471 if (buffer_) 472 delete[] buffer_; 473 } GetConfig(void)474 inline SDEPaData *GetConfig(void) { return this; } 475 476 private: SDEPaCfgWrapper()477 SDEPaCfgWrapper() {} 478 uint32_t *buffer_ = NULL; 479 }; 480 481 class SDEIgcLUTWrapper : private SDEIgcLUTData { 482 public: 483 static SDEIgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__))); ~SDEIgcLUTWrapper()484 ~SDEIgcLUTWrapper() { 485 if (buffer_) 486 delete[] buffer_; 487 } GetConfig(void)488 inline SDEIgcLUTData *GetConfig(void) { return this; } 489 490 private: SDEIgcLUTWrapper()491 SDEIgcLUTWrapper() {} 492 uint32_t *buffer_ = NULL; 493 }; 494 495 class SDEIgcV30LUTWrapper : private SDEIgcV30LUTData { 496 public: 497 static SDEIgcV30LUTWrapper *Init(uint32_t arg __attribute__((__unused__))); ~SDEIgcV30LUTWrapper()498 ~SDEIgcV30LUTWrapper() { 499 if (buffer_) 500 delete[] buffer_; 501 } GetConfig(void)502 inline SDEIgcV30LUTData *GetConfig(void) { return this; } 503 504 private: SDEIgcV30LUTWrapper(const SDEIgcV30LUTWrapper & src)505 SDEIgcV30LUTWrapper(const SDEIgcV30LUTWrapper& src __attribute__((__unused__))) { 506 /* do not create copies */ } 507 SDEIgcV30LUTWrapper& operator=(const SDEIgcV30LUTWrapper&) { return *this; } SDEIgcV30LUTWrapper()508 SDEIgcV30LUTWrapper() {} 509 uint32_t *buffer_ = NULL; 510 }; 511 512 class SDEPgcLUTWrapper : private SDEPgcLUTData { 513 public: 514 static SDEPgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__))); ~SDEPgcLUTWrapper()515 ~SDEPgcLUTWrapper() { 516 if (buffer_) 517 delete[] buffer_; 518 } GetConfig(void)519 inline SDEPgcLUTData *GetConfig(void) { return this; } 520 521 private: SDEPgcLUTWrapper()522 SDEPgcLUTWrapper() {} 523 uint32_t *buffer_ = NULL; 524 }; 525 526 // Individual Postprocessing feature representing physical attributes and information 527 // This template class wrapping around abstract data type representing different 528 // post-processing features. It will take output from ColorManager converting from raw metadata. 529 // The configuration will directly pass into HWInterface to program the hardware accordingly. 530 template <typename T> 531 class TPPFeatureInfo : public PPFeatureInfo { 532 public: ~TPPFeatureInfo()533 virtual ~TPPFeatureInfo() { 534 if (params_) 535 delete params_; 536 } 537 538 // API for data consumer to get underlying data configs to program into pp hardware block. GetConfigData(void)539 virtual void *GetConfigData(void) const { return params_->GetConfig(); } 540 541 // API for data producer to get access to underlying data configs to populate it. GetParamsReference(void)542 T *GetParamsReference(void) { return params_; } 543 544 // API for create this template object. 545 static TPPFeatureInfo *Init(uint32_t arg = 0) { 546 TPPFeatureInfo *info = new TPPFeatureInfo(); 547 if (info) { 548 info->params_ = T::Init(arg); 549 if (!info->params_) { 550 delete info; 551 info = NULL; 552 } 553 } 554 555 return info; 556 } 557 558 protected: 559 TPPFeatureInfo() = default; 560 561 private: 562 T *params_ = NULL; 563 }; 564 565 // This singleton class serves as data exchanging central between data producer 566 // <libsdm-color.so> and data consumer<SDM and HWC.> 567 // This class defines PP pending features to be programmed, which generated from 568 // ColorManager. Dirty flag indicates some features are available to be programmed. 569 // () Lock is needed since the object wil be accessed from 2 tasks. 570 // All API exposed are not threadsafe, it's caller's responsiblity to acquire the locker. 571 class PPFeaturesConfig { 572 public: PPFeaturesConfig()573 PPFeaturesConfig() { memset(feature_, 0, sizeof(feature_)); } ~PPFeaturesConfig()574 ~PPFeaturesConfig() { Reset(); } 575 576 // ColorManager installs one TFeatureInfo<T> to take the output configs computed 577 // from ColorManager, containing all physical features to be programmed and also compute 578 // metadata/populate into T. AddFeature(uint32_t feature_id,PPFeatureInfo * feature)579 inline DisplayError AddFeature(uint32_t feature_id, PPFeatureInfo *feature) { 580 if (feature_id < kMaxNumPPFeatures) { 581 if (feature_[feature_id]) { 582 delete feature_[feature_id]; 583 feature_[feature_id] = NULL; 584 } 585 feature_[feature_id] = feature; 586 } 587 return kErrorNone; 588 } 589 GetFeature(uint32_t feature_id)590 inline PPFeatureInfo* GetFeature(uint32_t feature_id) { 591 PPFeatureInfo* feature = nullptr; 592 if (feature_id < kMaxNumPPFeatures) { 593 if (feature_[feature_id]) { 594 feature = feature_[feature_id]; 595 } 596 } 597 return feature; 598 } 599 GetLocker(void)600 inline Locker &GetLocker(void) { return locker_; } GetFrameCaptureData(void)601 inline PPFrameCaptureData *GetFrameCaptureData(void) { return &frame_capture_data; } GetDETuningCfgData(void)602 inline PPDETuningCfgData *GetDETuningCfgData(void) { return &de_tuning_data_; } 603 // Once all features are consumed, destroy/release all TFeatureInfo<T> on the list, 604 // then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer. 605 void Reset(); 606 607 // Consumer to call this to retrieve all the TFeatureInfo<T> on the list to be programmed. 608 DisplayError RetrieveNextFeature(PPFeatureInfo **feature); 609 IsDirty()610 inline bool IsDirty() { return dirty_; } MarkAsDirty()611 inline void MarkAsDirty() { dirty_ = true; } 612 613 private: 614 bool dirty_ = 0; 615 Locker locker_; 616 PPFeatureInfo *feature_[kMaxNumPPFeatures]; // reference to TFeatureInfo<T>. 617 uint32_t next_idx_ = 0; 618 PPFrameCaptureData frame_capture_data; 619 PPDETuningCfgData de_tuning_data_; 620 }; 621 622 } // namespace sdm 623 624 #endif // __COLOR_PARAMS_H__ 625