src/platform/opengl/gles2.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 "gles2.h"
7
8#include "gba/video.h"
9
10static const char* const _vertexShader =
11 "attribute vec4 position;\n"
12 "varying vec2 texCoord;\n"
13
14 "void main() {\n"
15 " gl_Position = position;\n"
16 " texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
17 "}";
18
19static const char* const _fragmentShader =
20 "varying vec2 texCoord;\n"
21 "uniform sampler2D tex;\n"
22
23 "void main() {\n"
24 " vec4 color = texture2D(tex, texCoord);\n"
25 " color.a = 1.;\n"
26 " gl_FragColor = color;"
27 "}";
28
29static const GLfloat _vertices[] = {
30 -1.f, -1.f,
31 -1.f, 1.f,
32 1.f, 1.f,
33 1.f, -1.f,
34};
35
36static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
37 UNUSED(handle);
38 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
39 glGenTextures(1, &context->tex);
40 glBindTexture(GL_TEXTURE_2D, context->tex);
41 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
42 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
43 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
44 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
45
46#ifdef COLOR_16_BIT
47#ifdef COLOR_5_6_5
48 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
49#else
50 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
51#endif
52#else
53 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
54#endif
55
56 context->program = glCreateProgram();
57 context->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
58 context->vertexShader = glCreateShader(GL_VERTEX_SHADER);
59
60 glShaderSource(context->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
61 glShaderSource(context->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
62 glAttachShader(context->program, context->vertexShader);
63 glAttachShader(context->program, context->fragmentShader);
64 char log[1024];
65 glCompileShader(context->fragmentShader);
66 glCompileShader(context->vertexShader);
67 glGetShaderInfoLog(context->fragmentShader, 1024, 0, log);
68 glGetShaderInfoLog(context->vertexShader, 1024, 0, log);
69 glLinkProgram(context->program);
70 glGetProgramInfoLog(context->program, 1024, 0, log);
71 printf("%s\n", log);
72 context->texLocation = glGetUniformLocation(context->program, "tex");
73 context->positionLocation = glGetAttribLocation(context->program, "position");
74 glClearColor(0.f, 0.f, 0.f, 1.f);
75}
76
77static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
78 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
79 glDeleteTextures(1, &context->tex);
80 glDeleteShader(context->fragmentShader);
81 glDeleteShader(context->vertexShader);
82 glDeleteProgram(context->program);
83}
84
85static void GBAGLES2ContextResized(struct VideoBackend* v, int w, int h) {
86 int drawW = w;
87 int drawH = h;
88 if (v->lockAspectRatio) {
89 if (w * 2 > h * 3) {
90 drawW = h * 3 / 2;
91 } else if (w * 2 < h * 3) {
92 drawH = w * 2 / 3;
93 }
94 }
95 glViewport(0, 0, 240, 160);
96 glClearColor(0.f, 0.f, 0.f, 1.f);
97 glClear(GL_COLOR_BUFFER_BIT);
98 glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
99}
100
101static void GBAGLES2ContextClear(struct VideoBackend* v) {
102 UNUSED(v);
103 glClearColor(0.f, 0.f, 0.f, 1.f);
104 glClear(GL_COLOR_BUFFER_BIT);
105}
106
107void GBAGLES2ContextDrawFrame(struct VideoBackend* v) {
108 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
109 glUseProgram(context->program);
110 glUniform1i(context->texLocation, 0);
111 glActiveTexture(GL_TEXTURE0);
112 glBindTexture(GL_TEXTURE_2D, context->tex);
113 glVertexAttribPointer(context->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
114 glEnableVertexAttribArray(context->positionLocation);
115 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
116 glUseProgram(0);
117}
118
119void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) {
120 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
121 glBindTexture(GL_TEXTURE_2D, context->tex);
122#ifdef COLOR_16_BIT
123#ifdef COLOR_5_6_5
124 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
125#else
126 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
127#endif
128#else
129 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame);
130#endif
131}
132
133void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
134 context->d.init = GBAGLES2ContextInit;
135 context->d.deinit = GBAGLES2ContextDeinit;
136 context->d.resized = GBAGLES2ContextResized;
137 context->d.swap = 0;
138 context->d.clear = GBAGLES2ContextClear;
139 context->d.postFrame = GBAGLES2ContextPostFrame;
140 context->d.drawFrame = GBAGLES2ContextDrawFrame;
141 context->d.setMessage = 0;
142 context->d.clearMessage = 0;
143}