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 glShaderSource(context->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
57 glShaderSource(context->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
58 glAttachShader(context->program, context->vertexShader);
59 glAttachShader(context->program, context->fragmentShader);
60 char log[1024];
61 glCompileShader(context->fragmentShader);
62 glCompileShader(context->vertexShader);
63 glGetShaderInfoLog(context->fragmentShader, 1024, 0, log);
64 glGetShaderInfoLog(context->vertexShader, 1024, 0, log);
65 glLinkProgram(context->program);
66 glGetProgramInfoLog(context->program, 1024, 0, log);
67 printf("%s\n", log);
68 context->texLocation = glGetUniformLocation(context->program, "tex");
69 context->positionLocation = glGetAttribLocation(context->program, "position");
70 glClearColor(0.f, 0.f, 0.f, 1.f);
71}
72
73static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
74 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
75 glDeleteTextures(1, &context->tex);
76}
77
78static void GBAGLES2ContextResized(struct VideoBackend* v, int w, int h) {
79 int drawW = w;
80 int drawH = h;
81 if (v->lockAspectRatio) {
82 if (w * 2 > h * 3) {
83 drawW = h * 3 / 2;
84 } else if (w * 2 < h * 3) {
85 drawH = w * 2 / 3;
86 }
87 }
88 glViewport(0, 0, 240, 160);
89 glClearColor(0.f, 0.f, 0.f, 1.f);
90 glClear(GL_COLOR_BUFFER_BIT);
91 glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
92}
93
94static void GBAGLES2ContextClear(struct VideoBackend* v) {
95 UNUSED(v);
96 glClearColor(0.f, 0.f, 0.f, 1.f);
97 glClear(GL_COLOR_BUFFER_BIT);
98}
99
100void GBAGLES2ContextDrawFrame(struct VideoBackend* v) {
101 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
102 glUseProgram(context->program);
103 glUniform1i(context->texLocation, 0);
104 glActiveTexture(GL_TEXTURE0);
105 glBindTexture(GL_TEXTURE_2D, context->tex);
106 glVertexAttribPointer(context->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
107 glEnableVertexAttribArray(context->positionLocation);
108 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
109 glUseProgram(0);
110}
111
112void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) {
113 struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
114 glBindTexture(GL_TEXTURE_2D, context->tex);
115#ifdef COLOR_16_BIT
116#ifdef COLOR_5_6_5
117 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
118#else
119 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
120#endif
121#else
122 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame);
123#endif
124}
125
126void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
127 context->d.init = GBAGLES2ContextInit;
128 context->d.deinit = GBAGLES2ContextDeinit;
129 context->d.resized = GBAGLES2ContextResized;
130 context->d.swap = 0;
131 context->d.clear = GBAGLES2ContextClear;
132 context->d.postFrame = GBAGLES2ContextPostFrame;
133 context->d.drawFrame = GBAGLES2ContextDrawFrame;
134 context->d.setMessage = 0;
135 context->d.clearMessage = 0;
136}