implemented Asynchronous PBO transfer

This commit is contained in:
izzy2lost
2026-03-18 10:03:08 -04:00
parent e040a8d918
commit 76104e362a
2 changed files with 66 additions and 4 deletions
+5
View File
@@ -193,6 +193,11 @@ typedef struct PGRAPHGLState {
bool download_dirty_surfaces_pending;
QemuEvent dirty_surfaces_download_complete; // common
#ifdef __ANDROID__
GLuint gl_download_pbo;
size_t gl_download_pbo_size;
#endif
TextureBinding *texture_binding[NV2A_MAX_TEXTURES];
Lru texture_cache;
TextureLruNode *texture_cache_entries;
+61 -4
View File
@@ -92,6 +92,47 @@ static bool android_drain_gl_errors_silent(void)
return had_error;
}
static void android_glo_readpixels(PGRAPHGLState *r, GLenum gl_format, GLenum gl_type,
unsigned int bytes_per_pixel, unsigned int stride,
unsigned int width, unsigned int height, bool vflip,
void *data)
{
size_t required_size = stride * height;
glBindBuffer(GL_PIXEL_PACK_BUFFER, r->gl_download_pbo);
if (required_size > r->gl_download_pbo_size) {
glBufferData(GL_PIXEL_PACK_BUFFER, required_size, NULL, GL_STREAM_READ);
r->gl_download_pbo_size = required_size;
}
int rl, pa;
glGetIntegerv(GL_PACK_ROW_LENGTH, &rl);
glGetIntegerv(GL_PACK_ALIGNMENT, &pa);
glPixelStorei(GL_PACK_ROW_LENGTH, stride / bytes_per_pixel);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, gl_format, gl_type, 0);
void *mapped_data = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, required_size, GL_MAP_READ_BIT);
if (mapped_data) {
if (vflip) {
GLubyte *b = (GLubyte *) data;
GLubyte *c = &((GLubyte *) mapped_data)[stride * (height - 1)];
for (unsigned int irow = 0; irow < height; irow++) {
memcpy(b, c, width * bytes_per_pixel);
b += stride;
c -= stride;
}
} else {
memcpy(data, mapped_data, required_size);
}
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glPixelStorei(GL_PACK_ROW_LENGTH, rl);
glPixelStorei(GL_PACK_ALIGNMENT, pa);
}
static void android_sanitize_surface_format(PGRAPHGLState *r,
SurfaceFormatInfo *fmt)
{
@@ -1375,7 +1416,7 @@ static bool android_surface_download_depth16_to_guest(NV2AState *d,
}
rgba_pixels = g_malloc(read_height * rgba_stride);
glo_readpixels(GL_RGBA, GL_UNSIGNED_BYTE, 4, rgba_stride, read_width,
android_glo_readpixels(r, GL_RGBA, GL_UNSIGNED_BYTE, 4, rgba_stride, read_width,
read_height, flip, rgba_pixels);
if (android_log_surface_download_errors(
@@ -1533,7 +1574,7 @@ static bool android_surface_download_z24s8_to_guest(NV2AState *d,
}
depth_pixels = g_malloc(read_width * read_height * 4);
glo_readpixels(GL_RGBA, GL_UNSIGNED_BYTE, 4, read_width * 4, read_width,
android_glo_readpixels(r, GL_RGBA, GL_UNSIGNED_BYTE, 4, read_width * 4, read_width,
read_height, flip, depth_pixels);
if (android_log_surface_download_errors(
"surface_download_z24s8: post-read-depth-pack", surface)) {
@@ -1553,7 +1594,7 @@ static bool android_surface_download_z24s8_to_guest(NV2AState *d,
}
stencil_pixels = g_malloc0(read_width * read_height);
glo_readpixels(GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 1, read_width,
android_glo_readpixels(r, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 1, read_width,
read_width, read_height, flip,
stencil_pixels);
if (android_drain_gl_errors_silent()) {
@@ -1713,7 +1754,7 @@ static void surface_download_to_buffer(NV2AState *d, SurfaceBinding *surface,
uint8_t *rgba_linear = rgba_pixels;
uint8_t *linear_guest = pixels;
glo_readpixels(GL_RGBA, GL_UNSIGNED_BYTE, 4, rgba_stride,
android_glo_readpixels(pg->gl_renderer_state, GL_RGBA, GL_UNSIGNED_BYTE, 4, rgba_stride,
read_width, read_height, flip, rgba_pixels);
android_log_surface_download_errors(
"surface_download_to_buffer: post-read_rgba8", surface);
@@ -1768,7 +1809,11 @@ static void surface_download_to_buffer(NV2AState *d, SurfaceBinding *surface,
gl_read_buf = pg->scale_buf;
}
#ifdef __ANDROID__
android_glo_readpixels(pg->gl_renderer_state,
#else
glo_readpixels(
#endif
surface->fmt.gl_format, surface->fmt.gl_type, surface->fmt.bytes_per_pixel,
pg->surface_scale_factor * surface->pitch,
pg->surface_scale_factor * surface->width,
@@ -2520,6 +2565,10 @@ void pgraph_gl_init_surfaces(PGRAPHState *pg)
pgraph_gl_reload_surface_scale_factor(pg);
glGenFramebuffers(1, &r->gl_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, r->gl_framebuffer);
#ifdef __ANDROID__
glGenBuffers(1, &r->gl_download_pbo);
r->gl_download_pbo_size = 0;
#endif
QTAILQ_INIT(&r->surfaces);
r->downloads_pending = false;
qemu_event_init(&r->downloads_complete, false);
@@ -2558,6 +2607,14 @@ void pgraph_gl_finalize_surfaces(PGRAPHState *pg)
glDeleteFramebuffers(1, &r->gl_framebuffer);
r->gl_framebuffer = 0;
#ifdef __ANDROID__
if (r->gl_download_pbo) {
glDeleteBuffers(1, &r->gl_download_pbo);
r->gl_download_pbo = 0;
r->gl_download_pbo_size = 0;
}
#endif
finalize_render_to_texture(pg);
}