GBA Video: Begin fleshing out GL renderer

This commit is contained in:
Vicki Pfau 2019-05-08 20:43:55 -07:00
parent 618ddac387
commit f5d9e9ec5b
2 changed files with 106 additions and 5 deletions

View File

@ -267,6 +267,8 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s
struct GBACore* gbacore = (struct GBACore*) core; struct GBACore* gbacore = (struct GBACore*) core;
gbacore->renderer.outputBuffer = buffer; gbacore->renderer.outputBuffer = buffer;
gbacore->renderer.outputBufferStride = stride; gbacore->renderer.outputBufferStride = stride;
gbacore->glRenderer.outputBuffer = buffer;
gbacore->glRenderer.outputBufferStride = stride;
memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty)); memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty));
} }

View File

@ -22,6 +22,35 @@ static void GBAVideoGLRendererFinishFrame(struct GBAVideoRenderer* renderer);
static void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels);
static void GBAVideoGLRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); static void GBAVideoGLRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels);
static const GLchar* const _gl3Header =
"#version 120\n";
static const char* const _vertexShader =
"attribute vec4 position;\n"
"varying vec2 texCoord;\n"
"void main() {\n"
" gl_Position = position;\n"
" texCoord = (position.st + vec2(1.0, -1.0)) * vec2(0.5, 0.5);\n"
"}";
static const char* const _fragmentShader =
"varying vec2 texCoord;\n"
"uniform sampler2D tex;\n"
"void main() {\n"
" vec4 color = texture2D(tex, texCoord);\n"
" color.a = 1.;\n"
" gl_FragColor = color;\n"
"}";
static const GLfloat _vertices[] = {
-1.f, -1.f,
-1.f, 1.f,
1.f, 1.f,
1.f, -1.f,
};
void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) { void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) {
renderer->d.init = GBAVideoGLRendererInit; renderer->d.init = GBAVideoGLRendererInit;
renderer->d.reset = GBAVideoGLRendererReset; renderer->d.reset = GBAVideoGLRendererReset;
@ -40,20 +69,67 @@ void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) {
renderer->d.disableBG[2] = false; renderer->d.disableBG[2] = false;
renderer->d.disableBG[3] = false; renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false; renderer->d.disableOBJ = false;
renderer->temporaryBuffer = 0;
} }
void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) { void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glGenFramebuffers(6, glRenderer->fbo);
glGenTextures(6, glRenderer->layers);
glGenTextures(1, &glRenderer->paletteTex);
glBindTexture(GL_TEXTURE_2D, glRenderer->paletteTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GBAVideoGLRendererReset(renderer);
} }
void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) { void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glDeleteFramebuffers(6, glRenderer->fbo);
glDeleteTextures(6, glRenderer->layers);
glDeleteTextures(1, &glRenderer->paletteTex);
} }
void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) { void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[5]);
glBindTexture(GL_TEXTURE_2D, glRenderer->layers[5]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glRenderer->layers[5], 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glRenderer->compositeProgram = glCreateProgram();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* shaderBuffer[2];
const GLubyte* version = glGetString(GL_VERSION);
shaderBuffer[0] = _gl3Header;
shaderBuffer[1] = _vertexShader;
glShaderSource(vs, 2, shaderBuffer, 0);
shaderBuffer[1] = _fragmentShader;
glShaderSource(fs, 2, shaderBuffer, 0);
glAttachShader(glRenderer->compositeProgram, vs);
glAttachShader(glRenderer->compositeProgram, fs);
char log[1024];
glCompileShader(fs);
glGetShaderInfoLog(fs, 1024, 0, log);
glCompileShader(vs);
glGetShaderInfoLog(vs, 1024, 0, log);
glLinkProgram(glRenderer->compositeProgram);
glGetProgramInfoLog(glRenderer->compositeProgram, 1024, 0, log);
glRenderer->paletteDirty = false;
} }
void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) { void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
@ -65,7 +141,8 @@ void GBAVideoGLRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam)
} }
void GBAVideoGLRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { void GBAVideoGLRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glRenderer->paletteDirty = true;
} }
uint16_t GBAVideoGLRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { uint16_t GBAVideoGLRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
@ -73,11 +150,33 @@ uint16_t GBAVideoGLRendererWriteVideoRegister(struct GBAVideoRenderer* renderer,
} }
void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) { void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
if (glRenderer->paletteDirty) {
glBindTexture(GL_TEXTURE_2D, glRenderer->paletteTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 256, 2, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, glRenderer->d.palette);
glRenderer->paletteDirty = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[5]);
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS);
glUseProgram(glRenderer->compositeProgram);
glBindTexture(GL_TEXTURE_2D, glRenderer->paletteTex);
glUniform1i(0, 0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
void GBAVideoGLRendererFinishFrame(struct GBAVideoRenderer* renderer) { void GBAVideoGLRendererFinishFrame(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glFinish();
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[5]);
glPixelStorei(GL_PACK_ROW_LENGTH, glRenderer->outputBufferStride);
glReadPixels(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_BYTE, glRenderer->outputBuffer);
glClearColor(1.f, 1.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) {