all repos — mgba @ 284f4df31ba30f917d717485505d73f7465a9209

mGBA Game Boy Advance Emulator

src/platform/sdl/gl-sdl.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "main.h"
  7
  8#include "gba/supervisor/thread.h"
  9
 10#ifdef __APPLE__
 11#include <OpenGL/gl.h>
 12#else
 13#include <GL/gl.h>
 14#endif
 15
 16#ifdef BUILD_GL
 17static const GLint _glVertices[] = {
 18	0, 0,
 19	256, 0,
 20	256, 256,
 21	0, 256
 22};
 23
 24static const GLint _glTexCoords[] = {
 25	0, 0,
 26	1, 0,
 27	1, 1,
 28	0, 1
 29};
 30#endif
 31
 32static void _doViewport(int w, int h, struct SDLSoftwareRenderer* renderer) {
 33	int drawW = w;
 34	int drawH = h;
 35	if (renderer->lockAspectRatio) {
 36		if (w * 2 > h * 3) {
 37			drawW = h * 3 / 2;
 38		} else if (w * 2 < h * 3) {
 39			drawH = w * 2 / 3;
 40		}
 41	}
 42	glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
 43	glClear(GL_COLOR_BUFFER_BIT);
 44#if SDL_VERSION_ATLEAST(2, 0, 0)
 45	SDL_GL_SwapWindow(renderer->window);
 46#else
 47	SDL_GL_SwapBuffers();
 48#endif
 49	glClear(GL_COLOR_BUFFER_BIT);
 50}
 51
 52static bool GBASDLGLInit(struct SDLSoftwareRenderer* renderer);
 53static void GBASDLGLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer);
 54static void GBASDLGLDeinit(struct SDLSoftwareRenderer* renderer);
 55
 56void GBASDLGLCreate(struct SDLSoftwareRenderer* renderer) {
 57	renderer->init = GBASDLGLInit;
 58	renderer->deinit = GBASDLGLDeinit;
 59	renderer->runloop = GBASDLGLRunloop;
 60}
 61
 62bool GBASDLGLInit(struct SDLSoftwareRenderer* renderer) {
 63#ifndef COLOR_16_BIT
 64	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
 65	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
 66	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
 67#else
 68	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
 69#ifdef COLOR_5_6_5
 70	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
 71#else
 72	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
 73#endif
 74	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
 75#endif
 76
 77#if SDL_VERSION_ATLEAST(2, 0, 0)
 78	renderer->window = SDL_CreateWindow(PROJECT_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen));
 79	SDL_GL_CreateContext(renderer->window);
 80	SDL_GL_SetSwapInterval(1);
 81	SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
 82	renderer->player.window = renderer->window;
 83#else
 84	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
 85#ifdef COLOR_16_BIT
 86	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_OPENGL);
 87#else
 88	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_OPENGL);
 89#endif
 90#endif
 91
 92	renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 93	renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
 94	glGenTextures(1, &renderer->tex);
 95	glBindTexture(GL_TEXTURE_2D, renderer->tex);
 96	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 97	if (renderer->filter) {
 98		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 99		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
100	} else {
101		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
102		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
103	}
104#ifndef _WIN32
105	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
106	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
107#endif
108
109#ifdef COLOR_16_BIT
110#ifdef COLOR_5_6_5
111	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
112#else
113	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
114#endif
115#else
116	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
117#endif
118
119	_doViewport(renderer->viewportWidth, renderer->viewportHeight, renderer);
120	return true;
121}
122
123void GBASDLGLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
124	SDL_Event event;
125
126	glEnable(GL_TEXTURE_2D);
127	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
128	glEnableClientState(GL_VERTEX_ARRAY);
129	glVertexPointer(2, GL_INT, 0, _glVertices);
130	glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
131	glMatrixMode (GL_PROJECTION);
132	glLoadIdentity();
133	glOrtho(0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, 0, 0, 1);
134	while (context->state < THREAD_EXITING) {
135		while (SDL_PollEvent(&event)) {
136			GBASDLHandleEvent(context, &renderer->player, &event);
137#if SDL_VERSION_ATLEAST(2, 0, 0)
138			// Event handling can change the size of the screen
139			if (renderer->player.windowUpdated) {
140				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
141				_doViewport(renderer->viewportWidth, renderer->viewportHeight, renderer);
142				renderer->player.windowUpdated = 0;
143			}
144#endif
145		}
146
147		if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
148			glBindTexture(GL_TEXTURE_2D, renderer->tex);
149#ifdef COLOR_16_BIT
150#ifdef COLOR_5_6_5
151			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, renderer->d.outputBuffer);
152#else
153			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, renderer->d.outputBuffer);
154#endif
155#else
156			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
157#endif
158			if (context->sync.videoFrameWait) {
159				glFlush();
160			}
161		}
162		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
163		GBASyncWaitFrameEnd(&context->sync);
164#if SDL_VERSION_ATLEAST(2, 0, 0)
165		SDL_GL_SwapWindow(renderer->window);
166#else
167		SDL_GL_SwapBuffers();
168#endif
169	}
170}
171
172void GBASDLGLDeinit(struct SDLSoftwareRenderer* renderer) {
173	free(renderer->d.outputBuffer);
174}