all repos — mgba @ f6755a6e1b7b0cf2b944cd8ca842746f11d6bf82

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