mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 00:50:42 -05:00
7adbb58736
commit 0165cb6974
changed
mutter to release committed shm buffers as soon as they were
uploaded to the GPU.
It also inadvertently changed mutter to prematurely
release EGL buffers (which never get copied, but get used
directly).
This commit corrects that mistake.
https://bugzilla.gnome.org/show_bug.cgi?id=761312
182 lines
4.8 KiB
C
182 lines
4.8 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2014 Endless Mobile
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program 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
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*
|
|
* Written by:
|
|
* Jasper St. Pierre <jstpierre@mecheye.net>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "meta-wayland-buffer.h"
|
|
|
|
#include <clutter/clutter.h>
|
|
#include <cogl/cogl-wayland-server.h>
|
|
#include <meta/util.h>
|
|
|
|
static void
|
|
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
|
void *data)
|
|
{
|
|
MetaWaylandBuffer *buffer =
|
|
wl_container_of (listener, buffer, destroy_listener);
|
|
|
|
wl_signal_emit (&buffer->destroy_signal, buffer);
|
|
g_slice_free (MetaWaylandBuffer, buffer);
|
|
}
|
|
|
|
void
|
|
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
|
|
{
|
|
buffer->ref_count++;
|
|
}
|
|
|
|
void
|
|
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
|
|
{
|
|
buffer->ref_count--;
|
|
if (buffer->ref_count == 0)
|
|
{
|
|
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
|
|
|
if (buffer->accessible)
|
|
meta_wayland_buffer_release_control (buffer);
|
|
}
|
|
}
|
|
|
|
void
|
|
meta_wayland_buffer_take_control (MetaWaylandBuffer *buffer)
|
|
{
|
|
if (buffer->accessible)
|
|
meta_fatal ("buffer control taken twice");
|
|
|
|
buffer->accessible = TRUE;
|
|
}
|
|
|
|
void
|
|
meta_wayland_buffer_release_control (MetaWaylandBuffer *buffer)
|
|
{
|
|
if (!buffer->accessible)
|
|
meta_fatal ("buffer released when not in control");
|
|
|
|
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
|
buffer->accessible = FALSE;
|
|
}
|
|
|
|
MetaWaylandBuffer *
|
|
meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
|
{
|
|
MetaWaylandBuffer *buffer;
|
|
struct wl_listener *listener;
|
|
|
|
listener =
|
|
wl_resource_get_destroy_listener (resource,
|
|
meta_wayland_buffer_destroy_handler);
|
|
|
|
if (listener)
|
|
{
|
|
buffer = wl_container_of (listener, buffer, destroy_listener);
|
|
}
|
|
else
|
|
{
|
|
buffer = g_slice_new0 (MetaWaylandBuffer);
|
|
|
|
buffer->resource = resource;
|
|
wl_signal_init (&buffer->destroy_signal);
|
|
buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
|
|
wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
CoglTexture *
|
|
meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
|
|
{
|
|
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
CoglError *catch_error = NULL;
|
|
CoglTexture *texture;
|
|
struct wl_shm_buffer *shm_buffer;
|
|
|
|
if (!buffer->accessible)
|
|
meta_warning ("attempted to process damage on uncommitted buffer");
|
|
|
|
if (buffer->texture)
|
|
goto out;
|
|
|
|
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
|
|
|
if (shm_buffer)
|
|
wl_shm_buffer_begin_access (shm_buffer);
|
|
|
|
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
|
buffer->resource,
|
|
&catch_error));
|
|
|
|
if (shm_buffer)
|
|
wl_shm_buffer_end_access (shm_buffer);
|
|
|
|
if (!texture)
|
|
{
|
|
cogl_error_free (catch_error);
|
|
meta_fatal ("Could not import pending buffer, ignoring commit\n");
|
|
}
|
|
|
|
buffer->texture = texture;
|
|
|
|
if (shm_buffer)
|
|
buffer->copied_data = TRUE;
|
|
|
|
out:
|
|
return buffer->texture;
|
|
}
|
|
|
|
void
|
|
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
|
cairo_region_t *region)
|
|
{
|
|
struct wl_shm_buffer *shm_buffer;
|
|
|
|
if (!buffer->accessible)
|
|
meta_warning ("attempted to process damage on uncommitted buffer");
|
|
|
|
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
|
|
|
if (shm_buffer)
|
|
{
|
|
int i, n_rectangles;
|
|
|
|
n_rectangles = cairo_region_num_rectangles (region);
|
|
|
|
wl_shm_buffer_begin_access (shm_buffer);
|
|
|
|
for (i = 0; i < n_rectangles; i++)
|
|
{
|
|
cairo_rectangle_int_t rect;
|
|
cairo_region_get_rectangle (region, i, &rect);
|
|
cogl_wayland_texture_set_region_from_shm_buffer (buffer->texture,
|
|
rect.x, rect.y, rect.width, rect.height,
|
|
shm_buffer,
|
|
rect.x, rect.y, 0, NULL);
|
|
}
|
|
|
|
wl_shm_buffer_end_access (shm_buffer);
|
|
}
|
|
}
|