all repos — mgba @ 1a0e44c014ad34bea30d237d27015d82d02cda4b

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 _glTexCoords[] = {
 11	0, 0,
 12	1, 0,
 13	1, 1,
 14	0, 1
 15};
 16
 17static void mGLContextInit(struct VideoBackend* v, WHandle handle) {
 18	UNUSED(handle);
 19	struct mGLContext* context = (struct mGLContext*) v;
 20	glGenTextures(1, &context->tex);
 21	glBindTexture(GL_TEXTURE_2D, context->tex);
 22	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 23#ifndef _WIN32
 24	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 25	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 26#endif
 27}
 28
 29static void mGLContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) {
 30	struct mGLContext* context = (struct mGLContext*) v;
 31	v->width = width;
 32	v->height = height;
 33
 34	glBindTexture(GL_TEXTURE_2D, context->tex);
 35#ifdef COLOR_16_BIT
 36#ifdef COLOR_5_6_5
 37	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
 38#else
 39	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
 40#endif
 41#elif defined(__BIG_ENDIAN__)
 42	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
 43#else
 44	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 45#endif
 46
 47	context->vertices[0] = 0;
 48	context->vertices[1] = 0;
 49	context->vertices[2] = toPow2(width);
 50	context->vertices[3] = 0;
 51	context->vertices[4] = toPow2(width);
 52	context->vertices[5] = toPow2(height);
 53	context->vertices[6] = 0;
 54	context->vertices[7] = toPow2(height);
 55}
 56
 57static void mGLContextDeinit(struct VideoBackend* v) {
 58	struct mGLContext* context = (struct mGLContext*) v;
 59	glDeleteTextures(1, &context->tex);
 60}
 61
 62static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
 63	unsigned drawW = w;
 64	unsigned drawH = h;
 65	if (v->lockAspectRatio) {
 66		if (w * v->height > h * v->width) {
 67			drawW = h * v->width / v->height;
 68		} else if (w * v->height < h * v->width) {
 69			drawH = w * v->height / v->width;
 70		}
 71	}
 72	if (v->lockIntegerScaling) {
 73		drawW -= drawW % v->width;
 74		drawH -= drawH % v->height;
 75	}
 76	glMatrixMode(GL_MODELVIEW);
 77	glLoadIdentity();
 78	glClearColor(0, 0, 0, 0);
 79	glClear(GL_COLOR_BUFFER_BIT);
 80	glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
 81}
 82
 83static void mGLContextClear(struct VideoBackend* v) {
 84	UNUSED(v);
 85	glClearColor(0, 0, 0, 0);
 86	glClear(GL_COLOR_BUFFER_BIT);
 87}
 88
 89void mGLContextDrawFrame(struct VideoBackend* v) {
 90	struct mGLContext* context = (struct mGLContext*) v;
 91	glEnable(GL_TEXTURE_2D);
 92	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 93	glEnableClientState(GL_VERTEX_ARRAY);
 94	glVertexPointer(2, GL_INT, 0, context->vertices);
 95	glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
 96	glMatrixMode(GL_PROJECTION);
 97	glLoadIdentity();
 98	glOrtho(0, v->width, v->height, 0, 0, 1);
 99	glMatrixMode(GL_MODELVIEW);
100	glLoadIdentity();
101	glBindTexture(GL_TEXTURE_2D, context->tex);
102	if (v->filter) {
103		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
104		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
105	} else {
106		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
107		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
108	}
109	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
110}
111
112void mGLContextPostFrame(struct VideoBackend* v, const void* frame) {
113	struct mGLContext* context = (struct mGLContext*) v;
114	glBindTexture(GL_TEXTURE_2D, context->tex);
115#ifdef COLOR_16_BIT
116#ifdef COLOR_5_6_5
117	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
118#else
119	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
120#endif
121#elif defined(__BIG_ENDIAN__)
122	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
123#else
124	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, v->width, v->height,  GL_RGBA, GL_UNSIGNED_BYTE, frame);
125#endif
126}
127
128void mGLContextCreate(struct mGLContext* context) {
129	context->d.init = mGLContextInit;
130	context->d.deinit = mGLContextDeinit;
131	context->d.setDimensions = mGLContextSetDimensions;
132	context->d.resized = mGLContextResized;
133	context->d.swap = 0;
134	context->d.clear = mGLContextClear;
135	context->d.postFrame = mGLContextPostFrame;
136	context->d.drawFrame = mGLContextDrawFrame;
137	context->d.setMessage = 0;
138	context->d.clearMessage = 0;
139}