all repos — mgba @ 6cdfb3ae9a141a8951f6fe7ba932094bbd0c3fc6

mGBA Game Boy Advance Emulator

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}