diff --git a/binding-mri/graphics-binding.cpp b/binding-mri/graphics-binding.cpp
index 6b39697..562cec6 100644
--- a/binding-mri/graphics-binding.cpp
+++ b/binding-mri/graphics-binding.cpp
@@ -25,11 +25,19 @@
 #include "binding-types.h"
 #include "exception.h"
 
+#include <ruby/thread.h>
+
+static void *graphicsUpdate_internal(void*)
+{
+	shState->graphics().update();
+	return NULL;
+}
+
 RB_METHOD(graphicsUpdate)
 {
 	RB_UNUSED_PARAM;
 
-	shState->graphics().update();
+	rb_thread_call_without_gvl(&graphicsUpdate_internal, NULL, NULL, NULL);
 
 	return Qnil;
 }
@@ -43,17 +51,33 @@ RB_METHOD(graphicsFreeze)
 	return Qnil;
 }
 
+/** Argument structure used to pass arguments to various blocking calls,
+ * meanwhile releasing the ruby interpreter lock. */
+struct transition_args {
+	int duration;
+	const char *filename;
+	int vague;
+};
+
+static void *graphicsTransition_internal(void* args_in)
+{
+	struct transition_args *args = static_cast<transition_args*>(args_in);
+	GUARD_EXC( shState->graphics().transition(args->duration, args->filename, args->vague); )
+	return NULL;
+}
+
 RB_METHOD(graphicsTransition)
 {
 	RB_UNUSED_PARAM;
 
-	int duration = 8;
-	const char *filename = "";
-	int vague = 40;
+	struct transition_args args;
+	args.duration = 8;
+	args.filename = "";
+	args.vague = 40;
 
-	rb_get_args(argc, argv, "|izi", &duration, &filename, &vague RB_ARG_END);
+	rb_get_args(argc, argv, "|izi", &args.duration, &args.filename, &args.vague RB_ARG_END);
 
-	GUARD_EXC( shState->graphics().transition(duration, filename, vague); )
+	rb_thread_call_without_gvl(&graphicsTransition_internal, &args, NULL, NULL);
 
 	return Qnil;
 }
@@ -111,38 +135,56 @@ RB_METHOD(graphicsHeight)
 	return rb_fix_new(shState->graphics().height());
 }
 
+static void *graphicsWait_internal(void* args_in)
+{
+	struct transition_args *args = static_cast<transition_args*>(args_in);
+	shState->graphics().wait(args->duration);
+	return NULL;
+}
+
 RB_METHOD(graphicsWait)
 {
 	RB_UNUSED_PARAM;
 
-	int duration;
-	rb_get_args(argc, argv, "i", &duration RB_ARG_END);
-
-	shState->graphics().wait(duration);
+	struct transition_args args;
+	rb_get_args(argc, argv, "i", &args.duration RB_ARG_END);
+	rb_thread_call_without_gvl(&graphicsWait_internal, &args, NULL, NULL);
 
 	return Qnil;
 }
 
+static void *graphicsFadeout_internal(void* args_in)
+{
+	struct transition_args *args = static_cast<transition_args*>(args_in);
+	shState->graphics().fadeout(args->duration);
+	return NULL;
+}
+
 RB_METHOD(graphicsFadeout)
 {
 	RB_UNUSED_PARAM;
 
-	int duration;
-	rb_get_args(argc, argv, "i", &duration RB_ARG_END);
-
-	shState->graphics().fadeout(duration);
+	struct transition_args args;
+	rb_get_args(argc, argv, "i", &args.duration RB_ARG_END);
+	rb_thread_call_without_gvl(&graphicsFadeout_internal, &args, NULL, NULL);
 
 	return Qnil;
 }
 
+static void *graphicsFadein_internal(void* args_in)
+{
+	struct transition_args *args = static_cast<transition_args*>(args_in);
+	shState->graphics().fadein(args->duration);
+	return NULL;
+}
+
 RB_METHOD(graphicsFadein)
 {
 	RB_UNUSED_PARAM;
 
-	int duration;
-	rb_get_args(argc, argv, "i", &duration RB_ARG_END);
-
-	shState->graphics().fadein(duration);
+	struct transition_args args;
+	rb_get_args(argc, argv, "i", &args.duration RB_ARG_END);
+	rb_thread_call_without_gvl(&graphicsFadein_internal, &args, NULL, NULL);
 
 	return Qnil;
 }