diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 84c7387..765ad18 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -18,7 +18,7 @@ add_executable(
   main.c
 )
 
-target_link_libraries(lazier-player PRIVATE SDL3::SDL3 mpv m)
+target_link_libraries(lazier-player PRIVATE SDL3::SDL3 mpv m GL)
 set_property(TARGET lazier-player PROPERTY C_STANDARD 23)
 target_compile_options(lazier-player PRIVATE -Wall -Wextra -Wnull-dereference)
 target_include_directories(lazier-player PRIVATE include)
diff --git a/src/main.c b/src/main.c
index 4719db1..6f57c1e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,20 +1,18 @@
 #include <SDL3/SDL.h>
-#include <mpv/client.h>
-#include <mpv/render.h>
+#include <mpv/render_gl.h>
+#include <GL/gl.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 typedef struct {
 	mpv_handle *mpv;
 	mpv_render_context *render_ctx;
 	SDL_Window *window;
 	SDL_Renderer *renderer;
-	SDL_Texture *texture;
-	int width;
-	int height;
-	int running;
-	int needs_redraw;
+	bool running;
 } App;
 
 static void SDL_PrintError(const char *msg)
@@ -27,6 +25,12 @@ static void mpv_print_error(int code, const char *msg)
 	fprintf(stderr, "mpv: %s: %s\n", msg, mpv_error_string(code));
 }
 
+static void *get_proc_address_mpv(void *ctx, const char *name)
+{
+	(void)ctx;
+	return SDL_GL_GetProcAddress(name);
+}
+
 static void handle_mpv_events(App *app)
 {
 	while (true) {
@@ -35,38 +39,17 @@ static void handle_mpv_events(App *app)
 		if (event->event_id == MPV_EVENT_NONE)
 			break;
 
-		printf("mpv: event=%s\n", mpv_event_name(event->event_id));
-
 		if (event->event_id == MPV_EVENT_PROPERTY_CHANGE) {
 			mpv_event_property *prop = event->data;
-
-			if (!strcmp(prop->name, "width") || !strcmp(prop->name, "height")) {
-				int64_t width = 0;
-				int64_t height = 0;
-
-				mpv_get_property(app->mpv, "width", MPV_FORMAT_INT64, &width);
-				mpv_get_property(app->mpv, "height", MPV_FORMAT_INT64, &height);
-
-				if (width > 0 && height > 0 && (width != app->width || height != app->height)) {
-					app->width = width;
-					app->height = height;
-
-					if (app->texture)
-						SDL_DestroyTexture(app->texture);
-
-					app->texture = SDL_CreateTexture(app->renderer, SDL_PIXELFORMAT_XBGR8888,
-													 SDL_TEXTUREACCESS_STREAMING, width, height);
-
-					if (!app->texture) {
-						SDL_PrintError("SDL_CreateTexture");
-					} else {
-						// Resize window to match video dimensions
-						SDL_SetWindowSize(app->window, app->width, app->height);
-					}
-				}
-			}
+			printf("mpv: event=%s, name=%s\n", mpv_event_name(event->event_id), prop->name);
 		} else if (event->event_id == MPV_EVENT_END_FILE) {
-			app->running = 0;
+			printf("mpv: event=%s\n", mpv_event_name(event->event_id));
+			app->running = false;
+		} else if (event->event_id == MPV_EVENT_START_FILE) {
+			printf("mpv: event=%s\n", mpv_event_name(event->event_id));
+			app->running = true;
+		} else {
+			printf("mpv: event=%s\n", mpv_event_name(event->event_id));
 		}
 	}
 }
