Implement swizzler for BGRA/"wrong order" uploads
This commit is contained in:
parent
10e68400ed
commit
75abce1b80
@ -32,6 +32,7 @@ public class MainActivity extends Activity {
|
||||
}
|
||||
String copyCommand = "cp " + copySrc + "/* "+copyDst+"/";
|
||||
try {
|
||||
Runtime.getRuntime().exec("am force-stop "+targetAppInfo.packageName);
|
||||
ProcessBuilder processBuilder = new ProcessBuilder("su", "-c", copyCommand);
|
||||
Process process = processBuilder.start();
|
||||
int errorCode = process.waitFor();
|
||||
|
@ -400,6 +400,7 @@ LOCAL_SRC_FILES := \
|
||||
stubs.c \
|
||||
multidraw.c \
|
||||
vertexattrib.c \
|
||||
swizzle.c \
|
||||
vgpu_shaderconv/shaderconv.c \
|
||||
unordered_map/unordered_map.c \
|
||||
unordered_map/int_hash.c
|
||||
|
@ -30,6 +30,8 @@ static bool init_context(context_t* tw_context) {
|
||||
if(!tw_context->framebuffer_map) goto fail_dealloc;
|
||||
tw_context->program_map = alloc_intmap_safe();
|
||||
if(!tw_context->program_map) goto fail_dealloc;
|
||||
tw_context->texture_swztrack_map = alloc_intmap_safe();
|
||||
if(!tw_context->texture_swztrack_map) goto fail_dealloc;
|
||||
for(int i = 0; i < MAX_BOUND_BASEBUFFERS; i++) {
|
||||
unordered_map *map = alloc_intmap_safe();
|
||||
if(!map) goto fail_dealloc;
|
||||
@ -48,6 +50,8 @@ static bool init_context(context_t* tw_context) {
|
||||
unordered_map_free(tw_context->framebuffer_map);
|
||||
if(tw_context->program_map)
|
||||
unordered_map_free(tw_context->program_map);
|
||||
if(tw_context->texture_swztrack_map)
|
||||
unordered_map_free(tw_context->texture_swztrack_map);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
@ -56,6 +60,7 @@ static void free_context(context_t* tw_context) {
|
||||
unordered_map_free(tw_context->shader_map);
|
||||
unordered_map_free(tw_context->program_map);
|
||||
unordered_map_free(tw_context->framebuffer_map);
|
||||
unordered_map_free(tw_context->texture_swztrack_map);
|
||||
if(tw_context->extensions_string != NULL) free(tw_context->extensions_string);
|
||||
if(tw_context->nextras != 0 && tw_context->extra_extensions_array != NULL) {
|
||||
for(int i = 0; i < tw_context->nextras; i++) {
|
||||
|
@ -14,6 +14,8 @@
|
||||
#define MAX_BOUND_BASEBUFFERS 4
|
||||
#define MAX_DRAWBUFFERS 8
|
||||
#define MAX_FBTARGETS 8
|
||||
#define MAX_TMUS 8
|
||||
#define MAX_TEXTARGETS 8
|
||||
|
||||
typedef struct {
|
||||
bool ready;
|
||||
@ -48,11 +50,10 @@ typedef struct {
|
||||
} framebuffer_copier_t;
|
||||
|
||||
typedef struct {
|
||||
GLint internalformat;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
GLsizei width, height;
|
||||
} texture_t;
|
||||
GLenum original_swizzle[4];
|
||||
GLboolean goofy_byte_order;
|
||||
GLboolean upload_bgra;
|
||||
} texture_swizzle_track_t;
|
||||
|
||||
typedef struct {
|
||||
EGLContext phys_context;
|
||||
@ -65,7 +66,7 @@ typedef struct {
|
||||
unordered_map* shader_map;
|
||||
unordered_map* program_map;
|
||||
unordered_map* framebuffer_map;
|
||||
unordered_map* texture_map;
|
||||
unordered_map* texture_swztrack_map;
|
||||
unordered_map* bound_basebuffers[MAX_BOUND_BASEBUFFERS];
|
||||
int proxy_width, proxy_height, proxy_intformat, maxTextureSize;
|
||||
GLint max_drawbuffers;
|
||||
@ -81,5 +82,6 @@ typedef struct {
|
||||
|
||||
extern thread_local context_t *current_context;
|
||||
extern void init_egl();
|
||||
extern GLenum get_textarget_query_param(GLenum target);
|
||||
|
||||
#endif //POJAVLAUNCHER_EGL_H
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "egl.h"
|
||||
#include "glformats.h"
|
||||
#include "main.h"
|
||||
#include "swizzle.h"
|
||||
#include "libraryinternal.h"
|
||||
|
||||
void glClearDepth(GLdouble depth) {
|
||||
if(!current_context) return;
|
||||
@ -58,7 +60,7 @@ void *glMapBuffer(GLenum target, GLenum access) {
|
||||
return es3_functions.glMapBufferRange(target, 0, length, access_range);
|
||||
}
|
||||
|
||||
int isProxyTexture(GLenum target) {
|
||||
INTERNAL int isProxyTexture(GLenum target) {
|
||||
switch (target) {
|
||||
case GL_PROXY_TEXTURE_1D:
|
||||
case GL_PROXY_TEXTURE_2D:
|
||||
@ -69,6 +71,35 @@ int isProxyTexture(GLenum target) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
INTERNAL GLenum get_textarget_query_param(GLenum target) {
|
||||
switch (target) {
|
||||
case GL_TEXTURE_2D:
|
||||
return GL_TEXTURE_BINDING_2D;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
return GL_TEXTURE_BINDING_2D_MULTISAMPLE;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
return GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY;
|
||||
case GL_TEXTURE_3D:
|
||||
return GL_TEXTURE_BINDING_3D;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
return GL_TEXTURE_BINDING_2D_ARRAY;
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
return GL_TEXTURE_BINDING_CUBE_MAP;
|
||||
case GL_TEXTURE_CUBE_MAP_ARRAY:
|
||||
return GL_TEXTURE_BINDING_CUBE_MAP_ARRAY;
|
||||
case GL_TEXTURE_BUFFER:
|
||||
return GL_TEXTURE_BUFFER_BINDING;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int inline nlevel(int size, int level) {
|
||||
if(size) {
|
||||
size>>=level;
|
||||
@ -131,15 +162,16 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei widt
|
||||
current_context->proxy_height = ((height<<level)>current_context->maxTextureSize)?0:height;
|
||||
current_context->proxy_intformat = internalformat;
|
||||
} else {
|
||||
swizzle_process_upload(target, &format, &type);
|
||||
pick_internalformat(&internalformat, &type, &format, &data);
|
||||
es3_functions.glTexImage2D(target, level, internalformat, width, height, border, format, type, data);
|
||||
}
|
||||
}
|
||||
|
||||
bool filter_params_integer(GLenum target, GLenum pname, GLint param) {
|
||||
INTERNAL bool filter_params_integer(GLenum target, GLenum pname, GLint param) {
|
||||
return true;
|
||||
}
|
||||
bool filter_params_float(GLenum target, GLenum pname, GLfloat param) {
|
||||
INTERNAL bool filter_params_float(GLenum target, GLenum pname, GLfloat param) {
|
||||
if(pname == GL_TEXTURE_LOD_BIAS) {
|
||||
if(param != 0.0f) {
|
||||
static bool lodbias_trigger = false;
|
||||
@ -165,6 +197,7 @@ void glTexParameteri( GLenum target,
|
||||
if(!current_context) return;
|
||||
if(!filter_params_integer(target, pname, param)) return;
|
||||
if(!filter_params_float(target, pname, (GLfloat)param)) return;
|
||||
swizzle_process_swizzle_param(target, pname, ¶m);
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
@ -188,6 +221,7 @@ void glTexParameteriv( GLenum target,
|
||||
if(!current_context) return;
|
||||
if(!filter_params_integer(target, pname, *params)) return;
|
||||
if(!filter_params_float(target, pname, (GLfloat)*params)) return;
|
||||
swizzle_process_swizzle_param(target, pname, params);
|
||||
es3_functions.glTexParameteriv(target, pname, params);
|
||||
}
|
||||
static bool trigger_gltexparameteri = false;
|
||||
@ -202,8 +236,9 @@ void glTexParameterIiv( GLenum target,
|
||||
}
|
||||
return;
|
||||
}
|
||||
es3_functions.glTexParameteriv(target, pname, params);
|
||||
swizzle_process_swizzle_param(target, pname, params);
|
||||
}
|
||||
|
||||
void glTexParameterIuiv( GLenum target,
|
||||
GLenum pname,
|
||||
const GLuint * params) {
|
||||
@ -215,7 +250,7 @@ void glTexParameterIuiv( GLenum target,
|
||||
}
|
||||
return;
|
||||
}
|
||||
es3_functions.glTexParameteriv(target, pname, (const GLint*)params);
|
||||
swizzle_process_swizzle_param(target, pname, params);
|
||||
}
|
||||
|
||||
void glRenderbufferStorage( GLenum target,
|
||||
@ -269,7 +304,7 @@ void glEnable(GLenum cap) {
|
||||
es3_functions.glEnable(cap);
|
||||
}
|
||||
|
||||
int get_buffer_index(GLenum buffer) {
|
||||
INTERNAL int get_buffer_index(GLenum buffer) {
|
||||
switch (buffer) {
|
||||
case GL_ARRAY_BUFFER: return 0;
|
||||
case GL_COPY_READ_BUFFER: return 1;
|
||||
@ -284,7 +319,7 @@ int get_buffer_index(GLenum buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
int get_base_buffer_index(GLenum buffer) {
|
||||
INTERNAL int get_base_buffer_index(GLenum buffer) {
|
||||
switch (buffer) {
|
||||
case GL_ATOMIC_COUNTER_BUFFER: return 0;
|
||||
case GL_SHADER_STORAGE_BUFFER: return 1;
|
||||
@ -294,7 +329,7 @@ int get_base_buffer_index(GLenum buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
GLenum get_base_buffer_enum(int buffer_index) {
|
||||
INTERNAL GLenum get_base_buffer_enum(int buffer_index) {
|
||||
switch (buffer_index) {
|
||||
case 0: return GL_ATOMIC_COUNTER_BUFFER;
|
||||
case 1: return GL_SHADER_STORAGE_BUFFER;
|
||||
@ -387,6 +422,15 @@ void glDepthRange(GLdouble nearVal,
|
||||
es3_functions.glDepthRangef((GLfloat)nearVal, (GLfloat)farVal);
|
||||
}
|
||||
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures) {
|
||||
if(!current_context) return;
|
||||
es3_functions.glDeleteTextures(n, textures);
|
||||
for(int i = 0; i < n; i++) {
|
||||
void* tracker = unordered_map_remove(current_context->texture_swztrack_map, (void*)textures[i]);
|
||||
free(tracker);
|
||||
}
|
||||
}
|
||||
|
||||
void glDebugMessageControl( GLenum source,
|
||||
GLenum type,
|
||||
GLenum severity,
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "proc.h"
|
||||
#include "egl.h"
|
||||
#include <stdbool.h>
|
||||
#include "swizzle.h"
|
||||
void buffer_copier_init(context_t* context) {
|
||||
framebuffer_copier_t* copier = &context->framebuffer_copier;
|
||||
while(es3_functions.glGetError() != 0) {}
|
||||
@ -37,26 +38,11 @@ static void buffer_copier_store(GLint x, GLint y, GLsizei w, GLsizei h) {
|
||||
es3_functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_context->draw_framebuffer);
|
||||
}
|
||||
|
||||
static GLenum get_target_query_param(GLenum target) {
|
||||
switch (target) {
|
||||
case GL_TEXTURE_2D: return GL_TEXTURE_BINDING_2D;
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
return GL_TEXTURE_BINDING_CUBE_MAP;
|
||||
default:
|
||||
return GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void buffer_copier_release(GLenum target, GLint level, GLint x, GLint y, GLsizei w, GLsizei h) {
|
||||
framebuffer_copier_t* copier = ¤t_context->framebuffer_copier;
|
||||
if(!copier->ready) return;
|
||||
GLint current_texbind;
|
||||
GLenum target_query = get_target_query_param(target);
|
||||
GLenum target_query = get_textarget_query_param(target);
|
||||
if(target_query == GL_NONE) return;
|
||||
es3_functions.glGetIntegerv(target_query, ¤t_texbind);
|
||||
es3_functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copier->destfb);
|
||||
@ -77,7 +63,7 @@ void glGetTexImage( GLenum target,
|
||||
if(format != GL_RGBA && format != GL_RGBA_INTEGER && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_INT && type != GL_INT && type != GL_FLOAT) goto unsupported;
|
||||
framebuffer_copier_t* copier = ¤t_context->framebuffer_copier;
|
||||
GLint texture;
|
||||
es3_functions.glGetIntegerv(get_target_query_param(target), &texture);
|
||||
es3_functions.glGetIntegerv(get_textarget_query_param(target), &texture);
|
||||
es3_functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, copier->tempfb);
|
||||
es3_functions.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture, level);
|
||||
GLint w, h;
|
||||
@ -116,6 +102,7 @@ void glTexSubImage2D(GLenum target,
|
||||
GLenum type,
|
||||
const void * data) {
|
||||
if(!current_context) return;
|
||||
swizzle_process_upload(target, &format, &type);
|
||||
if(format == GL_DEPTH_COMPONENT) {
|
||||
framebuffer_copier_t* copier = ¤t_context->framebuffer_copier;
|
||||
if(width == copier->depthWidth && height == copier->depthHeight && copier->depthData == data) {
|
||||
@ -141,7 +128,7 @@ void glCopyTexSubImage2D(GLenum target,
|
||||
framebuffer_copier_t* copier = ¤t_context->framebuffer_copier;
|
||||
if(!copier->ready) return;
|
||||
GLint texture;
|
||||
es3_functions.glGetIntegerv(get_target_query_param(target), &texture);
|
||||
es3_functions.glGetIntegerv(get_textarget_query_param(target), &texture);
|
||||
es3_functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copier->destfb);
|
||||
es3_functions.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, texture, level);
|
||||
es3_functions.glBlitFramebuffer(x, y, width+x, height+y, xoffset, yoffset, width+xoffset, height+yoffset, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
|
102
app/src/main/tinywrapper/swizzle.c
Normal file
102
app/src/main/tinywrapper/swizzle.c
Normal file
@ -0,0 +1,102 @@
|
||||
//
|
||||
// Created by maks on 30.11.2024.
|
||||
//
|
||||
#include "proc.h"
|
||||
#include "egl.h"
|
||||
#include <string.h>
|
||||
#include "libraryinternal.h"
|
||||
//#include <GL/glext.h>
|
||||
|
||||
#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
|
||||
|
||||
static void swizzle_process_bgra(GLenum* swizzle) {
|
||||
GLenum red_src = swizzle[0];
|
||||
GLenum blue_src = swizzle[2];
|
||||
swizzle[0] = blue_src;
|
||||
swizzle[2] = red_src;
|
||||
}
|
||||
|
||||
static void swizzle_process_endianness(GLenum* swizzle) {
|
||||
GLenum orig_swizzle[4];
|
||||
memcpy(orig_swizzle, swizzle, 4 * sizeof(GLenum));
|
||||
swizzle[0] = orig_swizzle[3];
|
||||
swizzle[1] = orig_swizzle[2];
|
||||
swizzle[2] = orig_swizzle[1];
|
||||
swizzle[3] = orig_swizzle[0];
|
||||
}
|
||||
|
||||
static texture_swizzle_track_t* get_swizzle_track(GLenum target) {
|
||||
GLint texture;
|
||||
GLenum getter = get_textarget_query_param(target);
|
||||
if(getter == 0) return NULL;
|
||||
es3_functions.glGetIntegerv(getter, &texture);
|
||||
texture_swizzle_track_t* track = unordered_map_get(current_context->texture_swztrack_map, (void*)texture);
|
||||
if(track == NULL) {
|
||||
track = malloc(sizeof(texture_swizzle_track_t));
|
||||
es3_functions.glGetTexParameteriv(target, GL_TEXTURE_SWIZZLE_R, (GLint*)&track->original_swizzle[0]);
|
||||
es3_functions.glGetTexParameteriv(target, GL_TEXTURE_SWIZZLE_G, (GLint*)&track->original_swizzle[1]);
|
||||
es3_functions.glGetTexParameteriv(target, GL_TEXTURE_SWIZZLE_B, (GLint*)&track->original_swizzle[2]);
|
||||
es3_functions.glGetTexParameteriv(target, GL_TEXTURE_SWIZZLE_A, (GLint*)&track->original_swizzle[3]);
|
||||
unordered_map_put(current_context->texture_swztrack_map, (void*)texture, track);
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
static void apply_swizzles(GLenum target, texture_swizzle_track_t* track) {
|
||||
GLenum new_swizzle[4];
|
||||
memcpy(new_swizzle, track->original_swizzle, 4 * sizeof(GLenum));
|
||||
if(track->goofy_byte_order) swizzle_process_endianness(new_swizzle);
|
||||
if(track->upload_bgra) swizzle_process_bgra(new_swizzle);
|
||||
es3_functions.glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, new_swizzle[0]);
|
||||
es3_functions.glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, new_swizzle[1]);
|
||||
es3_functions.glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, new_swizzle[2]);
|
||||
es3_functions.glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, new_swizzle[3]);
|
||||
}
|
||||
|
||||
INTERNAL void swizzle_process_upload(GLenum target, GLenum* format, GLenum* type) {
|
||||
texture_swizzle_track_t* track = get_swizzle_track(target);
|
||||
if(track == NULL) return;
|
||||
bool apply_upload_bgra = false;
|
||||
bool apply_goofy_order = false;
|
||||
if((*format) == GL_BGRA_EXT) {
|
||||
apply_upload_bgra = true;
|
||||
*format = GL_RGBA;
|
||||
}
|
||||
if((*type) == 0x8035) {
|
||||
apply_goofy_order = true;
|
||||
*type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
if(apply_goofy_order != track->goofy_byte_order || apply_upload_bgra != track->upload_bgra) {
|
||||
track->goofy_byte_order = apply_goofy_order;
|
||||
track->upload_bgra = apply_upload_bgra;
|
||||
apply_swizzles(target, track);
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL void swizzle_process_swizzle_param(GLenum target, GLenum swizzle_param, const GLenum* swizzle) {
|
||||
switch (swizzle_param) {
|
||||
case GL_TEXTURE_SWIZZLE_R:
|
||||
case GL_TEXTURE_SWIZZLE_G:
|
||||
case GL_TEXTURE_SWIZZLE_B:
|
||||
case GL_TEXTURE_SWIZZLE_A:
|
||||
case GL_TEXTURE_SWIZZLE_RGBA:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
texture_swizzle_track_t* track = get_swizzle_track(target);
|
||||
if(track == NULL) return;
|
||||
switch(swizzle_param) {
|
||||
case GL_TEXTURE_SWIZZLE_R:
|
||||
case GL_TEXTURE_SWIZZLE_G:
|
||||
case GL_TEXTURE_SWIZZLE_B:
|
||||
case GL_TEXTURE_SWIZZLE_A:
|
||||
track->original_swizzle[swizzle_param - GL_TEXTURE_SWIZZLE_R] = *swizzle;
|
||||
apply_swizzles(target, track);
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_RGBA:
|
||||
memcpy(track->original_swizzle, swizzle, 4 * sizeof(GLenum));
|
||||
apply_swizzles(target, track);
|
||||
break;
|
||||
}
|
||||
}
|
13
app/src/main/tinywrapper/swizzle.h
Normal file
13
app/src/main/tinywrapper/swizzle.h
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by maks on 30.11.2024.
|
||||
//
|
||||
|
||||
#ifndef GL4ES_WRAPPER_SWIZZLE_H
|
||||
#define GL4ES_WRAPPER_SWIZZLE_H
|
||||
|
||||
#include "egl.h"
|
||||
|
||||
void swizzle_process_upload(GLenum target, GLenum *format, GLenum *type);
|
||||
void swizzle_process_swizzle_param(GLenum target, GLenum swizzle_param, const GLenum* swizzle);
|
||||
|
||||
#endif //GL4ES_WRAPPER_SWIZZLE_H
|
Reference in New Issue
Block a user