diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.c b/hw/xbox/nv2a/pgraph/gl/renderer.c index f3764f397d1..56318bcf353 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.c +++ b/hw/xbox/nv2a/pgraph/gl/renderer.c @@ -114,6 +114,7 @@ static void pgraph_gl_process_pending(NV2AState *d) if (qatomic_read(&r->downloads_pending) || qatomic_read(&r->download_dirty_surfaces_pending) || + qatomic_read(&r->download_dirty_surfaces_in_range_pending) || qatomic_read(&d->pgraph.sync_pending) || qatomic_read(&d->pgraph.flush_pending) || qatomic_read(&r->shader_cache_writeback_pending)) { @@ -125,6 +126,13 @@ static void pgraph_gl_process_pending(NV2AState *d) if (qatomic_read(&r->download_dirty_surfaces_pending)) { pgraph_gl_download_dirty_surfaces(d); } + if (qatomic_read(&r->download_dirty_surfaces_in_range_pending)) { + pgraph_gl_download_surfaces_in_range_if_dirty( + d, r->download_dirty_surfaces_in_range_start, + r->download_dirty_surfaces_in_range_size); + qatomic_set(&r->download_dirty_surfaces_in_range_pending, false); + qemu_event_set(&r->dirty_surfaces_download_complete); + } if (qatomic_read(&d->pgraph.sync_pending)) { pgraph_gl_sync(d); } @@ -156,6 +164,46 @@ static void pgraph_gl_pre_savevm_wait(NV2AState *d) qemu_event_wait(&r->dirty_surfaces_download_complete); } +static bool pgraph_gl_have_overlapping_dirty_surfaces(NV2AState *d, + hwaddr start, hwaddr size) +{ + PGRAPHState *pg = &d->pgraph; + PGRAPHGLState *r = pg->gl_renderer_state; + + SurfaceBinding *surface; + + hwaddr end = start + size - 1; + + QTAILQ_FOREACH (surface, &r->surfaces, entry) { + hwaddr surf_end = surface->vram_addr + surface->size - 1; + bool overlapping = !(surface->vram_addr >= end || start >= surf_end); + if (overlapping && surface->draw_dirty) { + return true; + } + } + + return false; +} + +static void pgraph_gl_download_overlapping_surfaces_trigger(NV2AState *d, + hwaddr start, + hwaddr size) +{ + PGRAPHState *pg = &d->pgraph; + PGRAPHGLState *r = pg->gl_renderer_state; + + r->download_dirty_surfaces_in_range_start = start; + r->download_dirty_surfaces_in_range_size = size; + qemu_event_reset(&r->dirty_surfaces_download_complete); + qatomic_set(&r->download_dirty_surfaces_in_range_pending, true); +} + +static void pgraph_gl_download_overlapping_surfaces_wait(NV2AState *d) +{ + qemu_event_wait( + &d->pgraph.gl_renderer_state->dirty_surfaces_download_complete); +} + static void pgraph_gl_pre_shutdown_trigger(NV2AState *d) { PGRAPHState *pg = &d->pgraph; @@ -173,33 +221,45 @@ static void pgraph_gl_pre_shutdown_wait(NV2AState *d) qemu_event_wait(&r->shader_cache_writeback_complete); } -static PGRAPHRenderer pgraph_gl_renderer = { - .type = CONFIG_DISPLAY_RENDERER_OPENGL, - .name = "OpenGL", - .ops = { - .init = pgraph_gl_init, - .early_context_init = early_context_init, - .finalize = pgraph_gl_finalize, - .clear_report_value = pgraph_gl_clear_report_value, - .clear_surface = pgraph_gl_clear_surface, - .draw_begin = pgraph_gl_draw_begin, - .draw_end = pgraph_gl_draw_end, - .flip_stall = pgraph_gl_flip_stall, - .flush_draw = pgraph_gl_flush_draw, - .get_report = pgraph_gl_get_report, - .image_blit = pgraph_gl_image_blit, - .pre_savevm_trigger = pgraph_gl_pre_savevm_trigger, - .pre_savevm_wait = pgraph_gl_pre_savevm_wait, - .pre_shutdown_trigger = pgraph_gl_pre_shutdown_trigger, - .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait, - .process_pending = pgraph_gl_process_pending, - .process_pending_reports = pgraph_gl_process_pending_reports, - .surface_update = pgraph_gl_surface_update, - .set_surface_scale_factor = pgraph_gl_set_surface_scale_factor, - .get_surface_scale_factor = pgraph_gl_get_surface_scale_factor, - .get_framebuffer_surface = pgraph_gl_get_framebuffer_surface, - } -}; +static PGRAPHRenderer + pgraph_gl_renderer = { .type = CONFIG_DISPLAY_RENDERER_OPENGL, + .name = "OpenGL", + .ops = { + .init = pgraph_gl_init, + .early_context_init = early_context_init, + .finalize = pgraph_gl_finalize, + .clear_report_value = + pgraph_gl_clear_report_value, + .clear_surface = pgraph_gl_clear_surface, + .draw_begin = pgraph_gl_draw_begin, + .draw_end = pgraph_gl_draw_end, + .flip_stall = pgraph_gl_flip_stall, + .flush_draw = pgraph_gl_flush_draw, + .get_report = pgraph_gl_get_report, + .image_blit = pgraph_gl_image_blit, + .pre_savevm_trigger = + pgraph_gl_pre_savevm_trigger, + .pre_savevm_wait = pgraph_gl_pre_savevm_wait, + .pre_shutdown_trigger = + pgraph_gl_pre_shutdown_trigger, + .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait, + .process_pending = pgraph_gl_process_pending, + .process_pending_reports = + pgraph_gl_process_pending_reports, + .surface_update = pgraph_gl_surface_update, + .have_overlapping_dirty_surfaces = + pgraph_gl_have_overlapping_dirty_surfaces, + .download_overlapping_surfaces_trigger = + pgraph_gl_download_overlapping_surfaces_trigger, + .download_overlapping_surfaces_wait = + pgraph_gl_download_overlapping_surfaces_wait, + .set_surface_scale_factor = + pgraph_gl_set_surface_scale_factor, + .get_surface_scale_factor = + pgraph_gl_get_surface_scale_factor, + .get_framebuffer_surface = + pgraph_gl_get_framebuffer_surface, + } }; static void __attribute__((constructor)) register_renderer(void) { diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.h b/hw/xbox/nv2a/pgraph/gl/renderer.h index d76e502c8c8..cf8a9717b0f 100644 --- a/hw/xbox/nv2a/pgraph/gl/renderer.h +++ b/hw/xbox/nv2a/pgraph/gl/renderer.h @@ -187,7 +187,11 @@ typedef struct PGRAPHGLState { SurfaceBinding *color_binding, *zeta_binding; bool downloads_pending; QemuEvent downloads_complete; + bool download_dirty_surfaces_pending; + bool download_dirty_surfaces_in_range_pending; + hwaddr download_dirty_surfaces_in_range_start; + hwaddr download_dirty_surfaces_in_range_size; QemuEvent dirty_surfaces_download_complete; // common TextureBinding *texture_binding[NV2A_MAX_TEXTURES]; @@ -280,6 +284,7 @@ void pgraph_gl_reload_surface_scale_factor(PGRAPHState *pg); void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface, TextureBinding *texture, TextureShape *texture_shape, int texture_unit); void pgraph_gl_set_surface_dirty(PGRAPHState *pg, bool color, bool zeta); void pgraph_gl_surface_download_if_dirty(NV2AState *d, SurfaceBinding *surface); +void pgraph_gl_download_surfaces_in_range_if_dirty(NV2AState *d, hwaddr start, hwaddr size); SurfaceBinding *pgraph_gl_surface_get(NV2AState *d, hwaddr addr); SurfaceBinding *pgraph_gl_surface_get_within(NV2AState *d, hwaddr addr); void pgraph_gl_surface_invalidate(NV2AState *d, SurfaceBinding *e); diff --git a/hw/xbox/nv2a/pgraph/gl/surface.c b/hw/xbox/nv2a/pgraph/gl/surface.c index 1adfbd9ac4b..b4d079d32c3 100644 --- a/hw/xbox/nv2a/pgraph/gl/surface.c +++ b/hw/xbox/nv2a/pgraph/gl/surface.c @@ -628,6 +628,24 @@ void pgraph_gl_surface_download_if_dirty(NV2AState *d, } } +void pgraph_gl_download_surfaces_in_range_if_dirty(NV2AState *d, hwaddr start, hwaddr size) +{ + PGRAPHState *pg = &d->pgraph; + PGRAPHGLState *r = pg->gl_renderer_state; + + SurfaceBinding *surface; + + hwaddr end = start + size - 1; + + QTAILQ_FOREACH(surface, &r->surfaces, entry) { + hwaddr surf_end = surface->vram_addr + surface->size - 1; + bool overlapping = !(surface->vram_addr >= end || start >= surf_end); + if (overlapping) { + pgraph_gl_surface_download_if_dirty(d, surface); + } + } +} + static void bind_current_surface(NV2AState *d) { PGRAPHState *pg = &d->pgraph; diff --git a/hw/xbox/nv2a/pgraph/gl/texture.c b/hw/xbox/nv2a/pgraph/gl/texture.c index eb0e4199fed..042190b4d75 100644 --- a/hw/xbox/nv2a/pgraph/gl/texture.c +++ b/hw/xbox/nv2a/pgraph/gl/texture.c @@ -302,15 +302,8 @@ void pgraph_gl_bind_textures(NV2AState *d) // FIXME: Restructure to support rendering surfaces to cubemap faces // Writeback any surfaces which this texture may index - hwaddr tex_vram_end = texture_vram_offset + length - 1; - QTAILQ_FOREACH(surface, &r->surfaces, entry) { - hwaddr surf_vram_end = surface->vram_addr + surface->size - 1; - bool overlapping = !(surface->vram_addr >= tex_vram_end - || texture_vram_offset >= surf_vram_end); - if (overlapping) { - pgraph_gl_surface_download_if_dirty(d, surface); - } - } + pgraph_gl_download_surfaces_in_range_if_dirty( + d, texture_vram_offset, length); } TextureKey key; diff --git a/hw/xbox/nv2a/pgraph/null/renderer.c b/hw/xbox/nv2a/pgraph/null/renderer.c index 8b34efc5d17..d0867d530c6 100644 --- a/hw/xbox/nv2a/pgraph/null/renderer.c +++ b/hw/xbox/nv2a/pgraph/null/renderer.c @@ -111,34 +111,61 @@ static void pgraph_null_surface_update(NV2AState *d, bool upload, { } +static bool pgraph_null_have_overlapping_dirty_surfaces(NV2AState *d, + hwaddr start, + hwaddr size) +{ + return false; +} + +static void pgraph_null_download_overlapping_surfaces_trigger(NV2AState *d, + hwaddr start, + hwaddr size) +{ +} + +static void pgraph_null_download_overlapping_surfaces_wait(NV2AState *d) +{ +} + static void pgraph_null_init(NV2AState *d, Error **errp) { PGRAPHState *pg = &d->pgraph; pg->null_renderer_state = NULL; } -static PGRAPHRenderer pgraph_null_renderer = { - .type = CONFIG_DISPLAY_RENDERER_NULL, - .name = "Null", - .ops = { - .init = pgraph_null_init, - .clear_report_value = pgraph_null_clear_report_value, - .clear_surface = pgraph_null_clear_surface, - .draw_begin = pgraph_null_draw_begin, - .draw_end = pgraph_null_draw_end, - .flip_stall = pgraph_null_flip_stall, - .flush_draw = pgraph_null_flush_draw, - .get_report = pgraph_null_get_report, - .image_blit = pgraph_null_image_blit, - .pre_savevm_trigger = pgraph_null_pre_savevm_trigger, - .pre_savevm_wait = pgraph_null_pre_savevm_wait, - .pre_shutdown_trigger = pgraph_null_pre_shutdown_trigger, - .pre_shutdown_wait = pgraph_null_pre_shutdown_wait, - .process_pending = pgraph_null_process_pending, - .process_pending_reports = pgraph_null_process_pending_reports, - .surface_update = pgraph_null_surface_update, - } -}; +static PGRAPHRenderer + pgraph_null_renderer = { .type = CONFIG_DISPLAY_RENDERER_NULL, + .name = "Null", + .ops = { + .init = pgraph_null_init, + .clear_report_value = + pgraph_null_clear_report_value, + .clear_surface = pgraph_null_clear_surface, + .draw_begin = pgraph_null_draw_begin, + .draw_end = pgraph_null_draw_end, + .flip_stall = pgraph_null_flip_stall, + .flush_draw = pgraph_null_flush_draw, + .get_report = pgraph_null_get_report, + .image_blit = pgraph_null_image_blit, + .pre_savevm_trigger = + pgraph_null_pre_savevm_trigger, + .pre_savevm_wait = pgraph_null_pre_savevm_wait, + .pre_shutdown_trigger = + pgraph_null_pre_shutdown_trigger, + .pre_shutdown_wait = + pgraph_null_pre_shutdown_wait, + .process_pending = pgraph_null_process_pending, + .process_pending_reports = + pgraph_null_process_pending_reports, + .surface_update = pgraph_null_surface_update, + .have_overlapping_dirty_surfaces = + pgraph_null_have_overlapping_dirty_surfaces, + .download_overlapping_surfaces_trigger = + pgraph_null_download_overlapping_surfaces_trigger, + .download_overlapping_surfaces_wait = + pgraph_null_download_overlapping_surfaces_wait, + } }; static void __attribute__((constructor)) register_renderer(void) { diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index cea424f8105..41e9f437b6d 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -354,6 +354,55 @@ void pgraph_destroy(PGRAPHState *pg) qemu_mutex_destroy(&pg->lock); } +static void pgraph_download_vga_surfaces(NV2AState *d) +{ + VGADisplayParams vga_display_params; + d->vga.get_params(&d->vga, &vga_display_params); + + hwaddr framebuffer_start = d->pcrtc.start + vga_display_params.line_offset; + if (!framebuffer_start) { + // Early exit during guest startup. + return; + } + + PGRAPHState *pg = &d->pgraph; + { + DisplaySurface *display_surface = qemu_console_surface(d->vga.con); + hwaddr framebuffer_size = + surface_height(display_surface) * surface_stride(display_surface); + + if (!pg->renderer->ops.have_overlapping_dirty_surfaces( + d, framebuffer_start, framebuffer_size)) { + return; + } + + trace_nv2a_pgraph_surface_download_vga_overlapping(framebuffer_start, + framebuffer_size); + bql_lock(); + qemu_mutex_lock(&d->pfifo.lock); + qatomic_set(&d->pfifo.halt, true); + + pg->renderer->ops.download_overlapping_surfaces_trigger( + d, framebuffer_start, framebuffer_size); + + pfifo_kick(d); + qemu_mutex_unlock(&d->pfifo.lock); + + bql_unlock(); + } + + pg->renderer->ops.download_overlapping_surfaces_wait(d); + + { + bql_lock(); + qemu_mutex_lock(&d->pfifo.lock); + qatomic_set(&d->pfifo.halt, false); + pfifo_kick(d); + qemu_mutex_unlock(&d->pfifo.lock); + bql_unlock(); + } +} + int nv2a_get_framebuffer_surface(void) { NV2AState *d = g_nv2a; @@ -363,9 +412,21 @@ int nv2a_get_framebuffer_surface(void) qemu_mutex_lock(&pg->renderer_lock); assert(!pg->framebuffer_in_use); pg->framebuffer_in_use = true; + + // Presumably in the case that there is no get_framebuffer_surface it's + // impossible for there to be an overlapping modified GL/VK surface and we + // could just bail early? if (pg->renderer->ops.get_framebuffer_surface) { s = pg->renderer->ops.get_framebuffer_surface(d); } + + if (!s) { + // If there is no framebuffer surface, it is possible that there are + // some GL surfaces that overlap the VGA region. Such surfaces must be + // downloaded before the default VGA texture is created. + pgraph_download_vga_surfaces(d); + } + qemu_mutex_unlock(&pg->renderer_lock); return s; diff --git a/hw/xbox/nv2a/pgraph/pgraph.h b/hw/xbox/nv2a/pgraph/pgraph.h index 49f941d450a..eea4aa6b0f8 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.h +++ b/hw/xbox/nv2a/pgraph/pgraph.h @@ -119,6 +119,12 @@ typedef struct PGRAPHRenderer { void (*process_pending_reports)(NV2AState *d); void (*surface_flush)(NV2AState *d); void (*surface_update)(NV2AState *d, bool upload, bool color_write, bool zeta_write); + bool (*have_overlapping_dirty_surfaces)(NV2AState *d, hwaddr start, + hwaddr size); + void (*download_overlapping_surfaces_trigger)(NV2AState *d, + hwaddr start, + hwaddr size); + void (*download_overlapping_surfaces_wait)(NV2AState *d); void (*set_surface_scale_factor)(NV2AState *d, unsigned int scale); unsigned int (*get_surface_scale_factor)(NV2AState *d); int (*get_framebuffer_surface)(NV2AState *d); diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.c b/hw/xbox/nv2a/pgraph/vk/renderer.c index 3dbc724b951..c3696f70436 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.c +++ b/hw/xbox/nv2a/pgraph/vk/renderer.c @@ -117,9 +117,9 @@ static void pgraph_vk_process_pending(NV2AState *d) if (qatomic_read(&r->downloads_pending) || qatomic_read(&r->download_dirty_surfaces_pending) || + qatomic_read(&r->download_dirty_surfaces_in_range_pending) || qatomic_read(&d->pgraph.sync_pending) || - qatomic_read(&d->pgraph.flush_pending) - ) { + qatomic_read(&d->pgraph.flush_pending)) { qemu_mutex_unlock(&d->pfifo.lock); qemu_mutex_lock(&d->pgraph.lock); if (qatomic_read(&r->downloads_pending)) { @@ -128,6 +128,13 @@ static void pgraph_vk_process_pending(NV2AState *d) if (qatomic_read(&r->download_dirty_surfaces_pending)) { pgraph_vk_download_dirty_surfaces(d); } + if (qatomic_read(&r->download_dirty_surfaces_in_range_pending)) { + pgraph_vk_download_surfaces_in_range_if_dirty( + &d->pgraph, r->download_dirty_surfaces_in_range_start, + r->download_dirty_surfaces_in_range_size); + qatomic_set(&r->download_dirty_surfaces_in_range_pending, false); + qemu_event_set(&r->dirty_surfaces_download_complete); + } if (qatomic_read(&d->pgraph.sync_pending)) { pgraph_vk_sync(d); } @@ -164,7 +171,7 @@ static void pgraph_vk_pre_shutdown_trigger(NV2AState *d) static void pgraph_vk_pre_shutdown_wait(NV2AState *d) { - // qemu_event_wait(&d->pgraph.vk_renderer_state->shader_cache_writeback_complete); + // qemu_event_wait(&d->pgraph.vk_renderer_state->shader_cache_writeback_complete); } static int pgraph_vk_get_framebuffer_surface(NV2AState *d) @@ -202,33 +209,84 @@ static int pgraph_vk_get_framebuffer_surface(NV2AState *d) #endif } -static PGRAPHRenderer pgraph_vk_renderer = { - .type = CONFIG_DISPLAY_RENDERER_VULKAN, - .name = "Vulkan", - .ops = { - .init = pgraph_vk_init, - .early_context_init = early_context_init, - .finalize = pgraph_vk_finalize, - .clear_report_value = pgraph_vk_clear_report_value, - .clear_surface = pgraph_vk_clear_surface, - .draw_begin = pgraph_vk_draw_begin, - .draw_end = pgraph_vk_draw_end, - .flip_stall = pgraph_vk_flip_stall, - .flush_draw = pgraph_vk_flush_draw, - .get_report = pgraph_vk_get_report, - .image_blit = pgraph_vk_image_blit, - .pre_savevm_trigger = pgraph_vk_pre_savevm_trigger, - .pre_savevm_wait = pgraph_vk_pre_savevm_wait, - .pre_shutdown_trigger = pgraph_vk_pre_shutdown_trigger, - .pre_shutdown_wait = pgraph_vk_pre_shutdown_wait, - .process_pending = pgraph_vk_process_pending, - .process_pending_reports = pgraph_vk_process_pending_reports, - .surface_update = pgraph_vk_surface_update, - .set_surface_scale_factor = pgraph_vk_set_surface_scale_factor, - .get_surface_scale_factor = pgraph_vk_get_surface_scale_factor, - .get_framebuffer_surface = pgraph_vk_get_framebuffer_surface, +static bool pgraph_vk_have_overlapping_dirty_surfaces(NV2AState *d, + hwaddr start, hwaddr size) +{ + PGRAPHState *pg = &d->pgraph; + PGRAPHVkState *r = pg->vk_renderer_state; + SurfaceBinding *surface; + + hwaddr end = start + size - 1; + + QTAILQ_FOREACH (surface, &r->surfaces, entry) { + hwaddr surf_end = surface->vram_addr + surface->size - 1; + bool overlapping = !(surface->vram_addr >= end || start >= surf_end); + if (overlapping && surface->draw_dirty) { + return true; + } } -}; + + return false; +} + +static void pgraph_vk_download_overlapping_surfaces_trigger(NV2AState *d, + hwaddr start, + hwaddr size) +{ + PGRAPHState *pg = &d->pgraph; + PGRAPHVkState *r = pg->vk_renderer_state; + + r->download_dirty_surfaces_in_range_start = start; + r->download_dirty_surfaces_in_range_size = size; + qemu_event_reset(&r->dirty_surfaces_download_complete); + qatomic_set(&r->download_dirty_surfaces_in_range_pending, true); +} + +static void pgraph_vk_download_overlapping_surfaces_wait(NV2AState *d) +{ + qemu_event_wait( + &d->pgraph.vk_renderer_state->dirty_surfaces_download_complete); +} + +static PGRAPHRenderer + pgraph_vk_renderer = { .type = CONFIG_DISPLAY_RENDERER_VULKAN, + .name = "Vulkan", + .ops = { + .init = pgraph_vk_init, + .early_context_init = early_context_init, + .finalize = pgraph_vk_finalize, + .clear_report_value = + pgraph_vk_clear_report_value, + .clear_surface = pgraph_vk_clear_surface, + .draw_begin = pgraph_vk_draw_begin, + .draw_end = pgraph_vk_draw_end, + .flip_stall = pgraph_vk_flip_stall, + .flush_draw = pgraph_vk_flush_draw, + .get_report = pgraph_vk_get_report, + .image_blit = pgraph_vk_image_blit, + .pre_savevm_trigger = + pgraph_vk_pre_savevm_trigger, + .pre_savevm_wait = pgraph_vk_pre_savevm_wait, + .pre_shutdown_trigger = + pgraph_vk_pre_shutdown_trigger, + .pre_shutdown_wait = pgraph_vk_pre_shutdown_wait, + .process_pending = pgraph_vk_process_pending, + .process_pending_reports = + pgraph_vk_process_pending_reports, + .surface_update = pgraph_vk_surface_update, + .have_overlapping_dirty_surfaces = + pgraph_vk_have_overlapping_dirty_surfaces, + .download_overlapping_surfaces_trigger = + pgraph_vk_download_overlapping_surfaces_trigger, + .download_overlapping_surfaces_wait = + pgraph_vk_download_overlapping_surfaces_wait, + .set_surface_scale_factor = + pgraph_vk_set_surface_scale_factor, + .get_surface_scale_factor = + pgraph_vk_get_surface_scale_factor, + .get_framebuffer_surface = + pgraph_vk_get_framebuffer_surface, + } }; static void __attribute__((constructor)) register_renderer(void) { diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h index d68e2c4207d..42011b527a6 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.h +++ b/hw/xbox/nv2a/pgraph/vk/renderer.h @@ -390,7 +390,11 @@ typedef struct PGRAPHVkState { SurfaceBinding *color_binding, *zeta_binding; bool downloads_pending; QemuEvent downloads_complete; + bool download_dirty_surfaces_pending; + bool download_dirty_surfaces_in_range_pending; + hwaddr download_dirty_surfaces_in_range_start; + hwaddr download_dirty_surfaces_in_range_size; QemuEvent dirty_surfaces_download_complete; // common Lru texture_cache; diff --git a/hw/xbox/nv2a/trace-events b/hw/xbox/nv2a/trace-events index 9cc8fef11eb..78a267c4ec5 100644 --- a/hw/xbox/nv2a/trace-events +++ b/hw/xbox/nv2a/trace-events @@ -30,4 +30,4 @@ nv2a_pgraph_surface_texture_compat_failed(int32_t surface_fmt, int32_t texture_f nv2a_pgraph_surface_upload(const char *binding, const char *layout, uint32_t addr, uint32_t width, uint32_t height, uint32_t pitch, uint32_t bytes_per_pixel) "[RAM->GPU] %s (%s) surface @ 0x%08" PRIx32 " (w=%d,h=%d,p=%d,bpp=%d)" nv2a_pgraph_flip_stall(void) "" nv2a_pgraph_flip_increment_write(uint32_t write3d_old, uint32_t write3d_new) "0x%"PRIx32" -> 0x%"PRIx32 - +nv2a_pgraph_surface_download_vga_overlapping(uint32_t addr, uint32_t length) "Downloading surfaces overlapping VGA @ 0x%08" PRIx32 " (%d)"