2016-04-05 04:42:56 -07:00
|
|
|
/* Portions of this code have been derived from Weston
|
|
|
|
*
|
|
|
|
* Copyright © 2008-2012 Kristian Høgsberg
|
|
|
|
* Copyright © 2010-2012 Intel Corporation
|
|
|
|
* Copyright © 2010-2011 Benjamin Franzke
|
|
|
|
* Copyright © 2011-2012 Collabora, Ltd.
|
|
|
|
* Copyright © 2010 Red Hat <mjg@redhat.com>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
#include "evas_common_private.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
#include "evas_engine.h"
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
2016-04-08 13:04:33 -07:00
|
|
|
typedef struct _Shm_Pool Shm_Pool;
|
|
|
|
struct _Shm_Pool
|
|
|
|
{
|
|
|
|
struct wl_shm_pool *pool;
|
|
|
|
size_t size, used;
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _Shm_Data Shm_Data;
|
|
|
|
struct _Shm_Data
|
|
|
|
{
|
|
|
|
struct wl_buffer *buffer;
|
|
|
|
Shm_Pool *pool;
|
|
|
|
void *map;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _Shm_Leaf Shm_Leaf;
|
|
|
|
struct _Shm_Leaf
|
|
|
|
{
|
|
|
|
int w, h, busy, age;
|
|
|
|
Shm_Data *data;
|
|
|
|
Shm_Pool *resize_pool;
|
|
|
|
Eina_Bool valid : 1;
|
|
|
|
Eina_Bool reconfigure : 1;
|
|
|
|
Eina_Bool drawn : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _Shm_Surface Shm_Surface;
|
|
|
|
struct _Shm_Surface
|
|
|
|
{
|
|
|
|
struct wl_display *disp;
|
|
|
|
struct wl_shm *shm;
|
|
|
|
struct wl_surface *surface;
|
|
|
|
int w, h;
|
|
|
|
int num_buff;
|
|
|
|
int compositor_version;
|
|
|
|
|
|
|
|
Shm_Leaf leaf[MAX_BUFFERS];
|
|
|
|
Shm_Leaf *current;
|
|
|
|
|
|
|
|
Eina_Bool alpha : 1;
|
|
|
|
};
|
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
static Eina_Bool _shm_leaf_create(Shm_Surface *surface, Shm_Leaf *leaf, int w, int h);
|
|
|
|
static void _shm_leaf_release(Shm_Leaf *leaf);
|
2016-04-04 14:57:30 -07:00
|
|
|
static void _shm_leaf_destroy(Shm_Leaf *leaf);
|
2015-03-17 12:49:09 -07:00
|
|
|
|
|
|
|
static struct wl_shm_pool *
|
|
|
|
_shm_pool_make(struct wl_shm *shm, int size, void **data)
|
|
|
|
{
|
|
|
|
struct wl_shm_pool *pool;
|
|
|
|
int fd = 0;
|
2016-07-26 10:22:36 -07:00
|
|
|
Eina_Tmpstr *fullname;
|
2017-02-08 18:27:48 -08:00
|
|
|
Efl_Vpath_File *file_obj;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
/* check for valid wl_shm */
|
|
|
|
if (!shm) return NULL;
|
|
|
|
|
|
|
|
/* create tmp file name */
|
2017-02-09 15:58:29 -08:00
|
|
|
file_obj = efl_vpath_manager_fetch(EFL_VPATH_MANAGER_CLASS,
|
|
|
|
"(:run:)/evas-wayland_shm-XXXXXX");
|
|
|
|
fd = eina_file_mkstemp(efl_vpath_file_result_get(file_obj), &fullname);
|
|
|
|
efl_del(file_obj);
|
|
|
|
|
2016-07-08 05:46:12 -07:00
|
|
|
if (fd < 0)
|
2015-03-17 12:49:09 -07:00
|
|
|
/* try to create tmp file */
|
2016-07-08 05:46:12 -07:00
|
|
|
/* if ((fd = mkstemp(name)) < 0) */
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
|
|
|
ERR("Could not create temporary file: %m");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-07-26 10:22:36 -07:00
|
|
|
unlink(fullname);
|
|
|
|
eina_tmpstr_del(fullname);
|
2015-03-17 12:49:09 -07:00
|
|
|
|
|
|
|
/* try to truncate file to size */
|
|
|
|
if (ftruncate(fd, size) < 0)
|
|
|
|
{
|
|
|
|
ERR("Could not truncate temporary file: %m");
|
|
|
|
goto fd_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try to mmap the file */
|
|
|
|
*data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
|
|
|
|
if (*data == MAP_FAILED)
|
|
|
|
{
|
|
|
|
ERR("Could not mmap temporary file: %m");
|
|
|
|
goto fd_err;
|
|
|
|
}
|
|
|
|
|
2015-07-27 12:53:02 -07:00
|
|
|
/* NB: Commented out. Used for debugging rendering issues */
|
|
|
|
/* memset(*data, 127, size); */
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
/* create wl_shm_pool using fd */
|
|
|
|
pool = wl_shm_create_pool(shm, fd, size);
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return pool;
|
|
|
|
|
|
|
|
fd_err:
|
|
|
|
close(fd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Shm_Pool *
|
|
|
|
_shm_pool_create(struct wl_shm *shm, size_t size)
|
|
|
|
{
|
|
|
|
Shm_Pool *pool;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
if (!(pool = malloc(sizeof(Shm_Pool)))) return NULL;
|
|
|
|
|
|
|
|
pool->pool = _shm_pool_make(shm, size, &pool->data);
|
|
|
|
if (!pool->pool) goto err;
|
|
|
|
|
|
|
|
pool->size = size;
|
|
|
|
pool->used = 0;
|
|
|
|
|
|
|
|
return pool;
|
|
|
|
|
|
|
|
err:
|
|
|
|
free(pool);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_pool_destroy(Shm_Pool *pool)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
munmap(pool->data, pool->size);
|
|
|
|
wl_shm_pool_destroy(pool->pool);
|
|
|
|
free(pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_shm_pool_allocate(Shm_Pool *pool, size_t size, int *offset)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
if ((pool->used + size) > pool->size)
|
2015-03-19 13:15:11 -07:00
|
|
|
{
|
|
|
|
WRN("Shm Pool Too Small");
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-03-17 12:49:09 -07:00
|
|
|
|
|
|
|
*offset = pool->used;
|
|
|
|
pool->used += size;
|
|
|
|
|
|
|
|
return (char *)pool->data + *offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_pool_reset(Shm_Pool *pool)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
pool->used = 0;
|
|
|
|
}
|
|
|
|
|
2015-08-06 06:52:16 -07:00
|
|
|
/* static void */
|
|
|
|
/* _shm_frame_release(void *data, struct wl_callback *callback, uint32_t timestamp EINA_UNUSED) */
|
|
|
|
/* { */
|
|
|
|
/* Shm_Surface *surf; */
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2015-08-06 06:52:16 -07:00
|
|
|
/* LOGFN(__FILE__, __LINE__, __FUNCTION__); */
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2015-08-06 06:52:16 -07:00
|
|
|
/* if (!(surf = data)) return; */
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2015-08-06 06:52:16 -07:00
|
|
|
/* wl_callback_destroy(callback); */
|
|
|
|
/* } */
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2015-08-06 06:52:16 -07:00
|
|
|
/* static const struct wl_callback_listener _shm_frame_listener = */
|
|
|
|
/* { */
|
|
|
|
/* _shm_frame_release */
|
|
|
|
/* }; */
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
static Shm_Data *
|
|
|
|
_shm_data_create_from_pool(Shm_Pool *pool, int w, int h, Eina_Bool alpha)
|
|
|
|
{
|
|
|
|
Shm_Data *data;
|
|
|
|
int len, offset;
|
2016-07-13 11:43:49 -07:00
|
|
|
uint32_t wl_format = WL_SHM_FORMAT_ARGB8888;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
/* try to malloc space for data */
|
|
|
|
if (!(data = malloc(sizeof(Shm_Data))))
|
|
|
|
{
|
|
|
|
ERR("Could not allocate space for data");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = (w * sizeof(int)) * h;
|
|
|
|
data->pool = NULL;
|
|
|
|
|
|
|
|
if (!(data->map = _shm_pool_allocate(pool, len, &offset)))
|
|
|
|
{
|
|
|
|
ERR("Could not map leaf data");
|
2015-03-19 13:15:11 -07:00
|
|
|
goto err;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (alpha)
|
|
|
|
wl_format = WL_SHM_FORMAT_ARGB8888;
|
|
|
|
|
|
|
|
data->buffer =
|
|
|
|
wl_shm_pool_create_buffer(pool->pool, offset, w, h,
|
|
|
|
(w * sizeof(int)), wl_format);
|
|
|
|
if (!data->buffer)
|
|
|
|
{
|
2016-01-14 10:05:55 -08:00
|
|
|
ERR("Could not create buffer from pool");
|
2015-03-19 13:15:11 -07:00
|
|
|
goto err;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
2015-03-19 13:15:11 -07:00
|
|
|
|
|
|
|
err:
|
|
|
|
free(data);
|
|
|
|
return NULL;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
static void
|
2015-03-17 12:49:09 -07:00
|
|
|
_shm_data_create(Shm_Pool *alt_pool, Shm_Data **ret, Shm_Surface *surface, int w, int h)
|
|
|
|
{
|
|
|
|
Shm_Pool *pool;
|
|
|
|
Shm_Data *data;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
if (ret) *ret = NULL;
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
if (alt_pool)
|
|
|
|
{
|
|
|
|
_shm_pool_reset(alt_pool);
|
|
|
|
if ((data = _shm_data_create_from_pool(alt_pool, w, h, surface->alpha)))
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pool = _shm_pool_create(surface->shm, ((w * sizeof(int)) * h))))
|
|
|
|
{
|
|
|
|
ERR("Could not create shm pool");
|
2015-03-19 13:15:11 -07:00
|
|
|
return;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(data = _shm_data_create_from_pool(pool, w, h, surface->alpha)))
|
|
|
|
{
|
|
|
|
ERR("Could not create data from pool");
|
|
|
|
_shm_pool_destroy(pool);
|
2015-03-19 13:15:11 -07:00
|
|
|
return;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
data->pool = pool;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (ret) *ret = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_data_destroy(Shm_Data *data)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
if (data->buffer) wl_buffer_destroy(data->buffer);
|
|
|
|
if (data->pool) _shm_pool_destroy(data->pool);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_buffer_release(void *data, struct wl_buffer *buffer)
|
|
|
|
{
|
|
|
|
Shm_Surface *surf;
|
|
|
|
Shm_Leaf *leaf;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
surf = data;
|
|
|
|
for (; i < surf->num_buff; i++)
|
|
|
|
{
|
|
|
|
leaf = &surf->leaf[i];
|
|
|
|
if ((leaf->data) && (leaf->data->buffer == buffer))
|
|
|
|
{
|
2015-03-19 13:15:11 -07:00
|
|
|
// DBG("Buffer Released: %d", (int)(leaf - &surf->leaf[0]));
|
2015-03-17 12:49:09 -07:00
|
|
|
leaf->busy = 0;
|
2015-03-19 13:15:11 -07:00
|
|
|
|
|
|
|
if (leaf->reconfigure)
|
|
|
|
{
|
|
|
|
_shm_leaf_release(leaf);
|
|
|
|
_shm_leaf_create(surf, leaf, surf->w, surf->h);
|
|
|
|
}
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_buffer_listener _shm_buffer_listener =
|
|
|
|
{
|
|
|
|
_shm_buffer_release
|
|
|
|
};
|
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_shm_leaf_create(Shm_Surface *surface, Shm_Leaf *leaf, int w, int h)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
_shm_data_create(leaf->resize_pool, &leaf->data, surface, w, h);
|
|
|
|
if (!leaf->data)
|
|
|
|
{
|
|
|
|
CRI("Failed to create leaf data");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
leaf->w = w;
|
|
|
|
leaf->h = h;
|
|
|
|
leaf->valid = EINA_TRUE;
|
2015-07-30 08:45:38 -07:00
|
|
|
leaf->drawn = EINA_FALSE;
|
|
|
|
leaf->age = 0;
|
2015-03-19 13:15:11 -07:00
|
|
|
wl_buffer_add_listener(leaf->data->buffer, &_shm_buffer_listener, surface);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_leaf_release(Shm_Leaf *leaf)
|
|
|
|
{
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
2016-04-04 14:57:30 -07:00
|
|
|
Shm_Pool *resize_pool;
|
2015-03-19 13:15:11 -07:00
|
|
|
|
2016-04-04 14:57:30 -07:00
|
|
|
/* if we delete resize_pool here we blow away the clever optimization
|
|
|
|
* it provides (and end up doing two allocations per resize when we
|
|
|
|
* might have done none at all).
|
|
|
|
*/
|
|
|
|
resize_pool = leaf->resize_pool;
|
2015-03-19 13:15:11 -07:00
|
|
|
if (leaf->data) _shm_data_destroy(leaf->data);
|
|
|
|
memset(leaf, 0, sizeof(*leaf));
|
|
|
|
leaf->valid = EINA_FALSE;
|
2016-04-04 14:57:30 -07:00
|
|
|
leaf->resize_pool = resize_pool;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shm_leaf_destroy(Shm_Leaf *leaf)
|
|
|
|
{
|
|
|
|
_shm_leaf_release(leaf);
|
|
|
|
if (leaf->resize_pool) _shm_pool_destroy(leaf->resize_pool);
|
|
|
|
leaf->resize_pool = NULL;
|
2015-03-19 13:15:11 -07:00
|
|
|
}
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
void
|
2016-04-08 13:11:21 -07:00
|
|
|
_evas_shm_surface_destroy(Surface *surface)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
2016-04-08 13:11:21 -07:00
|
|
|
if (!surface) return;
|
|
|
|
|
|
|
|
for (; i < surface->surf.shm->num_buff; i++)
|
|
|
|
_shm_leaf_destroy(&surface->surf.shm->leaf[i]);
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2016-04-08 13:11:21 -07:00
|
|
|
free(surface->surf.shm);
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-01-05 11:33:19 -08:00
|
|
|
_evas_shm_surface_reconfigure(Surface *s, int w, int h, uint32_t flags, Eina_Bool force)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2016-04-08 13:11:21 -07:00
|
|
|
Shm_Surface *surface;
|
2015-03-17 12:49:09 -07:00
|
|
|
int i = 0, resize = 0;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
2016-04-08 13:11:21 -07:00
|
|
|
surface = s->surf.shm;
|
2016-04-08 12:51:40 -07:00
|
|
|
resize = !!flags;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2017-01-06 06:33:58 -08:00
|
|
|
if (force)
|
|
|
|
{
|
|
|
|
for (; i < surface->num_buff; i++)
|
|
|
|
surface->leaf[i].busy = EINA_FALSE;
|
|
|
|
}
|
2017-01-05 11:33:19 -08:00
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
for (; i < surface->num_buff; i++)
|
|
|
|
{
|
|
|
|
/* don't resize any busy leafs */
|
|
|
|
if (surface->leaf[i].busy)
|
|
|
|
{
|
|
|
|
surface->leaf[i].reconfigure = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear this leaf */
|
|
|
|
_shm_leaf_release(&surface->leaf[i]);
|
|
|
|
}
|
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
surface->w = w;
|
|
|
|
surface->h = h;
|
|
|
|
|
2017-07-21 13:17:55 -07:00
|
|
|
if ((!w) || (!h)) return;
|
2015-03-19 13:15:11 -07:00
|
|
|
for (i = 0; i < surface->num_buff; i++)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
|
|
|
if (surface->leaf[i].busy) continue;
|
2015-03-19 13:15:11 -07:00
|
|
|
|
|
|
|
if ((resize) && (!surface->leaf[i].resize_pool))
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2015-03-19 13:15:11 -07:00
|
|
|
surface->leaf[i].resize_pool =
|
2015-10-01 12:51:21 -07:00
|
|
|
_shm_pool_create(surface->shm, 6 * 1024 * 1024);
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
2015-03-19 13:15:11 -07:00
|
|
|
if (!_shm_leaf_create(surface, &surface->leaf[i], w, h))
|
|
|
|
{
|
|
|
|
CRI("Failed to create leaf data");
|
|
|
|
abort();
|
|
|
|
}
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 12:37:14 -07:00
|
|
|
static Shm_Leaf *
|
|
|
|
_evas_shm_surface_wait(Shm_Surface *surface)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2016-10-26 08:53:49 -07:00
|
|
|
int i = 0, best = -1, best_age = -1;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2016-10-26 08:53:49 -07:00
|
|
|
for (i = 0; i < surface->num_buff; i++)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2016-10-26 08:53:49 -07:00
|
|
|
if (surface->leaf[i].busy) continue;
|
|
|
|
if ((surface->leaf[i].valid) && (surface->leaf[i].age > best_age))
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2016-10-26 08:53:49 -07:00
|
|
|
best = i;
|
|
|
|
best_age = surface->leaf[i].age;
|
2015-07-30 08:45:38 -07:00
|
|
|
}
|
|
|
|
}
|
2016-10-26 08:53:49 -07:00
|
|
|
|
|
|
|
if (best >= 0) return &surface->leaf[best];
|
2015-07-30 12:37:14 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-04-08 11:24:22 -07:00
|
|
|
int
|
2016-04-08 13:11:21 -07:00
|
|
|
_evas_shm_surface_assign(Surface *s)
|
2015-07-30 12:37:14 -07:00
|
|
|
{
|
|
|
|
int i;
|
2016-04-08 13:11:21 -07:00
|
|
|
Shm_Surface *surface;
|
2015-07-30 12:37:14 -07:00
|
|
|
|
2016-04-08 13:11:21 -07:00
|
|
|
surface = s->surf.shm;
|
2015-07-30 12:37:14 -07:00
|
|
|
surface->current = _evas_shm_surface_wait(surface);
|
2015-07-30 08:45:38 -07:00
|
|
|
|
|
|
|
/* If we ran out of buffers we're in trouble, reset all ages */
|
|
|
|
if (!surface->current)
|
|
|
|
{
|
2015-07-30 12:37:14 -07:00
|
|
|
WRN("No free SHM buffers, dropping a frame");
|
2015-07-30 08:45:38 -07:00
|
|
|
for (i = 0; i < surface->num_buff; i++)
|
|
|
|
{
|
|
|
|
if (surface->leaf[i].valid)
|
|
|
|
{
|
|
|
|
surface->leaf[i].drawn = EINA_FALSE;
|
|
|
|
surface->leaf[i].age = 0;
|
|
|
|
}
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
2016-04-08 11:24:22 -07:00
|
|
|
return 0;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
2015-07-30 08:45:38 -07:00
|
|
|
|
|
|
|
/* Increment ages of all valid buffers */
|
|
|
|
for (i = 0; i < surface->num_buff; i++)
|
|
|
|
{
|
|
|
|
if (surface->leaf[i].valid && surface->leaf[i].drawn)
|
|
|
|
{
|
|
|
|
surface->leaf[i].age++;
|
2016-10-26 08:19:28 -07:00
|
|
|
if (surface->leaf[i].age > 4)
|
2015-07-30 08:45:38 -07:00
|
|
|
{
|
|
|
|
surface->leaf[i].age = 0;
|
|
|
|
surface->leaf[i].drawn = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 11:24:22 -07:00
|
|
|
return surface->current->age;
|
2015-07-30 08:45:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2016-04-08 13:11:21 -07:00
|
|
|
_evas_shm_surface_data_get(Surface *s, int *w, int *h)
|
2015-07-30 08:45:05 -07:00
|
|
|
{
|
2016-04-08 13:11:21 -07:00
|
|
|
Shm_Surface *surface;
|
2015-07-30 08:45:05 -07:00
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2016-04-08 13:11:21 -07:00
|
|
|
surface = s->surf.shm;
|
2015-07-30 08:45:05 -07:00
|
|
|
if (w) *w = 0;
|
|
|
|
if (h) *h = 0;
|
|
|
|
|
|
|
|
if (!surface->current)
|
2015-03-19 13:15:11 -07:00
|
|
|
{
|
2015-04-30 08:13:36 -07:00
|
|
|
/* WRN("All buffers held by server"); */
|
2015-03-19 13:15:11 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* DBG("Leaf Data Get %d", (int)(leaf - &surface->leaf[0])); */
|
|
|
|
|
2015-07-30 08:45:05 -07:00
|
|
|
if (w) *w = surface->current->w;
|
|
|
|
if (h) *h = surface->current->h;
|
2015-04-29 08:49:49 -07:00
|
|
|
|
2015-07-30 08:45:05 -07:00
|
|
|
return surface->current->data->map;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
|
|
|
|
2015-07-28 06:14:31 -07:00
|
|
|
void
|
2016-12-02 10:24:42 -08:00
|
|
|
_evas_shm_surface_post(Surface *s, Eina_Rectangle *rects, unsigned int count, Eina_Bool hidden)
|
2015-03-17 12:49:09 -07:00
|
|
|
{
|
2016-04-13 11:58:15 -07:00
|
|
|
Shm_Surface *surf;
|
2015-07-28 06:14:31 -07:00
|
|
|
Shm_Leaf *leaf;
|
2015-07-27 12:53:02 -07:00
|
|
|
|
2015-03-17 12:49:09 -07:00
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
2016-04-13 11:58:15 -07:00
|
|
|
surf = s->surf.shm;
|
|
|
|
leaf = surf->current;
|
2015-07-28 06:14:31 -07:00
|
|
|
if (!leaf) return;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2016-04-13 11:58:15 -07:00
|
|
|
if (!surf->surface) return;
|
2015-03-17 12:49:09 -07:00
|
|
|
|
2016-12-02 10:24:42 -08:00
|
|
|
if (!hidden)
|
|
|
|
{
|
|
|
|
wl_surface_attach(surf->surface, leaf->data->buffer, 0, 0);
|
2016-04-13 11:58:15 -07:00
|
|
|
|
2016-12-02 10:24:42 -08:00
|
|
|
_evas_surface_damage(surf->surface, surf->compositor_version,
|
|
|
|
leaf->w, leaf->h, rects, count);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
wl_surface_attach(surf->surface, NULL, 0, 0);
|
2015-07-27 12:53:02 -07:00
|
|
|
|
2016-04-13 11:58:15 -07:00
|
|
|
wl_surface_commit(surf->surface);
|
2015-07-27 12:53:02 -07:00
|
|
|
|
2015-07-30 08:45:38 -07:00
|
|
|
leaf->busy = EINA_TRUE;
|
|
|
|
leaf->drawn = EINA_TRUE;
|
|
|
|
leaf->age = 0;
|
2016-04-13 11:58:15 -07:00
|
|
|
surf->current = NULL;
|
2015-03-17 12:49:09 -07:00
|
|
|
}
|
2016-04-11 13:39:09 -07:00
|
|
|
|
2017-01-05 11:36:35 -08:00
|
|
|
Eina_Bool
|
|
|
|
_evas_shm_surface_surface_set(Surface *s, struct wl_shm *wl_shm, struct zwp_linux_dmabuf_v1 *wl_dmabuf EINA_UNUSED, struct wl_surface *wl_surface)
|
|
|
|
{
|
|
|
|
Shm_Surface *surf;
|
|
|
|
|
|
|
|
surf = s->surf.shm;
|
|
|
|
|
|
|
|
if ((surf->shm == wl_shm) && (surf->surface == wl_surface))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
surf->shm = wl_shm;
|
|
|
|
surf->surface = wl_surface;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2016-04-15 08:38:28 -07:00
|
|
|
Eina_Bool
|
|
|
|
_evas_shm_surface_create(Surface *s, int w, int h, int num_buff)
|
2016-04-11 13:39:09 -07:00
|
|
|
{
|
|
|
|
Shm_Surface *surf;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
2016-04-15 08:38:28 -07:00
|
|
|
if (!(s->surf.shm = calloc(1, sizeof(Shm_Surface)))) return EINA_FALSE;
|
2016-04-11 13:39:09 -07:00
|
|
|
surf = s->surf.shm;
|
|
|
|
|
|
|
|
surf->w = w;
|
|
|
|
surf->h = h;
|
2016-11-01 10:07:10 -07:00
|
|
|
surf->disp = s->info->info.wl_display;
|
2016-04-15 08:38:28 -07:00
|
|
|
surf->shm = s->info->info.wl_shm;
|
|
|
|
surf->surface = s->info->info.wl_surface;
|
2016-04-11 13:39:09 -07:00
|
|
|
surf->num_buff = num_buff;
|
2016-04-15 08:38:28 -07:00
|
|
|
surf->alpha = s->info->info.destination_alpha;
|
|
|
|
surf->compositor_version = s->info->info.compositor_version;
|
2016-04-11 13:39:09 -07:00
|
|
|
|
2017-07-21 13:17:55 -07:00
|
|
|
if (w && h)
|
2016-04-11 13:39:09 -07:00
|
|
|
{
|
2017-07-21 13:17:55 -07:00
|
|
|
/* create surface buffers */
|
|
|
|
for (; i < surf->num_buff; i++)
|
2016-04-11 13:39:09 -07:00
|
|
|
{
|
2017-07-21 13:17:55 -07:00
|
|
|
if (!_shm_leaf_create(surf, &(surf->leaf[i]), w, h))
|
|
|
|
{
|
|
|
|
ERR("Could not create surface leaf");
|
|
|
|
goto err;
|
|
|
|
}
|
2016-04-11 13:39:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 08:38:28 -07:00
|
|
|
s->type = SURFACE_SHM;
|
2016-04-11 13:39:09 -07:00
|
|
|
s->funcs.destroy = _evas_shm_surface_destroy;
|
|
|
|
s->funcs.reconfigure = _evas_shm_surface_reconfigure;
|
|
|
|
s->funcs.data_get = _evas_shm_surface_data_get;
|
|
|
|
s->funcs.assign = _evas_shm_surface_assign;
|
|
|
|
s->funcs.post = _evas_shm_surface_post;
|
2017-01-05 11:36:35 -08:00
|
|
|
s->funcs.surface_set = _evas_shm_surface_surface_set;
|
2016-04-11 13:39:09 -07:00
|
|
|
|
2016-04-15 08:38:28 -07:00
|
|
|
return EINA_TRUE;
|
2016-04-11 13:39:09 -07:00
|
|
|
|
|
|
|
err:
|
|
|
|
_evas_shm_surface_destroy(s);
|
2016-04-15 08:38:28 -07:00
|
|
|
return EINA_FALSE;
|
2016-04-11 13:39:09 -07:00
|
|
|
}
|