1 // Copyright 2014 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <memory> 9 #include <string> 10 #include <boost/serialization/array.hpp> 11 #include "common/common_types.h" 12 #include "core/hle/result.h" 13 #include "core/hle/service/service.h" 14 15 namespace Core { 16 class System; 17 } 18 19 namespace Kernel { 20 class Event; 21 } 22 23 namespace Service::Y2R { 24 25 enum class InputFormat : u8 { 26 /// 8-bit input, with YUV components in separate planes and 4:2:2 subsampling. 27 YUV422_Indiv8 = 0, 28 /// 8-bit input, with YUV components in separate planes and 4:2:0 subsampling. 29 YUV420_Indiv8 = 1, 30 31 /// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:2 subsampling. 32 YUV422_Indiv16 = 2, 33 /// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:0 subsampling. 34 YUV420_Indiv16 = 3, 35 36 /// 8-bit input, with a single interleaved stream in YUYV format and 4:2:2 subsampling. 37 YUYV422_Interleaved = 4, 38 }; 39 40 enum class OutputFormat : u8 { 41 RGBA8 = 0, 42 RGB8 = 1, 43 RGB5A1 = 2, 44 RGB565 = 3, 45 }; 46 47 enum class Rotation : u8 { 48 None = 0, 49 Clockwise_90 = 1, 50 Clockwise_180 = 2, 51 Clockwise_270 = 3, 52 }; 53 54 enum class BlockAlignment : u8 { 55 /// Image is output in linear format suitable for use as a framebuffer. 56 Linear = 0, 57 /// Image is output in tiled PICA format, suitable for use as a texture. 58 Block8x8 = 1, 59 }; 60 61 enum class StandardCoefficient : u8 { 62 /// ITU Rec. BT.601 primaries, with PC ranges. 63 ITU_Rec601 = 0, 64 /// ITU Rec. BT.709 primaries, with PC ranges. 65 ITU_Rec709 = 1, 66 /// ITU Rec. BT.601 primaries, with TV ranges. 67 ITU_Rec601_Scaling = 2, 68 /// ITU Rec. BT.709 primaries, with TV ranges. 69 ITU_Rec709_Scaling = 3, 70 }; 71 72 /** 73 * A set of coefficients configuring the RGB to YUV conversion. Coefficients 0-4 are unsigned 2.8 74 * fixed pointer numbers representing entries on the conversion matrix, while coefficient 5-7 are 75 * signed 11.5 fixed point numbers added as offsets to the RGB result. 76 * 77 * The overall conversion process formula is: 78 * ``` 79 * R = trunc((c_0 * Y + c_1 * V) + c_5 + 0.75) 80 * G = trunc((c_0 * Y - c_3 * U - c_2 * V) + c_6 + 0.75) 81 * B = trunc((c_0 * Y + c_4 * U ) + c_7 + 0.75) 82 * ``` 83 */ 84 using CoefficientSet = std::array<s16, 8>; 85 86 struct ConversionBuffer { 87 /// Current reading/writing address of this buffer. 88 VAddr address; 89 /// Remaining amount of bytes to be DMAed, does not include the inter-trasfer gap. 90 u32 image_size; 91 /// Size of a single DMA transfer. 92 u16 transfer_unit; 93 /// Amount of bytes to be skipped between copying each `transfer_unit` bytes. 94 u16 gap; 95 96 private: 97 template <class Archive> serializeConversionBuffer98 void serialize(Archive& ar, const unsigned int) { 99 ar& address; 100 ar& image_size; 101 ar& transfer_unit; 102 ar& gap; 103 } 104 friend class boost::serialization::access; 105 }; 106 107 struct ConversionConfiguration { 108 InputFormat input_format; 109 OutputFormat output_format; 110 Rotation rotation; 111 BlockAlignment block_alignment; 112 u16 input_line_width; 113 u16 input_lines; 114 CoefficientSet coefficients; 115 u8 padding; 116 u16 alpha; 117 118 /// Input parameters for the Y (luma) plane 119 ConversionBuffer src_Y, src_U, src_V, src_YUYV; 120 /// Output parameters for the conversion results 121 ConversionBuffer dst; 122 123 ResultCode SetInputLineWidth(u16 width); 124 ResultCode SetInputLines(u16 lines); 125 ResultCode SetStandardCoefficient(StandardCoefficient standard_coefficient); 126 127 private: 128 template <class Archive> serializeConversionConfiguration129 void serialize(Archive& ar, const unsigned int) { 130 ar& input_format; 131 ar& output_format; 132 ar& rotation; 133 ar& block_alignment; 134 ar& input_line_width; 135 ar& input_lines; 136 ar& coefficients; 137 ar& padding; 138 ar& alpha; 139 ar& src_Y; 140 ar& src_U; 141 ar& src_V; 142 ar& src_YUYV; 143 ar& dst; 144 } 145 friend class boost::serialization::access; 146 }; 147 148 struct DitheringWeightParams { 149 u16 w0_xEven_yEven; 150 u16 w0_xOdd_yEven; 151 u16 w0_xEven_yOdd; 152 u16 w0_xOdd_yOdd; 153 u16 w1_xEven_yEven; 154 u16 w1_xOdd_yEven; 155 u16 w1_xEven_yOdd; 156 u16 w1_xOdd_yOdd; 157 u16 w2_xEven_yEven; 158 u16 w2_xOdd_yEven; 159 u16 w2_xEven_yOdd; 160 u16 w2_xOdd_yOdd; 161 u16 w3_xEven_yEven; 162 u16 w3_xOdd_yEven; 163 u16 w3_xEven_yOdd; 164 u16 w3_xOdd_yOdd; 165 166 private: 167 template <class Archive> serializeDitheringWeightParams168 void serialize(Archive& ar, const unsigned int) { 169 ar& w0_xEven_yEven; 170 ar& w0_xOdd_yEven; 171 ar& w0_xEven_yOdd; 172 ar& w0_xOdd_yOdd; 173 ar& w1_xEven_yEven; 174 ar& w1_xOdd_yEven; 175 ar& w1_xEven_yOdd; 176 ar& w1_xOdd_yOdd; 177 ar& w2_xEven_yEven; 178 ar& w2_xOdd_yEven; 179 ar& w2_xEven_yOdd; 180 ar& w2_xOdd_yOdd; 181 ar& w3_xEven_yEven; 182 ar& w3_xOdd_yEven; 183 ar& w3_xEven_yOdd; 184 ar& w3_xOdd_yOdd; 185 } 186 friend class boost::serialization::access; 187 }; 188 189 struct ConversionParameters { 190 InputFormat input_format; 191 OutputFormat output_format; 192 Rotation rotation; 193 BlockAlignment block_alignment; 194 u16 input_line_width; 195 u16 input_lines; 196 StandardCoefficient standard_coefficient; 197 u8 padding; 198 u16 alpha; 199 }; 200 static_assert(sizeof(ConversionParameters) == 12, "ConversionParameters struct has incorrect size"); 201 202 class Y2R_U final : public ServiceFramework<Y2R_U> { 203 public: 204 explicit Y2R_U(Core::System& system); 205 ~Y2R_U() override; 206 207 private: 208 void SetInputFormat(Kernel::HLERequestContext& ctx); 209 void GetInputFormat(Kernel::HLERequestContext& ctx); 210 void SetOutputFormat(Kernel::HLERequestContext& ctx); 211 void GetOutputFormat(Kernel::HLERequestContext& ctx); 212 void SetRotation(Kernel::HLERequestContext& ctx); 213 void GetRotation(Kernel::HLERequestContext& ctx); 214 void SetBlockAlignment(Kernel::HLERequestContext& ctx); 215 void GetBlockAlignment(Kernel::HLERequestContext& ctx); 216 217 /** 218 * Y2R_U::SetSpacialDithering service function 219 * Inputs: 220 * 1 : u8, 0 = Disabled, 1 = Enabled 221 * Outputs: 222 * 1 : Result of function, 0 on success, otherwise error code 223 */ 224 void SetSpacialDithering(Kernel::HLERequestContext& ctx); 225 226 /** 227 * Y2R_U::GetSpacialDithering service function 228 * Outputs: 229 * 1 : Result of function, 0 on success, otherwise error code 230 * 2 : u8, 0 = Disabled, 1 = Enabled 231 */ 232 void GetSpacialDithering(Kernel::HLERequestContext& ctx); 233 234 /** 235 * Y2R_U::SetTemporalDithering service function 236 * Inputs: 237 * 1 : u8, 0 = Disabled, 1 = Enabled 238 * Outputs: 239 * 1 : Result of function, 0 on success, otherwise error code 240 */ 241 void SetTemporalDithering(Kernel::HLERequestContext& ctx); 242 243 /** 244 * Y2R_U::GetTemporalDithering service function 245 * Outputs: 246 * 1 : Result of function, 0 on success, otherwise error code 247 * 2 : u8, 0 = Disabled, 1 = Enabled 248 */ 249 void GetTemporalDithering(Kernel::HLERequestContext& ctx); 250 251 /** 252 * Y2R_U::SetTransferEndInterrupt service function 253 * Inputs: 254 * 1 : u8, 0 = Disabled, 1 = Enabled 255 * Outputs: 256 * 1 : Result of function, 0 on success, otherwise error code 257 */ 258 void SetTransferEndInterrupt(Kernel::HLERequestContext& ctx); 259 260 /** 261 * Y2R_U::GetTransferEndInterrupt service function 262 * Outputs: 263 * 1 : Result of function, 0 on success, otherwise error code 264 * 2 : u8, 0 = Disabled, 1 = Enabled 265 */ 266 void GetTransferEndInterrupt(Kernel::HLERequestContext& ctx); 267 268 /** 269 * Y2R_U::GetTransferEndEvent service function 270 * Outputs: 271 * 1 : Result of function, 0 on success, otherwise error code 272 * 3 : The handle of the completion event 273 */ 274 void GetTransferEndEvent(Kernel::HLERequestContext& ctx); 275 276 void SetSendingY(Kernel::HLERequestContext& ctx); 277 void SetSendingU(Kernel::HLERequestContext& ctx); 278 void SetSendingV(Kernel::HLERequestContext& ctx); 279 void SetSendingYUYV(Kernel::HLERequestContext& ctx); 280 281 /** 282 * Y2R::IsFinishedSendingYuv service function 283 * Output: 284 * 1 : Result of the function, 0 on success, otherwise error code 285 * 2 : u8, 0 = Not Finished, 1 = Finished 286 */ 287 void IsFinishedSendingYuv(Kernel::HLERequestContext& ctx); 288 289 /** 290 * Y2R::IsFinishedSendingY service function 291 * Output: 292 * 1 : Result of the function, 0 on success, otherwise error code 293 * 2 : u8, 0 = Not Finished, 1 = Finished 294 */ 295 void IsFinishedSendingY(Kernel::HLERequestContext& ctx); 296 297 /** 298 * Y2R::IsFinishedSendingU service function 299 * Output: 300 * 1 : Result of the function, 0 on success, otherwise error code 301 * 2 : u8, 0 = Not Finished, 1 = Finished 302 */ 303 void IsFinishedSendingU(Kernel::HLERequestContext& ctx); 304 305 /** 306 * Y2R::IsFinishedSendingV service function 307 * Output: 308 * 1 : Result of the function, 0 on success, otherwise error code 309 * 2 : u8, 0 = Not Finished, 1 = Finished 310 */ 311 void IsFinishedSendingV(Kernel::HLERequestContext& ctx); 312 313 void SetReceiving(Kernel::HLERequestContext& ctx); 314 315 /** 316 * Y2R::IsFinishedReceiving service function 317 * Output: 318 * 1 : Result of the function, 0 on success, otherwise error code 319 * 2 : u8, 0 = Not Finished, 1 = Finished 320 */ 321 void IsFinishedReceiving(Kernel::HLERequestContext& ctx); 322 323 void SetInputLineWidth(Kernel::HLERequestContext& ctx); 324 void GetInputLineWidth(Kernel::HLERequestContext& ctx); 325 void SetInputLines(Kernel::HLERequestContext& ctx); 326 void GetInputLines(Kernel::HLERequestContext& ctx); 327 void SetCoefficient(Kernel::HLERequestContext& ctx); 328 void GetCoefficient(Kernel::HLERequestContext& ctx); 329 void SetStandardCoefficient(Kernel::HLERequestContext& ctx); 330 void GetStandardCoefficient(Kernel::HLERequestContext& ctx); 331 void SetAlpha(Kernel::HLERequestContext& ctx); 332 void GetAlpha(Kernel::HLERequestContext& ctx); 333 void SetDitheringWeightParams(Kernel::HLERequestContext& ctx); 334 void GetDitheringWeightParams(Kernel::HLERequestContext& ctx); 335 void StartConversion(Kernel::HLERequestContext& ctx); 336 void StopConversion(Kernel::HLERequestContext& ctx); 337 void IsBusyConversion(Kernel::HLERequestContext& ctx); 338 339 /** 340 * Y2R_U::SetPackageParameter service function 341 */ 342 void SetPackageParameter(Kernel::HLERequestContext& ctx); 343 344 void PingProcess(Kernel::HLERequestContext& ctx); 345 void DriverInitialize(Kernel::HLERequestContext& ctx); 346 void DriverFinalize(Kernel::HLERequestContext& ctx); 347 void GetPackageParameter(Kernel::HLERequestContext& ctx); 348 349 Core::System& system; 350 351 std::shared_ptr<Kernel::Event> completion_event; 352 ConversionConfiguration conversion{}; 353 DitheringWeightParams dithering_weight_params{}; 354 bool temporal_dithering_enabled = false; 355 bool transfer_end_interrupt_enabled = false; 356 bool spacial_dithering_enabled = false; 357 358 template <class Archive> 359 void serialize(Archive& ar, const unsigned int); 360 friend class boost::serialization::access; 361 }; 362 363 void InstallInterfaces(Core::System& system); 364 365 } // namespace Service::Y2R 366 367 SERVICE_CONSTRUCT(Service::Y2R::Y2R_U) 368 BOOST_CLASS_EXPORT_KEY(Service::Y2R::Y2R_U) 369