@@ -123,6 +123,7 @@ static void pgraph_gl_process_pending(NV2AState *d)
123123
124124 if (qatomic_read (& r -> downloads_pending ) ||
125125 qatomic_read (& r -> download_dirty_surfaces_pending ) ||
126+ qatomic_read (& r -> download_dirty_surfaces_in_range_pending ) ||
126127 qatomic_read (& d -> pgraph .sync_pending ) ||
127128 qatomic_read (& d -> pgraph .flush_pending ) ||
128129 qatomic_read (& r -> shader_cache_writeback_pending )) {
@@ -134,6 +135,13 @@ static void pgraph_gl_process_pending(NV2AState *d)
134135 if (qatomic_read (& r -> download_dirty_surfaces_pending )) {
135136 pgraph_gl_download_dirty_surfaces (d );
136137 }
138+ if (qatomic_read (& r -> download_dirty_surfaces_in_range_pending )) {
139+ pgraph_gl_download_surfaces_in_range_if_dirty (
140+ d , r -> download_dirty_surfaces_in_range_start ,
141+ r -> download_dirty_surfaces_in_range_size );
142+ qatomic_set (& r -> download_dirty_surfaces_in_range_pending , false);
143+ qemu_event_set (& r -> dirty_surfaces_download_complete );
144+ }
137145 if (qatomic_read (& d -> pgraph .sync_pending )) {
138146 pgraph_gl_sync (d );
139147 }
@@ -165,6 +173,46 @@ static void pgraph_gl_pre_savevm_wait(NV2AState *d)
165173 qemu_event_wait (& r -> dirty_surfaces_download_complete );
166174}
167175
176+ static bool pgraph_gl_have_overlapping_dirty_surfaces (NV2AState * d ,
177+ hwaddr start , hwaddr size )
178+ {
179+ PGRAPHState * pg = & d -> pgraph ;
180+ PGRAPHGLState * r = pg -> gl_renderer_state ;
181+
182+ SurfaceBinding * surface ;
183+
184+ hwaddr end = start + size - 1 ;
185+
186+ QTAILQ_FOREACH (surface , & r -> surfaces , entry ) {
187+ hwaddr surf_end = surface -> vram_addr + surface -> size - 1 ;
188+ bool overlapping = !(surface -> vram_addr >= end || start >= surf_end );
189+ if (overlapping && surface -> draw_dirty ) {
190+ return true;
191+ }
192+ }
193+
194+ return false;
195+ }
196+
197+ static void pgraph_gl_download_overlapping_surfaces_trigger (NV2AState * d ,
198+ hwaddr start ,
199+ hwaddr size )
200+ {
201+ PGRAPHState * pg = & d -> pgraph ;
202+ PGRAPHGLState * r = pg -> gl_renderer_state ;
203+
204+ r -> download_dirty_surfaces_in_range_start = start ;
205+ r -> download_dirty_surfaces_in_range_size = size ;
206+ qemu_event_reset (& r -> dirty_surfaces_download_complete );
207+ qatomic_set (& r -> download_dirty_surfaces_in_range_pending , true);
208+ }
209+
210+ static void pgraph_gl_download_overlapping_surfaces_wait (NV2AState * d )
211+ {
212+ qemu_event_wait (
213+ & d -> pgraph .gl_renderer_state -> dirty_surfaces_download_complete );
214+ }
215+
168216static void pgraph_gl_pre_shutdown_trigger (NV2AState * d )
169217{
170218 PGRAPHState * pg = & d -> pgraph ;
@@ -182,34 +230,47 @@ static void pgraph_gl_pre_shutdown_wait(NV2AState *d)
182230 qemu_event_wait (& r -> shader_cache_writeback_complete );
183231}
184232
185- static PGRAPHRenderer pgraph_gl_renderer = {
186- .type = CONFIG_DISPLAY_RENDERER_OPENGL ,
187- .name = "OpenGL" ,
188- .ops = {
189- .init = pgraph_gl_init ,
190- .early_context_init = early_context_init ,
191- .finalize = pgraph_gl_finalize ,
192- .clear_report_value = pgraph_gl_clear_report_value ,
193- .clear_surface = pgraph_gl_clear_surface ,
194- .draw_begin = pgraph_gl_draw_begin ,
195- .draw_end = pgraph_gl_draw_end ,
196- .flip_stall = pgraph_gl_flip_stall ,
197- .flush_draw = pgraph_gl_flush_draw ,
198- .get_report = pgraph_gl_get_report ,
199- .image_blit = pgraph_gl_image_blit ,
200- .pre_savevm_trigger = pgraph_gl_pre_savevm_trigger ,
201- .pre_savevm_wait = pgraph_gl_pre_savevm_wait ,
202- .pre_shutdown_trigger = pgraph_gl_pre_shutdown_trigger ,
203- .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait ,
204- .process_pending = pgraph_gl_process_pending ,
205- .process_pending_reports = pgraph_gl_process_pending_reports ,
206- .surface_update = pgraph_gl_surface_update ,
207- .set_surface_scale_factor = pgraph_gl_set_surface_scale_factor ,
208- .get_surface_scale_factor = pgraph_gl_get_surface_scale_factor ,
209- .get_framebuffer_surface = pgraph_gl_get_framebuffer_surface ,
210- .get_gpu_properties = pgraph_gl_get_gpu_properties ,
211- }
212- };
233+ static PGRAPHRenderer
234+ pgraph_gl_renderer = { .type = CONFIG_DISPLAY_RENDERER_OPENGL ,
235+ .name = "OpenGL" ,
236+ .ops = {
237+ .init = pgraph_gl_init ,
238+ .early_context_init = early_context_init ,
239+ .finalize = pgraph_gl_finalize ,
240+ .clear_report_value =
241+ pgraph_gl_clear_report_value ,
242+ .clear_surface = pgraph_gl_clear_surface ,
243+ .draw_begin = pgraph_gl_draw_begin ,
244+ .draw_end = pgraph_gl_draw_end ,
245+ .flip_stall = pgraph_gl_flip_stall ,
246+ .flush_draw = pgraph_gl_flush_draw ,
247+ .get_report = pgraph_gl_get_report ,
248+ .image_blit = pgraph_gl_image_blit ,
249+ .pre_savevm_trigger =
250+ pgraph_gl_pre_savevm_trigger ,
251+ .pre_savevm_wait = pgraph_gl_pre_savevm_wait ,
252+ .pre_shutdown_trigger =
253+ pgraph_gl_pre_shutdown_trigger ,
254+ .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait ,
255+ .process_pending = pgraph_gl_process_pending ,
256+ .process_pending_reports =
257+ pgraph_gl_process_pending_reports ,
258+ .surface_update = pgraph_gl_surface_update ,
259+ .have_overlapping_dirty_surfaces =
260+ pgraph_gl_have_overlapping_dirty_surfaces ,
261+ .download_overlapping_surfaces_trigger =
262+ pgraph_gl_download_overlapping_surfaces_trigger ,
263+ .download_overlapping_surfaces_wait =
264+ pgraph_gl_download_overlapping_surfaces_wait ,
265+ .set_surface_scale_factor =
266+ pgraph_gl_set_surface_scale_factor ,
267+ .get_surface_scale_factor =
268+ pgraph_gl_get_surface_scale_factor ,
269+ .get_framebuffer_surface =
270+ pgraph_gl_get_framebuffer_surface ,
271+ .get_gpu_properties =
272+ pgraph_gl_get_gpu_properties ,
273+ } };
213274
214275static void __attribute__((constructor )) register_renderer (void )
215276{
0 commit comments