SameBoy/gtk3/util.c

115 lines
2.7 KiB
C

#include "util.h"
#include "config.h"
#include <epoxy/gl.h>
// Workaround to figure out if we have proper OpenGL support.
// Otherwise the application would crash after our GtkGlArea is realized
// and the context it uses is a legacy OpenGL 1.4 context because
// GTK3 calls OpenGL 2.0+ functions on it.
bool test_gl_support(void) {
gboolean result = false;
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "realize", G_CALLBACK(gl_check_realize), &result);
gtk_widget_realize(window);
gtk_widget_destroy(window);
window = NULL;
return result;
}
// The main function for the OpenGL version check workaround
void gl_check_realize(GtkWidget *w, gpointer user_data_ptr) {
gboolean *result = (gboolean *) user_data_ptr;
GError *error = NULL;
GdkWindow *gdk_window = gtk_widget_get_window(w);
GdkGLContext *context = gdk_window_create_gl_context(gdk_window, &error);
if (error != NULL) {
g_warning("Failed to create context: %s", error->message);
g_error_free(error);
*result = false;
}
else {
gdk_gl_context_make_current(context);
int version = epoxy_gl_version();
g_object_run_dispose(G_OBJECT(context));
g_object_unref(context);
context = NULL;
gdk_gl_context_clear_current();
g_debug("OpenGL version: %d", version);
*result = version >= 32;
}
}
void replace_extension(const char *src, size_t length, char *dest, const char *ext) {
memcpy(dest, src, length);
dest[length] = 0;
/* Remove extension */
for (size_t i = length; i--;) {
if (dest[i] == '/') break;
if (dest[i] == '.') {
dest[i] = 0;
break;
}
}
/* Add new extension */
strcat(dest, ext);
}
double clamp_double(double min, double max, double value) {
if (value < min) return min;
if (value > max) return max;
return value;
}
double max_double(double a, double b) {
if (a > b) return a;
return b;
}
double min_double(double a, double b) {
if (a < b) return a;
return b;
}
uint32_t convert_color(uint16_t color) {
const uint8_t r = ((uint16_t)(color & 0x1F) * 255) / 31;
const uint8_t g = ((uint16_t)((color >> 5) & 0x1F) * 255) / 31;
const uint8_t b = ((uint16_t)((color >> 10) & 0x1F) * 255) / 31;
return (r << 16) | (g << 8) | b;
}
uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b) {
return 0xFF000000 | (r << 16) | (g << 8) | b;
}
GB_model_t config_get_model_type(GuiData *gui_data) {
if (gui_data->cli_options.model != -1) {
return gui_data->cli_options.model;
}
return config_get_model();
}
GtkWidget *menubar_to_menu(GtkMenuBar *menubar) {
GtkWidget *menu = gtk_menu_new();
g_autoptr(GList) iter = gtk_container_get_children(GTK_CONTAINER(menubar));
while (iter) {
GtkWidget *item = GTK_WIDGET(iter->data);
gtk_widget_reparent(item, menu);
iter = iter->next;
}
return menu;
}