mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge branch 'master' into core-macros-1
This commit is contained in:
		
						commit
						f0ea96f144
					
				
					 33 changed files with 717 additions and 480 deletions
				
			
		|  | @ -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"); | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										58
									
								
								src/citra_qt/camera/qt_camera_base.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/citra_qt/camera/qt_camera_base.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| // Copyright 2018 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QMessageBox> | ||||
| #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<int>(effect)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<u16> QtCameraInterface::ReceiveFrame() { | ||||
|     return CameraUtil::ProcessImage(QtReceiveFrame(), width, height, output_rgb, flip_horizontal, | ||||
|                                     flip_vertical); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> QtCameraFactory::CreatePreview(const std::string& config, | ||||
|                                                                 int width, int height, | ||||
|                                                                 const Service::CAM::Flip& flip) { | ||||
|     std::unique_ptr<CameraInterface> 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
 | ||||
							
								
								
									
										36
									
								
								src/citra_qt/camera/qt_camera_base.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/citra_qt/camera/qt_camera_base.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 <string> | ||||
| #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<u16> 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<CameraInterface> CreatePreview(const std::string& config, int width, int height, | ||||
|                                                    const Service::CAM::Flip& flip) override; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Camera
 | ||||
|  | @ -1,24 +0,0 @@ | |||
| // Copyright 2018 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QMessageBox> | ||||
| #include "citra_qt/camera/qt_camera_factory.h" | ||||
| 
 | ||||
| namespace Camera { | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> QtCameraFactory::CreatePreview(const std::string& config, | ||||
|                                                                 int width, int height) const { | ||||
|     std::unique_ptr<CameraInterface> camera = Create(config); | ||||
| 
 | ||||
|     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
 | ||||
|  | @ -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 <string> | ||||
| #include "core/frontend/camera/factory.h" | ||||
| 
 | ||||
| namespace Camera { | ||||
| 
 | ||||
| // Base class for camera factories of citra_qt
 | ||||
| class QtCameraFactory : public CameraFactory { | ||||
|     std::unique_ptr<CameraInterface> CreatePreview(const std::string& config, int width, | ||||
|                                                    int height) const override; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Camera
 | ||||
|  | @ -46,8 +46,9 @@ bool QtCameraSurface::present(const QVideoFrame& frame) { | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name) | ||||
|     : handler(QtMultimediaCameraHandler::GetHandler()) { | ||||
| QtMultimediaCamera::QtMultimediaCamera(const std::string& camera_name, | ||||
|                                        const Service::CAM::Flip& flip) | ||||
|     : QtCameraInterface(flip), handler(QtMultimediaCameraHandler::GetHandler(camera_name)) { | ||||
|     if (handler->thread() == QThread::currentThread()) { | ||||
|         handler->CreateCamera(camera_name); | ||||
|     } else { | ||||
|  | @ -73,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<QCamera::FrameRateRange, 13> FrameRateList = { | ||||
|         /* Rate_15 */ QCamera::FrameRateRange(15, 15), | ||||
|  | @ -96,57 +93,49 @@ void QtMultimediaCamera::SetFrameRate(Service::CAM::FrameRate frame_rate) { | |||
| 
 | ||||
|     auto framerate = FrameRateList[static_cast<int>(frame_rate)]; | ||||
| 
 | ||||
|     handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); | ||||
|     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 = (flip == Flip::Horizontal) || (flip == Flip::Reverse); | ||||
|     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<int>(effect)); | ||||
|     if (handler->camera->supportedViewfinderFrameRateRanges().contains(framerate)) { | ||||
|         handler->settings.setMinimumFrameRate(framerate.minimumFrameRate); | ||||
|         handler->settings.setMaximumFrameRate(framerate.maximumFrameRate); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<u16> 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() { | ||||
|     return handler->CameraAvailable(); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> QtMultimediaCameraFactory::Create( | ||||
|     const std::string& config) const { | ||||
|     return std::make_unique<QtMultimediaCamera>(config); | ||||
| std::unique_ptr<CameraInterface> QtMultimediaCameraFactory::Create(const std::string& config, | ||||
|                                                                    const Service::CAM::Flip& flip) { | ||||
|     return std::make_unique<QtMultimediaCamera>(config, flip); | ||||
| } | ||||
| 
 | ||||
| std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> QtMultimediaCameraHandler::handlers; | ||||
| 
 | ||||
| std::array<bool, 3> QtMultimediaCameraHandler::status; | ||||
| 
 | ||||
| std::unordered_map<std::string, std::shared_ptr<QtMultimediaCameraHandler>> | ||||
|     QtMultimediaCameraHandler::loaded; | ||||
| 
 | ||||
| void QtMultimediaCameraHandler::Init() { | ||||
|     for (auto& handler : handlers) { | ||||
|         handler = std::make_shared<QtMultimediaCameraHandler>(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<QtMultimediaCameraHandler> QtMultimediaCameraHandler::GetHandler() { | ||||
| std::shared_ptr<QtMultimediaCameraHandler> 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]; | ||||
|         } | ||||
|     } | ||||
|  | @ -161,6 +150,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; | ||||
|         } | ||||
|     } | ||||
|  | @ -178,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() { | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| 
 | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| #include <QAbstractVideoSurface> | ||||
| #include <QCamera> | ||||
|  | @ -13,7 +14,7 @@ | |||
| #include <QImage> | ||||
| #include <QMutex> | ||||
| #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,30 +37,24 @@ 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); | ||||
|     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<u16> ReceiveFrame() override; | ||||
|     QImage QtReceiveFrame() override; | ||||
|     bool IsPreviewAvailable() override; | ||||
| 
 | ||||
| private: | ||||
|     std::shared_ptr<QtMultimediaCameraHandler> handler; | ||||
|     int width, height; | ||||
|     bool output_rgb; | ||||
|     bool flip_horizontal, flip_vertical; | ||||
| }; | ||||
| 
 | ||||
| class QtMultimediaCameraFactory final : public QtCameraFactory { | ||||
| public: | ||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config) const override; | ||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||
|                                             const Service::CAM::Flip& flip) override; | ||||
| }; | ||||
| 
 | ||||
| class QtMultimediaCameraHandler final : public QObject { | ||||
|  | @ -68,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<QtMultimediaCameraHandler> GetHandler(); | ||||
|     static std::shared_ptr<QtMultimediaCameraHandler> GetHandler(const std::string& camera_name); | ||||
|     static void ReleaseHandler(const std::shared_ptr<QtMultimediaCameraHandler>& handler); | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -98,6 +93,7 @@ private: | |||
| 
 | ||||
|     static std::array<std::shared_ptr<QtMultimediaCameraHandler>, 3> handlers; | ||||
|     static std::array<bool, 3> status; | ||||
|     static std::unordered_map<std::string, std::shared_ptr<QtMultimediaCameraHandler>> loaded; | ||||
| 
 | ||||
|     friend class QtMultimediaCamera; // For access to camera_surface (and camera)
 | ||||
| }; | ||||
|  |  | |||
|  | @ -5,47 +5,36 @@ | |||
| #include <QFileDialog> | ||||
| #include <QImageReader> | ||||
| #include <QMessageBox> | ||||
| #include <QThread> | ||||
| #include "citra_qt/camera/still_image_camera.h" | ||||
| 
 | ||||
| namespace Camera { | ||||
| 
 | ||||
| StillImageCamera::StillImageCamera(QImage image_) : image(std::move(image_)) {} | ||||
| 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() {} | ||||
| 
 | ||||
| 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 = (flip == Flip::Horizontal) || (flip == Flip::Reverse); | ||||
|     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<int>(effect)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<u16> StillImageCamera::ReceiveFrame() { | ||||
|     return CameraUtil::ProcessImage(image, width, height, output_rgb, flip_horizontal, | ||||
|                                     flip_vertical); | ||||
| QImage StillImageCamera::QtReceiveFrame() { | ||||
|     return image; | ||||
| } | ||||
| 
 | ||||
| bool StillImageCamera::IsPreviewAvailable() { | ||||
|     return !image.isNull(); | ||||
| } | ||||
| 
 | ||||
| const std::string StillImageCameraFactory::getFilePath() { | ||||
| std::string StillImageCameraFactory::last_path; | ||||
| 
 | ||||
| const std::string StillImageCameraFactory::GetFilePath() const { | ||||
|     if (!last_path.empty()) { | ||||
|         return last_path; | ||||
|     } | ||||
|     QList<QByteArray> types = QImageReader::supportedImageFormats(); | ||||
|     QList<QString> temp_filters; | ||||
|     for (QByteArray type : types) { | ||||
|  | @ -53,21 +42,29 @@ 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(); | ||||
|     last_path = | ||||
|         QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"), ".", filter).toStdString(); | ||||
|     return last_path; | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> StillImageCameraFactory::Create(const std::string& config) const { | ||||
| std::unique_ptr<CameraInterface> 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()) { | ||||
|         NGLOG_ERROR(Service_CAM, "Couldn't load image \"{}\"", real_config.c_str()); | ||||
|     } | ||||
|     return std::make_unique<StillImageCamera>(image); | ||||
|     return std::make_unique<StillImageCamera>(image, flip); | ||||
| } | ||||
| 
 | ||||
| } // namespace Camera
 | ||||
|  |  | |||
|  | @ -7,37 +7,39 @@ | |||
| #include <vector> | ||||
| #include <QImage> | ||||
| #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); | ||||
|     StillImageCamera(QImage image, const Service::CAM::Flip& flip); | ||||
|     ~StillImageCamera(); | ||||
|     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<u16> ReceiveFrame() override; | ||||
|     QImage QtReceiveFrame() override; | ||||
|     bool IsPreviewAvailable() override; | ||||
| 
 | ||||
| private: | ||||
|     QImage image; | ||||
|     int width, height; | ||||
|     bool output_rgb; | ||||
|     bool flip_horizontal, flip_vertical; | ||||
| }; | ||||
| 
 | ||||
| class StillImageCameraFactory final : public QtCameraFactory { | ||||
| class StillImageCameraFactory final : public QObject, public QtCameraFactory { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config) const override; | ||||
|     std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||
|                                             const Service::CAM::Flip& flip) override; | ||||
| 
 | ||||
|     Q_INVOKABLE const std::string GetFilePath() const; | ||||
| 
 | ||||
| private: | ||||
|     static const std::string getFilePath(); | ||||
|     /// Record the path chosen to avoid multiple prompt problem
 | ||||
|     static std::string last_path; | ||||
| 
 | ||||
|     friend class StillImageCamera; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Camera
 | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
|  | @ -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<QCameraInfo> 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<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|             [=] { stopPreviewing(); }); | ||||
|     connect(ui->camera_flip, static_cast<void (QComboBox::*)(int)>(&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<int>(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<Service::CAM::Flip>(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(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ private: | |||
|     std::unique_ptr<Ui::ConfigureCamera> ui; | ||||
|     std::array<std::string, 3> camera_name; | ||||
|     std::array<std::string, 3> camera_config; | ||||
|     std::array<int, 3> camera_flip; | ||||
|     int timer_id = 0; | ||||
|     int preview_width = 0; | ||||
|     int preview_height = 0; | ||||
|  |  | |||
|  | @ -1,257 +1,347 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| 
 | ||||
| <ui version="4.0"> | ||||
|   <class>ConfigureCamera</class> | ||||
|   <widget class="QWidget" name="ConfigureCamera"> | ||||
|     <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|  <class>ConfigureCamera</class> | ||||
|  <widget class="QWidget" name="ConfigureCamera"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>400</width> | ||||
|     <height>300</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Form</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="groupBox"> | ||||
|      <property name="title"> | ||||
|       <string>Camera</string> | ||||
|      </property> | ||||
|      <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|       <item> | ||||
|         <widget class="QGroupBox" name="groupBox"> | ||||
|           <property name="title"> | ||||
|             <string>Camera</string> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="camera_selection_label"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the camera to configure</string> | ||||
|           </property> | ||||
|           <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="camera_selection_label"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the camera to configure</string> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>Camera to configure:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QComboBox" name="camera_selection"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the camera to configure</string> | ||||
|                     </property> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Front</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Rear</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="camera_mode_label"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the camera mode (single or double)</string> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>Camera mode:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QComboBox" name="camera_mode"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the camera mode (single or double)</string> | ||||
|                     </property> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Single (2D)</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Double (3D)</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="camera_position_label"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the position of camera to configure</string> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>Camera position:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QComboBox" name="camera_position"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select the position of camera to configure</string> | ||||
|                     </property> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Left</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Right</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|           </layout> | ||||
|         </widget> | ||||
|           <property name="text"> | ||||
|            <string>Camera to configure:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="camera_selection"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the camera to configure</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Front</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Rear</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|         <widget class="QGroupBox" name="configurationBox"> | ||||
|           <property name="title"> | ||||
|             <string>Configuration</string> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="camera_mode_label"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the camera mode (single or double)</string> | ||||
|           </property> | ||||
|           <layout class="QVBoxLayout" name="verticalLayout_configuration"> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="image_source_label"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select where the image of the emulated camera comes from. It may be an image or a real camera.</string> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>Camera Image Source:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QComboBox" name="image_source"> | ||||
|                     <property name="toolTip"> | ||||
|                       <string>Select where the image of the emulated camera come from. It may be an image or a real camera.</string> | ||||
|                     </property> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Blank (blank)</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>Still Image (image)</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string>System Camera (qt)</string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="camera_file_label"> | ||||
|                     <property name="frameShape"> | ||||
|                       <enum>QFrame::NoFrame</enum> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>File:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QLineEdit" name="camera_file"/> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QToolButton" name="toolButton"> | ||||
|                     <property name="text"> | ||||
|                       <string>...</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|             <item> | ||||
|               <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||||
|                 <item> | ||||
|                   <widget class="QLabel" name="system_camera_label"> | ||||
|                     <property name="frameShape"> | ||||
|                       <enum>QFrame::NoFrame</enum> | ||||
|                     </property> | ||||
|                     <property name="text"> | ||||
|                       <string>Camera:</string> | ||||
|                     </property> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                   <widget class="QComboBox" name="system_camera"> | ||||
|                     <item> | ||||
|                       <property name="text"> | ||||
|                         <string><Default></string> | ||||
|                       </property> | ||||
|                     </item> | ||||
|                   </widget> | ||||
|                 </item> | ||||
|               </layout> | ||||
|             </item> | ||||
|             <item> | ||||
|               <widget class="QCheckBox" name="prompt_before_load"> | ||||
|                 <property name="text"> | ||||
|                   <string>Prompt before load</string> | ||||
|                 </property> | ||||
|               </widget> | ||||
|             </item> | ||||
|           </layout> | ||||
|         </widget> | ||||
|           <property name="text"> | ||||
|            <string>Camera mode:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="camera_mode"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the camera mode (single or double)</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Single (2D)</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Double (3D)</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|         <widget class="QGroupBox" name="previewBox"> | ||||
|           <property name="title"> | ||||
|             <string>Preview</string> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="camera_position_label"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the position of camera to configure</string> | ||||
|           </property> | ||||
|           <layout class="QVBoxLayout" name="verticalLayout_3"> | ||||
|             <item> | ||||
|               <widget class="QLabel" name="preview_box"> | ||||
|                 <property name="baseSize"> | ||||
|                   <size> | ||||
|                     <width>512</width> | ||||
|                     <height>384</height> | ||||
|                   </size> | ||||
|                 </property> | ||||
|                 <property name="toolTip"> | ||||
|                   <string>Resolution: 512*384</string> | ||||
|                 </property> | ||||
|                 <property name="text"> | ||||
|                   <string/> | ||||
|                 </property> | ||||
|               </widget> | ||||
|             </item> | ||||
|             <item> | ||||
|               <widget class="QPushButton" name="preview_button"> | ||||
|                 <property name="text"> | ||||
|                   <string>Click to preview</string> | ||||
|                 </property> | ||||
|               </widget> | ||||
|             </item> | ||||
|           </layout> | ||||
|         </widget> | ||||
|           <property name="text"> | ||||
|            <string>Camera position:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="camera_position"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the position of camera to configure</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Left</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Right</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="configurationBox"> | ||||
|      <property name="title"> | ||||
|       <string>Configuration</string> | ||||
|      </property> | ||||
|      <layout class="QVBoxLayout" name="verticalLayout_configuration"> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="image_source_label"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select where the image of the emulated camera comes from. It may be an image or a real camera.</string> | ||||
|           </property> | ||||
|           <property name="text"> | ||||
|            <string>Camera Image Source:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="image_source"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select where the image of the emulated camera comes from. It may be an image or a real camera.</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Blank (blank)</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Still Image (image)</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>System Camera (qt)</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|         <spacer> | ||||
|           <property name="orientation"> | ||||
|             <enum>Qt::Vertical</enum> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="camera_file_label"> | ||||
|           <property name="frameShape"> | ||||
|            <enum>QFrame::NoFrame</enum> | ||||
|           </property> | ||||
|           <property name="sizeHint" stdset="0"> | ||||
|             <size> | ||||
|               <width>20</width> | ||||
|               <height>40</height> | ||||
|             </size> | ||||
|           <property name="text"> | ||||
|            <string>File:</string> | ||||
|           </property> | ||||
|         </spacer> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QLineEdit" name="camera_file"/> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QToolButton" name="toolButton"> | ||||
|           <property name="text"> | ||||
|            <string>...</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|     </layout> | ||||
|   </widget> | ||||
|   <resources/> | ||||
|   <connections/> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="system_camera_label"> | ||||
|           <property name="frameShape"> | ||||
|            <enum>QFrame::NoFrame</enum> | ||||
|           </property> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the system camera to use</string> | ||||
|           </property> | ||||
|           <property name="text"> | ||||
|            <string>Camera:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="system_camera"> | ||||
|           <property name="sizePolicy"> | ||||
|            <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||
|             <horstretch>0</horstretch> | ||||
|             <verstretch>0</verstretch> | ||||
|            </sizepolicy> | ||||
|           </property> | ||||
|           <property name="maximumSize"> | ||||
|            <size> | ||||
|             <width>250</width> | ||||
|             <height>16777215</height> | ||||
|            </size> | ||||
|           </property> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the system camera to use</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string><Default></string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout_8"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="camera_flip_label"> | ||||
|           <property name="frameShape"> | ||||
|            <enum>QFrame::NoFrame</enum> | ||||
|           </property> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the image flip to apply</string> | ||||
|           </property> | ||||
|           <property name="text"> | ||||
|            <string>Flip:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="camera_flip"> | ||||
|           <property name="enabled"> | ||||
|            <bool>true</bool> | ||||
|           </property> | ||||
|           <property name="sizePolicy"> | ||||
|            <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||
|             <horstretch>0</horstretch> | ||||
|             <verstretch>0</verstretch> | ||||
|            </sizepolicy> | ||||
|           </property> | ||||
|           <property name="maximumSize"> | ||||
|            <size> | ||||
|             <width>800</width> | ||||
|             <height>16777215</height> | ||||
|            </size> | ||||
|           </property> | ||||
|           <property name="toolTip"> | ||||
|            <string>Select the image flip to apply</string> | ||||
|           </property> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>None</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Horizontal</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Vertical</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Reverse</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QCheckBox" name="prompt_before_load"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Select an image file every time before the camera is loaded</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>Prompt before load</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="previewBox"> | ||||
|      <property name="title"> | ||||
|       <string>Preview</string> | ||||
|      </property> | ||||
|      <layout class="QVBoxLayout" name="verticalLayout_3"> | ||||
|       <item> | ||||
|        <widget class="QLabel" name="preview_box"> | ||||
|         <property name="baseSize"> | ||||
|          <size> | ||||
|           <width>512</width> | ||||
|           <height>384</height> | ||||
|          </size> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>Resolution: 512*384</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string/> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QPushButton" name="preview_button"> | ||||
|         <property name="text"> | ||||
|          <string>Click to preview</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <spacer> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Vertical</enum> | ||||
|      </property> | ||||
|      <property name="sizeHint" stdset="0"> | ||||
|       <size> | ||||
|        <width>20</width> | ||||
|        <height>40</height> | ||||
|       </size> | ||||
|      </property> | ||||
|     </spacer> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
|  |  | |||
|  | @ -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')) | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -17,28 +17,29 @@ void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> fac | |||
|     factories[name] = std::move(factory); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config) { | ||||
| std::unique_ptr<CameraInterface> 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") { | ||||
|         NGLOG_ERROR(Service_CAM, "Unknown camera \"{}\"", name); | ||||
|         NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); | ||||
|     } | ||||
|     return std::make_unique<BlankCamera>(); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<CameraInterface> 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") { | ||||
|         NGLOG_ERROR(Service_CAM, "Unknown camera \"{}\"", name); | ||||
|         NGLOG_ERROR(Service_CAM, "Unknown camera {}", name); | ||||
|     } | ||||
|     return std::make_unique<BlankCamera>(); | ||||
| } | ||||
|  |  | |||
|  | @ -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<CameraInterface> Create(const std::string& config) const = 0; | ||||
|     virtual std::unique_ptr<CameraInterface> Create(const std::string& config, | ||||
|                                                     const Service::CAM::Flip& flip) = 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 NGLOG_ERROR when error | ||||
|      * occurs. | ||||
|      */ | ||||
|     virtual std::unique_ptr<CameraInterface> CreatePreview(const std::string& config, int width, | ||||
|                                                            int height) const { | ||||
|         return Create(config); | ||||
|                                                            int height, | ||||
|                                                            const Service::CAM::Flip& flip) { | ||||
|         return Create(config, flip); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -50,7 +54,8 @@ void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> fac | |||
|  * @param config Configuration string to create the camera. The meaning of this string is | ||||
|  *     defined by the factory. | ||||
|  */ | ||||
| std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config); | ||||
| std::unique_ptr<CameraInterface> 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<CameraInterface> CreateCamera(const std::string& name, const std | |||
|  */ | ||||
| std::unique_ptr<CameraInterface> CreateCameraPreview(const std::string& name, | ||||
|                                                      const std::string& config, int width, | ||||
|                                                      int height); | ||||
|                                                      int height, const Service::CAM::Flip& flip); | ||||
| 
 | ||||
| } // namespace Camera
 | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Service::CAM::Flip>(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); | ||||
|  |  | |||
|  | @ -140,6 +140,7 @@ struct Values { | |||
|     // Camera
 | ||||
|     std::array<std::string, Service::CAM::NumCameras> camera_name; | ||||
|     std::array<std::string, Service::CAM::NumCameras> camera_config; | ||||
|     std::array<int, Service::CAM::NumCameras> camera_flip; | ||||
| 
 | ||||
|     // Debugging
 | ||||
|     bool use_gdbstub; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  | @ -580,10 +580,30 @@ 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(); | ||||
| } | ||||
| 
 | ||||
| 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 +747,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; | ||||
| } | ||||
|  | @ -885,10 +908,17 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* 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}; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <cstddef> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| #include <boost/optional.hpp> | ||||
| #include <nihstro/shader_bytecode.h> | ||||
| #include <xbyak.h> | ||||
| #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<Xbyak::Label, MAX_PROGRAM_CODE_LENGTH> 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<Xbyak::Label> loop_break_label; | ||||
| 
 | ||||
|     /// Offsets in code where a return needs to be inserted
 | ||||
|     std::vector<unsigned> return_offsets; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue