mirror of
https://github.com/PabloMK7/citra.git
synced 2025-10-11 20:10:03 +00:00
http/soc: Various implementations and fixes (#6828)
This commit is contained in:
parent
baf3ea4beb
commit
970f2284d8
17 changed files with 322 additions and 202 deletions
710
src/core/hle/service/cam/y2r_u.cpp
Normal file
710
src/core/hle/service/cam/y2r_u.cpp
Normal file
|
@ -0,0 +1,710 @@
|
|||
// Copyright 2015 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/service/cam/y2r_u.h"
|
||||
#include "core/hw/y2r.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::Y2R::Y2R_U)
|
||||
SERIALIZE_EXPORT_IMPL(Service::Y2R::Y2R_U)
|
||||
|
||||
namespace Service::Y2R {
|
||||
|
||||
template <class Archive>
|
||||
void Y2R_U::serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
|
||||
ar& completion_event;
|
||||
ar& conversion;
|
||||
ar& dithering_weight_params;
|
||||
ar& temporal_dithering_enabled;
|
||||
ar& transfer_end_interrupt_enabled;
|
||||
ar& spacial_dithering_enabled;
|
||||
}
|
||||
|
||||
constexpr std::array<CoefficientSet, 4> standard_coefficients{{
|
||||
{{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601
|
||||
{{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709
|
||||
{{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling
|
||||
{{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling
|
||||
}};
|
||||
|
||||
ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
|
||||
if (width == 0 || width > 1024 || width % 8 != 0) {
|
||||
return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
|
||||
ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
|
||||
}
|
||||
|
||||
// Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of
|
||||
// 1024 the `camera` module would set the value 0 here, but we don't need to emulate this
|
||||
// internal detail.
|
||||
this->input_line_width = width;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
|
||||
if (lines == 0 || lines > 1024) {
|
||||
return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
|
||||
ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
|
||||
}
|
||||
|
||||
// Note: In what appears to be a bug, the `camera` module does not set the hardware register at
|
||||
// all if `lines` is 1024, so the conversion uses the last value that was set. The intention
|
||||
// was probably to set it to 0 like in SetInputLineWidth.
|
||||
if (lines != 1024) {
|
||||
this->input_lines = lines;
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode ConversionConfiguration::SetStandardCoefficient(
|
||||
StandardCoefficient standard_coefficient) {
|
||||
const auto index = static_cast<std::size_t>(standard_coefficient);
|
||||
if (index >= standard_coefficients.size()) {
|
||||
return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
|
||||
ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED
|
||||
}
|
||||
|
||||
std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients));
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void Y2R_U::SetInputFormat(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.input_format = rp.PopEnum<InputFormat>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_format={}", conversion.input_format);
|
||||
}
|
||||
|
||||
void Y2R_U::GetInputFormat(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(conversion.input_format);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_format={}", conversion.input_format);
|
||||
}
|
||||
|
||||
void Y2R_U::SetOutputFormat(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.output_format = rp.PopEnum<OutputFormat>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called output_format={}", conversion.output_format);
|
||||
}
|
||||
|
||||
void Y2R_U::GetOutputFormat(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(conversion.output_format);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called output_format={}", conversion.output_format);
|
||||
}
|
||||
|
||||
void Y2R_U::SetRotation(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.rotation = rp.PopEnum<Rotation>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called rotation={}", conversion.rotation);
|
||||
}
|
||||
|
||||
void Y2R_U::GetRotation(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(conversion.rotation);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called rotation={}", conversion.rotation);
|
||||
}
|
||||
|
||||
void Y2R_U::SetBlockAlignment(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.block_alignment = rp.PopEnum<BlockAlignment>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called block_alignment={}", conversion.block_alignment);
|
||||
}
|
||||
|
||||
void Y2R_U::GetBlockAlignment(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(conversion.block_alignment);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called block_alignment={}", conversion.block_alignment);
|
||||
}
|
||||
|
||||
void Y2R_U::SetSpacialDithering(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
spacial_dithering_enabled = rp.Pop<bool>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetSpacialDithering(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(spacial_dithering_enabled);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetTemporalDithering(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
temporal_dithering_enabled = rp.Pop<bool>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetTemporalDithering(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(temporal_dithering_enabled);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetTransferEndInterrupt(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
transfer_end_interrupt_enabled = rp.Pop<bool>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetTransferEndInterrupt(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(transfer_end_interrupt_enabled);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetTransferEndEvent(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushCopyObjects(completion_event);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetSendingY(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
conversion.src_Y.address = rp.Pop<u32>();
|
||||
conversion.src_Y.image_size = rp.Pop<u32>();
|
||||
conversion.src_Y.transfer_unit = rp.Pop<u32>();
|
||||
conversion.src_Y.gap = rp.Pop<u32>();
|
||||
auto process = rp.PopObject<Kernel::Process>();
|
||||
// TODO (wwylele): pass process handle to y2r engine or convert VAddr to PAddr
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called image_size=0x{:08X}, transfer_unit={}, transfer_stride={}, "
|
||||
"src_process_id={}",
|
||||
conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap,
|
||||
process->process_id);
|
||||
}
|
||||
|
||||
void Y2R_U::SetSendingU(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
conversion.src_U.address = rp.Pop<u32>();
|
||||
conversion.src_U.image_size = rp.Pop<u32>();
|
||||
conversion.src_U.transfer_unit = rp.Pop<u32>();
|
||||
conversion.src_U.gap = rp.Pop<u32>();
|
||||
auto process = rp.PopObject<Kernel::Process>();
|
||||
// TODO (wwylele): pass the process handle to y2r engine or convert VAddr to PAddr
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called image_size=0x{:08X}, transfer_unit={}, transfer_stride={}, "
|
||||
"src_process_id={}",
|
||||
conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap,
|
||||
process->process_id);
|
||||
}
|
||||
|
||||
void Y2R_U::SetSendingV(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.src_V.address = rp.Pop<u32>();
|
||||
conversion.src_V.image_size = rp.Pop<u32>();
|
||||
conversion.src_V.transfer_unit = rp.Pop<u32>();
|
||||
conversion.src_V.gap = rp.Pop<u32>();
|
||||
auto process = rp.PopObject<Kernel::Process>();
|
||||
// TODO (wwylele): pass the process handle to y2r engine or convert VAddr to PAddr
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called image_size=0x{:08X}, transfer_unit={}, transfer_stride={}, "
|
||||
"src_process_id={}",
|
||||
conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap,
|
||||
process->process_id);
|
||||
}
|
||||
|
||||
void Y2R_U::SetSendingYUYV(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.src_YUYV.address = rp.Pop<u32>();
|
||||
conversion.src_YUYV.image_size = rp.Pop<u32>();
|
||||
conversion.src_YUYV.transfer_unit = rp.Pop<u32>();
|
||||
conversion.src_YUYV.gap = rp.Pop<u32>();
|
||||
auto process = rp.PopObject<Kernel::Process>();
|
||||
// TODO (wwylele): pass the process handle to y2r engine or convert VAddr to PAddr
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called image_size=0x{:08X}, transfer_unit={}, transfer_stride={}, "
|
||||
"src_process_id={}",
|
||||
conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit,
|
||||
conversion.src_YUYV.gap, process->process_id);
|
||||
}
|
||||
|
||||
void Y2R_U::IsFinishedSendingYuv(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::IsFinishedSendingY(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::IsFinishedSendingU(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::IsFinishedSendingV(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetReceiving(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
conversion.dst.address = rp.Pop<u32>();
|
||||
conversion.dst.image_size = rp.Pop<u32>();
|
||||
conversion.dst.transfer_unit = rp.Pop<u32>();
|
||||
conversion.dst.gap = rp.Pop<u32>();
|
||||
auto dst_process = rp.PopObject<Kernel::Process>();
|
||||
// TODO (wwylele): pass the process handle to y2r engine or convert VAddr to PAddr
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called image_size=0x{:08X}, transfer_unit={}, transfer_stride={}, "
|
||||
"dst_process_id={}",
|
||||
conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap,
|
||||
static_cast<u32>(dst_process->process_id));
|
||||
}
|
||||
|
||||
void Y2R_U::IsFinishedReceiving(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetInputLineWidth(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
u32 input_line_width = rp.Pop<u32>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(conversion.SetInputLineWidth(input_line_width));
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_line_width={}", input_line_width);
|
||||
}
|
||||
|
||||
void Y2R_U::GetInputLineWidth(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(conversion.input_line_width);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_line_width={}", conversion.input_line_width);
|
||||
}
|
||||
|
||||
void Y2R_U::SetInputLines(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
u32 input_lines = rp.Pop<u32>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(conversion.SetInputLines(input_lines));
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_lines={}", input_lines);
|
||||
}
|
||||
|
||||
void Y2R_U::GetInputLines(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(static_cast<u32>(conversion.input_lines));
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called input_lines={}", conversion.input_lines);
|
||||
}
|
||||
|
||||
void Y2R_U::SetCoefficient(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
rp.PopRaw<CoefficientSet>(conversion.coefficients);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called coefficients=[{:X}, {:X}, {:X}, {:X}, {:X}, {:X}, {:X}, {:X}]",
|
||||
conversion.coefficients[0], conversion.coefficients[1], conversion.coefficients[2],
|
||||
conversion.coefficients[3], conversion.coefficients[4], conversion.coefficients[5],
|
||||
conversion.coefficients[6], conversion.coefficients[7]);
|
||||
}
|
||||
|
||||
void Y2R_U::GetCoefficient(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(5, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(conversion.coefficients);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetStandardCoefficient(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
u32 index = rp.Pop<u32>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(conversion.SetStandardCoefficient(static_cast<StandardCoefficient>(index)));
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called standard_coefficient={}", index);
|
||||
}
|
||||
|
||||
void Y2R_U::GetStandardCoefficient(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const u32 index = rp.Pop<u32>();
|
||||
|
||||
if (index < standard_coefficients.size()) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(5, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(standard_coefficients[index]);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called standard_coefficient={} ", index);
|
||||
} else {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
|
||||
ErrorSummary::InvalidArgument, ErrorLevel::Usage));
|
||||
|
||||
LOG_ERROR(Service_Y2R, "called standard_coefficient={} The argument is invalid!", index);
|
||||
}
|
||||
}
|
||||
|
||||
void Y2R_U::SetAlpha(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
conversion.alpha = rp.Pop<u32>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called alpha={}", conversion.alpha);
|
||||
}
|
||||
|
||||
void Y2R_U::GetAlpha(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(conversion.alpha);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called alpha={}", conversion.alpha);
|
||||
}
|
||||
|
||||
void Y2R_U::SetDitheringWeightParams(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
rp.PopRaw(dithering_weight_params);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetDitheringWeightParams(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(9, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(dithering_weight_params);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
// dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
|
||||
u32 total_output_size =
|
||||
conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
|
||||
Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size,
|
||||
Memory::FlushMode::FlushAndInvalidate);
|
||||
|
||||
HW::Y2R::PerformConversion(system.Memory(), conversion);
|
||||
|
||||
completion_event->Signal();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::StopConversion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::IsBusyConversion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(0); // StartConversion always finishes immediately
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::SetPackageParameter(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
auto params = rp.PopRaw<ConversionParameters>();
|
||||
|
||||
conversion.input_format = params.input_format;
|
||||
conversion.output_format = params.output_format;
|
||||
conversion.rotation = params.rotation;
|
||||
conversion.block_alignment = params.block_alignment;
|
||||
|
||||
ResultCode result = conversion.SetInputLineWidth(params.input_line_width);
|
||||
|
||||
if (result.IsError())
|
||||
goto cleanup;
|
||||
|
||||
result = conversion.SetInputLines(params.input_lines);
|
||||
|
||||
if (result.IsError())
|
||||
goto cleanup;
|
||||
|
||||
result = conversion.SetStandardCoefficient(params.standard_coefficient);
|
||||
|
||||
if (result.IsError())
|
||||
goto cleanup;
|
||||
|
||||
conversion.padding = params.padding;
|
||||
conversion.alpha = params.alpha;
|
||||
|
||||
cleanup:
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(result);
|
||||
|
||||
LOG_DEBUG(Service_Y2R,
|
||||
"called input_format={} output_format={} rotation={} block_alignment={} "
|
||||
"input_line_width={} input_lines={} standard_coefficient={} reserved={} alpha={:X}",
|
||||
params.input_format, params.output_format, params.rotation, params.block_alignment,
|
||||
params.input_line_width, params.input_lines, params.standard_coefficient,
|
||||
params.padding, params.alpha);
|
||||
}
|
||||
|
||||
void Y2R_U::PingProcess(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(0);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "(STUBBED) called");
|
||||
}
|
||||
|
||||
void Y2R_U::DriverInitialize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
|
||||
conversion.input_format = InputFormat::YUV422_Indiv8;
|
||||
conversion.output_format = OutputFormat::RGBA8;
|
||||
conversion.rotation = Rotation::None;
|
||||
conversion.block_alignment = BlockAlignment::Linear;
|
||||
conversion.coefficients.fill(0);
|
||||
conversion.SetInputLineWidth(1024);
|
||||
conversion.SetInputLines(1024);
|
||||
conversion.alpha = 0;
|
||||
|
||||
ConversionBuffer zero_buffer = {};
|
||||
conversion.src_Y = zero_buffer;
|
||||
conversion.src_U = zero_buffer;
|
||||
conversion.src_V = zero_buffer;
|
||||
conversion.dst = zero_buffer;
|
||||
|
||||
completion_event->Clear();
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::DriverFinalize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
void Y2R_U::GetPackageParameter(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(4, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(conversion);
|
||||
|
||||
LOG_DEBUG(Service_Y2R, "called");
|
||||
}
|
||||
|
||||
Y2R_U::Y2R_U(Core::System& system) : ServiceFramework("y2r:u", 1), system(system) {
|
||||
static const FunctionInfo functions[] = {
|
||||
// clang-format off
|
||||
{0x0001, &Y2R_U::SetInputFormat, "SetInputFormat"},
|
||||
{0x0002, &Y2R_U::GetInputFormat, "GetInputFormat"},
|
||||
{0x0003, &Y2R_U::SetOutputFormat, "SetOutputFormat"},
|
||||
{0x0004, &Y2R_U::GetOutputFormat, "GetOutputFormat"},
|
||||
{0x0005, &Y2R_U::SetRotation, "SetRotation"},
|
||||
{0x0006, &Y2R_U::GetRotation, "GetRotation"},
|
||||
{0x0007, &Y2R_U::SetBlockAlignment, "SetBlockAlignment"},
|
||||
{0x0008, &Y2R_U::GetBlockAlignment, "GetBlockAlignment"},
|
||||
{0x0009, &Y2R_U::SetSpacialDithering, "SetSpacialDithering"},
|
||||
{0x000A, &Y2R_U::GetSpacialDithering, "GetSpacialDithering"},
|
||||
{0x000B, &Y2R_U::SetTemporalDithering, "SetTemporalDithering"},
|
||||
{0x000C, &Y2R_U::GetTemporalDithering, "GetTemporalDithering"},
|
||||
{0x000D, &Y2R_U::SetTransferEndInterrupt, "SetTransferEndInterrupt"},
|
||||
{0x000E, &Y2R_U::GetTransferEndInterrupt, "GetTransferEndInterrupt"},
|
||||
{0x000F, &Y2R_U::GetTransferEndEvent, "GetTransferEndEvent"},
|
||||
{0x0010, &Y2R_U::SetSendingY, "SetSendingY"},
|
||||
{0x0011, &Y2R_U::SetSendingU, "SetSendingU"},
|
||||
{0x0012, &Y2R_U::SetSendingV, "SetSendingV"},
|
||||
{0x0013, &Y2R_U::SetSendingYUYV, "SetSendingYUYV"},
|
||||
{0x0014, &Y2R_U::IsFinishedSendingYuv, "IsFinishedSendingYuv"},
|
||||
{0x0015, &Y2R_U::IsFinishedSendingY, "IsFinishedSendingY"},
|
||||
{0x0016, &Y2R_U::IsFinishedSendingU, "IsFinishedSendingU"},
|
||||
{0x0017, &Y2R_U::IsFinishedSendingV, "IsFinishedSendingV"},
|
||||
{0x0018, &Y2R_U::SetReceiving, "SetReceiving"},
|
||||
{0x0019, &Y2R_U::IsFinishedReceiving, "IsFinishedReceiving"},
|
||||
{0x001A, &Y2R_U::SetInputLineWidth, "SetInputLineWidth"},
|
||||
{0x001B, &Y2R_U::GetInputLineWidth, "GetInputLineWidth"},
|
||||
{0x001C, &Y2R_U::SetInputLines, "SetInputLines"},
|
||||
{0x001D, &Y2R_U::GetInputLines, "GetInputLines"},
|
||||
{0x001E, &Y2R_U::SetCoefficient, "SetCoefficient"},
|
||||
{0x001F, &Y2R_U::GetCoefficient, "GetCoefficient"},
|
||||
{0x0020, &Y2R_U::SetStandardCoefficient, "SetStandardCoefficient"},
|
||||
{0x0021, &Y2R_U::GetStandardCoefficient, "GetStandardCoefficient"},
|
||||
{0x0022, &Y2R_U::SetAlpha, "SetAlpha"},
|
||||
{0x0023, &Y2R_U::GetAlpha, "GetAlpha"},
|
||||
{0x0024, &Y2R_U::SetDitheringWeightParams, "SetDitheringWeightParams"},
|
||||
{0x0025, &Y2R_U::GetDitheringWeightParams, "GetDitheringWeightParams"},
|
||||
{0x0026, &Y2R_U::StartConversion, "StartConversion"},
|
||||
{0x0027, &Y2R_U::StopConversion, "StopConversion"},
|
||||
{0x0028, &Y2R_U::IsBusyConversion, "IsBusyConversion"},
|
||||
{0x0029, &Y2R_U::SetPackageParameter, "SetPackageParameter"},
|
||||
{0x002A, &Y2R_U::PingProcess, "PingProcess"},
|
||||
{0x002B, &Y2R_U::DriverInitialize, "DriverInitialize"},
|
||||
{0x002C, &Y2R_U::DriverFinalize, "DriverFinalize"},
|
||||
{0x002D, &Y2R_U::GetPackageParameter, "GetPackageParameter"},
|
||||
// clang-format on
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
completion_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "Y2R:Completed");
|
||||
}
|
||||
|
||||
Y2R_U::~Y2R_U() = default;
|
||||
|
||||
void InstallInterfaces(Core::System& system) {
|
||||
auto& service_manager = system.ServiceManager();
|
||||
std::make_shared<Y2R_U>(system)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Service::Y2R
|
368
src/core/hle/service/cam/y2r_u.h
Normal file
368
src/core/hle/service/cam/y2r_u.h
Normal file
|
@ -0,0 +1,368 @@
|
|||
// Copyright 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class Event;
|
||||
}
|
||||
|
||||
namespace Service::Y2R {
|
||||
|
||||
enum class InputFormat : u8 {
|
||||
/// 8-bit input, with YUV components in separate planes and 4:2:2 subsampling.
|
||||
YUV422_Indiv8 = 0,
|
||||
/// 8-bit input, with YUV components in separate planes and 4:2:0 subsampling.
|
||||
YUV420_Indiv8 = 1,
|
||||
|
||||
/// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:2 subsampling.
|
||||
YUV422_Indiv16 = 2,
|
||||
/// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:0 subsampling.
|
||||
YUV420_Indiv16 = 3,
|
||||
|
||||
/// 8-bit input, with a single interleaved stream in YUYV format and 4:2:2 subsampling.
|
||||
YUYV422_Interleaved = 4,
|
||||
};
|
||||
|
||||
enum class OutputFormat : u8 {
|
||||
RGBA8 = 0,
|
||||
RGB8 = 1,
|
||||
RGB5A1 = 2,
|
||||
RGB565 = 3,
|
||||
};
|
||||
|
||||
enum class Rotation : u8 {
|
||||
None = 0,
|
||||
Clockwise_90 = 1,
|
||||
Clockwise_180 = 2,
|
||||
Clockwise_270 = 3,
|
||||
};
|
||||
|
||||
enum class BlockAlignment : u8 {
|
||||
/// Image is output in linear format suitable for use as a framebuffer.
|
||||
Linear = 0,
|
||||
/// Image is output in tiled PICA format, suitable for use as a texture.
|
||||
Block8x8 = 1,
|
||||
};
|
||||
|
||||
enum class StandardCoefficient : u8 {
|
||||
/// ITU Rec. BT.601 primaries, with PC ranges.
|
||||
ITU_Rec601 = 0,
|
||||
/// ITU Rec. BT.709 primaries, with PC ranges.
|
||||
ITU_Rec709 = 1,
|
||||
/// ITU Rec. BT.601 primaries, with TV ranges.
|
||||
ITU_Rec601_Scaling = 2,
|
||||
/// ITU Rec. BT.709 primaries, with TV ranges.
|
||||
ITU_Rec709_Scaling = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* A set of coefficients configuring the RGB to YUV conversion. Coefficients 0-4 are unsigned 2.8
|
||||
* fixed pointer numbers representing entries on the conversion matrix, while coefficient 5-7 are
|
||||
* signed 11.5 fixed point numbers added as offsets to the RGB result.
|
||||
*
|
||||
* The overall conversion process formula is:
|
||||
* ```
|
||||
* R = trunc((c_0 * Y + c_1 * V) + c_5 + 0.75)
|
||||
* G = trunc((c_0 * Y - c_3 * U - c_2 * V) + c_6 + 0.75)
|
||||
* B = trunc((c_0 * Y + c_4 * U ) + c_7 + 0.75)
|
||||
* ```
|
||||
*/
|
||||
using CoefficientSet = std::array<s16, 8>;
|
||||
|
||||
struct ConversionBuffer {
|
||||
/// Current reading/writing address of this buffer.
|
||||
VAddr address;
|
||||
/// Remaining amount of bytes to be DMAed, does not include the inter-trasfer gap.
|
||||
u32 image_size;
|
||||
/// Size of a single DMA transfer.
|
||||
u16 transfer_unit;
|
||||
/// Amount of bytes to be skipped between copying each `transfer_unit` bytes.
|
||||
u16 gap;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& address;
|
||||
ar& image_size;
|
||||
ar& transfer_unit;
|
||||
ar& gap;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct ConversionConfiguration {
|
||||
InputFormat input_format;
|
||||
OutputFormat output_format;
|
||||
Rotation rotation;
|
||||
BlockAlignment block_alignment;
|
||||
u16 input_line_width;
|
||||
u16 input_lines;
|
||||
CoefficientSet coefficients;
|
||||
u8 padding;
|
||||
u16 alpha;
|
||||
|
||||
/// Input parameters for the Y (luma) plane
|
||||
ConversionBuffer src_Y, src_U, src_V, src_YUYV;
|
||||
/// Output parameters for the conversion results
|
||||
ConversionBuffer dst;
|
||||
|
||||
ResultCode SetInputLineWidth(u16 width);
|
||||
ResultCode SetInputLines(u16 lines);
|
||||
ResultCode SetStandardCoefficient(StandardCoefficient standard_coefficient);
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& input_format;
|
||||
ar& output_format;
|
||||
ar& rotation;
|
||||
ar& block_alignment;
|
||||
ar& input_line_width;
|
||||
ar& input_lines;
|
||||
ar& coefficients;
|
||||
ar& padding;
|
||||
ar& alpha;
|
||||
ar& src_Y;
|
||||
ar& src_U;
|
||||
ar& src_V;
|
||||
ar& src_YUYV;
|
||||
ar& dst;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct DitheringWeightParams {
|
||||
u16 w0_xEven_yEven;
|
||||
u16 w0_xOdd_yEven;
|
||||
u16 w0_xEven_yOdd;
|
||||
u16 w0_xOdd_yOdd;
|
||||
u16 w1_xEven_yEven;
|
||||
u16 w1_xOdd_yEven;
|
||||
u16 w1_xEven_yOdd;
|
||||
u16 w1_xOdd_yOdd;
|
||||
u16 w2_xEven_yEven;
|
||||
u16 w2_xOdd_yEven;
|
||||
u16 w2_xEven_yOdd;
|
||||
u16 w2_xOdd_yOdd;
|
||||
u16 w3_xEven_yEven;
|
||||
u16 w3_xOdd_yEven;
|
||||
u16 w3_xEven_yOdd;
|
||||
u16 w3_xOdd_yOdd;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& w0_xEven_yEven;
|
||||
ar& w0_xOdd_yEven;
|
||||
ar& w0_xEven_yOdd;
|
||||
ar& w0_xOdd_yOdd;
|
||||
ar& w1_xEven_yEven;
|
||||
ar& w1_xOdd_yEven;
|
||||
ar& w1_xEven_yOdd;
|
||||
ar& w1_xOdd_yOdd;
|
||||
ar& w2_xEven_yEven;
|
||||
ar& w2_xOdd_yEven;
|
||||
ar& w2_xEven_yOdd;
|
||||
ar& w2_xOdd_yOdd;
|
||||
ar& w3_xEven_yEven;
|
||||
ar& w3_xOdd_yEven;
|
||||
ar& w3_xEven_yOdd;
|
||||
ar& w3_xOdd_yOdd;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct ConversionParameters {
|
||||
InputFormat input_format;
|
||||
OutputFormat output_format;
|
||||
Rotation rotation;
|
||||
BlockAlignment block_alignment;
|
||||
u16 input_line_width;
|
||||
u16 input_lines;
|
||||
StandardCoefficient standard_coefficient;
|
||||
u8 padding;
|
||||
u16 alpha;
|
||||
};
|
||||
static_assert(sizeof(ConversionParameters) == 12, "ConversionParameters struct has incorrect size");
|
||||
|
||||
class Y2R_U final : public ServiceFramework<Y2R_U> {
|
||||
public:
|
||||
explicit Y2R_U(Core::System& system);
|
||||
~Y2R_U() override;
|
||||
|
||||
private:
|
||||
void SetInputFormat(Kernel::HLERequestContext& ctx);
|
||||
void GetInputFormat(Kernel::HLERequestContext& ctx);
|
||||
void SetOutputFormat(Kernel::HLERequestContext& ctx);
|
||||
void GetOutputFormat(Kernel::HLERequestContext& ctx);
|
||||
void SetRotation(Kernel::HLERequestContext& ctx);
|
||||
void GetRotation(Kernel::HLERequestContext& ctx);
|
||||
void SetBlockAlignment(Kernel::HLERequestContext& ctx);
|
||||
void GetBlockAlignment(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::SetSpacialDithering service function
|
||||
* Inputs:
|
||||
* 1 : u8, 0 = Disabled, 1 = Enabled
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void SetSpacialDithering(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::GetSpacialDithering service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Disabled, 1 = Enabled
|
||||
*/
|
||||
void GetSpacialDithering(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::SetTemporalDithering service function
|
||||
* Inputs:
|
||||
* 1 : u8, 0 = Disabled, 1 = Enabled
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void SetTemporalDithering(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::GetTemporalDithering service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Disabled, 1 = Enabled
|
||||
*/
|
||||
void GetTemporalDithering(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::SetTransferEndInterrupt service function
|
||||
* Inputs:
|
||||
* 1 : u8, 0 = Disabled, 1 = Enabled
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void SetTransferEndInterrupt(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::GetTransferEndInterrupt service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Disabled, 1 = Enabled
|
||||
*/
|
||||
void GetTransferEndInterrupt(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::GetTransferEndEvent service function
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
* 3 : The handle of the completion event
|
||||
*/
|
||||
void GetTransferEndEvent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
void SetSendingY(Kernel::HLERequestContext& ctx);
|
||||
void SetSendingU(Kernel::HLERequestContext& ctx);
|
||||
void SetSendingV(Kernel::HLERequestContext& ctx);
|
||||
void SetSendingYUYV(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R::IsFinishedSendingYuv service function
|
||||
* Output:
|
||||
* 1 : Result of the function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Not Finished, 1 = Finished
|
||||
*/
|
||||
void IsFinishedSendingYuv(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R::IsFinishedSendingY service function
|
||||
* Output:
|
||||
* 1 : Result of the function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Not Finished, 1 = Finished
|
||||
*/
|
||||
void IsFinishedSendingY(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R::IsFinishedSendingU service function
|
||||
* Output:
|
||||
* 1 : Result of the function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Not Finished, 1 = Finished
|
||||
*/
|
||||
void IsFinishedSendingU(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R::IsFinishedSendingV service function
|
||||
* Output:
|
||||
* 1 : Result of the function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Not Finished, 1 = Finished
|
||||
*/
|
||||
void IsFinishedSendingV(Kernel::HLERequestContext& ctx);
|
||||
|
||||
void SetReceiving(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R::IsFinishedReceiving service function
|
||||
* Output:
|
||||
* 1 : Result of the function, 0 on success, otherwise error code
|
||||
* 2 : u8, 0 = Not Finished, 1 = Finished
|
||||
*/
|
||||
void IsFinishedReceiving(Kernel::HLERequestContext& ctx);
|
||||
|
||||
void SetInputLineWidth(Kernel::HLERequestContext& ctx);
|
||||
void GetInputLineWidth(Kernel::HLERequestContext& ctx);
|
||||
void SetInputLines(Kernel::HLERequestContext& ctx);
|
||||
void GetInputLines(Kernel::HLERequestContext& ctx);
|
||||
void SetCoefficient(Kernel::HLERequestContext& ctx);
|
||||
void GetCoefficient(Kernel::HLERequestContext& ctx);
|
||||
void SetStandardCoefficient(Kernel::HLERequestContext& ctx);
|
||||
void GetStandardCoefficient(Kernel::HLERequestContext& ctx);
|
||||
void SetAlpha(Kernel::HLERequestContext& ctx);
|
||||
void GetAlpha(Kernel::HLERequestContext& ctx);
|
||||
void SetDitheringWeightParams(Kernel::HLERequestContext& ctx);
|
||||
void GetDitheringWeightParams(Kernel::HLERequestContext& ctx);
|
||||
void StartConversion(Kernel::HLERequestContext& ctx);
|
||||
void StopConversion(Kernel::HLERequestContext& ctx);
|
||||
void IsBusyConversion(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* Y2R_U::SetPackageParameter service function
|
||||
*/
|
||||
void SetPackageParameter(Kernel::HLERequestContext& ctx);
|
||||
|
||||
void PingProcess(Kernel::HLERequestContext& ctx);
|
||||
void DriverInitialize(Kernel::HLERequestContext& ctx);
|
||||
void DriverFinalize(Kernel::HLERequestContext& ctx);
|
||||
void GetPackageParameter(Kernel::HLERequestContext& ctx);
|
||||
|
||||
Core::System& system;
|
||||
|
||||
std::shared_ptr<Kernel::Event> completion_event;
|
||||
ConversionConfiguration conversion{};
|
||||
DitheringWeightParams dithering_weight_params{};
|
||||
bool temporal_dithering_enabled = false;
|
||||
bool transfer_end_interrupt_enabled = false;
|
||||
bool spacial_dithering_enabled = false;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int);
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::Y2R
|
||||
|
||||
SERVICE_CONSTRUCT(Service::Y2R::Y2R_U)
|
||||
BOOST_CLASS_EXPORT_KEY(Service::Y2R::Y2R_U)
|
Loading…
Add table
Add a link
Reference in a new issue