1
+ #include " opengl-priv.hpp"
1
2
#include " wayfire/output.hpp"
2
3
#include " wayfire/core.hpp"
3
4
#include " wayfire/output-layout.hpp"
@@ -249,6 +250,100 @@ inline bool is_shutting_down()
249
250
return wf::get_core ().get_current_state () == compositor_state_t ::SHUTDOWN;
250
251
}
251
252
253
+ class output_cloner_t
254
+ {
255
+ wf::wl_listener_wrapper source_commit;
256
+ wf::wl_listener_wrapper destination_frame;
257
+ wf::framebuffer_base_t content;
258
+
259
+ wlr_output *source;
260
+ wlr_output *destination;
261
+
262
+ public:
263
+ output_cloner_t (wlr_output *source, wlr_output *destination)
264
+ {
265
+ this ->source = source;
266
+ this ->destination = destination;
267
+ wlr_output_lock_software_cursors (source, true );
268
+ wlr_output_schedule_frame (destination);
269
+
270
+ source_commit.set_callback ([=] (void *data)
271
+ {
272
+ auto ev = (wlr_output_event_commit*)data;
273
+ if (!(ev->committed & WLR_OUTPUT_STATE_BUFFER))
274
+ {
275
+ // Something else than the output contents changed, nothing to do yet
276
+ return ;
277
+ }
278
+
279
+ int w = ev->buffer ->width ;
280
+ int h = ev->buffer ->height ;
281
+
282
+ OpenGL::render_begin ();
283
+ content.allocate (w, h);
284
+
285
+ // Bind buffer
286
+ auto renderer = get_core ().renderer ;
287
+ wlr_renderer_begin_with_buffer (renderer, ev->buffer );
288
+
289
+ // Store a copy for ourselves
290
+ GL_CALL (glBindFramebuffer (GL_DRAW_FRAMEBUFFER, content.fb ));
291
+ GL_CALL (glBlitFramebuffer (0 , 0 , w, h,
292
+ 0 , 0 , w, h,
293
+ GL_COLOR_BUFFER_BIT, GL_LINEAR));
294
+
295
+ wlr_renderer_end (renderer);
296
+ OpenGL::render_end ();
297
+
298
+ wlr_output_damage_whole (destination);
299
+ wlr_output_schedule_frame (destination);
300
+ });
301
+
302
+ destination_frame.set_callback ([=] (void *data)
303
+ {
304
+ auto renderer = get_core ().renderer ;
305
+ wlr_output_attach_render (destination, NULL );
306
+ wlr_renderer_begin (renderer, destination->width , destination->height );
307
+
308
+ int w = content.viewport_width ;
309
+ int h = content.viewport_height ;
310
+ if ((w > 0 ) && (h > 0 ))
311
+ {
312
+ int current_fb;
313
+ GL_CALL (glGetIntegerv (GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fb));
314
+ OpenGL::bind_output (current_fb);
315
+
316
+ OpenGL::render_begin ();
317
+ GL_CALL (glBindFramebuffer (GL_READ_FRAMEBUFFER, content.fb ));
318
+ GL_CALL (glBlitFramebuffer (0 , 0 , w, h,
319
+ 0 , 0 , destination->width , destination->height ,
320
+ GL_COLOR_BUFFER_BIT, GL_LINEAR));
321
+
322
+ OpenGL::render_end ();
323
+ }
324
+
325
+ wlr_renderer_end (renderer);
326
+ wlr_output_commit (destination);
327
+ });
328
+
329
+ source_commit.connect (&source->events .commit );
330
+ destination_frame.connect (&destination->events .frame );
331
+ }
332
+
333
+ ~output_cloner_t ()
334
+ {
335
+ wlr_output_lock_software_cursors (source, false );
336
+ OpenGL::render_begin ();
337
+ content.release ();
338
+ OpenGL::render_end ();
339
+ }
340
+
341
+ output_cloner_t (const output_cloner_t &) = delete ;
342
+ output_cloner_t (output_cloner_t &&) = delete ;
343
+ output_cloner_t & operator =(const output_cloner_t &) = delete ;
344
+ output_cloner_t & operator =(output_cloner_t &&) = delete ;
345
+ };
346
+
252
347
/* * Represents a single output in the output layout */
253
348
struct output_layout_output_t
254
349
{
@@ -589,64 +684,6 @@ struct output_layout_output_t
589
684
wlr_output_commit (handle);
590
685
}
591
686
592
- /* Mirroring implementation */
593
- wl_listener_wrapper on_mirrored_frame;
594
- wl_listener_wrapper on_frame;
595
- wlr_output *locked_cursors_on = NULL ;
596
-
597
- /* * Render the output using texture as source */
598
- void render_output (wlr_texture *texture)
599
- {
600
- auto renderer = get_core ().renderer ;
601
- wlr_output_attach_render (handle, NULL );
602
- wlr_renderer_begin (renderer, handle->width , handle->height );
603
-
604
- wf::texture_t tex{texture};
605
- OpenGL::render_transformed_texture (tex, {-1 , -1 , 2 , 2 });
606
-
607
- wlr_renderer_end (renderer);
608
- wlr_output_commit (handle);
609
- }
610
-
611
- /* Load output contents and render them */
612
- wlr_buffer *source_back_buffer = NULL ;
613
-
614
- void handle_frame ()
615
- {
616
- auto wo = get_core ().output_layout ->find_output (
617
- current_state.mirror_from );
618
- if (!wo)
619
- {
620
- LOGE (" Cannot find mirrored output " , current_state.mirror_from ,
621
- " for output " , handle->name );
622
-
623
- return ;
624
- }
625
-
626
- wlr_dmabuf_attributes attributes;
627
- if (source_back_buffer == NULL )
628
- {
629
- LOGE (" Got empty buffer on " , wo->handle ->name );
630
- return ;
631
- }
632
-
633
- if (!wlr_buffer_get_dmabuf (source_back_buffer, &attributes))
634
- {
635
- LOGE (" Failed reading mirrored output contents from " , wo->handle ->name );
636
-
637
- return ;
638
- }
639
-
640
- /* We export the output to mirror from to a dmabuf, then create
641
- * a texture from this and use it to render "our" output */
642
- auto texture = wlr_texture_from_dmabuf (
643
- get_core ().renderer , &attributes);
644
- render_output (texture);
645
-
646
- wlr_texture_destroy (texture);
647
- wlr_dmabuf_attributes_finish (&attributes);
648
- }
649
-
650
687
void set_enabled (bool enabled)
651
688
{
652
689
wlr_output_enable (handle, enabled);
@@ -656,6 +693,7 @@ struct output_layout_output_t
656
693
}
657
694
}
658
695
696
+ std::unique_ptr<output_cloner_t > cloner;
659
697
void setup_mirror ()
660
698
{
661
699
/* Check if we can mirror */
@@ -686,55 +724,12 @@ struct output_layout_output_t
686
724
return ;
687
725
}
688
726
689
- /* Force software cursors on the mirrored from output.
690
- * This ensures that they will be copied when reading pixels
691
- * from the main plane */
692
- wlr_output_lock_software_cursors (wo->handle , true );
693
- locked_cursors_on = wo->handle ;
694
-
695
- wlr_output_schedule_frame (handle);
696
- on_mirrored_frame.set_callback ([=] (void *data)
697
- {
698
- auto ev = (wlr_output_event_commit*)data;
699
-
700
- if (ev->buffer )
701
- {
702
- if (source_back_buffer)
703
- {
704
- wlr_buffer_unlock (source_back_buffer);
705
- }
706
-
707
- source_back_buffer = ev->buffer ;
708
- wlr_buffer_lock (ev->buffer );
709
- }
710
-
711
- /* The mirrored output was repainted, schedule repaint
712
- * for us as well */
713
- wlr_output_damage_whole (handle);
714
- wlr_output_schedule_frame (handle);
715
- });
716
- on_mirrored_frame.connect (&wo->handle ->events .commit );
717
-
718
- on_frame.set_callback ([=] (void *) { handle_frame (); });
719
- on_frame.connect (&handle->events .frame );
727
+ cloner = std::make_unique<output_cloner_t >(wo->handle , this ->handle );
720
728
}
721
729
722
730
void teardown_mirror ()
723
731
{
724
- if (locked_cursors_on)
725
- {
726
- wlr_output_lock_software_cursors (locked_cursors_on, false );
727
- locked_cursors_on = NULL ;
728
- }
729
-
730
- if (source_back_buffer)
731
- {
732
- wlr_buffer_unlock (source_back_buffer);
733
- source_back_buffer = NULL ;
734
- }
735
-
736
- on_mirrored_frame.disconnect ();
737
- on_frame.disconnect ();
732
+ cloner.reset ();
738
733
}
739
734
740
735
wf::dimensions_t get_effective_size ()
0 commit comments