Compare commits

..

2 Commits

Author SHA1 Message Date
GPUCode
39441a53b3 cam: Make sure impl is not null before using it 2024-01-20 20:01:04 +02:00
GPUCode
8e64e0b0df cam: Use PopEnum and update result names 2024-01-20 19:52:06 +02:00
4 changed files with 115 additions and 97 deletions

View File

@@ -10,7 +10,6 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/frontend/camera/factory.h" #include "core/frontend/camera/factory.h"
#include "core/hle/ipc.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@@ -77,10 +76,10 @@ constexpr std::array<int, 13> LATENCY_BY_FRAME_RATE{{
33, // Rate_30_To_10 33, // Rate_30_To_10
}}; }};
const Result ERROR_INVALID_ENUM_VALUE(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, constexpr Result ResultInvalidEnumValue(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
ErrorSummary::InvalidArgument, ErrorLevel::Usage); ErrorSummary::InvalidArgument, ErrorLevel::Usage);
const Result ERROR_OUT_OF_RANGE(ErrorDescription::OutOfRange, ErrorModule::CAM, constexpr Result ResultOutOfRange(ErrorDescription::OutOfRange, ErrorModule::CAM,
ErrorSummary::InvalidArgument, ErrorLevel::Usage); ErrorSummary::InvalidArgument, ErrorLevel::Usage);
void Module::PortConfig::Clear() { void Module::PortConfig::Clear() {
completion_event->Clear(); completion_event->Clear();
@@ -261,27 +260,32 @@ void Module::Interface::StartCapture(Kernel::HLERequestContext& ctx) {
if (port_select.IsValid()) { if (port_select.IsValid()) {
for (int i : port_select) { for (int i : port_select) {
if (!cam->ports[i].is_busy) { auto& port = cam->ports[i];
if (!cam->ports[i].is_active) { if (port.is_busy) {
// This doesn't return an error, but seems to put the camera in an undefined
// state
LOG_ERROR(Service_CAM, "port {} hasn't been activated", i);
} else {
cam->cameras[cam->ports[i].camera_id].impl->StartCapture();
cam->ports[i].is_busy = true;
if (cam->ports[i].is_pending_receiving) {
cam->ports[i].is_pending_receiving = false;
cam->StartReceiving(i);
}
}
} else {
LOG_WARNING(Service_CAM, "port {} already started", i); LOG_WARNING(Service_CAM, "port {} already started", i);
continue;
}
if (!port.is_active) {
// This doesn't return an error, but seems to put the camera in an undefined
// state
LOG_ERROR(Service_CAM, "port {} hasn't been activated", i);
continue;
}
auto& camera = cam->cameras[port.camera_id];
if (!camera.impl) {
cam->LoadCameraImplementation(camera, port.camera_id);
}
camera.impl->StartCapture();
port.is_busy = true;
if (port.is_pending_receiving) {
port.is_pending_receiving = false;
cam->StartReceiving(i);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val); LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val);
@@ -306,7 +310,7 @@ void Module::Interface::StopCapture(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val); LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val);
@@ -328,7 +332,7 @@ void Module::Interface::IsBusy(Kernel::HLERequestContext& ctx) {
rb.Push(is_busy); rb.Push(is_busy);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -356,7 +360,7 @@ void Module::Interface::GetVsyncInterruptEvent(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(cam->ports[port].vsync_interrupt_event); rb.PushCopyObjects(cam->ports[port].vsync_interrupt_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -374,7 +378,7 @@ void Module::Interface::GetBufferErrorInterruptEvent(Kernel::HLERequestContext&
rb.PushCopyObjects(cam->ports[port].buffer_error_interrupt_event); rb.PushCopyObjects(cam->ports[port].buffer_error_interrupt_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -409,7 +413,7 @@ void Module::Interface::SetReceiving(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(port.completion_event); rb.PushCopyObjects(port.completion_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -429,7 +433,7 @@ void Module::Interface::IsFinishedReceiving(Kernel::HLERequestContext& ctx) {
rb.Push(!is_busy); rb.Push(!is_busy);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -451,7 +455,7 @@ void Module::Interface::SetTransferLines(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_WARNING(Service_CAM, "(STUBBED) called, port_select={}, lines={}, width={}, height={}", LOG_WARNING(Service_CAM, "(STUBBED) called, port_select={}, lines={}, width={}, height={}",
@@ -469,7 +473,7 @@ void Module::Interface::GetMaxLines(Kernel::HLERequestContext& ctx) {
constexpr u32 MIN_TRANSFER_UNIT = 256; constexpr u32 MIN_TRANSFER_UNIT = 256;
constexpr u32 MAX_BUFFER_SIZE = 2560; constexpr u32 MAX_BUFFER_SIZE = 2560;
if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { if (width * height * 2 % MIN_TRANSFER_UNIT != 0) {
rb.Push(ERROR_OUT_OF_RANGE); rb.Push(ResultOutOfRange);
rb.Skip(1, false); rb.Skip(1, false);
} else { } else {
u32 lines = MAX_BUFFER_SIZE / width; u32 lines = MAX_BUFFER_SIZE / width;
@@ -480,7 +484,7 @@ void Module::Interface::GetMaxLines(Kernel::HLERequestContext& ctx) {
while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) {
--lines; --lines;
if (lines == 0) { if (lines == 0) {
result = ERROR_OUT_OF_RANGE; result = ResultOutOfRange;
break; break;
} }
} }
@@ -506,7 +510,7 @@ void Module::Interface::SetTransferBytes(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_WARNING(Service_CAM, "(STUBBED)called, port_select={}, bytes={}, width={}, height={}", LOG_WARNING(Service_CAM, "(STUBBED)called, port_select={}, bytes={}, width={}, height={}",
@@ -524,7 +528,7 @@ void Module::Interface::GetTransferBytes(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].transfer_bytes); rb.Push(cam->ports[port].transfer_bytes);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -542,7 +546,7 @@ void Module::Interface::GetMaxBytes(Kernel::HLERequestContext& ctx) {
constexpr u32 MIN_TRANSFER_UNIT = 256; constexpr u32 MIN_TRANSFER_UNIT = 256;
constexpr u32 MAX_BUFFER_SIZE = 2560; constexpr u32 MAX_BUFFER_SIZE = 2560;
if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { if (width * height * 2 % MIN_TRANSFER_UNIT != 0) {
rb.Push(ERROR_OUT_OF_RANGE); rb.Push(ResultOutOfRange);
rb.Skip(1, false); rb.Skip(1, false);
} else { } else {
u32 bytes = MAX_BUFFER_SIZE; u32 bytes = MAX_BUFFER_SIZE;
@@ -571,7 +575,7 @@ void Module::Interface::SetTrimming(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, trim={}", port_select.m_val, trim); LOG_DEBUG(Service_CAM, "called, port_select={}, trim={}", port_select.m_val, trim);
@@ -588,7 +592,7 @@ void Module::Interface::IsTrimming(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].is_trimming); rb.Push(cam->ports[port].is_trimming);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -614,7 +618,7 @@ void Module::Interface::SetTrimmingParams(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, x0={}, y0={}, x1={}, y1={}", port_select.m_val, LOG_DEBUG(Service_CAM, "called, port_select={}, x0={}, y0={}, x1={}, y1={}", port_select.m_val,
@@ -635,7 +639,7 @@ void Module::Interface::GetTrimmingParams(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].y1); rb.Push(cam->ports[port].y1);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
rb.Skip(4, false); rb.Skip(4, false);
} }
@@ -661,7 +665,7 @@ void Module::Interface::SetTrimmingParamsCenter(Kernel::HLERequestContext& ctx)
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, trim_w={}, trim_h={}, cam_w={}, cam_h={}", LOG_DEBUG(Service_CAM, "called, port_select={}, trim_w={}, trim_h={}, cam_w={}, cam_h={}",
@@ -687,7 +691,7 @@ void Module::Interface::Activate(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else if (camera_select[0] && camera_select[1]) { } else if (camera_select[0] && camera_select[1]) {
LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated");
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} else { } else {
if (camera_select[0]) { if (camera_select[0]) {
cam->ActivatePort(0, 0); cam->ActivatePort(0, 0);
@@ -702,7 +706,7 @@ void Module::Interface::Activate(Kernel::HLERequestContext& ctx) {
} }
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val); LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}", camera_select.m_val); LOG_DEBUG(Service_CAM, "called, camera_select={}", camera_select.m_val);
@@ -728,7 +732,7 @@ void Module::Interface::SwitchContext(Kernel::HLERequestContext& ctx) {
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, context_select={}", camera_select.m_val, LOG_DEBUG(Service_CAM, "called, camera_select={}, context_select={}", camera_select.m_val,
@@ -738,24 +742,29 @@ void Module::Interface::SwitchContext(Kernel::HLERequestContext& ctx) {
void Module::Interface::FlipImage(Kernel::HLERequestContext& ctx) { void Module::Interface::FlipImage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const Flip flip = static_cast<Flip>(rp.Pop<u8>()); const Flip flip = rp.PopEnum<Flip>();
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
cam->cameras[camera].contexts[context].flip = flip; camera.contexts[context].flip = flip;
if (cam->cameras[camera].current_context == context) { if (camera.current_context != context) {
cam->cameras[camera].impl->SetFlip(flip); continue;
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFlip(flip);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, flip={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, flip={}, context_select={}",
@@ -776,19 +785,24 @@ void Module::Interface::SetDetailSize(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
cam->cameras[camera].contexts[context].resolution = resolution; camera.contexts[context].resolution = resolution;
if (cam->cameras[camera].current_context == context) { if (camera.current_context != context) {
cam->cameras[camera].impl->SetResolution(resolution); continue;
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetResolution(resolution);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, LOG_DEBUG(Service_CAM,
@@ -806,19 +820,24 @@ void Module::Interface::SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
cam->cameras[camera].contexts[context].resolution = PRESET_RESOLUTION[size]; camera.contexts[context].resolution = PRESET_RESOLUTION[size];
if (cam->cameras[camera].current_context == context) { if (camera.current_context != context) {
cam->cameras[camera].impl->SetResolution(PRESET_RESOLUTION[size]); continue;
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetResolution(PRESET_RESOLUTION[size]);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, size={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, size={}, context_select={}",
@@ -828,18 +847,22 @@ void Module::Interface::SetSize(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) { void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const FrameRate frame_rate = static_cast<FrameRate>(rp.Pop<u8>()); const FrameRate frame_rate = rp.PopEnum<FrameRate>();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid()) { if (camera_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
cam->cameras[camera].frame_rate = frame_rate; auto& camera = cam->cameras[index];
cam->cameras[camera].impl->SetFrameRate(frame_rate); camera.frame_rate = frame_rate;
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFrameRate(frame_rate);
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val); LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select={}, frame_rate={}", LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select={}, frame_rate={}",
@@ -849,24 +872,29 @@ void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) { void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const Effect effect = static_cast<Effect>(rp.Pop<u8>()); const Effect effect = rp.PopEnum<Effect>();
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
cam->cameras[camera].contexts[context].effect = effect; camera.contexts[context].effect = effect;
if (cam->cameras[camera].current_context == context) { if (camera.current_context != context) {
cam->cameras[camera].impl->SetEffect(effect); continue;
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetEffect(effect);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, effect={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, effect={}, context_select={}",
@@ -876,24 +904,29 @@ void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetOutputFormat(Kernel::HLERequestContext& ctx) { void Module::Interface::SetOutputFormat(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const OutputFormat format = static_cast<OutputFormat>(rp.Pop<u8>()); const OutputFormat format = rp.PopEnum<OutputFormat>();
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int camera : camera_select) { for (int index : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
cam->cameras[camera].contexts[context].format = format; camera.contexts[context].format = format;
if (cam->cameras[camera].current_context == context) { if (camera.current_context != context) {
cam->cameras[camera].impl->SetFormat(format); continue;
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFormat(format);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE); rb.Push(ResultInvalidEnumValue);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, format={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, format={}, context_select={}",
@@ -919,7 +952,7 @@ void Module::Interface::GetLatestVsyncTiming(Kernel::HLERequestContext& ctx) {
if (!port_select.IsSingle() || count > MaxVsyncTimings) { if (!port_select.IsSingle() || count > MaxVsyncTimings) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ERROR_OUT_OF_RANGE); rb.Push(ResultOutOfRange);
rb.PushStaticBuffer({}, 0); rb.PushStaticBuffer({}, 0);
return; return;
} }
@@ -1003,7 +1036,7 @@ Result Module::SetPackageParameter(const PackageParameterType& package) {
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", package.camera_select, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", package.camera_select,
package.context_select); package.context_select);
return ERROR_INVALID_ENUM_VALUE; return ResultInvalidEnumValue;
} }
} }

View File

@@ -256,10 +256,6 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.bool_uniforms): case PICA_REG_INDEX(vs.bool_uniforms):
vs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value()); vs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value());
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No) {
gs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value());
}
break; break;
case PICA_REG_INDEX(vs.int_uniforms[0]): case PICA_REG_INDEX(vs.int_uniforms[0]):
@@ -268,10 +264,6 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.int_uniforms[3]): { case PICA_REG_INDEX(vs.int_uniforms[3]): {
const u32 index = (id - PICA_REG_INDEX(vs.int_uniforms[0])); const u32 index = (id - PICA_REG_INDEX(vs.int_uniforms[0]));
vs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index)); vs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index));
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No) {
gs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index));
}
break; break;
} }
@@ -283,11 +275,7 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.uniform_setup.set_value[5]): case PICA_REG_INDEX(vs.uniform_setup.set_value[5]):
case PICA_REG_INDEX(vs.uniform_setup.set_value[6]): case PICA_REG_INDEX(vs.uniform_setup.set_value[6]):
case PICA_REG_INDEX(vs.uniform_setup.set_value[7]): { case PICA_REG_INDEX(vs.uniform_setup.set_value[7]): {
const auto index = vs_setup.WriteUniformFloatReg(regs.internal.vs, value); vs_setup.WriteUniformFloatReg(regs.internal.vs, value);
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No && index) {
gs_setup.uniforms.f[index.value()] = vs_setup.uniforms.f[index.value()];
}
break; break;
} }

View File

@@ -27,23 +27,21 @@ void ShaderSetup::WriteUniformIntReg(u32 index, const Common::Vec4<u8> values) {
uniforms.i[index] = values; uniforms.i[index] = values;
} }
std::optional<u32> ShaderSetup::WriteUniformFloatReg(ShaderRegs& config, u32 value) { void ShaderSetup::WriteUniformFloatReg(ShaderRegs& config, u32 value) {
auto& uniform_setup = config.uniform_setup; auto& uniform_setup = config.uniform_setup;
const bool is_float32 = uniform_setup.IsFloat32(); const bool is_float32 = uniform_setup.IsFloat32();
if (!uniform_queue.Push(value, is_float32)) { if (!uniform_queue.Push(value, is_float32)) {
return std::nullopt; return;
} }
const auto uniform = uniform_queue.Get(is_float32); const auto uniform = uniform_queue.Get(is_float32);
if (uniform_setup.index >= uniforms.f.size()) { if (uniform_setup.index >= uniforms.f.size()) {
LOG_ERROR(HW_GPU, "Invalid float uniform index {}", uniform_setup.index.Value()); LOG_ERROR(HW_GPU, "Invalid float uniform index {}", uniform_setup.index.Value());
return std::nullopt; return;
} }
const u32 index = uniform_setup.index.Value(); uniforms.f[uniform_setup.index] = uniform;
uniforms.f[index] = uniform; uniform_setup.index.Assign(uniform_setup.index + 1);
uniform_setup.index.Assign(index + 1);
return index;
} }
u64 ShaderSetup::GetProgramCodeHash() { u64 ShaderSetup::GetProgramCodeHash() {

View File

@@ -4,7 +4,6 @@
#pragma once #pragma once
#include <optional>
#include "common/vector_math.h" #include "common/vector_math.h"
#include "video_core/pica/packed_attribute.h" #include "video_core/pica/packed_attribute.h"
#include "video_core/pica_types.h" #include "video_core/pica_types.h"
@@ -59,7 +58,7 @@ public:
void WriteUniformIntReg(u32 index, const Common::Vec4<u8> values); void WriteUniformIntReg(u32 index, const Common::Vec4<u8> values);
std::optional<u32> WriteUniformFloatReg(ShaderRegs& config, u32 value); void WriteUniformFloatReg(ShaderRegs& config, u32 value);
u64 GetProgramCodeHash(); u64 GetProgramCodeHash();