mutter/clutter/clutter/clutter-paint-context.c
Georges Basile Stavracas Neto 82b037e74c clutter/paint-context: Allow assigning a ClutterFrame
This is not yet used, but next commits will need to assign a frame
to the paint context whenever painting onscreens.

Assigning a frame to the paint context is a one-way operation, and
treats multiple assignments strictly as a programming error.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2804>
2023-04-07 12:19:23 +02:00

230 lines
6.6 KiB
C

/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-paint-context-private.h"
#include "clutter-frame.h"
struct _ClutterPaintContext
{
grefcount ref_count;
ClutterPaintFlag paint_flags;
GList *framebuffers;
ClutterStageView *view;
ClutterFrame *frame;
cairo_region_t *redraw_clip;
GArray *clip_frusta;
};
G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
clutter_paint_context_ref,
clutter_paint_context_unref)
ClutterPaintContext *
clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip,
GArray *clip_frusta,
ClutterPaintFlag paint_flags)
{
ClutterPaintContext *paint_context;
CoglFramebuffer *framebuffer;
paint_context = g_new0 (ClutterPaintContext, 1);
g_ref_count_init (&paint_context->ref_count);
paint_context->view = view;
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->clip_frusta = g_array_ref (clip_frusta);
paint_context->paint_flags = paint_flags;
framebuffer = clutter_stage_view_get_framebuffer (view);
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
return paint_context;
}
/**
* clutter_paint_context_new_for_framebuffer: (skip)
*/
ClutterPaintContext *
clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags)
{
ClutterPaintContext *paint_context;
paint_context = g_new0 (ClutterPaintContext, 1);
g_ref_count_init (&paint_context->ref_count);
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
return paint_context;
}
ClutterPaintContext *
clutter_paint_context_ref (ClutterPaintContext *paint_context)
{
g_ref_count_inc (&paint_context->ref_count);
return paint_context;
}
static void
clutter_paint_context_dispose (ClutterPaintContext *paint_context)
{
g_list_free_full (paint_context->framebuffers, g_object_unref);
paint_context->framebuffers = NULL;
g_clear_pointer (&paint_context->redraw_clip, cairo_region_destroy);
g_clear_pointer (&paint_context->clip_frusta, g_array_unref);
g_clear_pointer (&paint_context->frame, clutter_frame_unref);
}
void
clutter_paint_context_unref (ClutterPaintContext *paint_context)
{
if (g_ref_count_dec (&paint_context->ref_count))
{
clutter_paint_context_dispose (paint_context);
g_free (paint_context);
}
}
void
clutter_paint_context_destroy (ClutterPaintContext *paint_context)
{
clutter_paint_context_dispose (paint_context);
clutter_paint_context_unref (paint_context);
}
void
clutter_paint_context_push_framebuffer (ClutterPaintContext *paint_context,
CoglFramebuffer *framebuffer)
{
paint_context->framebuffers = g_list_prepend (paint_context->framebuffers,
g_object_ref (framebuffer));
}
void
clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context)
{
g_return_if_fail (paint_context->framebuffers);
g_object_unref (paint_context->framebuffers->data);
paint_context->framebuffers =
g_list_delete_link (paint_context->framebuffers,
paint_context->framebuffers);
}
const cairo_region_t *
clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context)
{
return paint_context->redraw_clip;
}
const GArray *
clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context)
{
return paint_context->clip_frusta;
}
/**
* clutter_paint_context_get_framebuffer:
* @paint_context: The #ClutterPaintContext
*
* Returns: (transfer none): The #CoglFramebuffer used for drawing
*/
CoglFramebuffer *
clutter_paint_context_get_framebuffer (ClutterPaintContext *paint_context)
{
g_return_val_if_fail (paint_context->framebuffers, NULL);
return paint_context->framebuffers->data;
}
CoglFramebuffer *
clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context)
{
return g_list_last (paint_context->framebuffers)->data;
}
/**
* clutter_paint_context_get_stage_view: (skip)
*/
ClutterStageView *
clutter_paint_context_get_stage_view (ClutterPaintContext *paint_context)
{
return paint_context->view;
}
/**
* clutter_paint_context_is_drawing_off_stage: (skip)
*
* Return %TRUE if the paint context is currently drawing off stage.
* This happens if there are any framebuffers pushed, and the base framebuffer
* comes from the stage view.
*/
gboolean
clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context)
{
if (g_list_length (paint_context->framebuffers) > 1)
return TRUE;
return !paint_context->view;
}
/**
* clutter_paint_context_get_paint_flags: (skip)
*/
ClutterPaintFlag
clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context)
{
return paint_context->paint_flags;
}
void
clutter_paint_context_assign_frame (ClutterPaintContext *paint_context,
ClutterFrame *frame)
{
g_assert (paint_context != NULL);
g_assert (paint_context->frame == NULL);
g_assert (frame != NULL);
paint_context->frame = clutter_frame_ref (frame);
}
/**
* clutter_paint_context_get_frame: (skip)
* @paint_context: The #ClutterPaintContext
*
* Retrieves the #ClutterFrame assigned to @paint_context, if any. A frame is
* only assigned when the paint context is created as part of a frame scheduled
* by the frame clock, and won't be assigned e.g. on offscreen paints.
*
* Returns: (transfer none)(nullable): The #ClutterFrame associated with the
* @paint_context, or %NULL
*/
ClutterFrame *
clutter_paint_context_get_frame (ClutterPaintContext *paint_context)
{
return paint_context->frame;
}