Handle number of M68K cycles used when tracing in debugger mode
[clinton/Virtual-Jaguar-Rx.git] / src / gui / glwidget.cpp
1 // OpenGL implementation in Qt
2 // Parts of this are blantantly ripped off from BSNES (thanks Byuu!)
3 //
4 // by James Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
9 //
10 // Who When What
11 // --- ---------- -------------------------------------------------------------
12 // JLH 01/14/2010 Created this file
13 // JLH 02/03/2013 Added "centered" fullscreen mode with correct aspect ratio
14 // JPM 06/06/2016 Visual Studio support
15 //
16
17 #include "glwidget.h"
18
19 #include "jaguar.h"
20 #include "settings.h"
21 #include "tom.h"
22
23 #if defined(__GCCWIN32__) || defined(_MSC_VER)
24 #if defined(_MSC_VER)
25 #include <GL/gl.h>
26 #endif
27 // Apparently on win32, various OpenGL constants aren't pulled in.
28 #include <GL/glext.h>
29 #endif
30
31
32 GLWidget::GLWidget(QWidget * parent/*= 0*/): QGLWidget(parent), texture(0),
33 textureWidth(0), textureHeight(0), buffer(0), rasterWidth(326), rasterHeight(240),
34 offset(0), hideMouseTimeout(60)
35 {
36 // Screen pitch has to be the texture width (in 32-bit pixels)...
37 JaguarSetScreenPitch(1024);
38 setMouseTracking(true);
39 }
40
41
42 GLWidget::~GLWidget()
43 {
44 if (buffer)
45 delete[] buffer;
46 }
47
48
49 void GLWidget::initializeGL()
50 {
51 format().setDoubleBuffer(true);
52 resizeGL(rasterWidth, rasterHeight);
53
54 glDisable(GL_ALPHA_TEST);
55 glDisable(GL_BLEND);
56 glDisable(GL_DEPTH_TEST);
57 glDisable(GL_POLYGON_SMOOTH);
58 glDisable(GL_STENCIL_TEST);
59 glEnable(GL_DITHER);
60 glEnable(GL_TEXTURE_2D);
61 glClearColor(0.0, 0.0, 0.0, 0.0);
62
63 CreateTextures();
64 }
65
66
67 void GLWidget::paintGL()
68 {
69 // If we're in fullscreen mode, we take the value of the screen width as
70 // set by MainWin, since it may be wider than what our aspect ratio allows.
71 // In that case, we adjust the viewport over so that it's centered on the
72 // screen. Otherwise, we simply take the width from our width() funtion
73 // which will always be correct in windowed mode.
74
75 if (!fullscreen)
76 outputWidth = width();
77
78 // Bit 0 in VP is interlace flag. 0 = interlace, 1 = non-interlaced
79 double multiplier = (TOMGetVP() & 0x0001 ? 1.0 : 2.0);
80 unsigned outputHeight = height();
81
82 glMatrixMode(GL_PROJECTION);
83 glLoadIdentity();
84 glOrtho(0, outputWidth, 0, outputHeight, -1.0, 1.0);
85 glViewport(0 + offset, 0, outputWidth, outputHeight);
86
87 glMatrixMode(GL_MODELVIEW);
88 glLoadIdentity();
89
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (vjs.glFilter ? GL_LINEAR : GL_NEAREST));
91 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (vjs.glFilter ? GL_LINEAR : GL_NEAREST));
92 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TOMGetVideoModeWidth(), rasterHeight * multiplier, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
93
94 double w = (double)TOMGetVideoModeWidth() / (double)textureWidth;
95 double h = ((double)rasterHeight * multiplier) / (double)textureHeight;
96 unsigned u = outputWidth;
97 unsigned v = outputHeight;
98
99 glBegin(GL_TRIANGLE_STRIP);
100 glTexCoord2f(0, 0); glVertex3i(0, v, 0);
101 glTexCoord2f(w, 0); glVertex3i(u, v, 0);
102 glTexCoord2f(0, h); glVertex3i(0, 0, 0);
103 glTexCoord2f(w, h); glVertex3i(u, 0, 0);
104 glEnd();
105 }
106
107
108 void GLWidget::resizeGL(int /*width*/, int /*height*/)
109 {
110 //kludge [No, this is where it belongs!]
111 rasterHeight = (vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL);
112
113 return;
114 }
115
116
117 // At some point, we'll have to create more than one texture to handle
118 // cases like Doom. Or have another go at TV type rendering; it will
119 // require a 2048x512 texture though. (Note that 512 is the correct height for
120 // interlaced screens; we won't have to change much here to support it.)
121 void GLWidget::CreateTextures(void)
122 {
123 // Seems that power of 2 sizes are still mandatory...
124 textureWidth = 1024;
125 textureHeight = 512;
126 buffer = new uint32_t[textureWidth * textureHeight];
127 JaguarSetScreenBuffer(buffer);
128
129 glGenTextures(1, &texture);
130 glBindTexture(GL_TEXTURE_2D, texture);
131 glPixelStorei(GL_UNPACK_ROW_LENGTH, textureWidth);
132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
134 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL);
135 }
136
137
138 void GLWidget::HandleMouseHiding(void)
139 {
140 // Mouse watchdog timer handling. Basically, if the timeout value is
141 // greater than zero, decrement it. Otherwise, check for zero, if so, then
142 // hide the mouse and set the hideMouseTimeout value to -1 to signal that
143 // the mouse has been hidden.
144 if (hideMouseTimeout > 0)
145 hideMouseTimeout--;
146 else if (hideMouseTimeout == 0)
147 {
148 hideMouseTimeout--;
149 setCursor(Qt::BlankCursor);
150 }
151 }
152
153
154 // We use this as part of a watchdog system for hiding/unhiding the mouse. This
155 // part shows the mouse (if hidden) and resets the watchdog timer.
156 void GLWidget::CheckAndRestoreMouseCursor(void)
157 {
158 // Has the mouse been hidden? (-1 means mouse was hidden)
159 if (hideMouseTimeout == -1)
160 setCursor(Qt::ArrowCursor);
161
162 hideMouseTimeout = 60;
163 }
164
165
166 // We check here for mouse movement; if there is any, show the mouse and reset
167 // the watchdog timer.
168 void GLWidget::mouseMoveEvent(QMouseEvent * /*event*/)
169 {
170 CheckAndRestoreMouseCursor();
171 }
172
173
174 #if 0
175 class RubyGLWidget: public QGLWidget
176 {
177 public:
178 GLuint texture;
179 unsigned textureWidth, textureHeight;
180
181 uint32_t * buffer;
182 unsigned rasterWidth, rasterHeight;
183
184 bool synchronize;
185 unsigned filter;
186
187 void updateSynchronization() {
188 #ifdef __APPLE__
189 makeCurrent();
190 CGLContextObj context = CGLGetCurrentContext();
191 GLint value = synchronize; //0 = draw immediately (no vsync), 1 = draw once per frame (vsync)
192 CGLSetParameter(context, kCGLCPSwapInterval, &value);
193 #endif
194 }
195 } * widget;
196 #endif