all repos — mgba @ e9a2b2a57c4f478fb3600fe9d87e1b97804d73de

mGBA Game Boy Advance Emulator

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

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