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}