summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-06-03 17:54:24 -0300
committerGravatar Yuri Kunde Schlesner2015-06-20 19:21:16 -0300
commit29d2b70ea475037b4928bd371e37e0bbb102ad80 (patch)
tree0e5babba8d8a745f8fefac5b30c32a04331661e8
parentMerge pull request #871 from gwicks/master (diff)
downloadyuzu-29d2b70ea475037b4928bd371e37e0bbb102ad80.tar.gz
yuzu-29d2b70ea475037b4928bd371e37e0bbb102ad80.tar.xz
yuzu-29d2b70ea475037b4928bd371e37e0bbb102ad80.zip
Y2R: Re-organize how params are stored. Support SetConversionParams
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/y2r_u.cpp172
1 files changed, 100 insertions, 72 deletions
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index 19bfde756..73a0899dd 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -20,7 +20,7 @@
20 20
21namespace Y2R_U { 21namespace Y2R_U {
22 22
23enum class InputFormat { 23enum class InputFormat : u8 {
24 /// 8-bit input, with YUV components in separate planes and using 4:2:2 subsampling. 24 /// 8-bit input, with YUV components in separate planes and using 4:2:2 subsampling.
25 YUV422_Indiv8 = 0, 25 YUV422_Indiv8 = 0,
26 /// 8-bit input, with YUV components in separate planes and using 4:2:0 subsampling. 26 /// 8-bit input, with YUV components in separate planes and using 4:2:0 subsampling.
@@ -31,28 +31,28 @@ enum class InputFormat {
31 YUV422_BATCH = 4, 31 YUV422_BATCH = 4,
32}; 32};
33 33
34enum class OutputFormat { 34enum class OutputFormat : u8 {
35 Rgb32 = 0, 35 Rgb32 = 0,
36 Rgb24 = 1, 36 Rgb24 = 1,
37 Rgb16_555 = 2, 37 Rgb16_555 = 2,
38 Rgb16_565 = 3, 38 Rgb16_565 = 3,
39}; 39};
40 40
41enum class Rotation { 41enum class Rotation : u8 {
42 None = 0, 42 None = 0,
43 Clockwise_90 = 1, 43 Clockwise_90 = 1,
44 Clockwise_180 = 2, 44 Clockwise_180 = 2,
45 Clockwise_270 = 3, 45 Clockwise_270 = 3,
46}; 46};
47 47
48enum class BlockAlignment { 48enum class BlockAlignment : u8 {
49 /// Image is output in linear format suitable for use as a framebuffer. 49 /// Image is output in linear format suitable for use as a framebuffer.
50 Linear = 0, 50 Linear = 0,
51 /// Image is output in tiled PICA format, suitable for use as a texture. 51 /// Image is output in tiled PICA format, suitable for use as a texture.
52 Block8x8 = 1, 52 Block8x8 = 1,
53}; 53};
54 54
55enum class StandardCoefficient { 55enum class StandardCoefficient : u8 {
56 ITU_Rec601 = 0, 56 ITU_Rec601 = 0,
57 ITU_Rec709 = 1, 57 ITU_Rec709 = 1,
58 ITU_Rec601_Scaling = 2, 58 ITU_Rec601_Scaling = 2,
@@ -65,30 +65,37 @@ struct ConversionParameters {
65 InputFormat input_format; 65 InputFormat input_format;
66 OutputFormat output_format; 66 OutputFormat output_format;
67 Rotation rotation; 67 Rotation rotation;
68 BlockAlignment alignment; 68 BlockAlignment block_alignment;
69 u16 input_line_width; 69 u16 input_line_width;
70 u16 input_lines; 70 u16 input_lines;
71 StandardCoefficient standard_coefficient;
72 u8 reserved;
73 u16 alpha;
74};
75static_assert(sizeof(ConversionParameters) == 12, "ConversionParameters struct has incorrect size");
76
77struct ConversionBuffer {
78 VAddr address;
79 u32 image_size;
80 u16 transfer_unit;
81 u16 stride;
82};
71 83
72 // Input parameters for the Y (luma) plane 84struct ConversionData {
73 VAddr srcY_address; 85 ConversionParameters params;
74 u32 srcY_image_size; 86 /// Input parameters for the Y (luma) plane
75 u16 srcY_transfer_unit; 87 ConversionBuffer src_Y;
76 u16 srcY_stride; 88 /// Output parameters for the conversion results
77 89 ConversionBuffer dst;
78 // Output parameters for the conversion results
79 VAddr dst_address;
80 u32 dst_image_size;
81 u16 dst_transfer_unit;
82 u16 dst_stride;
83}; 90};
84 91
85static ConversionParameters conversion_params; 92static ConversionData conversion;
86 93
87static void SetInputFormat(Service::Interface* self) { 94static void SetInputFormat(Service::Interface* self) {
88 u32* cmd_buff = Kernel::GetCommandBuffer(); 95 u32* cmd_buff = Kernel::GetCommandBuffer();
89 96
90 conversion_params.input_format = static_cast<InputFormat>(cmd_buff[1]); 97 conversion.params.input_format = static_cast<InputFormat>(cmd_buff[1]);
91 LOG_DEBUG(Service_Y2R, "called input_format=%u", conversion_params.input_format); 98 LOG_DEBUG(Service_Y2R, "called input_format=%u", conversion.params.input_format);
92 99
93 cmd_buff[1] = RESULT_SUCCESS.raw; 100 cmd_buff[1] = RESULT_SUCCESS.raw;
94} 101}
@@ -96,8 +103,8 @@ static void SetInputFormat(Service::Interface* self) {
96static void SetOutputFormat(Service::Interface* self) { 103static void SetOutputFormat(Service::Interface* self) {
97 u32* cmd_buff = Kernel::GetCommandBuffer(); 104 u32* cmd_buff = Kernel::GetCommandBuffer();
98 105
99 conversion_params.output_format = static_cast<OutputFormat>(cmd_buff[1]); 106 conversion.params.output_format = static_cast<OutputFormat>(cmd_buff[1]);
100 LOG_DEBUG(Service_Y2R, "called output_format=%u", conversion_params.output_format); 107 LOG_DEBUG(Service_Y2R, "called output_format=%u", conversion.params.output_format);
101 108
102 cmd_buff[1] = RESULT_SUCCESS.raw; 109 cmd_buff[1] = RESULT_SUCCESS.raw;
103} 110}
@@ -105,8 +112,8 @@ static void SetOutputFormat(Service::Interface* self) {
105static void SetRotation(Service::Interface* self) { 112static void SetRotation(Service::Interface* self) {
106 u32* cmd_buff = Kernel::GetCommandBuffer(); 113 u32* cmd_buff = Kernel::GetCommandBuffer();
107 114
108 conversion_params.rotation = static_cast<Rotation>(cmd_buff[1]); 115 conversion.params.rotation = static_cast<Rotation>(cmd_buff[1]);
109 LOG_DEBUG(Service_Y2R, "called rotation=%u", conversion_params.rotation); 116 LOG_DEBUG(Service_Y2R, "called rotation=%u", conversion.params.rotation);
110 117
111 cmd_buff[1] = RESULT_SUCCESS.raw; 118 cmd_buff[1] = RESULT_SUCCESS.raw;
112} 119}
@@ -114,18 +121,18 @@ static void SetRotation(Service::Interface* self) {
114static void SetBlockAlignment(Service::Interface* self) { 121static void SetBlockAlignment(Service::Interface* self) {
115 u32* cmd_buff = Kernel::GetCommandBuffer(); 122 u32* cmd_buff = Kernel::GetCommandBuffer();
116 123
117 conversion_params.alignment = static_cast<BlockAlignment>(cmd_buff[1]); 124 conversion.params.block_alignment = static_cast<BlockAlignment>(cmd_buff[1]);
118 LOG_DEBUG(Service_Y2R, "called alignment=%u", conversion_params.alignment); 125 LOG_DEBUG(Service_Y2R, "called alignment=%u", conversion.params.block_alignment);
119 126
120 cmd_buff[1] = RESULT_SUCCESS.raw; 127 cmd_buff[1] = RESULT_SUCCESS.raw;
121} 128}
122 129
123/** 130/**
124* Y2R_U::GetTransferEndEvent service function 131 * Y2R_U::GetTransferEndEvent service function
125* Outputs: 132 * Outputs:
126* 1 : Result of function, 0 on success, otherwise error code 133 * 1 : Result of function, 0 on success, otherwise error code
127* 3 : The handle of the completion event 134 * 3 : The handle of the completion event
128*/ 135 */
129static void GetTransferEndEvent(Service::Interface* self) { 136static void GetTransferEndEvent(Service::Interface* self) {
130 u32* cmd_buff = Kernel::GetCommandBuffer(); 137 u32* cmd_buff = Kernel::GetCommandBuffer();
131 138
@@ -137,14 +144,14 @@ static void GetTransferEndEvent(Service::Interface* self) {
137static void SetSendingY(Service::Interface* self) { 144static void SetSendingY(Service::Interface* self) {
138 u32* cmd_buff = Kernel::GetCommandBuffer(); 145 u32* cmd_buff = Kernel::GetCommandBuffer();
139 146
140 conversion_params.srcY_address = cmd_buff[1]; 147 conversion.src_Y.address = cmd_buff[1];
141 conversion_params.srcY_image_size = cmd_buff[2]; 148 conversion.src_Y.image_size = cmd_buff[2];
142 conversion_params.srcY_transfer_unit = cmd_buff[3]; 149 conversion.src_Y.transfer_unit = cmd_buff[3];
143 conversion_params.srcY_stride = cmd_buff[4]; 150 conversion.src_Y.stride = cmd_buff[4];
144 u32 src_process_handle = cmd_buff[6]; 151 u32 src_process_handle = cmd_buff[6];
145 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " 152 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
146 "src_process_handle=0x%08X", conversion_params.srcY_image_size, 153 "src_process_handle=0x%08X", conversion.src_Y.image_size,
147 conversion_params.srcY_transfer_unit, conversion_params.srcY_stride, src_process_handle); 154 conversion.src_Y.transfer_unit, conversion.src_Y.stride, src_process_handle);
148 155
149 cmd_buff[1] = RESULT_SUCCESS.raw; 156 cmd_buff[1] = RESULT_SUCCESS.raw;
150} 157}
@@ -152,14 +159,14 @@ static void SetSendingY(Service::Interface* self) {
152static void SetReceiving(Service::Interface* self) { 159static void SetReceiving(Service::Interface* self) {
153 u32* cmd_buff = Kernel::GetCommandBuffer(); 160 u32* cmd_buff = Kernel::GetCommandBuffer();
154 161
155 conversion_params.dst_address = cmd_buff[1]; 162 conversion.dst.address = cmd_buff[1];
156 conversion_params.dst_image_size = cmd_buff[2]; 163 conversion.dst.image_size = cmd_buff[2];
157 conversion_params.dst_transfer_unit = cmd_buff[3]; 164 conversion.dst.transfer_unit = cmd_buff[3];
158 conversion_params.dst_stride = cmd_buff[4]; 165 conversion.dst.stride = cmd_buff[4];
159 u32 dst_process_handle = cmd_buff[6]; 166 u32 dst_process_handle = cmd_buff[6];
160 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " 167 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
161 "dst_process_handle=0x%08X", conversion_params.dst_image_size, 168 "dst_process_handle=0x%08X", conversion.dst.image_size,
162 conversion_params.dst_transfer_unit, conversion_params.dst_stride, 169 conversion.dst.transfer_unit, conversion.dst.stride,
163 dst_process_handle); 170 dst_process_handle);
164 171
165 cmd_buff[1] = RESULT_SUCCESS.raw; 172 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -168,8 +175,8 @@ static void SetReceiving(Service::Interface* self) {
168static void SetInputLineWidth(Service::Interface* self) { 175static void SetInputLineWidth(Service::Interface* self) {
169 u32* cmd_buff = Kernel::GetCommandBuffer(); 176 u32* cmd_buff = Kernel::GetCommandBuffer();
170 177
171 conversion_params.input_line_width = cmd_buff[1]; 178 conversion.params.input_line_width = cmd_buff[1];
172 LOG_DEBUG(Service_Y2R, "input_line_width=%u", conversion_params.input_line_width); 179 LOG_DEBUG(Service_Y2R, "input_line_width=%u", conversion.params.input_line_width);
173 180
174 cmd_buff[1] = RESULT_SUCCESS.raw; 181 cmd_buff[1] = RESULT_SUCCESS.raw;
175} 182}
@@ -177,8 +184,8 @@ static void SetInputLineWidth(Service::Interface* self) {
177static void SetInputLines(Service::Interface* self) { 184static void SetInputLines(Service::Interface* self) {
178 u32* cmd_buff = Kernel::GetCommandBuffer(); 185 u32* cmd_buff = Kernel::GetCommandBuffer();
179 186
180 conversion_params.input_lines = cmd_buff[1]; 187 conversion.params.input_lines = cmd_buff[1];
181 LOG_DEBUG(Service_Y2R, "input_line_number=%u", conversion_params.input_lines); 188 LOG_DEBUG(Service_Y2R, "input_line_number=%u", conversion.params.input_lines);
182 189
183 cmd_buff[1] = RESULT_SUCCESS.raw; 190 cmd_buff[1] = RESULT_SUCCESS.raw;
184} 191}
@@ -186,23 +193,25 @@ static void SetInputLines(Service::Interface* self) {
186static void StartConversion(Service::Interface* self) { 193static void StartConversion(Service::Interface* self) {
187 u32* cmd_buff = Kernel::GetCommandBuffer(); 194 u32* cmd_buff = Kernel::GetCommandBuffer();
188 195
189 const u8* srcY_buffer = Memory::GetPointer(conversion_params.srcY_address); 196 const ConversionParameters& params = conversion.params;
190 u8* dst_buffer = Memory::GetPointer(conversion_params.dst_address); 197
198 const u8* srcY_buffer = Memory::GetPointer(conversion.src_Y.address);
199 u8* dst_buffer = Memory::GetPointer(conversion.dst.address);
191 200
192 // TODO: support color and other kinds of conversions 201 // TODO: support color and other kinds of conversions
193 ASSERT(conversion_params.input_format == InputFormat::YUV422_Indiv8 202 ASSERT(params.input_format == InputFormat::YUV422_Indiv8
194 || conversion_params.input_format == InputFormat::YUV420_Indiv8); 203 || params.input_format == InputFormat::YUV420_Indiv8);
195 ASSERT(conversion_params.output_format == OutputFormat::Rgb24); 204 ASSERT(params.output_format == OutputFormat::Rgb24);
196 ASSERT(conversion_params.rotation == Rotation::None); 205 ASSERT(params.rotation == Rotation::None);
197 const int bpp = 3; 206 const int bpp = 3;
198 207
199 switch (conversion_params.alignment) { 208 switch (params.block_alignment) {
200 case BlockAlignment::Linear: 209 case BlockAlignment::Linear:
201 { 210 {
202 const size_t input_lines = conversion_params.input_lines; 211 const size_t input_lines = params.input_lines;
203 const size_t input_line_width = conversion_params.input_line_width; 212 const size_t input_line_width = params.input_line_width;
204 const size_t srcY_stride = conversion_params.srcY_stride; 213 const size_t srcY_stride = conversion.src_Y.stride;
205 const size_t dst_stride = conversion_params.dst_stride; 214 const size_t dst_stride = conversion.dst.stride;
206 215
207 size_t srcY_offset = 0; 216 size_t srcY_offset = 0;
208 size_t dst_offset = 0; 217 size_t dst_offset = 0;
@@ -224,11 +233,11 @@ static void StartConversion(Service::Interface* self) {
224 } 233 }
225 case BlockAlignment::Block8x8: 234 case BlockAlignment::Block8x8:
226 { 235 {
227 const size_t input_lines = conversion_params.input_lines; 236 const size_t input_lines = params.input_lines;
228 const size_t input_line_width = conversion_params.input_line_width; 237 const size_t input_line_width = params.input_line_width;
229 const size_t srcY_stride = conversion_params.srcY_stride; 238 const size_t srcY_stride = conversion.src_Y.stride;
230 const size_t dst_transfer_unit = conversion_params.dst_transfer_unit; 239 const size_t dst_transfer_unit = conversion.dst.transfer_unit;
231 const size_t dst_stride = conversion_params.dst_stride; 240 const size_t dst_stride = conversion.dst.stride;
232 241
233 size_t srcY_offset = 0; 242 size_t srcY_offset = 0;
234 size_t dst_tile_line_offs = 0; 243 size_t dst_tile_line_offs = 0;
@@ -265,10 +274,10 @@ static void StartConversion(Service::Interface* self) {
265 } 274 }
266 275
267 // dst_image_size would seem to be perfect for this, but it doesn't include the stride :( 276 // dst_image_size would seem to be perfect for this, but it doesn't include the stride :(
268 u32 total_output_size = conversion_params.input_lines * 277 u32 total_output_size = params.input_lines *
269 (conversion_params.dst_transfer_unit + conversion_params.dst_stride); 278 (conversion.dst.transfer_unit + conversion.dst.stride);
270 VideoCore::g_renderer->hw_rasterizer->NotifyFlush( 279 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
271 Memory::VirtualToPhysicalAddress(conversion_params.dst_address), total_output_size); 280 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
272 281
273 LOG_DEBUG(Service_Y2R, "called"); 282 LOG_DEBUG(Service_Y2R, "called");
274 completion_event->Signal(); 283 completion_event->Signal();
@@ -277,11 +286,11 @@ static void StartConversion(Service::Interface* self) {
277} 286}
278 287
279/** 288/**
280* Y2R_U::IsBusyConversion service function 289 * Y2R_U::IsBusyConversion service function
281* Outputs: 290 * Outputs:
282* 1 : Result of function, 0 on success, otherwise error code 291 * 1 : Result of function, 0 on success, otherwise error code
283* 2 : 1 if there's a conversion running, otherwise 0. 292 * 2 : 1 if there's a conversion running, otherwise 0.
284*/ 293 */
285static void IsBusyConversion(Service::Interface* self) { 294static void IsBusyConversion(Service::Interface* self) {
286 u32* cmd_buff = Kernel::GetCommandBuffer(); 295 u32* cmd_buff = Kernel::GetCommandBuffer();
287 296
@@ -290,6 +299,24 @@ static void IsBusyConversion(Service::Interface* self) {
290 LOG_DEBUG(Service_Y2R, "called"); 299 LOG_DEBUG(Service_Y2R, "called");
291} 300}
292 301
302/**
303 * Y2R_U::SetConversionParams service function
304 */
305static void SetConversionParams(Service::Interface* self) {
306 u32* cmd_buff = Kernel::GetCommandBuffer();
307
308 auto params = reinterpret_cast<const ConversionParameters*>(&cmd_buff[1]);
309 conversion.params = *params;
310
311 cmd_buff[0] = 0x00290000; // TODO verify
312 cmd_buff[1] = RESULT_SUCCESS.raw;
313 LOG_DEBUG(Service_Y2R,
314 "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu "
315 "input_line_width=%hX input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX",
316 params->input_format, params->output_format, params->rotation, params->block_alignment,
317 params->input_line_width, params->input_lines, params->standard_coefficient);
318}
319
293static void PingProcess(Service::Interface* self) { 320static void PingProcess(Service::Interface* self) {
294 u32* cmd_buff = Kernel::GetCommandBuffer(); 321 u32* cmd_buff = Kernel::GetCommandBuffer();
295 322
@@ -316,6 +343,7 @@ const Interface::FunctionInfo FunctionTable[] = {
316 {0x00260000, StartConversion, "StartConversion"}, 343 {0x00260000, StartConversion, "StartConversion"},
317 {0x00270000, nullptr, "StopConversion"}, 344 {0x00270000, nullptr, "StopConversion"},
318 {0x00280000, IsBusyConversion, "IsBusyConversion"}, 345 {0x00280000, IsBusyConversion, "IsBusyConversion"},
346 {0x002901C0, SetConversionParams, "SetConversionParams"},
319 {0x002A0000, PingProcess, "PingProcess"}, 347 {0x002A0000, PingProcess, "PingProcess"},
320 {0x002B0000, nullptr, "DriverInitialize"}, 348 {0x002B0000, nullptr, "DriverInitialize"},
321 {0x002C0000, nullptr, "DriverFinalize"}, 349 {0x002C0000, nullptr, "DriverFinalize"},
@@ -326,7 +354,7 @@ const Interface::FunctionInfo FunctionTable[] = {
326 354
327Interface::Interface() { 355Interface::Interface() {
328 completion_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "Y2R:Completed"); 356 completion_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "Y2R:Completed");
329 std::memset(&conversion_params, 0, sizeof(conversion_params)); 357 std::memset(&conversion, 0, sizeof(conversion));
330 358
331 Register(FunctionTable); 359 Register(FunctionTable);
332} 360}