@@ -114,6 +114,7 @@ static void pgraph_gl_process_pending(NV2AState *d)
114114
115115 if (qatomic_read (& r -> downloads_pending ) ||
116116 qatomic_read (& r -> download_dirty_surfaces_pending ) ||
117+ qatomic_read (& r -> download_dirty_surfaces_in_range_pending ) ||
117118 qatomic_read (& d -> pgraph .sync_pending ) ||
118119 qatomic_read (& d -> pgraph .flush_pending ) ||
119120 qatomic_read (& r -> shader_cache_writeback_pending )) {
@@ -125,6 +126,13 @@ static void pgraph_gl_process_pending(NV2AState *d)
125126 if (qatomic_read (& r -> download_dirty_surfaces_pending )) {
126127 pgraph_gl_download_dirty_surfaces (d );
127128 }
129+ if (qatomic_read (& r -> download_dirty_surfaces_in_range_pending )) {
130+ pgraph_gl_download_surfaces_in_range_if_dirty (
131+ d , r -> download_dirty_surfaces_in_range_start ,
132+ r -> download_dirty_surfaces_in_range_size );
133+ qatomic_set (& r -> download_dirty_surfaces_in_range_pending , false);
134+ qemu_event_set (& r -> dirty_surfaces_download_complete );
135+ }
128136 if (qatomic_read (& d -> pgraph .sync_pending )) {
129137 pgraph_gl_sync (d );
130138 }
@@ -156,6 +164,46 @@ static void pgraph_gl_pre_savevm_wait(NV2AState *d)
156164 qemu_event_wait (& r -> dirty_surfaces_download_complete );
157165}
158166
167+ static bool pgraph_gl_have_overlapping_dirty_surfaces (NV2AState * d ,
168+ hwaddr start , hwaddr size )
169+ {
170+ PGRAPHState * pg = & d -> pgraph ;
171+ PGRAPHGLState * r = pg -> gl_renderer_state ;
172+
173+ SurfaceBinding * surface ;
174+
175+ hwaddr end = start + size - 1 ;
176+
177+ QTAILQ_FOREACH (surface , & r -> surfaces , entry ) {
178+ hwaddr surf_end = surface -> vram_addr + surface -> size - 1 ;
179+ bool overlapping = !(surface -> vram_addr >= end || start >= surf_end );
180+ if (overlapping && surface -> draw_dirty ) {
181+ return true;
182+ }
183+ }
184+
185+ return false;
186+ }
187+
188+ static void pgraph_gl_download_overlapping_surfaces_trigger (NV2AState * d ,
189+ hwaddr start ,
190+ hwaddr size )
191+ {
192+ PGRAPHState * pg = & d -> pgraph ;
193+ PGRAPHGLState * r = pg -> gl_renderer_state ;
194+
195+ r -> download_dirty_surfaces_in_range_start = start ;
196+ r -> download_dirty_surfaces_in_range_size = size ;
197+ qemu_event_reset (& r -> dirty_surfaces_download_complete );
198+ qatomic_set (& r -> download_dirty_surfaces_in_range_pending , true);
199+ }
200+
201+ static void pgraph_gl_download_overlapping_surfaces_wait (NV2AState * d )
202+ {
203+ qemu_event_wait (
204+ & d -> pgraph .gl_renderer_state -> dirty_surfaces_download_complete );
205+ }
206+
159207static void pgraph_gl_pre_shutdown_trigger (NV2AState * d )
160208{
161209 PGRAPHState * pg = & d -> pgraph ;
@@ -173,33 +221,45 @@ static void pgraph_gl_pre_shutdown_wait(NV2AState *d)
173221 qemu_event_wait (& r -> shader_cache_writeback_complete );
174222}
175223
176- static PGRAPHRenderer pgraph_gl_renderer = {
177- .type = CONFIG_DISPLAY_RENDERER_OPENGL ,
178- .name = "OpenGL" ,
179- .ops = {
180- .init = pgraph_gl_init ,
181- .early_context_init = early_context_init ,
182- .finalize = pgraph_gl_finalize ,
183- .clear_report_value = pgraph_gl_clear_report_value ,
184- .clear_surface = pgraph_gl_clear_surface ,
185- .draw_begin = pgraph_gl_draw_begin ,
186- .draw_end = pgraph_gl_draw_end ,
187- .flip_stall = pgraph_gl_flip_stall ,
188- .flush_draw = pgraph_gl_flush_draw ,
189- .get_report = pgraph_gl_get_report ,
190- .image_blit = pgraph_gl_image_blit ,
191- .pre_savevm_trigger = pgraph_gl_pre_savevm_trigger ,
192- .pre_savevm_wait = pgraph_gl_pre_savevm_wait ,
193- .pre_shutdown_trigger = pgraph_gl_pre_shutdown_trigger ,
194- .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait ,
195- .process_pending = pgraph_gl_process_pending ,
196- .process_pending_reports = pgraph_gl_process_pending_reports ,
197- .surface_update = pgraph_gl_surface_update ,
198- .set_surface_scale_factor = pgraph_gl_set_surface_scale_factor ,
199- .get_surface_scale_factor = pgraph_gl_get_surface_scale_factor ,
200- .get_framebuffer_surface = pgraph_gl_get_framebuffer_surface ,
201- }
202- };
224+ static PGRAPHRenderer
225+ pgraph_gl_renderer = { .type = CONFIG_DISPLAY_RENDERER_OPENGL ,
226+ .name = "OpenGL" ,
227+ .ops = {
228+ .init = pgraph_gl_init ,
229+ .early_context_init = early_context_init ,
230+ .finalize = pgraph_gl_finalize ,
231+ .clear_report_value =
232+ pgraph_gl_clear_report_value ,
233+ .clear_surface = pgraph_gl_clear_surface ,
234+ .draw_begin = pgraph_gl_draw_begin ,
235+ .draw_end = pgraph_gl_draw_end ,
236+ .flip_stall = pgraph_gl_flip_stall ,
237+ .flush_draw = pgraph_gl_flush_draw ,
238+ .get_report = pgraph_gl_get_report ,
239+ .image_blit = pgraph_gl_image_blit ,
240+ .pre_savevm_trigger =
241+ pgraph_gl_pre_savevm_trigger ,
242+ .pre_savevm_wait = pgraph_gl_pre_savevm_wait ,
243+ .pre_shutdown_trigger =
244+ pgraph_gl_pre_shutdown_trigger ,
245+ .pre_shutdown_wait = pgraph_gl_pre_shutdown_wait ,
246+ .process_pending = pgraph_gl_process_pending ,
247+ .process_pending_reports =
248+ pgraph_gl_process_pending_reports ,
249+ .surface_update = pgraph_gl_surface_update ,
250+ .have_overlapping_dirty_surfaces =
251+ pgraph_gl_have_overlapping_dirty_surfaces ,
252+ .download_overlapping_surfaces_trigger =
253+ pgraph_gl_download_overlapping_surfaces_trigger ,
254+ .download_overlapping_surfaces_wait =
255+ pgraph_gl_download_overlapping_surfaces_wait ,
256+ .set_surface_scale_factor =
257+ pgraph_gl_set_surface_scale_factor ,
258+ .get_surface_scale_factor =
259+ pgraph_gl_get_surface_scale_factor ,
260+ .get_framebuffer_surface =
261+ pgraph_gl_get_framebuffer_surface ,
262+ } };
203263
204264static void __attribute__((constructor )) register_renderer (void )
205265{
0 commit comments