all repos — mgba @ 2eb765eacc646b67440c021a2925951700dda460

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
 52bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
 53#ifndef COLOR_16_BIT
 54	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
 55	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
 56	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
 57#else
 58	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
 59#ifdef COLOR_5_6_5
 60	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
 61#else
 62	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
 63#endif
 64	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
 65#endif
 66
 67#if SDL_VERSION_ATLEAST(2, 0, 0)
 68	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));
 69	SDL_GL_CreateContext(renderer->window);
 70	SDL_GL_SetSwapInterval(1);
 71	SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
 72	renderer->player.window = renderer->window;
 73#else
 74	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
 75#ifdef COLOR_16_BIT
 76	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_OPENGL);
 77#else
 78	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_OPENGL);
 79#endif
 80#endif
 81
 82	renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
 83	renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
 84	glGenTextures(1, &renderer->tex);
 85	glBindTexture(GL_TEXTURE_2D, renderer->tex);
 86	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 87	if (renderer->filter) {
 88		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 89		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 90	} else {
 91		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 92		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 93	}
 94#ifndef _WIN32
 95	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 96	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 97#endif
 98
 99#ifdef COLOR_16_BIT
100#ifdef COLOR_5_6_5
101	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
102#else
103	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
104#endif
105#else
106	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
107#endif
108
109	_doViewport(renderer->viewportWidth, renderer->viewportHeight, renderer);
110	return true;
111}
112
113void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
114	SDL_Event event;
115
116	glEnable(GL_TEXTURE_2D);
117	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
118	glEnableClientState(GL_VERTEX_ARRAY);
119	glVertexPointer(2, GL_INT, 0, _glVertices);
120	glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
121	glMatrixMode (GL_PROJECTION);
122	glLoadIdentity();
123	glOrtho(0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, 0, 0, 1);
124	while (context->state < THREAD_EXITING) {
125		while (SDL_PollEvent(&event)) {
126			GBASDLHandleEvent(context, &renderer->player, &event);
127#if SDL_VERSION_ATLEAST(2, 0, 0)
128			// Event handling can change the size of the screen
129			if (renderer->player.windowUpdated) {
130				SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
131				_doViewport(renderer->viewportWidth, renderer->viewportHeight, renderer);
132				renderer->player.windowUpdated = 0;
133			}
134#endif
135		}
136
137		if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
138			glBindTexture(GL_TEXTURE_2D, renderer->tex);
139#ifdef COLOR_16_BIT
140#ifdef COLOR_5_6_5
141			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, renderer->d.outputBuffer);
142#else
143			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);
144#endif
145#else
146			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
147#endif
148			if (context->sync.videoFrameWait) {
149				glFlush();
150			}
151		}
152		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
153		GBASyncWaitFrameEnd(&context->sync);
154#if SDL_VERSION_ATLEAST(2, 0, 0)
155		SDL_GL_SwapWindow(renderer->window);
156#else
157		SDL_GL_SwapBuffers();
158#endif
159	}
160}
161
162void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
163	free(renderer->d.outputBuffer);
164}