#include <gtk/gtk.h>
#include "tt_core.h"
#include <glib/galloca.h>
struct TTSystem {
GtkWidget* window;
GtkWidget* screen;
GdkPixbuf* pixbuf;
guchar* frame_buffer;
};
static struct TTSystem* tt_system;
guchar* tt_frame_buffer;
guint tt_screen_width;
guint tt_screen_height;
static
void tt_init_gtk(gint argc, gchar** argv)
{
g_thread_init(NULL);
gdk_threads_init();
gdk_rgb_init();
gtk_init(&argc, &argv);
gtk_set_locale();
}
static
gboolean tt_quit(GtkWidget *wgt, GdkEventExpose *event, gpointer data)
{
gtk_main_quit();
}
static
gboolean tt_press_key(GtkWidget *wgt, GdkEventExpose *event, gpointer data)
{
}
static
gboolean tt_release_key(GtkWidget *wgt, GdkEventExpose *event, gpointer data)
{
GdkEventKey* key = (GdkEventKey*)event;
if(key->keyval == 'q') {
tt_quit(wgt, event, data);
}
}
static
void tt_set_sygnal_func_system(struct TTSystem* a)
{
g_signal_connect(
G_OBJECT(a->window),
"key-press-event",
G_CALLBACK(tt_press_key),
a
);
g_signal_connect(
G_OBJECT(a->window),
"key-release-event",
G_CALLBACK(tt_release_key),
a
);
g_signal_connect(
G_OBJECT(a->window),
"destroy",
G_CALLBACK(tt_quit),
NULL
);
}
struct TTSystem* tt_new_system(void)
{
struct TTSystem* a = g_malloc(sizeof(*a));
a->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
a->pixbuf = gdk_pixbuf_new(
GDK_COLORSPACE_RGB,
FALSE,
8,
tt_screen_width,
tt_screen_height
);
a->screen = gtk_image_new_from_pixbuf(a->pixbuf);
a->frame_buffer = gdk_pixbuf_get_pixels(a->pixbuf);
gtk_widget_set_size_request(a->screen, tt_screen_width, tt_screen_height);
gtk_widget_set_double_buffered(a->screen, TRUE);
gtk_container_add(GTK_CONTAINER(a->window), a->screen);
tt_set_sygnal_func_system(a);
gtk_widget_show_all(a->window);
return a;
}
void tt_sleep(void)
{
g_usleep((1000 * 1000) / 250);
}
static volatile gboolean tt_vsync_wait_flag;
static gboolean tt_vsync_count(gpointer _a)
{
tt_vsync_wait_flag = FALSE;
gtk_widget_hide(tt_system->screen);
gtk_widget_show_now(tt_system->screen);
}
void tt_vsync(void)
{
tt_vsync_wait_flag = TRUE;
while(tt_vsync_wait_flag == TRUE) {
tt_sleep();
}
}
void tt_flush(void)
{
guchar* p = tt_frame_buffer;
guchar* q = tt_system->frame_buffer;
int j, i;
for(j = 0; j < tt_screen_height; j++) {
for(i = 0; i < tt_screen_width; i++) {
q[0] = p[2];
q[1] = p[1];
q[2] = p[0];
p += 4;
q += 3;
}
}
}
struct Contenna {
gint argc;
gchar** argv;
tt_main_function f;
gint ret;
};
static struct Contenna tt_contenna;
static gpointer tt_main_lap(gpointer _a)
{
struct Contenna* a = (struct Contenna*)_a;
a->ret = a->f(a->argc, a->argv);
gtk_main_quit();
}
int tt_init(
gint argc,
gchar** argv,
tt_main_function f,
const guint screen_width,
const guint screen_height
)
{
tt_init_gtk(argc, argv);
tt_screen_width = screen_width;
tt_screen_height = screen_height;
tt_frame_buffer = g_malloc(
sizeof(*tt_frame_buffer) * 4 * screen_width * screen_height
);
tt_system = tt_new_system();
gtk_timeout_add(1000 / 60, tt_vsync_count, NULL);
tt_contenna.argc = argc;
tt_contenna.argv = argv;
tt_contenna.f = f;
GThread* tm = g_thread_create(tt_main_lap, (gpointer)&tt_contenna, FALSE, NULL);
gtk_main();
return tt_contenna.ret;
}