From 093e65675673fb856185ecc5e29d9f64c2d8e511 Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Fri, 20 Mar 2026 11:58:08 -0400 Subject: [PATCH] some gl work --- hw/xbox/nv2a/pgraph/gl/constants.h | 40 +++++++++++++++++++++++++++--- hw/xbox/nv2a/pgraph/gl/draw.c | 26 +++++++++++-------- hw/xbox/nv2a/pgraph/gl/renderer.c | 34 ++++++++++++++++++++++--- hw/xbox/nv2a/pgraph/gl/renderer.h | 3 +++ hw/xbox/nv2a/pgraph/gl/reports.c | 8 ++++++ hw/xbox/nv2a/pgraph/gl/surface.c | 16 ++++++++---- hw/xbox/nv2a/pgraph/gl/texture.c | 27 ++++++++++++-------- 7 files changed, 121 insertions(+), 33 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/gl/constants.h b/hw/xbox/nv2a/pgraph/gl/constants.h index 431df59928..b6fa07e01f 100644 --- a/hw/xbox/nv2a/pgraph/gl/constants.h +++ b/hw/xbox/nv2a/pgraph/gl/constants.h @@ -34,6 +34,38 @@ #define NV2A_GL_Z16_FLOAT_TYPE GL_UNSIGNED_SHORT /* GLES requires GL_DEPTH24_STENCIL8 when format=GL_DEPTH_STENCIL */ #define NV2A_GL_DEPTH_X8_Y24_INTERNAL GL_DEPTH24_STENCIL8 +# ifdef GL_TEXTURE_LOD_BIAS +# define NV2A_GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS +# elif defined(GL_TEXTURE_LOD_BIAS_EXT) +# define NV2A_GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS_EXT +# else +# define NV2A_GL_TEXTURE_LOD_BIAS 0 +# endif +# ifdef GL_ANY_SAMPLES_PASSED +# define NV2A_GL_ZPASS_QUERY_TARGET GL_ANY_SAMPLES_PASSED +# elif defined(GL_ANY_SAMPLES_PASSED_EXT) +# define NV2A_GL_ZPASS_QUERY_TARGET GL_ANY_SAMPLES_PASSED_EXT +# else +# define NV2A_GL_ZPASS_QUERY_TARGET 0 +# endif +# ifdef GL_CLAMP_TO_BORDER +# define NV2A_GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER +# elif defined(GL_CLAMP_TO_BORDER_EXT) +# define NV2A_GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER_EXT +# elif defined(GL_CLAMP_TO_BORDER_OES) +# define NV2A_GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER_OES +# else +# define NV2A_GL_CLAMP_TO_BORDER 0 +# endif +# ifdef GL_TEXTURE_BORDER_COLOR +# define NV2A_GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR +# elif defined(GL_TEXTURE_BORDER_COLOR_EXT) +# define NV2A_GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR_EXT +# elif defined(GL_TEXTURE_BORDER_COLOR_OES) +# define NV2A_GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR_OES +# else +# define NV2A_GL_TEXTURE_BORDER_COLOR 0 +# endif #else #define NV2A_GL_UNSIGNED_INT_8_8_8_8 GL_UNSIGNED_INT_8_8_8_8 #define NV2A_GL_UNSIGNED_INT_8_8_8_8_REV GL_UNSIGNED_INT_8_8_8_8_REV @@ -41,6 +73,10 @@ #define NV2A_GL_Z16_TYPE GL_HALF_FLOAT #define NV2A_GL_Z16_FLOAT_TYPE GL_HALF_FLOAT #define NV2A_GL_DEPTH_X8_Y24_INTERNAL GL_DEPTH_COMPONENT +#define NV2A_GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS +#define NV2A_GL_ZPASS_QUERY_TARGET GL_SAMPLES_PASSED +#define NV2A_GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER +#define NV2A_GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR #endif static const GLenum pgraph_texture_min_filter_gl_map[] = { @@ -67,7 +103,7 @@ static const GLenum pgraph_texture_addr_gl_map[] = { GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, - GL_CLAMP_TO_BORDER, + NV2A_GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE, /* Approximate GL_CLAMP */ }; @@ -337,5 +373,3 @@ static const SurfaceFormatInfo kelvin_surface_zeta_fixed_format_gl_map[] = { }; #endif - - diff --git a/hw/xbox/nv2a/pgraph/gl/draw.c b/hw/xbox/nv2a/pgraph/gl/draw.c index 6347a10c44..474f55af1a 100644 --- a/hw/xbox/nv2a/pgraph/gl/draw.c +++ b/hw/xbox/nv2a/pgraph/gl/draw.c @@ -350,10 +350,12 @@ void pgraph_gl_draw_begin(NV2AState *d) glScissor(xmin, ymin, scissor_width, scissor_height); /* Visibility testing */ - /* GL_SAMPLES_PASSED is desktop-only; GLES has GL_ANY_SAMPLES_PASSED but - * only returns boolean. Skip occlusion queries entirely on Android. */ -#ifndef __ANDROID__ - if (pg->zpass_pixel_count_enable) { + bool zpass_query_enabled = pg->zpass_pixel_count_enable; +#ifdef __ANDROID__ + zpass_query_enabled = zpass_query_enabled && + r->supported_extensions.occlusion_query_boolean; +#endif + if (zpass_query_enabled) { r->gl_zpass_pixel_count_query_count++; r->gl_zpass_pixel_count_queries = (GLuint*)g_realloc( r->gl_zpass_pixel_count_queries, @@ -363,9 +365,8 @@ void pgraph_gl_draw_begin(NV2AState *d) glGenQueries(1, &gl_query); r->gl_zpass_pixel_count_queries[ r->gl_zpass_pixel_count_query_count - 1] = gl_query; - glBeginQuery(GL_SAMPLES_PASSED, gl_query); + glBeginQuery(NV2A_GL_ZPASS_QUERY_TARGET, gl_query); } -#endif android_log_gl_errors("pgraph_gl_draw_begin"); } @@ -401,12 +402,15 @@ void pgraph_gl_draw_end(NV2AState *d) pgraph_gl_flush_draw(d); /* End of visibility testing */ -#ifndef __ANDROID__ - if (pg->zpass_pixel_count_enable) { - nv2a_profile_inc_counter(NV2A_PROF_QUERY); - glEndQuery(GL_SAMPLES_PASSED); - } + bool zpass_query_enabled = pg->zpass_pixel_count_enable; +#ifdef __ANDROID__ + zpass_query_enabled = zpass_query_enabled && + r->supported_extensions.occlusion_query_boolean; #endif + if (zpass_query_enabled) { + nv2a_profile_inc_counter(NV2A_PROF_QUERY); + glEndQuery(NV2A_GL_ZPASS_QUERY_TARGET); + } pg->draw_time++; #ifdef __ANDROID__ diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.c b/hw/xbox/nv2a/pgraph/gl/renderer.c index 2b93f3d363..08767b9a7b 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.c +++ b/hw/xbox/nv2a/pgraph/gl/renderer.c @@ -47,6 +47,11 @@ static bool gl_extension_list_has(const char *exts, const char *ext) } return false; } + +static bool gl_extension_supported(const char *exts, const char *ext) +{ + return gl_extension_list_has(exts, ext) || glo_check_extension(ext); +} #endif static void early_context_init(void) @@ -102,9 +107,9 @@ static void pgraph_gl_init(NV2AState *d, Error **errp) #ifdef __ANDROID__ const char *exts = (const char *)glGetString(GL_EXTENSIONS); - r->bgra_supported = gl_extension_list_has(exts, "GL_EXT_texture_format_BGRA8888") || - gl_extension_list_has(exts, "GL_OES_texture_format_BGRA8888") || - gl_extension_list_has(exts, "GL_EXT_texture_format_BGRA8888_OES"); + r->bgra_supported = gl_extension_supported(exts, "GL_EXT_texture_format_BGRA8888") || + gl_extension_supported(exts, "GL_OES_texture_format_BGRA8888") || + gl_extension_supported(exts, "GL_EXT_texture_format_BGRA8888_OES"); __android_log_print(ANDROID_LOG_INFO, "xemu-android", "pgraph_gl_init: bgra_supported=%s", r->bgra_supported ? "yes" : "no"); @@ -148,7 +153,30 @@ static void pgraph_gl_init(NV2AState *d, Error **errp) r->supported_extensions.texture_filter_anisotropic = glo_check_extension("GL_EXT_texture_filter_anisotropic"); + r->supported_extensions.texture_border_clamp = true; + r->supported_extensions.texture_lod_bias = true; + r->supported_extensions.occlusion_query_boolean = false; r->supported_extensions.max_texture_max_anisotropy = 1.0f; +#ifdef __ANDROID__ + r->supported_extensions.texture_border_clamp = + NV2A_GL_CLAMP_TO_BORDER != 0 && + NV2A_GL_TEXTURE_BORDER_COLOR != 0 && + (gl_extension_supported(exts, "GL_EXT_texture_border_clamp") || + gl_extension_supported(exts, "GL_OES_texture_border_clamp") || + gl_extension_supported(exts, "GL_NV_texture_border_clamp")); + r->supported_extensions.texture_lod_bias = + NV2A_GL_TEXTURE_LOD_BIAS != 0 && + gl_extension_supported(exts, "GL_EXT_texture_lod_bias"); + r->supported_extensions.occlusion_query_boolean = + NV2A_GL_ZPASS_QUERY_TARGET != 0 && + (epoxy_gl_version() >= 30 || + gl_extension_supported(exts, "GL_EXT_occlusion_query_boolean")); + __android_log_print(ANDROID_LOG_INFO, "xemu-android", + "pgraph_gl_init: texture_border_clamp=%s texture_lod_bias=%s occlusion_query_boolean=%s", + r->supported_extensions.texture_border_clamp ? "yes" : "no", + r->supported_extensions.texture_lod_bias ? "yes" : "no", + r->supported_extensions.occlusion_query_boolean ? "yes" : "no"); +#endif if (r->supported_extensions.texture_filter_anisotropic) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &r->supported_extensions.max_texture_max_anisotropy); diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.h b/hw/xbox/nv2a/pgraph/gl/renderer.h index a361c04122..a59606fb87 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.h +++ b/hw/xbox/nv2a/pgraph/gl/renderer.h @@ -259,6 +259,9 @@ typedef struct PGRAPHGLState { struct supported_extensions { GLboolean texture_filter_anisotropic; + GLboolean texture_border_clamp; + GLboolean texture_lod_bias; + GLboolean occlusion_query_boolean; GLfloat max_texture_max_anisotropy; } supported_extensions; diff --git a/hw/xbox/nv2a/pgraph/gl/reports.c b/hw/xbox/nv2a/pgraph/gl/reports.c index 2dea09e590..a7a23daa3a 100644 --- a/hw/xbox/nv2a/pgraph/gl/reports.c +++ b/hw/xbox/nv2a/pgraph/gl/reports.c @@ -42,6 +42,14 @@ static void process_pending_report(NV2AState *d, QueryReport *report) for (int i = 0; i < report->query_count; i++) { GLuint gl_query_result = 0; glGetQueryObjectuiv(report->queries[i], GL_QUERY_RESULT, &gl_query_result); +#ifdef __ANDROID__ + if (r->supported_extensions.occlusion_query_boolean) { + /* GLES visibility queries only tell us whether any samples passed. + * Preserve that boolean signal instead of reporting a permanent 0. */ + r->zpass_pixel_count_result += gl_query_result ? 1 : 0; + continue; + } +#endif gl_query_result /= pg->surface_scale_factor * pg->surface_scale_factor; r->zpass_pixel_count_result += gl_query_result; } diff --git a/hw/xbox/nv2a/pgraph/gl/surface.c b/hw/xbox/nv2a/pgraph/gl/surface.c index 440b55fc5d..fcb120f14f 100644 --- a/hw/xbox/nv2a/pgraph/gl/surface.c +++ b/hw/xbox/nv2a/pgraph/gl/surface.c @@ -789,12 +789,18 @@ static bool render_surface_to(NV2AState *d, SurfaceBinding *surface, float color[] = { 0.0f, 0.0f, 0.0f, 0.0f }; glBindTexture(GL_TEXTURE_2D, surface->gl_buffer); #ifdef __ANDROID__ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (r->supported_extensions.texture_border_clamp) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, NV2A_GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, NV2A_GL_CLAMP_TO_BORDER); + glTexParameterfv(GL_TEXTURE_2D, NV2A_GL_TEXTURE_BORDER_COLOR, color); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } #else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, NV2A_GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, NV2A_GL_CLAMP_TO_BORDER); + glTexParameterfv(GL_TEXTURE_2D, NV2A_GL_TEXTURE_BORDER_COLOR, color); #endif glBindVertexArray(r->s2t_rndr.vao); diff --git a/hw/xbox/nv2a/pgraph/gl/texture.c b/hw/xbox/nv2a/pgraph/gl/texture.c index 9825a1d10f..d8ec4638e8 100644 --- a/hw/xbox/nv2a/pgraph/gl/texture.c +++ b/hw/xbox/nv2a/pgraph/gl/texture.c @@ -506,22 +506,21 @@ static void apply_texture_parameters(PGRAPHGLState *r, pgraph_texture_mag_filter_gl_map[mag_filter]); binding->mag_filter = mag_filter; } -#ifndef __ANDROID__ if (lod_bias != binding->lod_bias) { binding->lod_bias = lod_bias; - glTexParameterf(binding->gl_target, GL_TEXTURE_LOD_BIAS, - pgraph_convert_lod_bias_to_float(lod_bias)); + if (r->supported_extensions.texture_lod_bias) { + glTexParameterf(binding->gl_target, NV2A_GL_TEXTURE_LOD_BIAS, + pgraph_convert_lod_bias_to_float(lod_bias)); + } } -#else - binding->lod_bias = lod_bias; -#endif /* Texture wrapping */ assert(addru < ARRAY_SIZE(pgraph_texture_addr_gl_map)); if (addru != binding->addru) { GLenum wrap_s = pgraph_texture_addr_gl_map[addru]; #ifdef __ANDROID__ - if (wrap_s == GL_CLAMP_TO_BORDER) { + if (!r->supported_extensions.texture_border_clamp && + wrap_s == NV2A_GL_CLAMP_TO_BORDER) { wrap_s = GL_CLAMP_TO_EDGE; } #endif @@ -535,7 +534,8 @@ static void apply_texture_parameters(PGRAPHGLState *r, assert(addrv < ARRAY_SIZE(pgraph_texture_addr_gl_map)); GLenum wrap_t = pgraph_texture_addr_gl_map[addrv]; #ifdef __ANDROID__ - if (wrap_t == GL_CLAMP_TO_BORDER) { + if (!r->supported_extensions.texture_border_clamp && + wrap_t == NV2A_GL_CLAMP_TO_BORDER) { wrap_t = GL_CLAMP_TO_EDGE; } #endif @@ -550,7 +550,8 @@ static void apply_texture_parameters(PGRAPHGLState *r, assert(addrp < ARRAY_SIZE(pgraph_texture_addr_gl_map)); GLenum wrap_r = pgraph_texture_addr_gl_map[addrp]; #ifdef __ANDROID__ - if (wrap_r == GL_CLAMP_TO_BORDER) { + if (!r->supported_extensions.texture_border_clamp && + wrap_r == NV2A_GL_CLAMP_TO_BORDER) { wrap_r = GL_CLAMP_TO_EDGE; } #endif @@ -572,15 +573,19 @@ static void apply_texture_parameters(PGRAPHGLState *r, clamped_anisotropy); } + if (!is_bordered && needs_border_color) { #ifdef __ANDROID__ - needs_border_color = false; + if (!r->supported_extensions.texture_border_clamp) { + needs_border_color = false; + } #endif + } if (!is_bordered && needs_border_color) { if (!binding->border_color_set || binding->border_color != border_color) { /* FIXME: Color channels might be wrong order */ GLfloat gl_border_color[4]; pgraph_argb_pack32_to_rgba_float(border_color, gl_border_color); - glTexParameterfv(binding->gl_target, GL_TEXTURE_BORDER_COLOR, + glTexParameterfv(binding->gl_target, NV2A_GL_TEXTURE_BORDER_COLOR, gl_border_color); binding->border_color_set = true;