all repos — mgba @ 3c9433b74ca1203003481b4f142010b240599375

mGBA Game Boy Advance Emulator

src/platform/sdl/egl-sdl.c (view raw)

  1/* Copyright (c) 2013-2014 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 "main.h"
  7
  8static const char* _vertexShader =
  9	"attribute vec4 position;\n"
 10	"varying vec2 texCoord;\n"
 11
 12	"void main() {\n"
 13	"	gl_Position = position;\n"
 14	"	texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.46875, -0.3125);\n"
 15	"}";
 16
 17static const char* _fragmentShader =
 18	"varying vec2 texCoord;\n"
 19	"uniform sampler2D tex;\n"
 20
 21	"void main() {\n"
 22	"	vec4 color = texture2D(tex, texCoord);\n"
 23	"	color.a = 1.;\n"
 24	"	gl_FragColor = color;"
 25	"}";
 26
 27static const GLfloat _vertices[] = {
 28	-1.f, -1.f,
 29	-1.f, 1.f,
 30	1.f, 1.f,
 31	1.f, -1.f,
 32};
 33
 34bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
 35	bcm_host_init();
 36	renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 37	int major, minor;
 38	if (EGL_FALSE == eglInitialize(renderer->display, &major, &minor)) {
 39		printf("Failed to initialize EGL");
 40		return false;
 41	}
 42
 43	if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) {
 44		printf("Failed to get GLES API");
 45		return false;
 46	}
 47
 48	const EGLint requestConfig[] = {
 49		EGL_RED_SIZE, 5,
 50		EGL_GREEN_SIZE, 5,
 51		EGL_BLUE_SIZE, 5,
 52		EGL_ALPHA_SIZE, 1,
 53		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
 54		EGL_NONE
 55	};
 56
 57	EGLConfig config;
 58	EGLint numConfigs;
 59
 60	if (EGL_FALSE == eglChooseConfig(renderer->display, requestConfig, &config, 1, &numConfigs)) {
 61		printf("Failed to choose EGL config\n");
 62		return false;
 63	}
 64
 65	const EGLint contextAttributes[] = {
 66		EGL_CONTEXT_CLIENT_VERSION, 2,
 67		EGL_NONE
 68	};
 69
 70	int dispWidth = 240, dispHeight = 160, adjWidth;
 71	renderer->context = eglCreateContext(renderer->display, config, EGL_NO_CONTEXT, contextAttributes);
 72	graphics_get_display_size(0, &dispWidth, &dispHeight);
 73	adjWidth = dispHeight / 2 * 3;
 74
 75	DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
 76	DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
 77
 78	VC_RECT_T destRect = {
 79		.x = (dispWidth - adjWidth) / 2,
 80		.y = 0,
 81		.width = adjWidth,
 82		.height = dispHeight
 83	};
 84
 85	VC_RECT_T srcRect = {
 86		.x = 0,
 87		.y = 0,
 88		.width = 240 << 16,
 89		.height = 160 << 16
 90	};
 91
 92	DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, 0);
 93	vc_dispmanx_update_submit_sync(update);
 94
 95	renderer->window.element = element;
 96	renderer->window.width = dispWidth;
 97	renderer->window.height = dispHeight;
 98
 99	renderer->surface = eglCreateWindowSurface(renderer->display, config, &renderer->window, 0);
100	if (EGL_FALSE == eglMakeCurrent(renderer->display, renderer->surface, renderer->surface, renderer->context)) {
101		return false;
102	}
103
104	renderer->d.outputBuffer = memalign(16, 256 * 256 * 4);
105	renderer->d.outputBufferStride = 256;
106	glGenTextures(1, &renderer->tex);
107	glBindTexture(GL_TEXTURE_2D, renderer->tex);
108	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
109	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
110	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
111	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
112	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
113	renderer->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
114	renderer->vertexShader = glCreateShader(GL_VERTEX_SHADER);
115	renderer->program = glCreateProgram();
116
117	glShaderSource(renderer->fragmentShader, 1, (const GLchar**) &_fragmentShader, 0);
118	glShaderSource(renderer->vertexShader, 1, (const GLchar**) &_vertexShader, 0);
119	glAttachShader(renderer->program, renderer->vertexShader);
120	glAttachShader(renderer->program, renderer->fragmentShader);
121	char log[1024];
122	glCompileShader(renderer->fragmentShader);
123	glCompileShader(renderer->vertexShader);
124	glGetShaderInfoLog(renderer->fragmentShader, 1024, 0, log);
125	glGetShaderInfoLog(renderer->vertexShader, 1024, 0, log);
126	glLinkProgram(renderer->program);
127	glGetProgramInfoLog(renderer->program, 1024, 0, log);
128	printf("%s\n", log);
129	renderer->texLocation = glGetUniformLocation(renderer->program, "tex");
130	renderer->positionLocation = glGetAttribLocation(renderer->program, "position");
131	glClearColor(1.f, 0.f, 0.f, 1.f);
132}
133
134void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
135	SDL_Event event;
136
137	while (context->state < THREAD_EXITING) {
138		while (SDL_PollEvent(&event)) {
139			GBASDLHandleEvent(context, &renderer->player, &event);
140		}
141
142		if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
143			glViewport(0, 0, 240, 160);
144			glClear(GL_COLOR_BUFFER_BIT);
145			glUseProgram(renderer->program);
146			glUniform1i(renderer->texLocation, 0);
147			glActiveTexture(GL_TEXTURE0);
148			glBindTexture(GL_TEXTURE_2D, renderer->tex);
149			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
150			glVertexAttribPointer(renderer->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
151			glEnableVertexAttribArray(renderer->positionLocation);
152			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
153			glUseProgram(0);
154			eglSwapBuffers(renderer->display, renderer->surface);
155		}
156		GBASyncWaitFrameEnd(&context->sync);
157	}
158}
159
160void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
161	eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
162	eglDestroySurface(renderer->display, renderer->surface);
163	eglDestroyContext(renderer->display, renderer->context);
164	eglTerminate(renderer->display);
165	bcm_host_deinit();
166}