1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "host/libs/graphics_detector/graphics_configuration.h"
18 
19 #include <ostream>
20 
21 #include <android-base/strings.h>
22 
23 #include "host/libs/config/cuttlefish_config.h"
24 
25 namespace cuttlefish {
26 namespace {
27 
28 struct AngleFeatures {
29   // Prefer linear filtering for YUV AHBs to pass
30   // android.media.decoder.cts.DecodeAccuracyTest.
31   bool prefer_linear_filtering_for_yuv = true;
32 
33   // Map unspecified color spaces to PASS_THROUGH to pass
34   // android.media.codec.cts.DecodeEditEncodeTest and
35   // android.media.codec.cts.EncodeDecodeTest.
36   bool map_unspecified_color_space_to_pass_through = true;
37 
38   // b/264575911: Nvidia seems to have issues with YUV samplers with
39   // 'lowp' and 'mediump' precision qualifiers.
40   bool ignore_precision_qualifiers = false;
41 };
42 
operator <<(std::ostream & stream,const AngleFeatures & features)43 std::ostream& operator<<(std::ostream& stream, const AngleFeatures& features) {
44   std::ios_base::fmtflags flags_backup(stream.flags());
45   stream << std::boolalpha;
46   stream << "ANGLE features: "
47          << "\n";
48   stream << " - prefer_linear_filtering_for_yuv: "
49          << features.prefer_linear_filtering_for_yuv << "\n";
50   stream << " - map_unspecified_color_space_to_pass_through: "
51          << features.map_unspecified_color_space_to_pass_through << "\n";
52   stream << " - ignore_precision_qualifiers: "
53          << features.ignore_precision_qualifiers << "\n";
54   stream.flags(flags_backup);
55   return stream;
56 }
57 
GetNeededAngleFeaturesBasedOnQuirks(const RenderingMode mode,const GraphicsAvailability & availability)58 AngleFeatures GetNeededAngleFeaturesBasedOnQuirks(
59     const RenderingMode mode, const GraphicsAvailability& availability) {
60   AngleFeatures features = {};
61   switch (mode) {
62     case RenderingMode::kGfxstream:
63       break;
64     case RenderingMode::kGfxstreamGuestAngle: {
65       if (availability
66               .vulkan_has_issue_with_precision_qualifiers_on_yuv_samplers) {
67         features.ignore_precision_qualifiers = true;
68       }
69       break;
70     }
71     case RenderingMode::kGuestSwiftShader:
72     case RenderingMode::kVirglRenderer:
73     case RenderingMode::kNone:
74       break;
75   }
76   return features;
77 }
78 
79 }  // namespace
80 
GetRenderingMode(const std::string & mode)81 Result<RenderingMode> GetRenderingMode(const std::string& mode) {
82   if (mode == std::string(kGpuModeDrmVirgl)) {
83     return RenderingMode::kVirglRenderer;
84   }
85   if (mode == std::string(kGpuModeGfxstream)) {
86     return RenderingMode::kGfxstream;
87   }
88   if (mode == std::string(kGpuModeGfxstreamGuestAngle)) {
89     return RenderingMode::kGfxstreamGuestAngle;
90   }
91   if (mode == std::string(kGpuModeGuestSwiftshader)) {
92     return RenderingMode::kGuestSwiftShader;
93   }
94   if (mode == std::string(kGpuModeNone)) {
95     return RenderingMode::kNone;
96   }
97   return CF_ERR("Unsupported rendering mode: " << mode);
98 }
99 
GetNeededAngleFeatures(const RenderingMode mode,const GraphicsAvailability & availability)100 Result<AngleFeatureOverrides> GetNeededAngleFeatures(
101     const RenderingMode mode, const GraphicsAvailability& availability) {
102   const AngleFeatures features =
103       GetNeededAngleFeaturesBasedOnQuirks(mode, availability);
104   LOG(DEBUG) << features;
105 
106   std::vector<std::string> enable_feature_strings;
107   std::vector<std::string> disable_feature_strings;
108   if (features.prefer_linear_filtering_for_yuv) {
109     enable_feature_strings.push_back("preferLinearFilterForYUV");
110   }
111   if (features.map_unspecified_color_space_to_pass_through) {
112     enable_feature_strings.push_back("mapUnspecifiedColorSpaceToPassThrough");
113   }
114   if (features.ignore_precision_qualifiers) {
115     disable_feature_strings.push_back("enablePrecisionQualifiers");
116   }
117 
118   return AngleFeatureOverrides{
119       .angle_feature_overrides_enabled =
120           android::base::Join(enable_feature_strings, ':'),
121       .angle_feature_overrides_disabled =
122           android::base::Join(disable_feature_strings, ':'),
123   };
124 }
125 
126 }  // namespace cuttlefish