all repos — mgba @ 30e0be098fdab754da67838db1c319cfea7aeb4f

mGBA Game Boy Advance Emulator

src/platform/opengl/gl.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 "gl.h"
  7
  8#include <mgba-util/math.h>
  9
 10static const GLint _glVertices[] = {
 11	0, 0,
 12	256, 0,
 13	256, 256,
 14	0, 256
 15};
 16
 17static const GLint _glTexCoords[] = {
 18	0, 0,
 19	1, 0,
 20	1, 1,
 21	0, 1
 22};
 23
 24static void mGLContextInit(struct VideoBackend* v, WHandle handle) {
 25	UNUSED(handle);
 26	struct mGLContext* context = (struct mGLContext*) v;
 27	v->width = 1;
 28	v->height = 1;
 29	glGenTextures(2, context->tex);
 30	glBindTexture(GL_TEXTURE_2D, context->tex[0]);
 31	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 32#ifndef _WIN32
 33	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 34	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 35#endif
 36	glBindTexture(GL_TEXTURE_2D, context->tex[1]);
 37	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 38#ifndef _WIN32
 39	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 40	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 41#endif
 42	context->activeTex = 0;
 43}
 44
 45static void mGLContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) {
 46	struct mGLContext* context = (struct mGLContext*) v;
 47	if (width == v->width && height == v->height) {
 48		return;
 49	}
 50	v->width = width;
 51	v->height = height;
 52
 53	glBindTexture(GL_TEXTURE_2D, context->tex[0]);
 54#ifdef COLOR_16_BIT
 55#ifdef COLOR_5_6_5
 56	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
 57#else
 58	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
 59#endif
 60#elif defined(__BIG_ENDIAN__)
 61	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
 62#else
 63	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 64#endif
 65
 66	glBindTexture(GL_TEXTURE_2D, context->tex[1]);
 67#ifdef COLOR_16_BIT
 68#ifdef COLOR_5_6_5
 69	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
 70#else
 71	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
 72#endif
 73#elif defined(__BIG_ENDIAN__)
 74	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
 75#else
 76	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 77#endif
 78}
 79
 80static void mGLContextDeinit(struct VideoBackend* v) {
 81	struct mGLContext* context = (struct mGLContext*) v;
 82	glDeleteTextures(2, context->tex);
 83}
 84
 85static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
 86	unsigned drawW = w;
 87	unsigned drawH = h;
 88	if (v->lockAspectRatio) {
 89		if (w * v->height > h * v->width) {
 90			drawW = h * v->width / v->height;
 91		} else if (w * v->height < h * v->width) {
 92			drawH = w * v->height / v->width;
 93		}
 94	}
 95	if (v->lockIntegerScaling) {
 96		if (drawW >= v->width) {
 97			drawW -= drawW % v->width;
 98		}
 99		if (drawH >= v->height) {
100			drawH -= drawH % v->height;
101		}
102	}
103	glMatrixMode(GL_MODELVIEW);
104	glLoadIdentity();
105	glClearColor(0, 0, 0, 0);
106	glClear(GL_COLOR_BUFFER_BIT);
107	glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
108}
109
110static void mGLContextClear(struct VideoBackend* v) {
111	UNUSED(v);
112	glClearColor(0, 0, 0, 0);
113	glClear(GL_COLOR_BUFFER_BIT);
114}
115
116void mGLContextDrawFrame(struct VideoBackend* v) {
117	struct mGLContext* context = (struct mGLContext*) v;
118	glEnable(GL_TEXTURE_2D);
119	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
120	glEnableClientState(GL_VERTEX_ARRAY);
121	glVertexPointer(2, GL_INT, 0, _glVertices);
122	glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
123	glMatrixMode(GL_PROJECTION);
124	glLoadIdentity();
125	glOrtho(0, v->width, v->height, 0, 0, 1);
126	glMatrixMode(GL_MODELVIEW);
127	glLoadIdentity();
128	if (v->interframeBlending) {
129		glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
130		glBlendColor(1, 1, 1, 0.5);
131		glBindTexture(GL_TEXTURE_2D, context->tex[context->activeTex ^ 1]);
132		if (v->filter) {
133			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
134			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
135		} else {
136			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
137			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
138		}
139		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
140		glEnable(GL_BLEND);
141	}
142	glBindTexture(GL_TEXTURE_2D, context->tex[context->activeTex]);
143	if (v->filter) {
144		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
145		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
146	} else {
147		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
148		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
149	}
150	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
151	glDisable(GL_BLEND);
152}
153
154void mGLContextPostFrame(struct VideoBackend* v, const void* frame) {
155	struct mGLContext* context = (struct mGLContext*) v;
156	context->activeTex ^= 1;
157	glBindTexture(GL_TEXTURE_2D, context->tex[context->activeTex]);
158#ifdef COLOR_16_BIT
159#ifdef COLOR_5_6_5
160	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
161#else
162	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
163#endif
164#elif defined(__BIG_ENDIAN__)
165	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
166#else
167	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height,  GL_RGBA, GL_UNSIGNED_BYTE, frame);
168#endif
169}
170
171void mGLContextCreate(struct mGLContext* context) {
172	context->d.init = mGLContextInit;
173	context->d.deinit = mGLContextDeinit;
174	context->d.setDimensions = mGLContextSetDimensions;
175	context->d.resized = mGLContextResized;
176	context->d.swap = 0;
177	context->d.clear = mGLContextClear;
178	context->d.postFrame = mGLContextPostFrame;
179	context->d.drawFrame = mGLContextDrawFrame;
180	context->d.setMessage = 0;
181	context->d.clearMessage = 0;
182}