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}