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}