From 874cb42e704f81cbb4c2dd88e25283828c4d7a87 Mon Sep 17 00:00:00 2001 From: wwylele Date: Mon, 28 May 2018 14:28:03 +0300 Subject: [PATCH 01/19] shader/jit: preserve integer & condition register across invocation --- .../shader/shader_jit_x64_compiler.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/video_core/shader/shader_jit_x64_compiler.cpp b/src/video_core/shader/shader_jit_x64_compiler.cpp index 06c6f52e5..9744ce56d 100644 --- a/src/video_core/shader/shader_jit_x64_compiler.cpp +++ b/src/video_core/shader/shader_jit_x64_compiler.cpp @@ -580,6 +580,18 @@ void JitShader::Compile_RSQ(Instruction instr) { void JitShader::Compile_NOP(Instruction instr) {} void JitShader::Compile_END(Instruction instr) { + // Save conditional code + mov(byte[STATE + offsetof(UnitState, conditional_code[0])], COND0.cvt8()); + mov(byte[STATE + offsetof(UnitState, conditional_code[1])], COND1.cvt8()); + + // Save address/loop registers + sar(ADDROFFS_REG_0, 4); + sar(ADDROFFS_REG_1, 4); + sar(LOOPCOUNT_REG, 4); + mov(dword[STATE + offsetof(UnitState, address_registers[0])], ADDROFFS_REG_0.cvt32()); + mov(dword[STATE + offsetof(UnitState, address_registers[1])], ADDROFFS_REG_1.cvt32()); + mov(dword[STATE + offsetof(UnitState, address_registers[2])], LOOPCOUNT_REG); + ABI_PopRegistersAndAdjustStack(*this, ABI_ALL_CALLEE_SAVED, 8, 16); ret(); } @@ -885,10 +897,17 @@ void JitShader::Compile(const std::array* program_ mov(UNIFORMS, ABI_PARAM1); mov(STATE, ABI_PARAM2); - // Zero address/loop registers - xor_(ADDROFFS_REG_0.cvt32(), ADDROFFS_REG_0.cvt32()); - xor_(ADDROFFS_REG_1.cvt32(), ADDROFFS_REG_1.cvt32()); - xor_(LOOPCOUNT_REG, LOOPCOUNT_REG); + // Load address/loop registers + movsxd(ADDROFFS_REG_0, dword[STATE + offsetof(UnitState, address_registers[0])]); + movsxd(ADDROFFS_REG_1, dword[STATE + offsetof(UnitState, address_registers[1])]); + mov(LOOPCOUNT_REG, dword[STATE + offsetof(UnitState, address_registers[2])]); + shl(ADDROFFS_REG_0, 4); + shl(ADDROFFS_REG_1, 4); + shl(LOOPCOUNT_REG, 4); + + // Load conditional code + mov(COND0, byte[STATE + offsetof(UnitState, conditional_code[0])]); + mov(COND1, byte[STATE + offsetof(UnitState, conditional_code[1])]); // Used to set a register to one static const __m128 one = {1.f, 1.f, 1.f, 1.f}; From 9060e08e491bf1065656ba62abe94e2da9f51a5b Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 18 May 2018 23:28:58 +0300 Subject: [PATCH 02/19] shader/jit: implement breakc --- .../shader/shader_jit_x64_compiler.cpp | 139 ++++++++++-------- .../shader/shader_jit_x64_compiler.h | 6 + 2 files changed, 81 insertions(+), 64 deletions(-) diff --git a/src/video_core/shader/shader_jit_x64_compiler.cpp b/src/video_core/shader/shader_jit_x64_compiler.cpp index 06c6f52e5..9ca06e766 100644 --- a/src/video_core/shader/shader_jit_x64_compiler.cpp +++ b/src/video_core/shader/shader_jit_x64_compiler.cpp @@ -33,70 +33,70 @@ namespace Shader { typedef void (JitShader::*JitFunction)(Instruction instr); const JitFunction instr_table[64] = { - &JitShader::Compile_ADD, // add - &JitShader::Compile_DP3, // dp3 - &JitShader::Compile_DP4, // dp4 - &JitShader::Compile_DPH, // dph - nullptr, // unknown - &JitShader::Compile_EX2, // ex2 - &JitShader::Compile_LG2, // lg2 - nullptr, // unknown - &JitShader::Compile_MUL, // mul - &JitShader::Compile_SGE, // sge - &JitShader::Compile_SLT, // slt - &JitShader::Compile_FLR, // flr - &JitShader::Compile_MAX, // max - &JitShader::Compile_MIN, // min - &JitShader::Compile_RCP, // rcp - &JitShader::Compile_RSQ, // rsq - nullptr, // unknown - nullptr, // unknown - &JitShader::Compile_MOVA, // mova - &JitShader::Compile_MOV, // mov - nullptr, // unknown - nullptr, // unknown - nullptr, // unknown - nullptr, // unknown - &JitShader::Compile_DPH, // dphi - nullptr, // unknown - &JitShader::Compile_SGE, // sgei - &JitShader::Compile_SLT, // slti - nullptr, // unknown - nullptr, // unknown - nullptr, // unknown - nullptr, // unknown - nullptr, // unknown - &JitShader::Compile_NOP, // nop - &JitShader::Compile_END, // end - nullptr, // break - &JitShader::Compile_CALL, // call - &JitShader::Compile_CALLC, // callc - &JitShader::Compile_CALLU, // callu - &JitShader::Compile_IF, // ifu - &JitShader::Compile_IF, // ifc - &JitShader::Compile_LOOP, // loop - &JitShader::Compile_EMIT, // emit - &JitShader::Compile_SETE, // sete - &JitShader::Compile_JMP, // jmpc - &JitShader::Compile_JMP, // jmpu - &JitShader::Compile_CMP, // cmp - &JitShader::Compile_CMP, // cmp - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // madi - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad - &JitShader::Compile_MAD, // mad + &JitShader::Compile_ADD, // add + &JitShader::Compile_DP3, // dp3 + &JitShader::Compile_DP4, // dp4 + &JitShader::Compile_DPH, // dph + nullptr, // unknown + &JitShader::Compile_EX2, // ex2 + &JitShader::Compile_LG2, // lg2 + nullptr, // unknown + &JitShader::Compile_MUL, // mul + &JitShader::Compile_SGE, // sge + &JitShader::Compile_SLT, // slt + &JitShader::Compile_FLR, // flr + &JitShader::Compile_MAX, // max + &JitShader::Compile_MIN, // min + &JitShader::Compile_RCP, // rcp + &JitShader::Compile_RSQ, // rsq + nullptr, // unknown + nullptr, // unknown + &JitShader::Compile_MOVA, // mova + &JitShader::Compile_MOV, // mov + nullptr, // unknown + nullptr, // unknown + nullptr, // unknown + nullptr, // unknown + &JitShader::Compile_DPH, // dphi + nullptr, // unknown + &JitShader::Compile_SGE, // sgei + &JitShader::Compile_SLT, // slti + nullptr, // unknown + nullptr, // unknown + nullptr, // unknown + nullptr, // unknown + nullptr, // unknown + &JitShader::Compile_NOP, // nop + &JitShader::Compile_END, // end + &JitShader::Compile_BREAKC, // breakc + &JitShader::Compile_CALL, // call + &JitShader::Compile_CALLC, // callc + &JitShader::Compile_CALLU, // callu + &JitShader::Compile_IF, // ifu + &JitShader::Compile_IF, // ifc + &JitShader::Compile_LOOP, // loop + &JitShader::Compile_EMIT, // emit + &JitShader::Compile_SETE, // sete + &JitShader::Compile_JMP, // jmpc + &JitShader::Compile_JMP, // jmpu + &JitShader::Compile_CMP, // cmp + &JitShader::Compile_CMP, // cmp + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // madi + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad + &JitShader::Compile_MAD, // mad }; // The following is used to alias some commonly used registers. Generally, RAX-RDX and XMM0-XMM3 can @@ -584,6 +584,14 @@ void JitShader::Compile_END(Instruction instr) { ret(); } +void JitShader::Compile_BREAKC(Instruction instr) { + Compile_Assert(looping, "BREAKC must be inside a LOOP"); + if (looping) { + Compile_EvaluateCondition(instr); + jnz(*loop_break_label); + } +} + void JitShader::Compile_CALL(Instruction instr) { // Push offset of the return push(qword, (instr.flow_control.dest_offset + instr.flow_control.num_instructions)); @@ -727,11 +735,14 @@ void JitShader::Compile_LOOP(Instruction instr) { Label l_loop_start; L(l_loop_start); + loop_break_label = Xbyak::Label(); Compile_Block(instr.flow_control.dest_offset + 1); add(LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component sub(LOOPCOUNT, 1); // Increment loop count by 1 jnz(l_loop_start); // Loop if not equal + L(*loop_break_label); + loop_break_label = boost::none; looping = false; } diff --git a/src/video_core/shader/shader_jit_x64_compiler.h b/src/video_core/shader/shader_jit_x64_compiler.h index 923c34f0d..8e1c87346 100644 --- a/src/video_core/shader/shader_jit_x64_compiler.h +++ b/src/video_core/shader/shader_jit_x64_compiler.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "common/bit_set.h" @@ -58,6 +59,7 @@ public: void Compile_MOV(Instruction instr); void Compile_NOP(Instruction instr); void Compile_END(Instruction instr); + void Compile_BREAKC(Instruction instr); void Compile_CALL(Instruction instr); void Compile_CALLC(Instruction instr); void Compile_CALLU(Instruction instr); @@ -119,6 +121,10 @@ private: /// Mapping of Pica VS instructions to pointers in the emitted code std::array instruction_labels; + /// Label pointing to the end of the current LOOP block. Used by the BREAKC instruction to break + /// out of the loop. + boost::optional loop_break_label; + /// Offsets in code where a return needs to be inserted std::vector return_offsets; From a9b7720d98bf051dc79a7c3d34d6690d0adf418c Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 2 Jun 2018 08:30:23 +0000 Subject: [PATCH 03/19] externals: don't try install cubeb files Install the project... /usr/local/bin/cmake -P cmake_install.cmake -- Install configuration: "Release" -- Installing: /prefix/share/man/man6/citra.6 CMake Error at externals/cubeb/cmake_install.cmake:44 (file): file INSTALL cannot find "/path/to/citra/include". Call Stack (most recent call first): externals/cmake_install.cmake:46 (include) cmake_install.cmake:49 (include) gmake: *** [Makefile:74: install] Error 1 --- externals/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index cb7530f2d..016c445dd 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -81,5 +81,5 @@ endif() # Cubeb if(ENABLE_CUBEB) set(BUILD_TESTS OFF CACHE BOOL "") - add_subdirectory(cubeb) + add_subdirectory(cubeb EXCLUDE_FROM_ALL) endif() From a4bed294fb870a4f7d89a4d90c030f09767ad0e7 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 3 Jun 2018 20:54:32 +0100 Subject: [PATCH 04/19] dynarmic: Update to 4b350a354a21339052c7fff88832c3f81f5624be --- externals/dynarmic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/dynarmic b/externals/dynarmic index d1d470536..4b350a354 160000 --- a/externals/dynarmic +++ b/externals/dynarmic @@ -1 +1 @@ -Subproject commit d1d4705364031512cb89333aebc00b8d75a2f732 +Subproject commit 4b350a354a21339052c7fff88832c3f81f5624be From b8c50071537d72e267bb3e7a8573971c6e946b88 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 3 Jun 2018 21:06:57 +0100 Subject: [PATCH 05/19] arm_dyncom_interpreter: Clear exclusive memory state after SVC call --- src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index b8c0cb34e..9548d0e16 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -3866,6 +3866,8 @@ SWI_INST : { num_instrs >= cpu->NumInstrsToExecute ? 0 : cpu->NumInstrsToExecute - num_instrs; num_instrs = 0; Kernel::CallSVC(inst_cream->num & 0xFFFF); + // The kernel would call ERET to get here, which clears exclusive memory state. + cpu->UnsetExclusiveMemoryAddress(); } cpu->Reg[15] += cpu->GetInstructionSize(); From 5ebd4668690c9e51ae80342d5e43bccac2339c1d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sun, 20 May 2018 09:07:37 +0800 Subject: [PATCH 06/19] camera: Add camera flip config --- src/citra/config.cpp | 6 + src/citra/default_ini.h | 6 + src/citra_qt/camera/qt_camera_factory.cpp | 6 +- src/citra_qt/camera/qt_camera_factory.h | 4 +- src/citra_qt/camera/qt_multimedia_camera.cpp | 14 +- src/citra_qt/camera/qt_multimedia_camera.h | 6 +- src/citra_qt/camera/still_image_camera.cpp | 16 +- src/citra_qt/camera/still_image_camera.h | 6 +- src/citra_qt/configuration/config.cpp | 8 + .../configuration/configure_camera.cpp | 23 +- src/citra_qt/configuration/configure_camera.h | 1 + .../configuration/configure_camera.ui | 572 ++++++++++-------- src/core/frontend/camera/factory.cpp | 9 +- src/core/frontend/camera/factory.h | 15 +- src/core/hle/service/cam/cam.cpp | 5 +- src/core/settings.h | 1 + 16 files changed, 416 insertions(+), 282 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index b4e3a2ce9..ce51b687b 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -155,14 +155,20 @@ void Config::ReadValues() { sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); Settings::values.camera_config[OuterRightCamera] = sdl2_config->Get("Camera", "camera_outer_right_config", ""); + Settings::values.camera_flip[OuterRightCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_right_flip", 0); Settings::values.camera_name[InnerCamera] = sdl2_config->Get("Camera", "camera_inner_name", "blank"); Settings::values.camera_config[InnerCamera] = sdl2_config->Get("Camera", "camera_inner_config", ""); + Settings::values.camera_flip[InnerCamera] = + sdl2_config->GetInteger("Camera", "camera_inner_flip", 0); Settings::values.camera_name[OuterLeftCamera] = sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); Settings::values.camera_config[OuterLeftCamera] = sdl2_config->Get("Camera", "camera_outer_left_config", ""); + Settings::values.camera_flip[OuterLeftCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0); // Miscellaneous Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 7179d6f94..4a17eb6ca 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -178,13 +178,19 @@ camera_outer_right_name = # A config string for the right outer camera. Its meaning is defined by the camera engine camera_outer_right_config = +# The image flip to apply +# 0: None (default), 1: Horizontal, 2: Vertical, 3: Reverse +camera_outer_right_flip = + # ... for the left outer camera camera_outer_left_name = camera_outer_left_config = +camera_outer_left_flip = # ... for the inner camera camera_inner_name = camera_inner_config = +camera_inner_flip = [Miscellaneous] # A filter which removes logs below a certain logging level. diff --git a/src/citra_qt/camera/qt_camera_factory.cpp b/src/citra_qt/camera/qt_camera_factory.cpp index fa78591ba..063a600df 100644 --- a/src/citra_qt/camera/qt_camera_factory.cpp +++ b/src/citra_qt/camera/qt_camera_factory.cpp @@ -7,9 +7,9 @@ namespace Camera { -std::unique_ptr QtCameraFactory::CreatePreview(const std::string& config, - int width, int height) const { - std::unique_ptr camera = Create(config); +std::unique_ptr QtCameraFactory::CreatePreview( + const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { + std::unique_ptr camera = Create(config, flip); if (camera->IsPreviewAvailable()) { return camera; diff --git a/src/citra_qt/camera/qt_camera_factory.h b/src/citra_qt/camera/qt_camera_factory.h index 7efc21b58..9e590ca66 100644 --- a/src/citra_qt/camera/qt_camera_factory.h +++ b/src/citra_qt/camera/qt_camera_factory.h @@ -11,8 +11,8 @@ namespace Camera { // Base class for camera factories of citra_qt class QtCameraFactory : public CameraFactory { - std::unique_ptr CreatePreview(const std::string& config, int width, - int height) const override; + std::unique_ptr CreatePreview(const std::string& config, int width, int height, + const Service::CAM::Flip& flip) const override; }; } // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 6c2668df6..5f2137835 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -46,7 +46,8 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { return true; } -QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) +QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, + const Service::CAM::Flip& flip) : handler(QtMultimediaCameraHandler::GetHandler()) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); @@ -54,6 +55,9 @@ QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) QMetaObject::invokeMethod(handler.get(), "CreateCamera", Qt::BlockingQueuedConnection, Q_ARG(const std::string&, camera_name)); } + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); } QtMultimediaCamera::~QtMultimediaCamera() { @@ -107,8 +111,8 @@ void QtMultimediaCamera::SetResolution(const Service::CAM::Resolution& resolutio void QtMultimediaCamera::SetFlip(Service::CAM::Flip flip) { using namespace Service::CAM; - flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); } void QtMultimediaCamera::SetEffect(Service::CAM::Effect effect) { @@ -128,8 +132,8 @@ bool QtMultimediaCamera::IsPreviewAvailable() { } std::unique_ptr QtMultimediaCameraFactory::Create( - const std::string& config) const { - return std::make_unique(config); + const std::string& config, const Service::CAM::Flip& flip) const { + return std::make_unique(config, flip); } std::array, 3> QtMultimediaCameraHandler::handlers; diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 103aff8a0..580834275 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -38,7 +38,7 @@ class QtMultimediaCameraHandler; /// This class is only an interface. It just calls QtMultimediaCameraHandler. class QtMultimediaCamera final : public CameraInterface { public: - QtMultimediaCamera(const std::string& camera_name); + QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip); ~QtMultimediaCamera(); void StartCapture() override; void StopCapture() override; @@ -55,11 +55,13 @@ private: int width, height; bool output_rgb; bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; }; class QtMultimediaCameraFactory final : public QtCameraFactory { public: - std::unique_ptr Create(const std::string& config) const override; + std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const override; }; class QtMultimediaCameraHandler final : public QObject { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index ab0d18308..7e54fad3e 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -9,7 +9,12 @@ namespace Camera { -StillImageCamera::StillImageCamera(QImage image_) : image(std::move(image_)) {} +StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) + : image(std::move(image_)) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); +} void StillImageCamera::StartCapture() {} @@ -26,8 +31,8 @@ void StillImageCamera::SetResolution(const Service::CAM::Resolution& resolution) void StillImageCamera::SetFlip(Service::CAM::Flip flip) { using namespace Service::CAM; - flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); } void StillImageCamera::SetEffect(Service::CAM::Effect effect) { @@ -58,7 +63,8 @@ const std::string StillImageCameraFactory::getFilePath() { .toStdString(); } -std::unique_ptr StillImageCameraFactory::Create(const std::string& config) const { +std::unique_ptr StillImageCameraFactory::Create( + const std::string& config, const Service::CAM::Flip& flip) const { std::string real_config = config; if (config.empty()) { real_config = getFilePath(); @@ -67,7 +73,7 @@ std::unique_ptr StillImageCameraFactory::Create(const std::stri if (image.isNull()) { NGLOG_ERROR(Service_CAM, "Couldn't load image \"{}\"", real_config.c_str()); } - return std::make_unique(image); + return std::make_unique(image, flip); } } // namespace Camera diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index c54d367e8..e9016981b 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -14,7 +14,7 @@ namespace Camera { class StillImageCamera final : public CameraInterface { public: - StillImageCamera(QImage image); + StillImageCamera(QImage image, const Service::CAM::Flip& flip); void StartCapture() override; void StopCapture() override; void SetResolution(const Service::CAM::Resolution&) override; @@ -30,11 +30,13 @@ private: int width, height; bool output_rgb; bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; }; class StillImageCameraFactory final : public QtCameraFactory { public: - std::unique_ptr Create(const std::string& config) const override; + std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const override; private: static const std::string getFilePath(); diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index bdb296659..e5d252c81 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -128,14 +128,19 @@ void Config::ReadValues() { qt_config->value("camera_outer_right_name", "blank").toString().toStdString(); Settings::values.camera_config[OuterRightCamera] = qt_config->value("camera_outer_right_config", "").toString().toStdString(); + Settings::values.camera_flip[OuterRightCamera] = + qt_config->value("camera_outer_right_flip", "0").toInt(); Settings::values.camera_name[InnerCamera] = qt_config->value("camera_inner_name", "blank").toString().toStdString(); Settings::values.camera_config[InnerCamera] = qt_config->value("camera_inner_config", "").toString().toStdString(); + Settings::values.camera_flip[InnerCamera] = qt_config->value("camera_inner_flip", "").toInt(); Settings::values.camera_name[OuterLeftCamera] = qt_config->value("camera_outer_left_name", "blank").toString().toStdString(); Settings::values.camera_config[OuterLeftCamera] = qt_config->value("camera_outer_left_config", "").toString().toStdString(); + Settings::values.camera_flip[OuterLeftCamera] = + qt_config->value("camera_outer_left_flip", "").toInt(); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); @@ -317,14 +322,17 @@ void Config::SaveValues() { QString::fromStdString(Settings::values.camera_name[OuterRightCamera])); qt_config->setValue("camera_outer_right_config", QString::fromStdString(Settings::values.camera_config[OuterRightCamera])); + qt_config->setValue("camera_outer_right_flip", Settings::values.camera_flip[OuterRightCamera]); qt_config->setValue("camera_inner_name", QString::fromStdString(Settings::values.camera_name[InnerCamera])); qt_config->setValue("camera_inner_config", QString::fromStdString(Settings::values.camera_config[InnerCamera])); + qt_config->setValue("camera_inner_flip", Settings::values.camera_flip[InnerCamera]); qt_config->setValue("camera_outer_left_name", QString::fromStdString(Settings::values.camera_name[OuterLeftCamera])); qt_config->setValue("camera_outer_left_config", QString::fromStdString(Settings::values.camera_config[OuterLeftCamera])); + qt_config->setValue("camera_outer_left_flip", Settings::values.camera_flip[OuterLeftCamera]); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); diff --git a/src/citra_qt/configuration/configure_camera.cpp b/src/citra_qt/configuration/configure_camera.cpp index ca6db4623..e9d964b3a 100644 --- a/src/citra_qt/configuration/configure_camera.cpp +++ b/src/citra_qt/configuration/configure_camera.cpp @@ -27,14 +27,7 @@ ConfigureCamera::ConfigureCamera(QWidget* parent) // Load settings camera_name = Settings::values.camera_name; camera_config = Settings::values.camera_config; - for (auto&& item : camera_name) { - if (item == "opencv") { - QMessageBox::critical(this, tr("Error"), - tr("Sorry, Citra has removed support for OpenCV cameras.\n\nYour " - "existing OpenCV cameras have been replaced with Blank.")); - item = "blank"; - } - } + camera_flip = Settings::values.camera_flip; QList cameras = QCameraInfo::availableCameras(); for (const QCameraInfo& cameraInfo : cameras) { ui->system_camera->addItem(cameraInfo.deviceName()); @@ -98,6 +91,8 @@ void ConfigureCamera::connectEvents() { connect(ui->system_camera, static_cast(&QComboBox::currentIndexChanged), this, [=] { stopPreviewing(); }); + connect(ui->camera_flip, static_cast(&QComboBox::currentIndexChanged), + this, [=] { stopPreviewing(); }); } void ConfigureCamera::updateCameraMode() { @@ -148,6 +143,8 @@ void ConfigureCamera::updateImageSourceUI() { } ui->system_camera_label->setHidden(image_source != 2); ui->system_camera->setHidden(image_source != 2); + ui->camera_flip_label->setHidden(image_source == 0); + ui->camera_flip->setHidden(image_source == 0); } void ConfigureCamera::recordConfig() { @@ -166,10 +163,12 @@ void ConfigureCamera::recordConfig() { if (current_selected == CameraPosition::RearBoth) { camera_name[0] = camera_name[2] = implementation; camera_config[0] = camera_config[2] = config; + camera_flip[0] = camera_flip[2] = ui->camera_flip->currentIndex(); } else if (current_selected != CameraPosition::Null) { int index = static_cast(current_selected); camera_name[index] = implementation; camera_config[index] = config; + camera_flip[index] = ui->camera_flip->currentIndex(); } current_selected = getCameraSelection(); } @@ -187,9 +186,9 @@ void ConfigureCamera::startPreviewing() { ui->preview_box->setToolTip(tr("Resolution: ") + QString::number(preview_width) + "*" + QString::number(preview_height)); // Load previewing camera - previewing_camera = - Camera::CreateCameraPreview(camera_name[camera_selection], camera_config[camera_selection], - preview_width, preview_height); + previewing_camera = Camera::CreateCameraPreview( + camera_name[camera_selection], camera_config[camera_selection], preview_width, + preview_height, static_cast(camera_flip[camera_selection])); if (!previewing_camera) { stopPreviewing(); return; @@ -262,6 +261,7 @@ void ConfigureCamera::setConfiguration() { } else { ui->camera_file->setText(QString::fromStdString(camera_config[index])); } + ui->camera_flip->setCurrentIndex(camera_flip[index]); updateImageSourceUI(); } @@ -288,6 +288,7 @@ void ConfigureCamera::applyConfiguration() { stopPreviewing(); Settings::values.camera_name = camera_name; Settings::values.camera_config = camera_config; + Settings::values.camera_flip = camera_flip; Settings::Apply(); } diff --git a/src/citra_qt/configuration/configure_camera.h b/src/citra_qt/configuration/configure_camera.h index 5621de7ef..0aa55996e 100644 --- a/src/citra_qt/configuration/configure_camera.h +++ b/src/citra_qt/configuration/configure_camera.h @@ -47,6 +47,7 @@ private: std::unique_ptr ui; std::array camera_name; std::array camera_config; + std::array camera_flip; int timer_id = 0; int preview_width = 0; int preview_height = 0; diff --git a/src/citra_qt/configuration/configure_camera.ui b/src/citra_qt/configuration/configure_camera.ui index cd4d2e108..46c56b266 100644 --- a/src/citra_qt/configuration/configure_camera.ui +++ b/src/citra_qt/configuration/configure_camera.ui @@ -1,257 +1,347 @@ - - ConfigureCamera - - + ConfigureCamera + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Camera + + - - - Camera + + + + + Select the camera to configure - - - - - - - Select the camera to configure - - - Camera to configure: - - - - - - - Select the camera to configure - - - - Front - - - - - Rear - - - - - - - - - - - - Select the camera mode (single or double) - - - Camera mode: - - - - - - - Select the camera mode (single or double) - - - - Single (2D) - - - - - Double (3D) - - - - - - - - - - - - Select the position of camera to configure - - - Camera position: - - - - - - - Select the position of camera to configure - - - - Left - - - - - Right - - - - - - - - + + Camera to configure: + + + + + + + Select the camera to configure + + + + Front + + + + + Rear + + + + + - - - Configuration + + + + + Select the camera mode (single or double) - - - - - - - Select where the image of the emulated camera comes from. It may be an image or a real camera. - - - Camera Image Source: - - - - - - - Select where the image of the emulated camera come from. It may be an image or a real camera. - - - - Blank (blank) - - - - - Still Image (image) - - - - - System Camera (qt) - - - - - - - - - - - - QFrame::NoFrame - - - File: - - - - - - - - - - ... - - - - - - - - - - - QFrame::NoFrame - - - Camera: - - - - - - - - <Default> - - - - - - - - - - Prompt before load - - - - - + + Camera mode: + + + + + + + Select the camera mode (single or double) + + + + Single (2D) + + + + + Double (3D) + + + + + - - - Preview + + + + + Select the position of camera to configure - - - - - - 512 - 384 - - - - Resolution: 512*384 - - - - - - - - - - Click to preview - - - - - + + Camera position: + + + + + + + Select the position of camera to configure + + + + Left + + + + + Right + + + + + + + + + + + + + Configuration + + + + + + + + Select where the image of the emulated camera comes from. It may be an image or a real camera. + + + Camera Image Source: + + + + + + + Select where the image of the emulated camera comes from. It may be an image or a real camera. + + + + Blank (blank) + + + + + Still Image (image) + + + + + System Camera (qt) + + + + + - - - Qt::Vertical + + + + + QFrame::NoFrame - - - 20 - 40 - + + File: - + + + + + + + + + ... + + + + - - - - + + + + + + QFrame::NoFrame + + + Select the system camera to use + + + Camera: + + + + + + + + 0 + 0 + + + + + 250 + 16777215 + + + + Select the system camera to use + + + + <Default> + + + + + + + + + + + + QFrame::NoFrame + + + Select the image flip to apply + + + Flip: + + + + + + + true + + + + 0 + 0 + + + + + 800 + 16777215 + + + + Select the image flip to apply + + + + None + + + + + Horizontal + + + + + Vertical + + + + + Reverse + + + + + + + + + + Select an image file every time before the camera is loaded + + + Prompt before load + + + + + + + + + + Preview + + + + + + + 512 + 384 + + + + Resolution: 512*384 + + + + + + + + + + Click to preview + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp index f0434cdad..2a871196c 100644 --- a/src/core/frontend/camera/factory.cpp +++ b/src/core/frontend/camera/factory.cpp @@ -17,10 +17,11 @@ void RegisterFactory(const std::string& name, std::unique_ptr fac factories[name] = std::move(factory); } -std::unique_ptr CreateCamera(const std::string& name, const std::string& config) { +std::unique_ptr CreateCamera(const std::string& name, const std::string& config, + const Service::CAM::Flip& flip) { auto pair = factories.find(name); if (pair != factories.end()) { - return pair->second->Create(config); + return pair->second->Create(config, flip); } if (name != "blank") { @@ -31,10 +32,10 @@ std::unique_ptr CreateCamera(const std::string& name, const std std::unique_ptr CreateCameraPreview(const std::string& name, const std::string& config, int width, - int height) { + int height, const Service::CAM::Flip& flip) { auto pair = factories.find(name); if (pair != factories.end()) { - return pair->second->CreatePreview(config, width, height); + return pair->second->CreatePreview(config, width, height, flip); } if (name != "blank") { diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index 840be7022..2c4ab1479 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -18,22 +18,26 @@ public: * Creates a camera object based on the configuration string. * @param config Configuration string to create the camera. The implementation can decide the * meaning of this string. + * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. */ - virtual std::unique_ptr Create(const std::string& config) const = 0; + virtual std::unique_ptr Create(const std::string& config, + const Service::CAM::Flip& flip) const = 0; /** * Creates a camera object for preview based on the configuration string. * @param config Configuration string to create the camera. The implementation can decide the * meaning of this string. + * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. * Note: The default implementation for this is to call Create(). Derived classes may have other * Implementations. For example, A dialog may be used instead of LOG_ERROR when error * occurs. */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, - int height) const { - return Create(config); + int height, + const Service::CAM::Flip& flip) const { + return Create(config, flip); } }; @@ -50,7 +54,8 @@ void RegisterFactory(const std::string& name, std::unique_ptr fac * @param config Configuration string to create the camera. The meaning of this string is * defined by the factory. */ -std::unique_ptr CreateCamera(const std::string& name, const std::string& config); +std::unique_ptr CreateCamera(const std::string& name, const std::string& config, + const Service::CAM::Flip& flip); /** * Creates a camera from the factory for previewing. @@ -60,6 +65,6 @@ std::unique_ptr CreateCamera(const std::string& name, const std */ std::unique_ptr CreateCameraPreview(const std::string& name, const std::string& config, int width, - int height); + int height, const Service::CAM::Flip& flip); } // namespace Camera diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index 3328dcf8e..78cdb23e8 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -1041,8 +1041,9 @@ void Module::ReloadCameraDevices() { } void Module::LoadCameraImplementation(CameraConfig& camera, int camera_id) { - camera.impl = Camera::CreateCamera(Settings::values.camera_name[camera_id], - Settings::values.camera_config[camera_id]); + camera.impl = Camera::CreateCamera( + Settings::values.camera_name[camera_id], Settings::values.camera_config[camera_id], + static_cast(Settings::values.camera_flip[camera_id])); camera.impl->SetFlip(camera.contexts[0].flip); camera.impl->SetEffect(camera.contexts[0].effect); camera.impl->SetFormat(camera.contexts[0].format); diff --git a/src/core/settings.h b/src/core/settings.h index b57a1cbed..5ce4811af 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -140,6 +140,7 @@ struct Values { // Camera std::array camera_name; std::array camera_config; + std::array camera_flip; // Debugging bool use_gdbstub; From 6e410dcef55d55a40305baa574ace61d5f7fe86b Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 26 May 2018 11:26:58 +0800 Subject: [PATCH 07/19] camera: refactor (add qt_camera_base) --- src/citra_qt/CMakeLists.txt | 4 +- src/citra_qt/camera/qt_camera_base.cpp | 57 ++++++++++++++++++++ src/citra_qt/camera/qt_camera_base.h | 36 +++++++++++++ src/citra_qt/camera/qt_camera_factory.cpp | 24 --------- src/citra_qt/camera/qt_camera_factory.h | 18 ------- src/citra_qt/camera/qt_multimedia_camera.cpp | 31 ++--------- src/citra_qt/camera/qt_multimedia_camera.h | 14 ++--- src/citra_qt/camera/still_image_camera.cpp | 32 ++--------- src/citra_qt/camera/still_image_camera.h | 14 ++--- 9 files changed, 107 insertions(+), 123 deletions(-) create mode 100644 src/citra_qt/camera/qt_camera_base.cpp create mode 100644 src/citra_qt/camera/qt_camera_base.h delete mode 100644 src/citra_qt/camera/qt_camera_factory.cpp delete mode 100644 src/citra_qt/camera/qt_camera_factory.h diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 4e0fcdbeb..7b0d0eaac 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -13,8 +13,8 @@ add_executable(citra-qt camera/camera_util.h camera/still_image_camera.cpp camera/still_image_camera.h - camera/qt_camera_factory.cpp - camera/qt_camera_factory.h + camera/qt_camera_base.cpp + camera/qt_camera_base.h camera/qt_multimedia_camera.cpp camera/qt_multimedia_camera.h citra-qt.rc diff --git a/src/citra_qt/camera/qt_camera_base.cpp b/src/citra_qt/camera/qt_camera_base.cpp new file mode 100644 index 000000000..65bf2361c --- /dev/null +++ b/src/citra_qt/camera/qt_camera_base.cpp @@ -0,0 +1,57 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "citra_qt/camera/camera_util.h" +#include "citra_qt/camera/qt_camera_base.h" + +namespace Camera { + +QtCameraInterface::QtCameraInterface(const Service::CAM::Flip& flip) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); + flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); +} + +void QtCameraInterface::SetFormat(Service::CAM::OutputFormat output_format) { + output_rgb = output_format == Service::CAM::OutputFormat::RGB565; +} + +void QtCameraInterface::SetResolution(const Service::CAM::Resolution& resolution) { + width = resolution.width; + height = resolution.height; +} + +void QtCameraInterface::SetFlip(Service::CAM::Flip flip) { + using namespace Service::CAM; + flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); + flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); +} + +void QtCameraInterface::SetEffect(Service::CAM::Effect effect) { + if (effect != Service::CAM::Effect::None) { + NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); + } +} + +std::vector QtCameraInterface::ReceiveFrame() { + return CameraUtil::ProcessImage(QtReceiveFrame(), width, height, output_rgb, flip_horizontal, + flip_vertical); +} + +std::unique_ptr QtCameraFactory::CreatePreview( + const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { + std::unique_ptr camera = Create(config, flip); + + if (camera->IsPreviewAvailable()) { + return camera; + } + QMessageBox::critical( + nullptr, QObject::tr("Error"), + (config.empty() ? QObject::tr("Couldn't load the camera") + : QObject::tr("Couldn't load %1").arg(QString::fromStdString(config)))); + return nullptr; +} + +} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_base.h b/src/citra_qt/camera/qt_camera_base.h new file mode 100644 index 000000000..e66c3bb46 --- /dev/null +++ b/src/citra_qt/camera/qt_camera_base.h @@ -0,0 +1,36 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "core/frontend/camera/factory.h" + +namespace Camera { + +// Base class for camera interfaces of citra_qt +class QtCameraInterface : public CameraInterface { +public: + QtCameraInterface(const Service::CAM::Flip& flip); + void SetResolution(const Service::CAM::Resolution&) override; + void SetFlip(Service::CAM::Flip) override; + void SetEffect(Service::CAM::Effect) override; + void SetFormat(Service::CAM::OutputFormat) override; + std::vector ReceiveFrame() override; + virtual QImage QtReceiveFrame() = 0; + +private: + int width, height; + bool output_rgb; + bool flip_horizontal, flip_vertical; + bool basic_flip_horizontal, basic_flip_vertical; +}; + +// Base class for camera factories of citra_qt +class QtCameraFactory : public CameraFactory { + std::unique_ptr CreatePreview(const std::string& config, int width, int height, + const Service::CAM::Flip& flip) const override; +}; + +} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_factory.cpp b/src/citra_qt/camera/qt_camera_factory.cpp deleted file mode 100644 index 063a600df..000000000 --- a/src/citra_qt/camera/qt_camera_factory.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "citra_qt/camera/qt_camera_factory.h" - -namespace Camera { - -std::unique_ptr QtCameraFactory::CreatePreview( - const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { - std::unique_ptr camera = Create(config, flip); - - if (camera->IsPreviewAvailable()) { - return camera; - } - QMessageBox::critical( - nullptr, QObject::tr("Error"), - (config.empty() ? QObject::tr("Couldn't load the camera") - : QObject::tr("Couldn't load %1").arg(QString::fromStdString(config)))); - return nullptr; -} - -} // namespace Camera diff --git a/src/citra_qt/camera/qt_camera_factory.h b/src/citra_qt/camera/qt_camera_factory.h deleted file mode 100644 index 9e590ca66..000000000 --- a/src/citra_qt/camera/qt_camera_factory.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include "core/frontend/camera/factory.h" - -namespace Camera { - -// Base class for camera factories of citra_qt -class QtCameraFactory : public CameraFactory { - std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const override; -}; - -} // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 5f2137835..abf2ff25e 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -48,16 +48,13 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip) - : handler(QtMultimediaCameraHandler::GetHandler()) { + : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler()) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); } else { QMetaObject::invokeMethod(handler.get(), "CreateCamera", Qt::BlockingQueuedConnection, Q_ARG(const std::string&, camera_name)); } - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); } QtMultimediaCamera::~QtMultimediaCamera() { @@ -77,10 +74,6 @@ void QtMultimediaCamera::StopCapture() { handler->StopCamera(); } -void QtMultimediaCamera::SetFormat(Service::CAM::OutputFormat output_format) { - output_rgb = output_format == Service::CAM::OutputFormat::RGB565; -} - void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { const std::array FrameRateList = { /* Rate_15 */ QCamera::FrameRateRange(15, 15), @@ -104,27 +97,9 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { handler->settings.setMinimumFrameRate(framerate.maximumFrameRate); } -void QtMultimediaCamera::SetResolution(const Service::CAM::Resolution& resolution) { - width = resolution.width; - height = resolution.height; -} - -void QtMultimediaCamera::SetFlip(Service::CAM::Flip flip) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); - flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); -} - -void QtMultimediaCamera::SetEffect(Service::CAM::Effect effect) { - if (effect != Service::CAM::Effect::None) { - NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); - } -} - -std::vector QtMultimediaCamera::ReceiveFrame() { +QImage QtMultimediaCamera::QtReceiveFrame() { QMutexLocker locker(&handler->camera_surface.mutex); - return CameraUtil::ProcessImage(handler->camera_surface.current_frame, width, height, - output_rgb, flip_horizontal, flip_vertical); + return handler->camera_surface.current_frame; } bool QtMultimediaCamera::IsPreviewAvailable() { diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 580834275..41024214c 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -13,7 +13,7 @@ #include #include #include "citra_qt/camera/camera_util.h" -#include "citra_qt/camera/qt_camera_factory.h" +#include "citra_qt/camera/qt_camera_base.h" #include "core/frontend/camera/interface.h" class GMainWindow; @@ -36,26 +36,18 @@ private: class QtMultimediaCameraHandler; /// This class is only an interface. It just calls QtMultimediaCameraHandler. -class QtMultimediaCamera final : public CameraInterface { +class QtMultimediaCamera final : public QtCameraInterface { public: QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip); ~QtMultimediaCamera(); void StartCapture() override; void StopCapture() override; - void SetResolution(const Service::CAM::Resolution&) override; - void SetFlip(Service::CAM::Flip) override; - void SetEffect(Service::CAM::Effect) override; - void SetFormat(Service::CAM::OutputFormat) override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override; - std::vector ReceiveFrame() override; + QImage QtReceiveFrame() override; bool IsPreviewAvailable() override; private: std::shared_ptr handler; - int width, height; - bool output_rgb; - bool flip_horizontal, flip_vertical; - bool basic_flip_horizontal, basic_flip_vertical; }; class QtMultimediaCameraFactory final : public QtCameraFactory { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index 7e54fad3e..2b9f4e54b 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -10,40 +10,14 @@ namespace Camera { StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) - : image(std::move(image_)) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal = (flip == Flip::Horizontal) || (flip == Flip::Reverse); - flip_vertical = basic_flip_vertical = (flip == Flip::Vertical) || (flip == Flip::Reverse); -} + : QtCameraInterface(flip), image(std::move(image_)) {} void StillImageCamera::StartCapture() {} void StillImageCamera::StopCapture() {} -void StillImageCamera::SetFormat(Service::CAM::OutputFormat output_format) { - output_rgb = output_format == Service::CAM::OutputFormat::RGB565; -} - -void StillImageCamera::SetResolution(const Service::CAM::Resolution& resolution) { - width = resolution.width; - height = resolution.height; -} - -void StillImageCamera::SetFlip(Service::CAM::Flip flip) { - using namespace Service::CAM; - flip_horizontal = basic_flip_horizontal ^ (flip == Flip::Horizontal || flip == Flip::Reverse); - flip_vertical = basic_flip_vertical ^ (flip == Flip::Vertical || flip == Flip::Reverse); -} - -void StillImageCamera::SetEffect(Service::CAM::Effect effect) { - if (effect != Service::CAM::Effect::None) { - NGLOG_ERROR(Service_CAM, "Unimplemented effect {}", static_cast(effect)); - } -} - -std::vector StillImageCamera::ReceiveFrame() { - return CameraUtil::ProcessImage(image, width, height, output_rgb, flip_horizontal, - flip_vertical); +QImage StillImageCamera::QtReceiveFrame() { + return image; } bool StillImageCamera::IsPreviewAvailable() { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index e9016981b..11011622f 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -7,30 +7,22 @@ #include #include #include "citra_qt/camera/camera_util.h" -#include "citra_qt/camera/qt_camera_factory.h" +#include "citra_qt/camera/qt_camera_base.h" #include "core/frontend/camera/interface.h" namespace Camera { -class StillImageCamera final : public CameraInterface { +class StillImageCamera final : public QtCameraInterface { public: StillImageCamera(QImage image, const Service::CAM::Flip& flip); void StartCapture() override; void StopCapture() override; - void SetResolution(const Service::CAM::Resolution&) override; - void SetFlip(Service::CAM::Flip) override; - void SetEffect(Service::CAM::Effect) override; - void SetFormat(Service::CAM::OutputFormat) override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override {} - std::vector ReceiveFrame() override; + QImage QtReceiveFrame() override; bool IsPreviewAvailable() override; private: QImage image; - int width, height; - bool output_rgb; - bool flip_horizontal, flip_vertical; - bool basic_flip_horizontal, basic_flip_vertical; }; class StillImageCameraFactory final : public QtCameraFactory { From 3cb91338e966730cbda7940577246b50b35f8259 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 26 May 2018 11:32:18 +0800 Subject: [PATCH 08/19] camera: migrate logging macros --- src/core/frontend/camera/factory.cpp | 4 ++-- src/core/frontend/camera/factory.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp index 2a871196c..619fa3974 100644 --- a/src/core/frontend/camera/factory.cpp +++ b/src/core/frontend/camera/factory.cpp @@ -25,7 +25,7 @@ std::unique_ptr CreateCamera(const std::string& name, const std } if (name != "blank") { - LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); + NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); } return std::make_unique(); } @@ -39,7 +39,7 @@ std::unique_ptr CreateCameraPreview(const std::string& name, } if (name != "blank") { - LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); + NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); } return std::make_unique(); } diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index 2c4ab1479..dc795f0ce 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -31,7 +31,7 @@ public: * @param flip The image flip to apply * @returns a unique_ptr to the created camera object. * Note: The default implementation for this is to call Create(). Derived classes may have other - * Implementations. For example, A dialog may be used instead of LOG_ERROR when error + * Implementations. For example, A dialog may be used instead of NGLOG_ERROR when error * occurs. */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, From 341c07156ac02f213e14c18ca2e28d119df7719f Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 2 Jun 2018 22:13:54 +0800 Subject: [PATCH 09/19] camera: Single/Double (QtMultimediaCamera) --- src/citra_qt/camera/qt_multimedia_camera.cpp | 20 +++++++++++++++++--- src/citra_qt/camera/qt_multimedia_camera.h | 4 +++- src/citra_qt/camera/still_image_camera.cpp | 5 ++--- src/citra_qt/camera/still_image_camera.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index abf2ff25e..05bcbd4f8 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -48,7 +48,7 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, const Service::CAM::Flip& flip) - : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler()) { + : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler(camera_name)) { if (handler->thread() == QThread::currentThread()) { handler->CreateCamera(camera_name); } else { @@ -94,7 +94,7 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { auto framerate = FrameRateList[static_cast(frame_rate)]; handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); - handler->settings.setMinimumFrameRate(framerate.maximumFrameRate); + handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); } QImage QtMultimediaCamera::QtReceiveFrame() { @@ -115,17 +115,25 @@ std::array, 3> QtMultimediaCameraHand std::array QtMultimediaCameraHandler::status; +std::unordered_map> + QtMultimediaCameraHandler::loaded; + void QtMultimediaCameraHandler::Init() { for (auto& handler : handlers) { handler = std::make_shared(); } } -std::shared_ptr QtMultimediaCameraHandler::GetHandler() { +std::shared_ptr QtMultimediaCameraHandler::GetHandler( + const std::string& camera_name) { + if (loaded.count(camera_name)) { + return loaded.at(camera_name); + } for (int i = 0; i < handlers.size(); i++) { if (!status[i]) { NGLOG_INFO(Service_CAM, "Successfully got handler {}", i); status[i] = true; + loaded.emplace(camera_name, handlers[i]); return handlers[i]; } } @@ -140,6 +148,12 @@ void QtMultimediaCameraHandler::ReleaseHandler( NGLOG_INFO(Service_CAM, "Successfully released handler {}", i); status[i] = false; handlers[i]->started = false; + for (auto it = loaded.begin(); it != loaded.end(); it++) { + if (it->second == handlers[i]) { + loaded.erase(it); + break; + } + } break; } } diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index 41024214c..e6d7b6b6d 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -62,7 +63,7 @@ class QtMultimediaCameraHandler final : public QObject { public: /// Creates the global handler. Must be called in UI thread. static void Init(); - static std::shared_ptr GetHandler(); + static std::shared_ptr GetHandler(const std::string& camera_name); static void ReleaseHandler(const std::shared_ptr& handler); /** @@ -92,6 +93,7 @@ private: static std::array, 3> handlers; static std::array status; + static std::unordered_map> loaded; friend class QtMultimediaCamera; // For access to camera_surface (and camera) }; diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index 2b9f4e54b..a166e3336 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -24,7 +24,7 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } -const std::string StillImageCameraFactory::getFilePath() { +const std::string StillImageCameraFactory::GetFilePath() { QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -32,7 +32,6 @@ const std::string StillImageCameraFactory::getFilePath() { } QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); - return QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter) .toStdString(); } @@ -41,7 +40,7 @@ std::unique_ptr StillImageCameraFactory::Create( const std::string& config, const Service::CAM::Flip& flip) const { std::string real_config = config; if (config.empty()) { - real_config = getFilePath(); + real_config = GetFilePath(); } QImage image(QString::fromStdString(real_config)); if (image.isNull()) { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index 11011622f..80e43ba17 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -31,7 +31,7 @@ public: const Service::CAM::Flip& flip) const override; private: - static const std::string getFilePath(); + static const std::string GetFilePath(); }; } // namespace Camera From 7c48160beb8a4b0937dbe39ac2e84bcd422be08e Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sun, 3 Jun 2018 11:29:46 +0800 Subject: [PATCH 10/19] StillImageCamera: move GetFilePath to UI thread --- src/citra_qt/camera/qt_camera_base.cpp | 5 +++-- src/citra_qt/camera/qt_camera_base.h | 2 +- src/citra_qt/camera/qt_multimedia_camera.cpp | 4 ++-- src/citra_qt/camera/qt_multimedia_camera.h | 2 +- src/citra_qt/camera/still_image_camera.cpp | 16 ++++++++++++---- src/citra_qt/camera/still_image_camera.h | 9 +++++---- src/core/frontend/camera/factory.h | 4 ++-- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/citra_qt/camera/qt_camera_base.cpp b/src/citra_qt/camera/qt_camera_base.cpp index 65bf2361c..69593ab51 100644 --- a/src/citra_qt/camera/qt_camera_base.cpp +++ b/src/citra_qt/camera/qt_camera_base.cpp @@ -40,8 +40,9 @@ std::vector QtCameraInterface::ReceiveFrame() { flip_vertical); } -std::unique_ptr QtCameraFactory::CreatePreview( - const std::string& config, int width, int height, const Service::CAM::Flip& flip) const { +std::unique_ptr QtCameraFactory::CreatePreview(const std::string& config, + int width, int height, + const Service::CAM::Flip& flip) { std::unique_ptr camera = Create(config, flip); if (camera->IsPreviewAvailable()) { diff --git a/src/citra_qt/camera/qt_camera_base.h b/src/citra_qt/camera/qt_camera_base.h index e66c3bb46..6c6095a28 100644 --- a/src/citra_qt/camera/qt_camera_base.h +++ b/src/citra_qt/camera/qt_camera_base.h @@ -30,7 +30,7 @@ private: // Base class for camera factories of citra_qt class QtCameraFactory : public CameraFactory { std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; }; } // namespace Camera diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index 05bcbd4f8..ad6bad876 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -106,8 +106,8 @@ bool QtMultimediaCamera::IsPreviewAvailable() { return handler->CameraAvailable(); } -std::unique_ptr QtMultimediaCameraFactory::Create( - const std::string& config, const Service::CAM::Flip& flip) const { +std::unique_ptr QtMultimediaCameraFactory::Create(const std::string& config, + const Service::CAM::Flip& flip) { return std::make_unique(config, flip); } diff --git a/src/citra_qt/camera/qt_multimedia_camera.h b/src/citra_qt/camera/qt_multimedia_camera.h index e6d7b6b6d..14242c554 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.h +++ b/src/citra_qt/camera/qt_multimedia_camera.h @@ -54,7 +54,7 @@ private: class QtMultimediaCameraFactory final : public QtCameraFactory { public: std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; }; class QtMultimediaCameraHandler final : public QObject { diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index a166e3336..b466d17df 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "citra_qt/camera/still_image_camera.h" namespace Camera { @@ -24,7 +25,7 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } -const std::string StillImageCameraFactory::GetFilePath() { +const std::string StillImageCameraFactory::GetFilePath() const { QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -36,11 +37,18 @@ const std::string StillImageCameraFactory::GetFilePath() { .toStdString(); } -std::unique_ptr StillImageCameraFactory::Create( - const std::string& config, const Service::CAM::Flip& flip) const { +std::unique_ptr StillImageCameraFactory::Create(const std::string& config, + const Service::CAM::Flip& flip) { std::string real_config = config; if (config.empty()) { - real_config = GetFilePath(); + // call GetFilePath() in UI thread (note: StillImageCameraFactory itself is initialized in + // UI thread, so we can just pass in "this" here) + if (thread() == QThread::currentThread()) { + real_config = GetFilePath(); + } else { + QMetaObject::invokeMethod(this, "GetFilePath", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(std::string, real_config)); + } } QImage image(QString::fromStdString(real_config)); if (image.isNull()) { diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index 80e43ba17..ccfc13211 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -25,13 +25,14 @@ private: QImage image; }; -class StillImageCameraFactory final : public QtCameraFactory { +class StillImageCameraFactory final : public QObject, public QtCameraFactory { + Q_OBJECT + public: std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const override; + const Service::CAM::Flip& flip) override; -private: - static const std::string GetFilePath(); + Q_INVOKABLE const std::string GetFilePath() const; }; } // namespace Camera diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h index dc795f0ce..0fe9f314f 100644 --- a/src/core/frontend/camera/factory.h +++ b/src/core/frontend/camera/factory.h @@ -22,7 +22,7 @@ public: * @returns a unique_ptr to the created camera object. */ virtual std::unique_ptr Create(const std::string& config, - const Service::CAM::Flip& flip) const = 0; + const Service::CAM::Flip& flip) = 0; /** * Creates a camera object for preview based on the configuration string. @@ -36,7 +36,7 @@ public: */ virtual std::unique_ptr CreatePreview(const std::string& config, int width, int height, - const Service::CAM::Flip& flip) const { + const Service::CAM::Flip& flip) { return Create(config, flip); } }; From a15e4e80c695e8a5976418c333a99b610f3b6d9d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 7 Jun 2018 12:59:18 +0800 Subject: [PATCH 11/19] QtMultimediaCamera: fix invalid settings --- src/citra_qt/camera/qt_multimedia_camera.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/camera/qt_multimedia_camera.cpp b/src/citra_qt/camera/qt_multimedia_camera.cpp index ad6bad876..76a21453d 100644 --- a/src/citra_qt/camera/qt_multimedia_camera.cpp +++ b/src/citra_qt/camera/qt_multimedia_camera.cpp @@ -93,8 +93,10 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { auto framerate = FrameRateList[static_cast(frame_rate)]; - handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); - handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); + if (handler->camera->supportedViewfinderFrameRateRanges().contains(framerate)) { + handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); + handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); + } } QImage QtMultimediaCamera::QtReceiveFrame() { @@ -171,6 +173,7 @@ void QtMultimediaCameraHandler::CreateCamera(const std::string& camera_name) { settings.setMinimumFrameRate(30); settings.setMaximumFrameRate(30); camera->setViewfinder(&camera_surface); + camera->load(); } void QtMultimediaCameraHandler::StopCamera() { From 3c554153c78ece768e05b126ff2bc51338f0c08d Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 7 Jun 2018 14:48:52 +0800 Subject: [PATCH 12/19] StillImageCamera: fix multiple prompt --- src/citra_qt/camera/still_image_camera.cpp | 14 ++++++++++++-- src/citra_qt/camera/still_image_camera.h | 7 +++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/camera/still_image_camera.cpp b/src/citra_qt/camera/still_image_camera.cpp index b466d17df..e02d0d0d3 100644 --- a/src/citra_qt/camera/still_image_camera.cpp +++ b/src/citra_qt/camera/still_image_camera.cpp @@ -13,6 +13,10 @@ namespace Camera { StillImageCamera::StillImageCamera(QImage image_, const Service::CAM::Flip& flip) : QtCameraInterface(flip), image(std::move(image_)) {} +StillImageCamera::~StillImageCamera() { + StillImageCameraFactory::last_path.clear(); +} + void StillImageCamera::StartCapture() {} void StillImageCamera::StopCapture() {} @@ -25,7 +29,12 @@ bool StillImageCamera::IsPreviewAvailable() { return !image.isNull(); } +std::string StillImageCameraFactory::last_path; + const std::string StillImageCameraFactory::GetFilePath() const { + if (!last_path.empty()) { + return last_path; + } QList types = QImageReader::supportedImageFormats(); QList temp_filters; for (QByteArray type : types) { @@ -33,8 +42,9 @@ const std::string StillImageCameraFactory::GetFilePath() const { } QString filter = QObject::tr("Supported image files (%1)").arg(temp_filters.join(" ")); - return QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter) - .toStdString(); + last_path = + QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter).toStdString(); + return last_path; } std::unique_ptr StillImageCameraFactory::Create(const std::string& config, diff --git a/src/citra_qt/camera/still_image_camera.h b/src/citra_qt/camera/still_image_camera.h index ccfc13211..19ca044f0 100644 --- a/src/citra_qt/camera/still_image_camera.h +++ b/src/citra_qt/camera/still_image_camera.h @@ -15,6 +15,7 @@ namespace Camera { class StillImageCamera final : public QtCameraInterface { public: StillImageCamera(QImage image, const Service::CAM::Flip& flip); + ~StillImageCamera(); void StartCapture() override; void StopCapture() override; void SetFrameRate(Service::CAM::FrameRate frame_rate) override {} @@ -33,6 +34,12 @@ public: const Service::CAM::Flip& flip) override; Q_INVOKABLE const std::string GetFilePath() const; + +private: + /// Record the path chosen to avoid multiple prompt problem + static std::string last_path; + + friend class StillImageCamera; }; } // namespace Camera From cb52033133e6ec39ca61ad06c11dd822c6641759 Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Thu, 7 Jun 2018 17:49:18 +0800 Subject: [PATCH 13/19] game_list: fix system title display --- src/citra_qt/game_list_p.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 1546709aa..a9341de00 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -173,14 +173,20 @@ public: &extension); QString title = data(TitleRole).toString(); QString second_name = QString::fromStdString(filename + extension); - static QRegExp installed_system_pattern( + static QRegExp installed_pattern( QString::fromStdString( FileUtil::GetUserPath(D_SDMC_IDX) + "Nintendo " "3DS/00000000000000000000000000000000/00000000000000000000000000000000/" - "title/000400(0|1)0/[0-9a-f]{8}/content/") + "title/0004000(0|e)/[0-9a-f]{8}/content/") .replace("\\", "\\\\")); - if (installed_system_pattern.exactMatch(QString::fromStdString(path))) { + static QRegExp system_pattern( + QString::fromStdString(FileUtil::GetUserPath(D_NAND_IDX) + + "00000000000000000000000000000000/" + "title/00040010/[0-9a-f]{8}/content/") + .replace("\\", "\\\\")); + if (installed_pattern.exactMatch(QString::fromStdString(path)) || + system_pattern.exactMatch(QString::fromStdString(path))) { // Use a different mechanism for system / installed titles showing program ID second_name = QString("%1-%2") .arg(data(ProgramIdRole).toULongLong(), 16, 16, QChar('0')) From 613593167079ef874faa06095bfa06f39c7013a3 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Fri, 8 Jun 2018 02:01:36 -0600 Subject: [PATCH 14/19] travis: share env variables with Docker --- .travis/common/travis-ci.env | 15 +++++++++++++++ .travis/linux-frozen/build.sh | 2 +- .travis/linux/build.sh | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 .travis/common/travis-ci.env diff --git a/.travis/common/travis-ci.env b/.travis/common/travis-ci.env new file mode 100644 index 000000000..7d63674b4 --- /dev/null +++ b/.travis/common/travis-ci.env @@ -0,0 +1,15 @@ +# List of environment variables to be shared with Docker containers +CI +TRAVIS +CONTINUOUS_INTEGRATION +TRAVIS_BRANCH +TRAVIS_BUILD_ID +TRAVIS_BUILD_NUMBER +TRAVIS_COMMIT +TRAVIS_JOB_ID +TRAVIS_JOB_NUMBER +TRAVIS_REPO_SLUG +TRAVIS_TAG + +# citra specific flags +ENABLE_COMPATIBILITY_REPORTING diff --git a/.travis/linux-frozen/build.sh b/.travis/linux-frozen/build.sh index a6372bd33..d849ceaf2 100755 --- a/.travis/linux-frozen/build.sh +++ b/.travis/linux-frozen/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -ex mkdir -p "$HOME/.ccache" docker pull ubuntu:18.04 -docker run -e ENABLE_COMPATIBILITY_REPORTING -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash -ex /citra/.travis/linux-frozen/docker.sh +docker run --env-file .travis/common/travis-ci.env -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash -ex /citra/.travis/linux-frozen/docker.sh diff --git a/.travis/linux/build.sh b/.travis/linux/build.sh index 53e8fa610..499d15b1b 100755 --- a/.travis/linux/build.sh +++ b/.travis/linux/build.sh @@ -1,3 +1,3 @@ #!/bin/bash -ex mkdir -p "$HOME/.ccache" -docker run -e ENABLE_COMPATIBILITY_REPORTING -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash -ex /citra/.travis/linux/docker.sh +docker run --env-file .travis/common/travis-ci.env -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash -ex /citra/.travis/linux/docker.sh From 9f18ec6247909cc2b67cb2b91516f2ccd3e28e07 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Fri, 8 Jun 2018 08:34:57 +0000 Subject: [PATCH 15/19] externals: update soundtouch to pick up x86 fix --- externals/soundtouch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/soundtouch b/externals/soundtouch index 019d2089b..060181eaf 160000 --- a/externals/soundtouch +++ b/externals/soundtouch @@ -1 +1 @@ -Subproject commit 019d2089bbadf70d73ba85aa8ea51490b071262c +Subproject commit 060181eaf273180d3a7e87349895bd0cb6ccbf4a From 23ef36a1cf9a82a4383bdba957768f2e7b5d1955 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Fri, 8 Jun 2018 11:03:04 +0000 Subject: [PATCH 16/19] externals: update cryptopp to CRYPTOPP_7_0_0-23-gf320e7d9 --- externals/cryptopp/cryptopp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/cryptopp/cryptopp b/externals/cryptopp/cryptopp index 5be140bce..f320e7d92 160000 --- a/externals/cryptopp/cryptopp +++ b/externals/cryptopp/cryptopp @@ -1 +1 @@ -Subproject commit 5be140bcea453a00f7f2fec09fb9e37849d65d98 +Subproject commit f320e7d92a33ee80ae42deef79da78cfc30868af From e24fb768e33cef5f41fe075f782dd57892ca6e73 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 8 Jun 2018 18:12:35 -0700 Subject: [PATCH 17/19] boss: Return buff_size in parameter 2 of ReceiveProperty. --- src/core/hle/service/boss/boss.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp index 7eae94972..974b5ed29 100644 --- a/src/core/hle/service/boss/boss.cpp +++ b/src/core/hle/service/boss/boss.cpp @@ -404,7 +404,7 @@ void ReceiveProperty(Service::Interface* self) { cmd_buff[0] = IPC::MakeHeader(0x16, 0x2, 0x2); cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32 bit value) + cmd_buff[2] = buff_size; // Should be actual number of read bytes. cmd_buff[3] = (buff_size << 4 | 0xC); cmd_buff[4] = buff_addr; From 2cecb3bd6e04a3ff753efc625ed0d4324d51864c Mon Sep 17 00:00:00 2001 From: liushuyu Date: Fri, 8 Jun 2018 19:11:59 -0600 Subject: [PATCH 18/19] appveyor: fix mingw issue (again) --- appveyor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a6e66881d..772635267 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,13 +27,14 @@ install: - ps: | if ($env:BUILD_TYPE -eq 'mingw') { $dependencies = "mingw64/mingw-w64-x86_64-qt5" + C:\msys64\usr\bin\bash -lc "pacman -Syy" # redirect err to null to prevent warnings from becoming errors # workaround to prevent pacman from failing due to cyclical dependencies C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw64/mingw-w64-x86_64-freetype mingw64/mingw-w64-x86_64-fontconfig" 2> $null C:\msys64\usr\bin\bash -lc "pacman --noconfirm -U http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-SDL2-2.0.5-2-any.pkg.tar.xz" 2> $null C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S $dependencies" 2> $null - # stick to cmake 3.9.6 since on lower versions it could happen that cmake generates a Makefile that links against gcc_eh - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -U http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-cmake-3.9.6-1-any.pkg.tar.xz" 2> $null + # freeze the cmake to a stable version, on version < 3.9.6 cmake may generate a Makefile links against gcc_eh instead of gcc_s_eh + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -U http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-cmake-3.11.1-2-any.pkg.tar.xz" 2> $null } before_build: From e206f6c202c90ff7ea7687bbb518a288737168cd Mon Sep 17 00:00:00 2001 From: liushuyu Date: Sat, 9 Jun 2018 14:19:15 -0600 Subject: [PATCH 19/19] travis: fix tx push (again) --- .travis/transifex/docker.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.travis/transifex/docker.sh b/.travis/transifex/docker.sh index 9ca97e222..88913ba9e 100644 --- a/.travis/transifex/docker.sh +++ b/.travis/transifex/docker.sh @@ -9,7 +9,21 @@ echo -e "\e[1m\e[33mInstalling dependencies...\e[0m" apk update apk add build-base cmake python3-dev qt5-qttools-dev qt5-qtmultimedia-dev -pip3 install transifex-client +pip3 install --upgrade pip transifex-client + +cat << 'EOF' > /usr/bin/tx +#!/usr/bin/python3 + +# -*- coding: utf-8 -*- +import re +import sys + +from txclib.cmdline import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) +EOF echo -e "\e[1m\e[33mBuild tools information:\e[0m" cmake --version