Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/gtk/gtkglwidget.c
2 views
1
/* Copyright 2006 Guillaume Duhamel
2
Copyright 2006 Fabien Coulon
3
4
This file is part of Yabause.
5
6
Yabause is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
Yabause is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with Yabause; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include "gtkglwidget.h"
22
#ifdef HAVE_LIBGTKGLEXT
23
#include <gtk/gtkgl.h>
24
#endif
25
#include "../vidsoft.h"
26
#include "../peripheral.h"
27
28
#define X_NOSCALE 160
29
#define Y_NOSCALE 120
30
31
static void yui_gl_class_init (YuiGlClass * klass);
32
static void yui_gl_init (YuiGl * yfe);
33
static gboolean yui_gl_resize (GtkWidget *w,GdkEventConfigure *event, gpointer data);
34
35
void yui_gl_draw(YuiGl * glxarea) {
36
#ifdef HAVE_LIBGTKGLEXT
37
GdkGLContext *glcontext = gtk_widget_get_gl_context (GTK_WIDGET(glxarea));
38
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (GTK_WIDGET(glxarea));
39
40
if (!gdk_gl_drawable_make_current (gldrawable, glcontext)) {
41
g_print("Cannot set gl drawable current\n");
42
return;
43
}
44
45
gdk_gl_drawable_swap_buffers(gldrawable);
46
#else
47
int buf_width, buf_height;
48
GdkPixbuf * pixbuf, * scaledpixbuf;
49
50
VIDCore->GetGlSize( &buf_width, &buf_height );
51
glxarea->pixels_width = GTK_WIDGET(glxarea)->allocation.width;
52
glxarea->pixels_height = GTK_WIDGET(glxarea)->allocation.height;
53
glxarea->pixels_rowstride = glxarea->pixels_width * 4;
54
glxarea->pixels_rowstride += (glxarea->pixels_rowstride % 4)? (4 - (glxarea->pixels_rowstride % 4)): 0;
55
56
if (dispbuffer == NULL) return;
57
58
pixbuf = gdk_pixbuf_new_from_data((const guchar *) dispbuffer, GDK_COLORSPACE_RGB, TRUE, 8,
59
buf_width, buf_height, buf_width*4, NULL, NULL);
60
61
if (( glxarea->pixels_width < buf_width + X_NOSCALE )&&( glxarea->pixels_height < buf_height + Y_NOSCALE )) {
62
63
gdk_draw_pixbuf(GTK_WIDGET(glxarea)->window, NULL, pixbuf, 0, 0,
64
(glxarea->pixels_width-buf_width)/2, (glxarea->pixels_height-buf_height)/2,
65
buf_width, buf_height, GDK_RGB_DITHER_NONE, 0, 0);
66
} else {
67
68
scaledpixbuf = gdk_pixbuf_scale_simple(pixbuf,
69
glxarea->pixels_width, glxarea->pixels_height, GDK_INTERP_NEAREST );
70
gdk_draw_pixbuf(GTK_WIDGET(glxarea)->window, NULL,
71
scaledpixbuf, 0, 0, 0, 0, glxarea->pixels_width, glxarea->pixels_height,
72
GDK_RGB_DITHER_NONE, 0, 0);
73
g_object_unref(scaledpixbuf);
74
}
75
g_object_unref(pixbuf);
76
#endif
77
glxarea->is_init = 1;
78
}
79
80
void yui_gl_draw_pause(YuiGl * glxarea) {
81
#ifdef HAVE_LIBGTKGLEXT
82
if (glxarea->pixels) {
83
/* The "correct" raster position would be (0, height) but it's not a
84
* valid position, so I have to use this hack... found here:
85
* http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */
86
glRasterPos2i(0, 0);
87
glBitmap(0, 0, 0, 0, 0, - glxarea->pixels_height, NULL);
88
glPixelZoom(1, 1);
89
glDrawPixels(glxarea->pixels_width, glxarea->pixels_height, GL_RGB, GL_UNSIGNED_BYTE, glxarea->pixels);
90
yui_gl_draw(glxarea);
91
} else {
92
gdk_draw_rectangle(GTK_WIDGET(glxarea)->window, GTK_WIDGET(glxarea)->style->bg_gc[GTK_WIDGET_STATE (glxarea)],
93
TRUE, 0, 0, GTK_WIDGET(glxarea)->allocation.width, GTK_WIDGET(glxarea)->allocation.height);
94
}
95
#else
96
if (dispbuffer)
97
yui_gl_draw(glxarea);
98
#endif
99
}
100
101
static gboolean yui_gl_resize(GtkWidget *w,GdkEventConfigure *event, gpointer data) {
102
#ifdef HAVE_LIBGTKGLEXT
103
GdkGLContext *glcontext = gtk_widget_get_gl_context (w);
104
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (w);
105
106
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
107
return FALSE;
108
109
glViewport(0, 0, event->width, event->height);
110
if ( YUI_GL(w)->is_init ) VIDCore->Resize(event->width, event->height, FALSE );
111
#endif
112
return FALSE;
113
}
114
115
int beforehiding = 0;
116
117
static gboolean gonna_hide(gpointer data) {
118
beforehiding--;
119
120
if (beforehiding == 0) {
121
static char source_data[] = { 0 };
122
static char mask_data[] = { 0 };
123
124
GdkCursor *cursor;
125
GdkPixmap *source, *mask;
126
GdkColor fg = { 0, 65535, 65535, 65535 };
127
GdkColor bg = { 0, 0, 0, 0 };
128
129
source = gdk_bitmap_create_from_data(NULL, source_data, 1, 1);
130
mask = gdk_bitmap_create_from_data(NULL, mask_data, 1, 1);
131
cursor = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, 1, 1);
132
gdk_pixmap_unref(source);
133
gdk_pixmap_unref(mask);
134
135
gdk_window_set_cursor(GTK_WIDGET(data)->window, cursor);
136
137
return FALSE;
138
} else {
139
return TRUE;
140
}
141
}
142
143
extern void * padbits;
144
extern GKeyFile * keyfile;
145
int oldx = 0;
146
int oldy = 0;
147
148
static gboolean yui_gl_hide_cursor(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) {
149
if (PerGetId(padbits) == PERMOUSE) {
150
int x = event->x;
151
int y = event->y;
152
double speed = g_key_file_get_double(keyfile, "General", "MouseSpeed", NULL);
153
154
PerMouseMove(padbits, speed * (x - oldx), -speed * (y - oldy));
155
oldx = x;
156
oldy = y;
157
}
158
159
if (beforehiding == 0) {
160
gdk_window_set_cursor(widget->window, NULL);
161
g_timeout_add(1000, gonna_hide, widget);
162
}
163
164
beforehiding = 2;
165
166
return FALSE;
167
}
168
169
static gboolean yui_gl_button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) {
170
if (PerGetId(padbits) == PERMOUSE) {
171
switch(event->button) {
172
case 1:
173
PerMouseLeftPressed(padbits);
174
break;
175
case 2:
176
PerMouseMiddlePressed(padbits);
177
break;
178
case 3:
179
PerMouseRightPressed(padbits);
180
break;
181
}
182
}
183
return FALSE;
184
}
185
186
static gboolean yui_gl_button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) {
187
if (PerGetId(padbits) == PERMOUSE) {
188
switch(event->button) {
189
case 1:
190
PerMouseLeftReleased(padbits);
191
break;
192
case 2:
193
PerMouseMiddleReleased(padbits);
194
break;
195
case 3:
196
PerMouseRightReleased(padbits);
197
break;
198
}
199
}
200
return FALSE;
201
}
202
203
GtkWidget * yui_gl_new(void) {
204
GtkWidget * drawingArea;
205
#ifdef HAVE_LIBGTKGLEXT
206
int attribs[] = {
207
GDK_GL_RGBA,
208
GDK_GL_RED_SIZE, 1,
209
GDK_GL_GREEN_SIZE, 1,
210
GDK_GL_BLUE_SIZE, 1,
211
212
GDK_GL_DOUBLEBUFFER,
213
214
GDK_GL_DEPTH_SIZE ,1,
215
GDK_GL_STENCIL_SIZE ,8,
216
GDK_GL_ATTRIB_LIST_NONE
217
};
218
#endif
219
220
drawingArea = GTK_WIDGET(g_object_new(yui_gl_get_type(), NULL));
221
YUI_GL(drawingArea)->is_init = 0;
222
223
#ifdef HAVE_LIBGTKGLEXT
224
gtk_widget_set_gl_capability(drawingArea, gdk_gl_config_new(attribs), NULL, TRUE, GDK_GL_RGBA_TYPE);
225
#endif
226
227
g_signal_connect (GTK_OBJECT(drawingArea),"configure_event", GTK_SIGNAL_FUNC(yui_gl_resize),0);
228
229
gtk_widget_set_events(drawingArea, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
230
231
g_signal_connect(GTK_OBJECT(drawingArea), "motion-notify-event", GTK_SIGNAL_FUNC(yui_gl_hide_cursor),0);
232
g_signal_connect(GTK_OBJECT(drawingArea), "button-press-event", GTK_SIGNAL_FUNC(yui_gl_button_press),0);
233
g_signal_connect(GTK_OBJECT(drawingArea), "button-release-event", GTK_SIGNAL_FUNC(yui_gl_button_release),0);
234
235
return drawingArea;
236
}
237
238
void yui_gl_dump_screen(YuiGl * glxarea) {
239
#ifdef HAVE_LIBGTKGLEXT
240
int size;
241
242
glxarea->pixels_width = GTK_WIDGET(glxarea)->allocation.width;
243
glxarea->pixels_height = GTK_WIDGET(glxarea)->allocation.height;
244
glxarea->pixels_rowstride = glxarea->pixels_width * 3;
245
glxarea->pixels_rowstride += (glxarea->pixels_rowstride % 4)? (4 - (glxarea->pixels_rowstride % 4)): 0;
246
247
size = glxarea->pixels_rowstride * glxarea->pixels_height;
248
249
if (glxarea->pixels) free(glxarea->pixels);
250
glxarea->pixels = malloc(sizeof(GLubyte) * size);
251
if (glxarea->pixels == NULL) return;
252
253
glReadPixels(0, 0, glxarea->pixels_width, glxarea->pixels_height, GL_RGB, GL_UNSIGNED_BYTE, glxarea->pixels);
254
#else
255
int buf_width, buf_height;
256
int i, j;
257
int size;
258
int cur = 0;
259
u8 * pixels;
260
u8 * buffer;
261
262
VIDCore->GetGlSize( &buf_width, &buf_height );
263
size = buf_width * buf_height * 3;
264
265
glxarea->pixels_width = buf_width;
266
glxarea->pixels_height = buf_height;
267
glxarea->pixels_rowstride = glxarea->pixels_width * 3;
268
glxarea->pixels_rowstride += (glxarea->pixels_rowstride % 4)? (4 - (glxarea->pixels_rowstride % 4)): 0;
269
270
if (! glxarea->pixels) glxarea->pixels = malloc(sizeof(u8) * size);
271
272
pixels = (u8 *)glxarea->pixels;
273
pixels += size - (buf_width * 3);
274
buffer = (u8 *)dispbuffer;
275
276
for(i = 0;i < buf_height;i++) {
277
for(j = 0;j < buf_width;j++) {
278
*pixels++ = buffer[cur];
279
*pixels++ = buffer[cur + 1];
280
*pixels++ = buffer[cur + 2];
281
cur += 4;
282
}
283
pixels -= buf_width * 6;
284
}
285
#endif
286
}
287
288
GType yui_gl_get_type (void) {
289
static GType yfe_type = 0;
290
291
if (!yfe_type)
292
{
293
static const GTypeInfo yfe_info =
294
{
295
sizeof (YuiGlClass),
296
NULL, /* base_init */
297
NULL, /* base_finalize */
298
(GClassInitFunc) yui_gl_class_init,
299
NULL, /* class_finalize */
300
NULL, /* class_data */
301
sizeof (YuiGl),
302
0,
303
(GInstanceInitFunc) yui_gl_init,
304
NULL,
305
};
306
307
yfe_type = g_type_register_static(GTK_TYPE_DRAWING_AREA, "YuiGl", &yfe_info, 0);
308
}
309
310
return yfe_type;
311
}
312
313
static void yui_gl_class_init (UNUSED YuiGlClass * klass) {
314
}
315
316
static void yui_gl_init (YuiGl * y) {
317
y->pixels = NULL;
318
}
319
320