all repos — mgba @ 36c1fb59be4710543c4a5476a554757efe306ccd

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(1, &context->tex);
 28	glBindTexture(GL_TEXTURE_2D, context->tex);
 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}
 35
 36static void mGLContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) {
 37	struct mGLContext* context = (struct mGLContext*) v;
 38	v->width = width;
 39	v->height = height;
 40
 41	glBindTexture(GL_TEXTURE_2D, context->tex);
 42#ifdef COLOR_16_BIT
 43#ifdef COLOR_5_6_5
 44	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
 45#else
 46	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
 47#endif
 48#else
 49	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 50#endif
 51}
 52
 53static void mGLContextDeinit(struct VideoBackend* v) {
 54	struct mGLContext* context = (struct mGLContext*) v;
 55	glDeleteTextures(1, &context->tex);
 56}
 57
 58static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
 59	unsigned drawW = w;
 60	unsigned drawH = h;
 61	if (v->lockAspectRatio) {
 62		if (w * v->height > h * v->width) {
 63			drawW = h * v->width / v->height;
 64		} else if (w * v->height < h * v->width) {
 65			drawH = w * v->height / v->width;
 66		}
 67	}
 68	if (v->lockIntegerScaling) {
 69		drawW -= drawW % v->width;
 70		drawH -= drawH % v->height;
 71	}
 72	glMatrixMode(GL_MODELVIEW);
 73	glLoadIdentity();
 74	glClearColor(0, 0, 0, 0);
 75	glClear(GL_COLOR_BUFFER_BIT);
 76	glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
 77}
 78
 79static void mGLContextClear(struct VideoBackend* v) {
 80	UNUSED(v);
 81	glClearColor(0, 0, 0, 0);
 82	glClear(GL_COLOR_BUFFER_BIT);
 83}
 84
 85void mGLContextDrawFrame(struct VideoBackend* v) {
 86	struct mGLContext* context = (struct mGLContext*) v;
 87	glEnable(GL_TEXTURE_2D);
 88	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 89	glEnableClientState(GL_VERTEX_ARRAY);
 90	glVertexPointer(2, GL_INT, 0, _glVertices);
 91	glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
 92	glMatrixMode(GL_PROJECTION);
 93	glLoadIdentity();
 94	glOrtho(0, v->width, v->height, 0, 0, 1);
 95	glMatrixMode(GL_MODELVIEW);
 96	glLoadIdentity();
 97	glBindTexture(GL_TEXTURE_2D, context->tex);
 98	if (v->filter) {
 99		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
100		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
101	} else {
102		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
103		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
104	}
105	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
106}
107
108void mGLContextPostFrame(struct VideoBackend* v, const void* frame) {
109	struct mGLContext* context = (struct mGLContext*) v;
110	glBindTexture(GL_TEXTURE_2D, context->tex);
111#ifdef COLOR_16_BIT
112#ifdef COLOR_5_6_5
113	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, toPow2(v->width), v->height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
114#else
115	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, toPow2(v->width), v->height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
116#endif
117#else
118	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, toPow2(v->width), v->height,  GL_RGBA, GL_UNSIGNED_BYTE, frame);
119#endif
120}
121
122void mGLContextCreate(struct mGLContext* context) {
123	context->d.init = mGLContextInit;
124	context->d.deinit = mGLContextDeinit;
125	context->d.setDimensions = mGLContextSetDimensions;
126	context->d.resized = mGLContextResized;
127	context->d.swap = 0;
128	context->d.clear = mGLContextClear;
129	context->d.postFrame = mGLContextPostFrame;
130	context->d.drawFrame = mGLContextDrawFrame;
131	context->d.setMessage = 0;
132	context->d.clearMessage = 0;
133}