Added OpenGL 3D code to gtk-glade UI (adapted from gtk code by Masscat).

Warning: on my nvidia, execution is faster with "--gdk-gl-force-indirect".
This commit is contained in:
evilynux 2007-04-21 19:45:08 +00:00
parent 84dc5d98ef
commit 341f73f24a
6 changed files with 610 additions and 6 deletions

View File

@ -11,6 +11,7 @@ desmume_glade_SOURCES = \
dTools/callbacks_3_palview.c dTools/callbacks_4_tileview.c \
dTools/callbacks_dtools.h \
dTools/dTools_display.h \
gdk_3Demu.c gdk_3Demu.h \
../sndsdl.h ../sndsdl.c ../ctrlssdl.h ../ctrlssdl.c
gladedir = $(datadir)/desmume/glade

View File

@ -0,0 +1,199 @@
/* $Id: gdk_3Demu.c,v 1.1 2007-04-21 19:45:08 evilynux Exp $
*/
/*
Copyright (C) 2006-2007 Ben Jaques
This file is part of DeSmuME
DeSmuME 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 2 of the License, or
(at your option) any later version.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef GTKGLEXT_AVAILABLE
#include <gdk/gdkgl.h>
#include "../types.h"
#include "../render3D.h"
#include "../opengl_collector_3Demu.h"
#include "gdk_3Demu.h"
/*
* The GDK 3D emulation.
* This uses the OpenGL Collector plugin, using gdkGLext for the platform
* specific helper functions.
*/
static GdkPixmap *target_pixmap;
static GdkGLContext *glcontext = NULL;
static GdkGLDrawable *gldrawable;
static void
print_gl_config_attrib (GdkGLConfig *glconfig,
const gchar *attrib_str,
int attrib,
gboolean is_boolean)
{
int value;
g_print ("%s = ", attrib_str);
if (gdk_gl_config_get_attrib (glconfig, attrib, &value))
{
if (is_boolean)
g_print ("%s\n", value == TRUE ? "TRUE" : "FALSE");
else
g_print ("%d\n", value);
}
else
g_print ("*** Cannot get %s attribute value\n", attrib_str);
}
static void
examine_gl_config_attrib (GdkGLConfig *glconfig)
{
g_print ("\nOpenGL visual configurations :\n\n");
g_print ("gdk_gl_config_is_rgba (glconfig) = %s\n",
gdk_gl_config_is_rgba (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_is_double_buffered (glconfig) = %s\n",
gdk_gl_config_is_double_buffered (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_is_stereo (glconfig) = %s\n",
gdk_gl_config_is_stereo (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_has_alpha (glconfig) = %s\n",
gdk_gl_config_has_alpha (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_has_depth_buffer (glconfig) = %s\n",
gdk_gl_config_has_depth_buffer (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_has_stencil_buffer (glconfig) = %s\n",
gdk_gl_config_has_stencil_buffer (glconfig) ? "TRUE" : "FALSE");
g_print ("gdk_gl_config_has_accum_buffer (glconfig) = %s\n",
gdk_gl_config_has_accum_buffer (glconfig) ? "TRUE" : "FALSE");
g_print ("\n");
print_gl_config_attrib (glconfig, "GDK_GL_USE_GL",
GDK_GL_USE_GL, TRUE);
print_gl_config_attrib (glconfig, "GDK_GL_BUFFER_SIZE",
GDK_GL_BUFFER_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_LEVEL",
GDK_GL_LEVEL, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_RGBA",
GDK_GL_RGBA, TRUE);
print_gl_config_attrib (glconfig, "GDK_GL_DOUBLEBUFFER",
GDK_GL_DOUBLEBUFFER, TRUE);
print_gl_config_attrib (glconfig, "GDK_GL_STEREO",
GDK_GL_STEREO, TRUE);
print_gl_config_attrib (glconfig, "GDK_GL_AUX_BUFFERS",
GDK_GL_AUX_BUFFERS, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_RED_SIZE",
GDK_GL_RED_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_GREEN_SIZE",
GDK_GL_GREEN_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_BLUE_SIZE",
GDK_GL_BLUE_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_ALPHA_SIZE",
GDK_GL_ALPHA_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_DEPTH_SIZE",
GDK_GL_DEPTH_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_STENCIL_SIZE",
GDK_GL_STENCIL_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_RED_SIZE",
GDK_GL_ACCUM_RED_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_GREEN_SIZE",
GDK_GL_ACCUM_GREEN_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_BLUE_SIZE",
GDK_GL_ACCUM_BLUE_SIZE, FALSE);
print_gl_config_attrib (glconfig, "GDK_GL_ACCUM_ALPHA_SIZE",
GDK_GL_ACCUM_ALPHA_SIZE, FALSE);
g_print ("\n");
}
static int
begin_opengl_region_gdk_3d( void) {
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) {
return 0;
}
return 1;
}
static void
end_opengl_region_gdk_3d( void) {
gdk_gl_drawable_gl_end (gldrawable);
}
static int
initialise_gdk_3d( void) {
/* this does nothing */
return 1;
}
int
init_opengl_gdk_3Demu( void) {
GdkGLConfig *glconfig;
/* create the off screen pixmap */
target_pixmap = gdk_pixmap_new ( NULL, 256, 192, 24);
if ( target_pixmap == NULL) {
g_print ("*** Failed to create pixmap.\n");
return 0;
}
glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA |
GDK_GL_MODE_ALPHA |
GDK_GL_MODE_DEPTH |
GDK_GL_MODE_SINGLE);
if (glconfig == NULL)
{
g_print ("*** No appropriate OpenGL-capable visual found.\n");
return 0;
}
/*
* Set OpenGL-capability to the pixmap
*/
gldrawable = GDK_GL_DRAWABLE (gdk_pixmap_set_gl_capability (target_pixmap,
glconfig,
NULL));
if ( gldrawable == NULL) {
g_print ("Failed to create the GdkGLPixmap\n");
return 0;
}
glcontext = gdk_gl_context_new (gldrawable,
NULL,
FALSE,
GDK_GL_RGBA_TYPE);
if (glcontext == NULL)
{
g_print ("Connot create the OpenGL rendering context\n");
return 0;
}
begin_opengl_ogl_collector_platform = begin_opengl_region_gdk_3d;
end_opengl_ogl_collector_platform = end_opengl_region_gdk_3d;
initialise_ogl_collector_platform = initialise_gdk_3d;
return 1;
}
#endif

View File

@ -0,0 +1,32 @@
/* $Id: gdk_3Demu.h,v 1.1 2007-04-21 19:45:07 evilynux Exp $
*/
/*
Copyright (C) 2006-2007 Ben Jaques
This file is part of DeSmuME
DeSmuME 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 2 of the License, or
(at your option) any later version.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef GTKGLEXT_AVAILABLE
/*
* The GDK 3D emulation.
* This uses the OpenGL Collector plugin, using gdkGLext for the platform
* specific helper functions.
*/
int
init_opengl_gdk_3Demu( void);
#endif

View File

@ -35,6 +35,8 @@ GdkGLContext *my_glContext[8]={_DUP8(NULL)};
GdkGLDrawable *my_glDrawable[8]={_DUP8(NULL)};
GtkWidget *pDrawingTexArea;
GLuint screen_texture[1];
#undef _DUP8
#undef _DUP4
#undef _DUP2
@ -118,9 +120,9 @@ void init_GL(GtkWidget * widget, int screen, int share_num) {
exit(1);
}
// realize so that we get a GdkWindow
gtk_widget_realize(widget);
gtk_widget_realize(widget);
// make sure we realize
gdk_flush();
gdk_flush();
my_glDrawable[screen] = gtk_widget_get_gl_drawable(widget);
@ -172,6 +174,25 @@ void init_GL_capabilities() {
// initialize 2nd drawing area (sharing context)
init_GL(pDrawingArea2,1,0);
my_gl_Clear(1);
// Signals binding
// Top screen
g_signal_connect_after (G_OBJECT (pDrawingArea), "realize",
G_CALLBACK (gtk_init_main_gl_area),
NULL);
g_signal_connect( G_OBJECT(pDrawingArea), "expose_event",
G_CALLBACK(top_screen_expose_fn), NULL ) ;
g_signal_connect( G_OBJECT(pDrawingArea), "configure_event",
G_CALLBACK(common_configure_fn), NULL ) ;
// Bottom screen
g_signal_connect_after (G_OBJECT (pDrawingArea2), "realize",
G_CALLBACK (gtk_init_sub_gl_area),
NULL);
g_signal_connect( G_OBJECT(pDrawingArea2), "expose_event",
G_CALLBACK(bottom_screen_expose_fn), NULL ) ;
g_signal_connect( G_OBJECT(pDrawingArea2), "configure_event",
G_CALLBACK(common_configure_fn), NULL ) ;
}
/************************************************/
@ -301,4 +322,324 @@ gboolean screen (GtkWidget * widget, int viewportscreen) {
return TRUE;
}
/* 3D Rendering */
static void
gtk_init_main_gl_area(GtkWidget *widget,
gpointer data)
{
GLenum errCode;
int i;
GdkGLContext *glcontext;
GdkGLDrawable *gldrawable;
GtkWidget *other_drawing_area = (GtkWidget *)data;
glcontext = gtk_widget_get_gl_context (widget);
gldrawable = gtk_widget_get_gl_drawable (widget);
uint16_t blank_texture[256 * 512];
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return;
//printf("Doing GL init\n");
for ( i = 0; i < 256 * 512; i++) {
blank_texture[i] = 0x001f;
}
/* Enable Texture Mapping */
glEnable( GL_TEXTURE_2D );
/* Set the background black */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
/* Create The Texture */
glGenTextures( 1, &screen_texture[0]);
glBindTexture( GL_TEXTURE_2D, screen_texture[0]);
/* Generate The Texture */
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 256, 512,
0, GL_RGBA,
GL_UNSIGNED_SHORT_1_5_5_5_REV,
blank_texture);
/* Linear Filtering */
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "Failed to init GL: %s\n", errString);
}
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
}
static void
gtk_init_sub_gl_area(GtkWidget *widget,
gpointer data)
{
GLenum errCode;
GdkGLContext *glcontext;
GdkGLDrawable *gldrawable;
glcontext = gtk_widget_get_gl_context (widget);
gldrawable = gtk_widget_get_gl_drawable (widget);
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return;
/* Enable Texture Mapping */
glEnable( GL_TEXTURE_2D );
/* Set the background black */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glBindTexture( GL_TEXTURE_2D, screen_texture[0]);
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "Failed to init GL: %s\n", errString);
}
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
}
static int
top_screen_expose_fn( GtkWidget *widget, GdkEventExpose *event, gpointer data) {
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
// FIXME: Hardcoded to false for now...
int software_convert = 0;
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
GLenum errCode;
/* Clear The Screen And The Depth Buffer */
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
/* Move Into The Screen 5 Units */
//glLoadIdentity( );
/* Select screen Texture */
glBindTexture( GL_TEXTURE_2D, screen_texture[0]);
if ( software_convert) {
int i;
u8 converted[256 * 384 * 3];
for ( i = 0; i < (256 * 384); i++) {
converted[(i * 3) + 0] = ((*((u16 *)&GPU_screen[(i<<1)]) >> 0) & 0x1f) << 3;
converted[(i * 3) + 1] = ((*((u16 *)&GPU_screen[(i<<1)]) >> 5) & 0x1f) << 3;
converted[(i * 3) + 2] = ((*((u16 *)&GPU_screen[(i<<1)]) >> 10) & 0x1f) << 3;
}
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384,
GL_RGB,
GL_UNSIGNED_BYTE,
converted);
}
else {
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 384,
GL_RGBA,
GL_UNSIGNED_SHORT_1_5_5_5_REV,
&GPU_screen);
}
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "GL subimage failed: %s\n", errString);
}
glBegin( GL_QUADS);
/* Top screen */
glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 0.0f, 0.0f, 0.0f );
glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 256.0f, 0.0f, 0.0f );
glTexCoord2f( 1.0f, 0.375f ); glVertex3f( 256.0f, 192.0f, 0.0f );
glTexCoord2f( 0.0f, 0.375f ); glVertex3f( 0.0f, 192.0f, 0.0f );
glEnd( );
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "GL draw failed: %s\n", errString);
}
if (gdk_gl_drawable_is_double_buffered (gldrawable))
gdk_gl_drawable_swap_buffers (gldrawable);
else
glFlush ();
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
gtk_widget_queue_draw(pDrawingArea2);
}
static int
bottom_screen_expose_fn(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
//g_print("Sub Expose\n");
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) {
g_print("begin failed\n");
return FALSE;
}
//g_print("begin\n");
GLenum errCode;
/* Clear The Screen */
glClear( GL_COLOR_BUFFER_BIT);
//glBindTexture( GL_TEXTURE_2D, screen_texture[0]);
glBegin( GL_QUADS);
/* Bottom screen */
glTexCoord2f( 0.0f, 0.375f ); glVertex2f( 0.0f, 0.0f);
glTexCoord2f( 1.0f, 0.375f ); glVertex2f( 256.0f, 0.0f);
glTexCoord2f( 1.0f, 0.75f ); glVertex2f( 256.0f, 192.0f);
glTexCoord2f( 0.0f, 0.75f ); glVertex2f( 0.0f, 192.0f);
glEnd( );
if (gdk_gl_drawable_is_double_buffered (gldrawable))
gdk_gl_drawable_swap_buffers (gldrawable);
else
glFlush ();
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "sub GL draw failed: %s\n", errString);
}
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
return 1;
}
static gboolean
common_configure_fn( GtkWidget *widget,
GdkEventConfigure *event ) {
if ( gtk_widget_is_gl_capable( widget) == FALSE)
return TRUE;
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
int comp_width = 3 * event->width;
int comp_height = 4 * event->height;
int use_width = 1;
GLenum errCode;
/* Height / width ration */
GLfloat ratio;
//g_print("wdith %d, height %d\n", event->width, event->height);
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
return FALSE;
if ( comp_width > comp_height) {
use_width = 0;
}
/* Protect against a divide by zero */
if ( event->height == 0 )
event->height = 1;
if ( event->width == 0)
event->width = 1;
ratio = ( GLfloat )event->width / ( GLfloat )event->height;
/* Setup our viewport. */
glViewport( 0, 0, ( GLint )event->width, ( GLint )event->height );
/*
* change to the projection matrix and set
* our viewing volume.
*/
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
{
double left;
double right;
double bottom;
double top;
double other_dimen;
if ( use_width) {
left = 0.0;
right = 256.0;
other_dimen = (double)event->width * 3.0 / 4.0;
top = 0.0;
bottom = 192.0 * ((double)event->height / other_dimen);
}
else {
top = 0.0;
bottom = 192.0;
other_dimen = (double)event->height * 4.0 / 3.0;
left = 0.0;
right = 256.0 * ((double)event->width / other_dimen);
}
/*
printf("%d,%d\n", width, height);
printf("l %lf, r %lf, t %lf, b %lf, other dimen %lf\n",
left, right, top, bottom, other_dimen);
*/
/* get the area (0,0) to (256,384) into the middle of the viewport */
gluOrtho2D( left, right, bottom, top);
}
/* Make sure we're chaning the model view and not the projection */
glMatrixMode( GL_MODELVIEW );
/* Reset The View */
glLoadIdentity( );
if ((errCode = glGetError()) != GL_NO_ERROR) {
GLubyte errString;
errString = gluErrorString(errCode);
fprintf( stderr, "GL resie failed: %s\n", errString);
}
gdk_gl_drawable_gl_end (gldrawable);
/*** OpenGL END ***/
return TRUE;
}
#endif /* if HAVE_LIBGDKGLEXT_X11_1_0 */

