GBA Video: Convert OpenGL VRAM texture to integer

This commit is contained in:
Vicki Pfau 2020-09-26 16:29:47 -07:00
parent e11dc3fad0
commit b5ca2b89e2
2 changed files with 29 additions and 33 deletions

View File

@ -81,6 +81,7 @@ Misc:
- GB: Add support for sleep and shutdown callbacks
- GBA: Allow pausing event loop while CPU is blocked
- GBA BIOS: Division by zero should emit a FATAL error
- GBA Video: Convert OpenGL VRAM texture to integer
- Debugger: Keep track of global cycle count
- FFmpeg: Add looping option for GIF/APNG
- mGUI: Show battery percentage

View File

@ -84,8 +84,8 @@ static const char* const _vertexShader =
static const char* const _renderTile16 =
"vec4 renderTile(int tile, int paletteId, ivec2 localCoord) {\n"
" int address = charBase + tile * 16 + (localCoord.x >> 2) + (localCoord.y << 1);\n"
" vec4 halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0);\n"
" int entry = int(halfrow[3 - (localCoord.x & 3)] * 15.9);\n"
" int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n"
" int entry = (halfrow >> (4 * (localCoord.x & 3))) & 15;\n"
" if (entry == 0) {\n"
" discard;\n"
" }\n"
@ -97,13 +97,12 @@ static const char* const _renderTile16 =
static const char* const _renderTile256 =
"vec4 renderTile(int tile, int paletteId, ivec2 localCoord) {\n"
" int address = charBase + tile * 32 + (localCoord.x >> 1) + (localCoord.y << 2);\n"
" vec4 halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0);\n"
" int entry = int(halfrow[3 - 2 * (localCoord.x & 1)] * 15.9);\n"
" int pal2 = int(halfrow[2 - 2 * (localCoord.x & 1)] * 15.9);\n"
" if ((pal2 | entry) == 0) {\n"
" int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n"
" int entry = (halfrow >> (8 * (localCoord.x & 1))) & 255;\n"
" if (entry == 0) {\n"
" discard;\n"
" }\n"
" int paletteEntry = palette[pal2 * 16 + entry];\n"
" int paletteEntry = palette[entry];\n"
" vec4 color = vec4(PALETTE_ENTRY(paletteEntry), 1.);\n"
" return color;\n"
"}";
@ -123,7 +122,7 @@ static const struct GBAVideoGLUniform _uniformsMode0[] = {
static const char* const _renderMode0 =
"in vec2 texCoord;\n"
"uniform sampler2D vram;\n"
"uniform isampler2D vram;\n"
"uniform int palette[256];\n"
"uniform int screenBase;\n"
"uniform int charBase;\n"
@ -158,16 +157,15 @@ static const char* const _renderMode0 =
" coord &= 255;\n"
" coord.y += wrap.x + wrap.y * doty;\n"
" int mapAddress = screenBase + (coord.x >> 3) + (coord.y >> 3) * 32;\n"
" vec4 map = texelFetch(vram, ivec2(mapAddress & 255, mapAddress >> 8), 0);\n"
" int tileFlags = int(map.g * 15.9);\n"
" if ((tileFlags & 4) == 4) {\n"
" int map = texelFetch(vram, ivec2(mapAddress & 255, mapAddress >> 8), 0).r;\n"
" if ((map & 1024) == 1024) {\n"
" coord.x ^= 7;\n"
" }\n"
" if ((tileFlags & 8) == 8) {\n"
" if ((map & 2048) == 2048) {\n"
" coord.y ^= 7;\n"
" }\n"
" int tile = int(map.a * 15.9) + int(map.b * 15.9) * 16 + (tileFlags & 0x3) * 256;\n"
" color = renderTile(tile, int(map.r * 15.9), coord & 7);\n"
" int tile = map & 1023;\n"
" color = renderTile(tile, map >> 12, coord & 7);\n"
"}";
static const char* const _fetchTileOverflow =
@ -225,7 +223,7 @@ static const char* const _interpolate =
static const char* const _renderMode2 =
"in vec2 texCoord;\n"
"uniform sampler2D vram;\n"
"uniform isampler2D vram;\n"
"uniform int palette[256];\n"
"uniform int screenBase;\n"
"uniform int charBase;\n"
@ -242,16 +240,15 @@ static const char* const _renderMode2 =
"vec4 renderTile(ivec2 coord) {\n"
" int map = (coord.x >> 11) + (((coord.y >> 7) & 0x7F0) << size);\n"
" int mapAddress = screenBase + (map >> 1);\n"
" vec4 twomaps = texelFetch(vram, ivec2(mapAddress & 255, mapAddress >> 8), 0);\n"
" int tile = int(twomaps[3 - 2 * (map & 1)] * 15.9) + int(twomaps[2 - 2 * (map & 1)] * 15.9) * 16;\n"
" int twomaps = texelFetch(vram, ivec2(mapAddress & 255, mapAddress >> 8), 0).r;\n"
" int tile = (twomaps >> (8 * (map & 1))) & 255;\n"
" int address = charBase + tile * 32 + ((coord.x >> 9) & 3) + ((coord.y >> 6) & 0x1C);\n"
" vec4 halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0);\n"
" int entry = int(halfrow[3 - ((coord.x >> 7) & 2)] * 15.9);\n"
" int pal2 = int(halfrow[2 - ((coord.x >> 7) & 2)] * 15.9);\n"
" if ((pal2 | entry) == 0) {\n"
" int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n"
" int entry = (halfrow >> (8 * ((coord.x >> 8) & 1))) & 255;\n"
" if (entry == 0) {\n"
" discard;\n"
" }\n"
" int paletteEntry = palette[pal2 * 16 + entry];\n"
" int paletteEntry = palette[entry];\n"
" vec4 color = vec4(PALETTE_ENTRY(paletteEntry), 1.);\n"
" return color;\n"
"}\n"
@ -294,7 +291,7 @@ static const struct GBAVideoGLUniform _uniformsMode35[] = {
static const char* const _renderMode35 =
"in vec2 texCoord;\n"
"uniform sampler2D vram;\n"
"uniform isampler2D vram;\n"
"uniform int charBase;\n"
"uniform ivec2 size;\n"
"uniform ivec4 transform[160];\n"
@ -333,9 +330,8 @@ static const char* const _renderMode35 =
" discard;\n"
" }\n"
" int address = charBase + (coord.x >> 8) + (coord.y >> 8) * size.x;\n"
" ivec4 entry = ivec4(texelFetch(vram, ivec2(address & 255, address >> 8), 0) * 15.9);\n"
" int sixteen = (entry.x << 12) | (entry.y << 8) | (entry.z << 4) | entry.w;\n"
" color = vec4(float(sixteen & 0x1F) / 31., float((sixteen >> 5) & 0x1F) / 31., float((sixteen >> 10) & 0x1F) / 31., 1.);\n"
" int entry = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n"
" color = vec4(float(entry & 0x1F) / 31., float((entry >> 5) & 0x1F) / 31., float((entry >> 10) & 0x1F) / 31., 1.);\n"
"}";
static const struct GBAVideoGLUniform _uniformsMode4[] = {
@ -354,7 +350,7 @@ static const struct GBAVideoGLUniform _uniformsMode4[] = {
static const char* const _renderMode4 =
"in vec2 texCoord;\n"
"uniform sampler2D vram;\n"
"uniform isampler2D vram;\n"
"uniform int palette[256];\n"
"uniform int charBase;\n"
"uniform ivec2 size;\n"
@ -394,9 +390,8 @@ static const char* const _renderMode4 =
" discard;\n"
" }\n"
" int address = charBase + (coord.x >> 8) + (coord.y >> 8) * size.x;\n"
" vec4 twoEntries = texelFetch(vram, ivec2((address >> 1) & 255, address >> 9), 0);\n"
" ivec2 entry = ivec2(twoEntries[3 - 2 * (address & 1)] * 15.9, twoEntries[2 - 2 * (address & 1)] * 15.9);\n"
" int paletteEntry = palette[entry.y * 16 + entry.x];\n"
" int twoEntries = texelFetch(vram, ivec2((address >> 1) & 255, address >> 9), 0).r;\n"
" int paletteEntry = palette[(twoEntries >> (8 * (address & 1)) & 255)];\n"
" color = vec4(PALETTE_ENTRY(paletteEntry), 1.);\n"
"}";
@ -419,7 +414,7 @@ static const struct GBAVideoGLUniform _uniformsObj[] = {
static const char* const _renderObj =
"in vec2 texCoord;\n"
"uniform sampler2D vram;\n"
"uniform isampler2D vram;\n"
"uniform int palette[256];\n"
"uniform int charBase;\n"
"uniform int stride;\n"
@ -781,7 +776,7 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
glBindTexture(GL_TEXTURE_2D, glRenderer->vramTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 256, 192, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, 256, 192, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, 0);
glGenBuffers(1, &glRenderer->vbo);
glBindBuffer(GL_ARRAY_BUFFER, glRenderer->vbo);
@ -1355,7 +1350,7 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
for (i = 0; i < 25; ++i) {
if (!(glRenderer->vramDirty & (1 << i))) {
if (first >= 0) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 8 * first, 256, 8 * (i - first), GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, &glRenderer->d.vram[2048 * first]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 8 * first, 256, 8 * (i - first), GL_RED_INTEGER, GL_UNSIGNED_SHORT, &glRenderer->d.vram[2048 * first]);
first = -1;
}
} else if (first < 0) {