/* Copyright 2016-2023 melonDS team This file is part of melonDS. melonDS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. melonDS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ #ifndef SCREEN_H #define SCREEN_H #include "glad/glad.h" #include "FrontendUtil.h" #include "duckstation/gl/context.h" #include #include #include #include #include #include #include #include #include class EmuThread; const struct { int id; float ratio; const char* label; } aspectRatios[] = { { 0, 1, "4:3 (native)" }, { 4, (5.f / 3) / (4.f / 3), "5:3 (3DS)"}, { 1, (16.f / 9) / (4.f / 3), "16:9" }, { 2, (21.f / 9) / (4.f / 3), "21:9" }, { 3, 0, "window" } }; constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]); class ScreenHandler { Q_GADGET public: ScreenHandler(QWidget* widget); virtual ~ScreenHandler(); QTimer* setupMouseTimer(); void updateMouseTimer(); QTimer* mouseTimer; QSize screenGetMinSize(int factor); protected: void screenSetupLayout(int w, int h); void screenOnMousePress(QMouseEvent* event); void screenOnMouseRelease(QMouseEvent* event); void screenOnMouseMove(QMouseEvent* event); void screenHandleTablet(QTabletEvent* event); void screenHandleTouch(QTouchEvent* event); float screenMatrix[Frontend::MaxScreenTransforms][6]; int screenKind[Frontend::MaxScreenTransforms]; int numScreens; bool touching = false; void showCursor(); }; class ScreenPanelNative : public QWidget, public ScreenHandler { Q_OBJECT public: explicit ScreenPanelNative(QWidget* parent); virtual ~ScreenPanelNative(); protected: void paintEvent(QPaintEvent* event) override; void resizeEvent(QResizeEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void tabletEvent(QTabletEvent* event) override; bool event(QEvent* event) override; private slots: void onScreenLayoutChanged(); private: void setupScreenLayout(); QImage screen[2]; QTransform screenTrans[Frontend::MaxScreenTransforms]; }; class ScreenPanelGL : public QWidget, public ScreenHandler { Q_OBJECT public: explicit ScreenPanelGL(QWidget* parent); virtual ~ScreenPanelGL(); std::optional getWindowInfo(); bool createContext(); void setSwapInterval(int intv); void initOpenGL(); void deinitOpenGL(); void drawScreenGL(); GL::Context* getContext() { return glContext.get(); } void transferLayout(); protected: qreal devicePixelRatioFromScreen() const; int scaledWindowWidth() const; int scaledWindowHeight() const; QPaintEngine* paintEngine() const override; void resizeEvent(QResizeEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void tabletEvent(QTabletEvent* event) override; bool event(QEvent* event) override; private slots: void onScreenLayoutChanged(); private: void setupScreenLayout(); std::unique_ptr glContext; GLuint screenVertexBuffer, screenVertexArray; GLuint screenTexture; GLuint screenShaderProgram[3]; GLuint screenShaderTransformULoc, screenShaderScreenSizeULoc; QMutex screenSettingsLock; WindowInfo windowInfo; bool filter; int lastScreenWidth = -1, lastScreenHeight = -1; }; #endif // SCREEN_H