1 /* Copyright (c) 2013-2015 Jeffrey Pfau
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #pragma once
7 
8 #if defined(BUILD_GL) || defined(BUILD_GLES2)
9 
10 #include "Display.h"
11 
12 #ifdef USE_EPOXY
13 #include <epoxy/gl.h>
14 #ifndef GLdouble
15 #define GLdouble GLdouble
16 #endif
17 #endif
18 
19 #include <QAtomicInt>
20 #include <QElapsedTimer>
21 #include <QHash>
22 #include <QList>
23 #include <QMouseEvent>
24 #include <QOpenGLContext>
25 #include <QPainter>
26 #include <QQueue>
27 #include <QThread>
28 #include <QTimer>
29 
30 #include <array>
31 
32 #include "CoreController.h"
33 #include "VideoProxy.h"
34 
35 #include "platform/video-backend.h"
36 
37 class QOpenGLPaintDevice;
38 
39 uint qHash(const QSurfaceFormat&, uint seed = 0);
40 
41 namespace QGBA {
42 
43 class PainterGL;
44 class DisplayGL : public Display {
45 Q_OBJECT
46 
47 public:
48 	DisplayGL(const QSurfaceFormat& format, QWidget* parent = nullptr);
49 	~DisplayGL();
50 
51 	void startDrawing(std::shared_ptr<CoreController>) override;
isDrawing()52 	bool isDrawing() const override { return m_isDrawing; }
53 	bool supportsShaders() const override;
54 	VideoShader* shaders() override;
55 	void setVideoProxy(std::shared_ptr<VideoProxy>) override;
56 	int framebufferHandle() override;
57 
58 	static bool supportsFormat(const QSurfaceFormat&);
59 
60 public slots:
61 	void stopDrawing() override;
62 	void pauseDrawing() override;
63 	void unpauseDrawing() override;
64 	void forceDraw() override;
65 	void lockAspectRatio(bool lock) override;
66 	void lockIntegerScaling(bool lock) override;
67 	void interframeBlending(bool enable) override;
68 	void showOSDMessages(bool enable) override;
69 	void filter(bool filter) override;
70 	void framePosted() override;
71 	void setShaders(struct VDir*) override;
72 	void clearShaders() override;
73 	void resizeContext() override;
74 	void setVideoScale(int scale) override;
75 
76 protected:
paintEvent(QPaintEvent *)77 	virtual void paintEvent(QPaintEvent*) override { forceDraw(); }
78 	virtual void resizeEvent(QResizeEvent*) override;
79 
80 private:
81 	void resizePainter();
82 
83 	static QHash<QSurfaceFormat, bool> s_supports;
84 
85 	bool m_isDrawing = false;
86 	bool m_hasStarted = false;
87 	std::unique_ptr<PainterGL> m_painter;
88 	QThread m_drawThread;
89 	std::shared_ptr<CoreController> m_context;
90 };
91 
92 class PainterGL : public QObject {
93 Q_OBJECT
94 
95 public:
96 	PainterGL(QWindow* surface, const QSurfaceFormat& format);
97 	~PainterGL();
98 
99 	void setThread(QThread*);
100 	void setContext(std::shared_ptr<CoreController>);
101 	void setMessagePainter(MessagePainter*);
102 	void enqueue(const uint32_t* backing);
103 
supportsShaders()104 	bool supportsShaders() const { return m_supportsShaders; }
105 	int glTex();
106 
107 	void setVideoProxy(std::shared_ptr<VideoProxy>);
108 	void interrupt();
109 
110 public slots:
111 	void create();
112 	void destroy();
113 
114 	void forceDraw();
115 	void draw();
116 	void start();
117 	void stop();
118 	void pause();
119 	void unpause();
120 	void resize(const QSize& size);
121 	void lockAspectRatio(bool lock);
122 	void lockIntegerScaling(bool lock);
123 	void interframeBlending(bool enable);
124 	void showOSD(bool enable);
125 	void filter(bool filter);
126 	void resizeContext();
127 
128 	void setShaders(struct VDir*);
129 	void clearShaders();
130 	VideoShader* shaders();
131 
132 signals:
133 	void started();
134 
135 private:
136 	void makeCurrent();
137 	void performDraw();
138 	void dequeue();
139 	void dequeueAll(bool keep = false);
140 
141 	std::array<std::array<uint32_t, 0x100000>, 3> m_buffers;
142 	QList<uint32_t*> m_free;
143 	QQueue<uint32_t*> m_queue;
144 	uint32_t* m_buffer = nullptr;
145 	QPainter m_painter;
146 	QMutex m_mutex;
147 	QWindow* m_surface;
148 	QSurfaceFormat m_format;
149 	std::unique_ptr<QOpenGLPaintDevice> m_window;
150 	std::unique_ptr<QOpenGLContext> m_gl;
151 	bool m_active = false;
152 	bool m_started = false;
153 	QTimer m_drawTimer;
154 	std::shared_ptr<CoreController> m_context;
155 	CoreController::Interrupter m_interrupter;
156 	bool m_supportsShaders;
157 	bool m_showOSD;
158 	VideoShader m_shader{};
159 	VideoBackend* m_backend = nullptr;
160 	QSize m_size;
161 	QSize m_dims;
162 	MessagePainter* m_messagePainter = nullptr;
163 	QElapsedTimer m_delayTimer;
164 	std::shared_ptr<VideoProxy> m_videoProxy;
165 };
166 
167 }
168 
169 #endif
170