mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 17:10:40 -05:00
7ddbcd1fd2
d42f1873fc
introduced a semi circular
reference between the CoglFramebuffer, and CoglJournal, where
CoglJournal would keep a reference on the CoglFramebuffer when there
were any entries in the journal log.
To avoid risking leaking these objects indefinitely, when freeing
objects without doing anything that triggered a flush, CoglFramebuffer
had a "filter" on cogl_object_unref() calls, which knew
about under what conditions CoglJournal had a reference to it. When it
could detect that there were only the journal itself holding such a
reference, it'd flush the journal, effectively releasing the reference
the journal held, thus freeing itself, as well as the journal.
When CoglFramebuffer was ported to be implemented using GObject instead
of CoglObject, this "filter" was missed, causing not only awkward but
infrequent leaks, but also situations where we'd flush journals when
only the journal itself held the last reference to the framebuffer,
meaning the journal would free the framebuffer, thus itself, in the
middle of flushing, causing memory corruption and crashes.
A way to detect this, by asserting on CoglObject reference count during
flush, is by adding the `g_assert()` as described below, which will
assert instead cause memory corruption.
void
_cogl_journal_flush (CoglJournal *journal
{
...
_cogl_journal_discard (journal);
+ g_assert (journal->_parent.ref_count > 0);
...
}
Fix this by making CoglFramebuffer the owner of the journal, which it
already was, and remove any circle referencing that was there before, as
it is not needed given that the CoglFramebuffer pointer is guaranteed to
be valid for the lifetime of CoglJournal as the framebuffer is the owner
of the journal.
However, to not miss flushing before tearing down, which is important as
this flushes painting calls to the driver that is important for e.g.
using the result of those journal entries, flush the journal the first
time cogl_framebuffer_dispose() is called, before doing anything else.
This also adds a test case. Without having broken the circular
reference, the test would fail on g_assert_null (offscreen), as it would
have been "leaked" at this point, but the actual memory corruption would
be a result of the `cogl_texture_get_data()` call, which flushes the
framebuffer, and causes the 'mid-flush' destruction of the journal
described above. Note that the texture keeps track of dependent
framebuffers, but it does not hold any references to them.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1474
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1735>
54 lines
1.7 KiB
C
54 lines
1.7 KiB
C
#ifndef COGL_TEST_DECLARATIONS_H
|
|
#define COGL_TEST_DECLARATIONS_H
|
|
|
|
void test_pipeline_user_matrix (void);
|
|
void test_blend_strings (void);
|
|
void test_blend (void);
|
|
void test_premult (void);
|
|
void test_path (void);
|
|
void test_path_clip (void);
|
|
void test_depth_test (void);
|
|
void test_backface_culling (void);
|
|
void test_layer_remove (void);
|
|
void test_sparse_pipeline (void);
|
|
void test_npot_texture (void);
|
|
void test_sub_texture (void);
|
|
void test_pixel_buffer_map (void);
|
|
void test_pixel_buffer_set_data (void);
|
|
void test_pixel_buffer_sub_region (void);
|
|
void test_wrap_modes (void);
|
|
void test_texture_get_set_data (void);
|
|
void test_atlas_migration (void);
|
|
void test_read_texture_formats (void);
|
|
void test_write_texture_formats (void);
|
|
void test_alpha_textures (void);
|
|
void test_primitive (void);
|
|
void test_just_vertex_shader (void);
|
|
void test_pipeline_uniforms (void);
|
|
void test_snippets (void);
|
|
void test_custom_attributes (void);
|
|
void test_offscreen (void);
|
|
void test_journal_unref_flush (void);
|
|
void test_framebuffer_get_bits (void);
|
|
void test_point_size (void);
|
|
void test_point_size_attribute (void);
|
|
void test_point_size_attribute_snippet (void);
|
|
void test_point_sprite (void);
|
|
void test_point_sprite_orientation (void);
|
|
void test_point_sprite_glsl (void);
|
|
void test_alpha_test (void);
|
|
void test_map_buffer_range (void);
|
|
void test_primitive_and_journal (void);
|
|
void test_copy_replace_texture (void);
|
|
void test_pipeline_cache_unrefs_texture (void);
|
|
void test_pipeline_shader_state (void);
|
|
void test_gles2_context (void);
|
|
void test_gles2_context_fbo (void);
|
|
void test_gles2_context_copy_tex_image (void);
|
|
void test_color_hsl (void);
|
|
void test_fence (void);
|
|
void test_texture_no_allocate (void);
|
|
void test_texture_rg (void);
|
|
|
|
#endif /* COGL_TEST_DECLARATIONS_H */
|