View File

@ -39,6 +39,12 @@ void init_GL_capabilities();
void init_GL(GtkWidget * widget, int screen, int share_num);
int init_GL_free_s(GtkWidget * widget, int share_num);
int init_GL_free(GtkWidget * widget);
#ifdef HAVE_LIBGDKGLEXT_X11_1_0
static void gtk_init_main_gl_area(GtkWidget *, gpointer);
static void gtk_init_sub_gl_area(GtkWidget *, gpointer);
static int top_screen_expose_fn(GtkWidget *, GdkEventExpose *, gpointer);
static int bottom_screen_expose_fn(GtkWidget *, GdkEventExpose *, gpointer);
static gboolean common_configure_fn( GtkWidget *, GdkEventConfigure *);
#endif
void reshape (GtkWidget * widget, int screen);
gboolean screen (GtkWidget * widget, int off);

View File

@ -25,6 +25,11 @@
#include "dTools/callbacks_dtools.h"
#include "globals.h"
#ifdef HAVE_LIBGDKGLEXT_X11_1_0
#include "../opengl_collector_3Demu.h"
#include "gdk_3Demu.h"
#endif
GtkWidget * pWindow;
GtkWidget * pDrawingArea, * pDrawingArea2;
GladeXML * xml, * xml_tools;
@ -38,6 +43,10 @@ NULL
GPU3DInterface *core3DList[] = {
&gpu3DNull
#ifdef HAVE_LIBGDKGLEXT_X11_1_0
,
&gpu3D_opengl_collector
#endif
};
@ -213,7 +222,6 @@ void update_savestate(u8 num)
/* ***** ***** MAIN ***** ***** */
#ifdef WIN32
int WinMain ()
{
@ -225,6 +233,7 @@ int main(int argc, char *argv[]) {
const char *commandLine_File = NULL;
gtk_init(&argc, &argv);
#ifdef HAVE_LIBGDKGLEXT_X11_1_0
// check if you have GTHREAD when running configure script
// g_thread_init(NULL);
@ -280,8 +289,24 @@ int main(int argc, char *argv[]) {
}
}
gtk_widget_show(pDrawingArea);
gtk_widget_show(pDrawingArea2);
gtk_widget_show(pDrawingArea);
gtk_widget_show(pDrawingArea2);
#ifdef HAVE_LIBGDKGLEXT_X11_1_0
/* setup the gdk 3D emulation */
if ( init_opengl_gdk_3Demu()) {
NDS_3D_SetDriver(1);
if (!gpu3D->NDS_3D_Init()) {
fprintf( stderr, "Failed to initialise openGL 3D emulation; "
"removing 3D support\n");
}
}
else {
fprintf( stderr, "Failed to setup openGL 3D emulation; "
"removing 3D support\n");
}
#endif
// on_menu_tileview_activate(NULL,NULL);