mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Begin fleshing out GL renderer
This commit is contained in:
parent
618ddac387
commit
f5d9e9ec5b
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue