mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 02:20:43 -05:00
serialize upload of asyncronously loaded textures
Rate limit the uploading of textures to stop if it uses more than 5ms during one master clock iteration.
This commit is contained in:
parent
211bf79854
commit
8fb3a48ae2
@ -119,12 +119,17 @@ struct _ClutterTextureAsyncData
|
|||||||
/* Source ID of the idle handler for loading. If this is zero then
|
/* Source ID of the idle handler for loading. If this is zero then
|
||||||
the data is being loaded in a thread from the thread pool. Once
|
the data is being loaded in a thread from the thread pool. Once
|
||||||
the thread is finished it will be converted to idle load handler
|
the thread is finished it will be converted to idle load handler
|
||||||
and load_idle will be nonzero. If load_idle is nonzero then the
|
and load_idle will be nonzero. If load_idle is nonzero, and
|
||||||
rest of the load can safely be aborted by just removing the
|
upload_queued is FALSE then the rest of the load can safely be
|
||||||
source, otherwise the abort flag needs to be set and the data
|
aborted by just removing the source, otherwise the abort flag
|
||||||
should be disowned */
|
needs to be set and the data should be disowned */
|
||||||
guint load_idle;
|
guint load_idle;
|
||||||
|
|
||||||
|
/* Set when the texture is queued for GPU upload, used to determine
|
||||||
|
* what to do with the texture data when load_idle is zero.
|
||||||
|
*/
|
||||||
|
gboolean upload_queued;
|
||||||
|
|
||||||
gchar *load_filename;
|
gchar *load_filename;
|
||||||
CoglHandle load_bitmap;
|
CoglHandle load_bitmap;
|
||||||
GError *load_error;
|
GError *load_error;
|
||||||
@ -160,6 +165,9 @@ enum
|
|||||||
static int texture_signals[LAST_SIGNAL] = { 0 };
|
static int texture_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static GThreadPool *async_thread_pool = NULL;
|
static GThreadPool *async_thread_pool = NULL;
|
||||||
|
static guint repaint_upload_func = 0;
|
||||||
|
static GList *upload_list = NULL;
|
||||||
|
static GStaticMutex upload_list_mutex = G_STATIC_MUTEX_INIT;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
texture_fbo_free_resources (ClutterTexture *texture);
|
texture_fbo_free_resources (ClutterTexture *texture);
|
||||||
@ -647,8 +655,8 @@ clutter_texture_async_data_free (ClutterTextureAsyncData *data)
|
|||||||
{
|
{
|
||||||
/* This function should only be called either from the main thread
|
/* This function should only be called either from the main thread
|
||||||
once it is known that the load thread has completed or from the
|
once it is known that the load thread has completed or from the
|
||||||
load thread itself if the abort flag is true (in which case the
|
load thread/upload function itself if the abort flag is true (in
|
||||||
main thread has disowned the data) */
|
which case the main thread has disowned the data) */
|
||||||
|
|
||||||
if (data->load_filename)
|
if (data->load_filename)
|
||||||
g_free (data->load_filename);
|
g_free (data->load_filename);
|
||||||
@ -702,7 +710,8 @@ clutter_texture_async_load_cancel (ClutterTexture *texture)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise we need to tell the thread to abort and disown
|
/* Otherwise we need to tell the thread to abort and disown
|
||||||
the data */
|
the data, if the data has been loaded and decoded the data
|
||||||
|
is now waiting for a master clock iteration to be repainted */
|
||||||
priv->async_data->abort = TRUE;
|
priv->async_data->abort = TRUE;
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
@ -1682,6 +1691,12 @@ clutter_texture_thread_idle_func (gpointer user_data)
|
|||||||
/* Grab the mutex so we can be sure the thread has unlocked it
|
/* Grab the mutex so we can be sure the thread has unlocked it
|
||||||
before we destroy it */
|
before we destroy it */
|
||||||
g_mutex_lock (data->mutex);
|
g_mutex_lock (data->mutex);
|
||||||
|
if (data->abort)
|
||||||
|
{
|
||||||
|
g_mutex_unlock (data->mutex);
|
||||||
|
clutter_texture_async_data_free (data);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
g_mutex_unlock (data->mutex);
|
g_mutex_unlock (data->mutex);
|
||||||
|
|
||||||
clutter_texture_async_load_complete (data->texture, data->load_bitmap,
|
clutter_texture_async_load_complete (data->texture, data->load_bitmap,
|
||||||
@ -1692,6 +1707,36 @@ clutter_texture_thread_idle_func (gpointer user_data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_texture_repaint_upload_func (gpointer user_data)
|
||||||
|
{
|
||||||
|
gulong start_time;
|
||||||
|
|
||||||
|
g_static_mutex_lock (&upload_list_mutex);
|
||||||
|
|
||||||
|
if (upload_list)
|
||||||
|
{
|
||||||
|
start_time = clutter_get_timestamp ();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ClutterTextureAsyncData *data = upload_list->data;
|
||||||
|
clutter_texture_thread_idle_func (data);
|
||||||
|
upload_list = g_list_remove (upload_list, data);
|
||||||
|
}
|
||||||
|
/* continue uploading textures as long as we havent spent more
|
||||||
|
* then 5ms doing so this stage redraw cycle.
|
||||||
|
*/
|
||||||
|
while (upload_list && clutter_get_timestamp () < start_time + 5 * 1000);
|
||||||
|
}
|
||||||
|
if (upload_list)
|
||||||
|
{
|
||||||
|
_clutter_master_clock_ensure_next_iteration (
|
||||||
|
_clutter_master_clock_get_default());
|
||||||
|
}
|
||||||
|
g_static_mutex_unlock (&upload_list_mutex);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_texture_thread_func (gpointer user_data, gpointer pool_data)
|
clutter_texture_thread_func (gpointer user_data, gpointer pool_data)
|
||||||
{
|
{
|
||||||
@ -1732,10 +1777,21 @@ clutter_texture_thread_func (gpointer user_data, gpointer pool_data)
|
|||||||
* set it while we're holding the mutex so we can safely start the
|
* set it while we're holding the mutex so we can safely start the
|
||||||
* idle handler now without the possibility of calling the
|
* idle handler now without the possibility of calling the
|
||||||
* callback after it is aborted */
|
* callback after it is aborted */
|
||||||
data->load_idle =
|
g_static_mutex_lock (&upload_list_mutex);
|
||||||
clutter_threads_add_idle_full (G_PRIORITY_LOW, clutter_texture_thread_idle_func, data, NULL);
|
if (repaint_upload_func == 0)
|
||||||
|
{
|
||||||
|
repaint_upload_func = clutter_threads_add_repaint_func (
|
||||||
|
clutter_texture_repaint_upload_func,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
upload_list = g_list_append (upload_list, data);
|
||||||
|
data->upload_queued = TRUE;
|
||||||
|
g_static_mutex_unlock (&upload_list_mutex);
|
||||||
|
|
||||||
g_mutex_unlock (data->mutex);
|
g_mutex_unlock (data->mutex);
|
||||||
|
|
||||||
|
_clutter_master_clock_ensure_next_iteration (
|
||||||
|
_clutter_master_clock_get_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user