@@ -75,83 +58,52 @@ static void render_video(App *app)
 {
 	int err;
 
-	// Clear the renderer
-	if (!SDL_SetRenderDrawColor(app->renderer, 0, 0, 0, 255))
-		SDL_PrintError("SDL_SetRenderDrawColor");
+	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+	glClear(GL_COLOR_BUFFER_BIT);
 
-	if (!SDL_RenderClear(app->renderer))
-		SDL_PrintError("SDL_RenderClear");
+	glColor3f(1.0f, 1.0f, 1.0f);
+	glBegin(GL_LINES);
+	glVertex2d(-0.5, 0.5);
+	glVertex2d(0.5, -0.5);
+	glEnd();
 
-	// Render MPV frame
-	if (app->texture && app->render_ctx) {
-		void *pixels;
-		int stride = 0;
+	int w, h;
+	if (!SDL_GetCurrentRenderOutputSize(app->renderer, &w, &h)) {
+		SDL_PrintError("SDL_GetCurrentRenderOutputSize");
+		return;
+	}
 
-		if (!SDL_LockTexture(app->texture, NULL, &pixels, &stride)) {
-			SDL_PrintError("SDL_LockTexture");
-			return;
-		}
+	// Render MPV frame using OpenGL
+	if (app->render_ctx) {
+		int flip_y = 1;
 
-		float w, h;
-		if (!SDL_GetTextureSize(app->texture, &w, &h))
-			SDL_PrintError("SDL_GetTextureSize");
-
-		int size[] = { w, h };
+		mpv_opengl_fbo mpv_fbo = {
+			.fbo = 0,
+			.w = w,
+			.h = h,
+			.internal_format = 0,
+		};
 
 		mpv_render_param params[] = {
-			{ MPV_RENDER_PARAM_SW_SIZE, &size },	 //
-			{ MPV_RENDER_PARAM_SW_FORMAT, "rgb0" },	 //
-			{ MPV_RENDER_PARAM_SW_STRIDE, &stride }, //
-			{ MPV_RENDER_PARAM_SW_POINTER, pixels }, //
+			{ MPV_RENDER_PARAM_OPENGL_FBO, &mpv_fbo },
+			{ MPV_RENDER_PARAM_FLIP_Y, &flip_y },
 			{ MPV_RENDER_PARAM_INVALID, NULL },
 		};
 
 		if ((err = mpv_render_context_render(app->render_ctx, params)))
 			mpv_print_error(err, "mpv_render_context_render");
-
-		SDL_UnlockTexture(app->texture);
-
-		if (!SDL_RenderTexture(app->renderer, app->texture, NULL, NULL)) {
-			SDL_PrintError("SDL_RenderTexture");
-		}
 	}
 
-	// Draw shapes over the video
-	// 1. Red rectangle
-	if (!SDL_SetRenderDrawColor(app->renderer, 255, 0, 0, 128))
-		SDL_PrintError("SDL_SetRenderDrawColor");
-
-	SDL_FRect rect = { 50, 50, 100, 80 };
-
-	if (!SDL_RenderFillRect(app->renderer, &rect))
-		SDL_PrintError("SDL_RenderFillRect");
-
-	// 2. Blue circle (approximated with points)
-	if (!SDL_SetRenderDrawColor(app->renderer, 0, 0, 255, 128))
-		SDL_PrintError("SDL_SetRenderDrawColor");
-
-	int centerX = app->width - 100;
-	int centerY = app->height - 100;
-	int radius = 40;
-
-	for (int i = 0; i < 360; i++) {
-		float angle = i * 3.14159f / 180.0f;
-		float x = centerX + radius * SDL_cosf(angle);
-		float y = centerY + radius * SDL_sinf(angle);
-
-		if (!SDL_RenderPoint(app->renderer, x, y))
-			SDL_PrintError("SDL_RenderPoint");
+	glColor3f(1.0f, 1.0f, 1.0f);
+	glBegin(GL_LINES);
+	{
+		glVertex2d(-0.5, -0.5);
+		glVertex2d(0.5, 0.5);
 	}
+	glEnd();
 
-	// 3. Green line
-	if (!SDL_SetRenderDrawColor(app->renderer, 0, 255, 0, 200))
-		SDL_PrintError("SDL_SetRenderDrawColor");
-
-	if (!SDL_RenderLine(app->renderer, 0, 0, app->width, app->height))
-		SDL_PrintError("SDL_RenderLine");
-
-	if (!SDL_RenderPresent(app->renderer))
-		SDL_PrintError("SDL_RenderPresent");
+	if (!SDL_GL_SwapWindow(app->window))
+		SDL_PrintError("SDL_GL_SwapWindow");
 }
 
 int main(int argc, char *argv[])
@@ -165,8 +117,6 @@ int main(int argc, char *argv[])
 
 	static App app = { 0 };
 	app.running = 1;
-	app.width = 800;
-	app.height = 600;
 
 	// Initialize SDL
 	if (!SDL_Init(SDL_INIT_VIDEO)) {
@@ -175,15 +125,41 @@ int main(int argc, char *argv[])
 	}
 
 	// Create window
-	app.window = SDL_CreateWindow("SDL3 + MPV Video Player", app.width, app.height, 0);
+	SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
+	app.window = SDL_CreateWindow("Lazier Player", 800, 600, flags);
+
 	if (!app.window) {
 		SDL_PrintError("SDL_CreateWindow");
 		SDL_Quit();
 		return 1;
 	}
 
-	// Create renderer
-	app.renderer = SDL_CreateRenderer(app.window, "software");
+	// Create OpenGL renderer
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+	SDL_GLContext gl_ctx = SDL_GL_CreateContext(app.window);
+	if (!gl_ctx) {
+		SDL_PrintError("SDL_GL_CreateContext");
+		SDL_DestroyWindow(app.window);
+		SDL_Quit();
+		return 1;
+	}
+
+	if (!SDL_GL_SetSwapInterval(1))
+		SDL_PrintError("SDL_GL_SetSwapInterval");
+
+	if (!SDL_GL_MakeCurrent(app.window, gl_ctx)) {
+		SDL_PrintError("SDL_GL_MakeCurrent");
+		SDL_GL_DestroyContext(gl_ctx);
+		SDL_DestroyWindow(app.window);
+		SDL_Quit();
+		return 1;
+	}
+
+	app.renderer = SDL_CreateRenderer(app.window, "opengl");
 	if (!app.renderer) {
 		SDL_PrintError("SDL_CreateRenderer");
 		SDL_DestroyWindow(app.window);
@@ -211,9 +187,14 @@ int main(int argc, char *argv[])
 	if ((err = mpv_initialize(app.mpv)))
 		mpv_print_error(err, "mpv_initialize");
 
-	// Initialize MPV render context
+	// Initialize MPV OpenGL render context
+	mpv_opengl_init_params gl_init_params = {
+		.get_proc_address = get_proc_address_mpv,
+	};
+
 	mpv_render_param params[] = {
-		{ MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_SW },
+		{ MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL },
+		{ MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params },
 		{ MPV_RENDER_PARAM_INVALID, NULL },
 	};
 
@@ -248,15 +229,12 @@ int main(int argc, char *argv[])
 		SDL_Delay(16); // ~60fps
 	}
 
-	// Cleanup
-	if (app.texture)
-		SDL_DestroyTexture(app.texture);
-
 	if (app.render_ctx)
 		mpv_render_context_free(app.render_ctx);
 
 	mpv_terminate_destroy(app.mpv);
 	SDL_DestroyRenderer(app.renderer);
+	SDL_GL_DestroyContext(gl_ctx);
 	SDL_DestroyWindow(app.window);
 	SDL_Quit();