[Cogl] [PATCH 2/2] Use the Wayland embedded linked list implementation instead of BSD's
Robert Bragg
robert at sixbynine.org
Wed Jun 12 03:38:56 PDT 2013
This is a really good patch, thanks for looking at this. We talked a
bit more about the CoglPipeline pointers offline and I think it would
be good if we can at least keep in mind re-visiting this later to try
and reduce the size, but we shouldn't block landing this.
This looks good to land to me:
Reviewed-by: Robert Bragg <robert at linux.intel.com>
thanks,
- Robert
On Mon, Jun 10, 2013 at 2:15 PM, Neil Roberts <neil at linux.intel.com> wrote:
> This removes cogl-queue.h and adds a copy of Wayland's embedded list
> implementation. The advantage of the Wayland model is that it is much
> simpler and so it is easier to follow. It also doesn't require
> defining a typedef for every list type.
>
> The downside is that there is only one list type which is a
> doubly-linked list where the head has a pointer to both the beginning
> and the end. The BSD implementation has many more combinations some of
> which we were taking advantage of to reduce the size of critical
> structs where we didn't need a pointer to the end of the list.
>
> The corresponding changes to uses of cogl-queue.h are:
>
> • COGL_STAILQ_* was used for onscreen the list of events and dirty
> notifications. This makes the size of the CoglContext grow by one
> pointer.
>
> • COGL_TAILQ_* was used for fences.
>
> • COGL_LIST_* for CoglClosures. In this case the list head now has an
> extra pointer which means CoglOnscreen will grow by the size of
> three pointers, but this doesn't seem like a particularly important
> struct to optimise for size anyway.
>
> • COGL_LIST_* was used for the list of foreign GLES2 offscreens.
>
> • COGL_TAILQ_* was used for the list of sub stacks in a
> CoglMemoryStack.
>
> • COGL_LIST_* was used to track the list of layers that haven't had
> code generated yet while generating a fragment shader for a
> pipeline.
>
> • COGL_LIST_* was used to track the pipeline hierarchy in CoglNode.
>
> The last part is a bit more controversial because it increases the
> size of CoglPipeline and CoglPipelineLayer by one pointer in order to
> have the redundant tail pointer for the list head. Normally we try to
> be very careful about the size of the CoglPipeline struct. Because
> CoglPipeline is slice-allocated, this effectively ends up adding two
> pointers to the size because GSlice rounds up to the size of two
> pointers.
> ---
> cogl/Makefile.am | 3 +-
> cogl/cogl-closure-list-private.h | 52 ++-
> cogl/cogl-closure-list.c | 10 +-
> cogl/cogl-context-private.h | 6 +-
> cogl/cogl-context.c | 6 +-
> cogl/cogl-fence-private.h | 6 +-
> cogl/cogl-fence.c | 25 +-
> cogl/cogl-gles2-context-private.h | 14 +-
> cogl/cogl-gles2-context.c | 21 +-
> cogl/cogl-journal-private.h | 2 +-
> cogl/cogl-journal.c | 8 +-
> cogl/cogl-list.c | 94 ++++
> cogl/cogl-list.h | 123 ++++++
> cogl/cogl-memory-stack.c | 39 +-
> cogl/cogl-node-private.h | 8 +-
> cogl/cogl-node.c | 10 +-
> cogl/cogl-onscreen-private.h | 28 +-
> cogl/cogl-onscreen.c | 29 +-
> cogl/cogl-pipeline-layer.c | 4 +-
> cogl/cogl-pipeline-private.h | 2 +-
> cogl/cogl-pipeline.c | 4 +-
> cogl/cogl-poll.c | 2 +-
> cogl/cogl-queue.h | 647 ----------------------------
> cogl/cogl-renderer-private.h | 2 +-
> cogl/cogl-renderer.c | 2 +-
> cogl/cogl-sdl.c | 2 +-
> cogl/driver/gl/cogl-pipeline-fragend-glsl.c | 47 +-
> doc/reference/cogl2/Makefile.am | 1 -
> 28 files changed, 375 insertions(+), 822 deletions(-)
> create mode 100644 cogl/cogl-list.c
> create mode 100644 cogl/cogl-list.h
> delete mode 100644 cogl/cogl-queue.h
>
> diff --git a/cogl/Makefile.am b/cogl/Makefile.am
> index 323239d..0c470f0 100644
> --- a/cogl/Makefile.am
> +++ b/cogl/Makefile.am
> @@ -375,7 +375,8 @@ cogl_sources_c = \
> $(srcdir)/cogl-point-in-poly-private.h \
> $(srcdir)/cogl-point-in-poly.c \
> $(srcdir)/cogl-clutter.c \
> - $(srcdir)/cogl-queue.h \
> + $(srcdir)/cogl-list.c \
> + $(srcdir)/cogl-list.h \
> $(srcdir)/winsys/cogl-winsys-stub-private.h \
> $(srcdir)/winsys/cogl-winsys-stub.c \
> $(srcdir)/cogl-config-private.h \
> diff --git a/cogl/cogl-closure-list-private.h b/cogl/cogl-closure-list-private.h
> index 9aaa179..92ba0a1 100644
> --- a/cogl/cogl-closure-list-private.h
> +++ b/cogl/cogl-closure-list-private.h
> @@ -25,7 +25,7 @@
> #define _COGL_CLOSURE_LIST_PRIVATE_H_
>
> #include "cogl-object.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
>
> /*
> * This implements a list of callbacks that can be used a bit like
> @@ -43,18 +43,14 @@
> * point.
> */
>
> -typedef struct _CoglClosure CoglClosure;
> -
> -COGL_LIST_HEAD (CoglClosureList, CoglClosure);
> -
> -struct _CoglClosure
> +typedef struct _CoglClosure
> {
> - COGL_LIST_ENTRY (CoglClosure) list_node;
> + CoglList link;
>
> void *function;
> void *user_data;
> CoglUserDataDestroyCallback destroy_cb;
> -};
> +} CoglClosure;
>
> /*
> * _cogl_closure_disconnect:
> @@ -67,10 +63,10 @@ void
> _cogl_closure_disconnect (CoglClosure *closure);
>
> void
> -_cogl_closure_list_disconnect_all (CoglClosureList *list);
> +_cogl_closure_list_disconnect_all (CoglList *list);
>
> CoglClosure *
> -_cogl_closure_list_add (CoglClosureList *list,
> +_cogl_closure_list_add (CoglList *list,
> void *function,
> void *user_data,
> CoglUserDataDestroyCallback destroy_cb);
> @@ -91,26 +87,26 @@ _cogl_closure_list_add (CoglClosureList *list,
> * callbacks. If you want to handle the return value you should
> * manually iterate the list and invoke the callbacks yourself.
> */
> -#define _cogl_closure_list_invoke(list, cb_type, ...) \
> - G_STMT_START { \
> - CoglClosure *_c, *_tmp; \
> - \
> - COGL_LIST_FOREACH_SAFE (_c, (list), list_node, _tmp) \
> - { \
> - cb_type _cb = _c->function; \
> - _cb (__VA_ARGS__, _c->user_data); \
> - } \
> +#define _cogl_closure_list_invoke(list, cb_type, ...) \
> + G_STMT_START { \
> + CoglClosure *_c, *_tmp; \
> + \
> + _cogl_list_for_each_safe (_c, _tmp, (list), link) \
> + { \
> + cb_type _cb = _c->function; \
> + _cb (__VA_ARGS__, _c->user_data); \
> + } \
> } G_STMT_END
>
> -#define _cogl_closure_list_invoke_no_args(list) \
> - G_STMT_START { \
> - CoglClosure *_c, *_tmp; \
> - \
> - COGL_LIST_FOREACH_SAFE (_c, (list), list_node, _tmp) \
> - { \
> - void (*_cb)(void *) = _c->function; \
> - _cb (_c->user_data); \
> - } \
> +#define _cogl_closure_list_invoke_no_args(list) \
> + G_STMT_START { \
> + CoglClosure *_c, *_tmp; \
> + \
> + _cogl_list_for_each_safe (_c, _tmp, (list), link) \
> + { \
> + void (*_cb)(void *) = _c->function; \
> + _cb (_c->user_data); \
> + } \
> } G_STMT_END
>
> #endif /* _COGL_CLOSURE_LIST_PRIVATE_H_ */
> diff --git a/cogl/cogl-closure-list.c b/cogl/cogl-closure-list.c
> index 60b26b4..dfb5bf3 100644
> --- a/cogl/cogl-closure-list.c
> +++ b/cogl/cogl-closure-list.c
> @@ -30,7 +30,7 @@
> void
> _cogl_closure_disconnect (CoglClosure *closure)
> {
> - COGL_LIST_REMOVE (closure, list_node);
> + _cogl_list_remove (&closure->link);
>
> if (closure->destroy_cb)
> closure->destroy_cb (closure->user_data);
> @@ -39,16 +39,16 @@ _cogl_closure_disconnect (CoglClosure *closure)
> }
>
> void
> -_cogl_closure_list_disconnect_all (CoglClosureList *list)
> +_cogl_closure_list_disconnect_all (CoglList *list)
> {
> CoglClosure *closure, *next;
>
> - COGL_LIST_FOREACH_SAFE (closure, list, list_node, next)
> + _cogl_list_for_each_safe (closure, next, list, link)
> _cogl_closure_disconnect (closure);
> }
>
> CoglClosure *
> -_cogl_closure_list_add (CoglClosureList *list,
> +_cogl_closure_list_add (CoglList *list,
> void *function,
> void *user_data,
> CoglUserDataDestroyCallback destroy_cb)
> @@ -59,7 +59,7 @@ _cogl_closure_list_add (CoglClosureList *list,
> closure->user_data = user_data;
> closure->destroy_cb = destroy_cb;
>
> - COGL_LIST_INSERT_HEAD (list, closure, list_node);
> + _cogl_list_insert (list, &closure->link);
>
> return closure;
> }
> diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
> index 7978232..c5f215d 100644
> --- a/cogl/cogl-context-private.h
> +++ b/cogl/cogl-context-private.h
> @@ -176,8 +176,8 @@ struct _CoglContext
> gboolean have_last_offscreen_allocate_flags;
> CoglOffscreenAllocateFlags last_offscreen_allocate_flags;
>
> - CoglOnscreenEventList onscreen_events_queue;
> - CoglOnscreenQueuedDirtyList onscreen_dirty_queue;
> + CoglList onscreen_events_queue;
> + CoglList onscreen_dirty_queue;
> CoglClosure *onscreen_dispatch_idle;
>
> CoglGLES2Context *current_gles2_context;
> @@ -274,7 +274,7 @@ struct _CoglContext
> int n_uniform_names;
>
> CoglPollSource *fences_poll_source;
> - CoglFenceList fences;
> + CoglList fences;
>
> /* This defines a list of function pointers that Cogl uses from
> either GL or GLES. All functions are accessed indirectly through
> diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
> index 39901b1..26fe85c 100644
> --- a/cogl/cogl-context.c
> +++ b/cogl/cogl-context.c
> @@ -292,8 +292,8 @@ cogl_context_new (CoglDisplay *display,
> context->current_draw_buffer_state_flushed = 0;
> context->current_draw_buffer_changes = COGL_FRAMEBUFFER_STATE_ALL;
>
> - COGL_TAILQ_INIT (&context->onscreen_events_queue);
> - COGL_TAILQ_INIT (&context->onscreen_dirty_queue);
> + _cogl_list_init (&context->onscreen_events_queue);
> + _cogl_list_init (&context->onscreen_dirty_queue);
>
> g_queue_init (&context->gles2_context_stack);
>
> @@ -431,7 +431,7 @@ cogl_context_new (CoglDisplay *display,
> cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
> GE (context, glEnable (GL_POINT_SPRITE));
>
> - COGL_TAILQ_INIT (&context->fences);
> + _cogl_list_init (&context->fences);
>
> return context;
> }
> diff --git a/cogl/cogl-fence-private.h b/cogl/cogl-fence-private.h
> index 0817b7d..7a41c51 100644
> --- a/cogl/cogl-fence-private.h
> +++ b/cogl/cogl-fence-private.h
> @@ -25,11 +25,9 @@
> #define __COGL_FENCE_PRIVATE_H__
>
> #include "cogl-fence.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
> #include "cogl-winsys-private.h"
>
> -COGL_TAILQ_HEAD (CoglFenceList, CoglFenceClosure);
> -
> typedef enum
> {
> FENCE_TYPE_PENDING,
> @@ -42,7 +40,7 @@ typedef enum
>
> struct _CoglFenceClosure
> {
> - COGL_TAILQ_ENTRY (CoglFenceClosure) list;
> + CoglList link;
> CoglFramebuffer *framebuffer;
>
> CoglFenceType type;
> diff --git a/cogl/cogl-fence.c b/cogl/cogl-fence.c
> index 2055ac4..77469d7 100644
> --- a/cogl/cogl-fence.c
> +++ b/cogl/cogl-fence.c
> @@ -73,9 +73,9 @@ static void
> _cogl_fence_poll_dispatch (void *source, int revents)
> {
> CoglContext *context = source;
> - CoglFenceClosure *fence, *next;
> + CoglFenceClosure *fence, *tmp;
>
> - COGL_TAILQ_FOREACH_SAFE (fence, &context->fences, list, next)
> + _cogl_list_for_each_safe (fence, tmp, &context->fences, link)
> _cogl_fence_check (fence);
> }
>
> @@ -92,11 +92,11 @@ _cogl_fence_poll_prepare (void *source)
> {
> CoglFramebuffer *fb = l->data;
>
> - if (!COGL_TAILQ_EMPTY (&fb->journal->pending_fences))
> + if (!_cogl_list_empty (&fb->journal->pending_fences))
> _cogl_framebuffer_flush_journal (fb);
> }
>
> - if (!COGL_TAILQ_EMPTY (&context->fences))
> + if (!_cogl_list_empty (&context->fences))
> return FENCE_CHECK_TIMEOUT;
> else
> return -1;
> @@ -134,7 +134,7 @@ _cogl_fence_submit (CoglFenceClosure *fence)
> #endif
>
> done:
> - COGL_TAILQ_INSERT_TAIL (&context->fences, fence, list);
> + _cogl_list_insert (context->fences.prev, &fence->link);
>
> if (!context->fences_poll_source)
> {
> @@ -166,7 +166,7 @@ cogl_framebuffer_add_fence_callback (CoglFramebuffer *framebuffer,
>
> if (journal->entries->len)
> {
> - COGL_TAILQ_INSERT_TAIL (&journal->pending_fences, fence, list);
> + _cogl_list_insert (journal->pending_fences.prev, &fence->link);
> fence->type = FENCE_TYPE_PENDING;
> }
> else
> @@ -179,16 +179,15 @@ void
> cogl_framebuffer_cancel_fence_callback (CoglFramebuffer *framebuffer,
> CoglFenceClosure *fence)
> {
> - CoglJournal *journal = framebuffer->journal;
> CoglContext *context = framebuffer->context;
>
> if (fence->type == FENCE_TYPE_PENDING)
> {
> - COGL_TAILQ_REMOVE (&journal->pending_fences, fence, list);
> + _cogl_list_remove (&fence->link);
> }
> else
> {
> - COGL_TAILQ_REMOVE (&context->fences, fence, list);
> + _cogl_list_remove (&fence->link);
>
> if (fence->type == FENCE_TYPE_WINSYS)
> {
> @@ -212,15 +211,15 @@ _cogl_fence_cancel_fences_for_framebuffer (CoglFramebuffer *framebuffer)
> {
> CoglJournal *journal = framebuffer->journal;
> CoglContext *context = framebuffer->context;
> - CoglFenceClosure *fence, *next;
> + CoglFenceClosure *fence, *tmp;
>
> - while (!COGL_TAILQ_EMPTY (&journal->pending_fences))
> + while (!_cogl_list_empty (&journal->pending_fences))
> {
> - fence = COGL_TAILQ_FIRST (&journal->pending_fences);
> + fence = _cogl_container_of (journal->pending_fences.next, fence, link);
> cogl_framebuffer_cancel_fence_callback (framebuffer, fence);
> }
>
> - COGL_TAILQ_FOREACH_SAFE (fence, &context->fences, list, next)
> + _cogl_list_for_each_safe (fence, tmp, &context->fences, link)
> {
> if (fence->framebuffer == framebuffer)
> cogl_framebuffer_cancel_fence_callback (framebuffer, fence);
> diff --git a/cogl/cogl-gles2-context-private.h b/cogl/cogl-gles2-context-private.h
> index 5afb296..c9d4bcc 100644
> --- a/cogl/cogl-gles2-context-private.h
> +++ b/cogl/cogl-gles2-context-private.h
> @@ -33,18 +33,14 @@
>
> #include "cogl-object-private.h"
> #include "cogl-framebuffer-private.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
>
> -typedef struct _CoglGLES2Offscreen CoglGLES2Offscreen;
> -
> -COGL_LIST_HEAD (CoglGLES2OffscreenList, CoglGLES2Offscreen);
> -
> -struct _CoglGLES2Offscreen
> +typedef struct _CoglGLES2Offscreen
> {
> - COGL_LIST_ENTRY (CoglGLES2Offscreen) list_node;
> + CoglList link;
> CoglOffscreen *original_offscreen;
> CoglGLFramebuffer gl_framebuffer;
> -};
> +} CoglGLES2Offscreen;
>
> typedef struct
> {
> @@ -143,7 +139,7 @@ struct _CoglGLES2Context
>
> GLuint current_fbo_handle;
>
> - CoglGLES2OffscreenList foreign_offscreens;
> + CoglList foreign_offscreens;
>
> CoglGLES2Vtable *vtable;
>
> diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c
> index 2d0ab52..4063fdc 100644
> --- a/cogl/cogl-gles2-context.c
> +++ b/cogl/cogl-gles2-context.c
> @@ -1435,7 +1435,7 @@ gl_tex_image_2d_wrapper (GLenum target,
> static void
> _cogl_gles2_offscreen_free (CoglGLES2Offscreen *gles2_offscreen)
> {
> - COGL_LIST_REMOVE (gles2_offscreen, list_node);
> + _cogl_list_remove (&gles2_offscreen->link);
> g_slice_free (CoglGLES2Offscreen, gles2_offscreen);
> }
>
> @@ -1513,10 +1513,12 @@ _cogl_gles2_context_free (CoglGLES2Context *gles2_context)
> winsys = ctx->display->renderer->winsys_vtable;
> winsys->destroy_gles2_context (gles2_context);
>
> - while (gles2_context->foreign_offscreens.lh_first)
> + while (!_cogl_list_empty (&gles2_context->foreign_offscreens))
> {
> CoglGLES2Offscreen *gles2_offscreen =
> - gles2_context->foreign_offscreens.lh_first;
> + _cogl_container_of (gles2_context->foreign_offscreens.next,
> + gles2_offscreen,
> + link);
>
> /* Note: this will also indirectly free the gles2_offscreen by
> * calling the destroy notify for the _user_data */
> @@ -1572,7 +1574,7 @@ cogl_gles2_context_new (CoglContext *ctx, CoglError **error)
>
> gles2_ctx->context = ctx;
>
> - COGL_LIST_INIT (&gles2_ctx->foreign_offscreens);
> + _cogl_list_init (&gles2_ctx->foreign_offscreens);
>
> winsys = ctx->display->renderer->winsys_vtable;
> gles2_ctx->winsys = winsys->context_create_gles2_context (ctx, error);
> @@ -1694,9 +1696,9 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
> return NULL;
> }
>
> - for (gles2_offscreen = gles2_context->foreign_offscreens.lh_first;
> - gles2_offscreen;
> - gles2_offscreen = gles2_offscreen->list_node.le_next)
> + _cogl_list_for_each (gles2_offscreen,
> + &gles2_context->foreign_offscreens,
> + link)
> {
> if (gles2_offscreen->original_offscreen == offscreen)
> return gles2_offscreen;
> @@ -1740,9 +1742,8 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
>
> gles2_offscreen->original_offscreen = offscreen;
>
> - COGL_LIST_INSERT_HEAD (&gles2_context->foreign_offscreens,
> - gles2_offscreen,
> - list_node);
> + _cogl_list_insert (&gles2_context->foreign_offscreens,
> + &gles2_offscreen->link);
>
> /* So we avoid building up an ever growing collection of ancillary
> * buffers for wrapped framebuffers, we make sure that the wrappers
> diff --git a/cogl/cogl-journal-private.h b/cogl/cogl-journal-private.h
> index b73fbd1..63cbc23 100644
> --- a/cogl/cogl-journal-private.h
> +++ b/cogl/cogl-journal-private.h
> @@ -59,7 +59,7 @@ typedef struct _CoglJournal
>
> int fast_read_pixel_count;
>
> - CoglFenceList pending_fences;
> + CoglList pending_fences;
>
> } CoglJournal;
>
> diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
> index 518a797..703f162 100644
> --- a/cogl/cogl-journal.c
> +++ b/cogl/cogl-journal.c
> @@ -153,7 +153,7 @@ _cogl_journal_new (CoglFramebuffer *framebuffer)
> journal->entries = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
> journal->vertices = g_array_new (FALSE, FALSE, sizeof (float));
>
> - COGL_TAILQ_INIT (&journal->pending_fences);
> + _cogl_list_init (&journal->pending_fences);
>
> return _cogl_journal_object_new (journal);
> }
> @@ -1262,11 +1262,11 @@ _cogl_journal_all_entries_within_bounds (CoglJournal *journal,
> static void
> post_fences (CoglJournal *journal)
> {
> - CoglFenceClosure *fence, *next;
> + CoglFenceClosure *fence, *tmp;
>
> - COGL_TAILQ_FOREACH_SAFE (fence, &journal->pending_fences, list, next)
> + _cogl_list_for_each_safe (fence, tmp, &journal->pending_fences, link)
> {
> - COGL_TAILQ_REMOVE (&journal->pending_fences, fence, list);
> + _cogl_list_remove (&fence->link);
> _cogl_fence_submit (fence);
> }
> }
> diff --git a/cogl/cogl-list.c b/cogl/cogl-list.c
> new file mode 100644
> index 0000000..3fbc675
> --- /dev/null
> +++ b/cogl/cogl-list.c
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright © 2008-2011 Kristian Høgsberg
> + * Copyright © 2011, 2012 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission. The copyright holders make no representations
> + * about the suitability of this software for any purpose. It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +/* This list implementation is based on the Wayland source code */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include "cogl-list.h"
> +
> +void
> +_cogl_list_init (CoglList *list)
> +{
> + list->prev = list;
> + list->next = list;
> +}
> +
> +void
> +_cogl_list_insert (CoglList *list, CoglList *elm)
> +{
> + elm->prev = list;
> + elm->next = list->next;
> + list->next = elm;
> + elm->next->prev = elm;
> +}
> +
> +void
> +_cogl_list_remove (CoglList *elm)
> +{
> + elm->prev->next = elm->next;
> + elm->next->prev = elm->prev;
> + elm->next = NULL;
> + elm->prev = NULL;
> +}
> +
> +int
> +_cogl_list_length (CoglList *list)
> +{
> + CoglList *e;
> + int count;
> +
> + count = 0;
> + e = list->next;
> + while (e != list)
> + {
> + e = e->next;
> + count++;
> + }
> +
> + return count;
> +}
> +
> +int
> +_cogl_list_empty (CoglList *list)
> +{
> + return list->next == list;
> +}
> +
> +void
> +_cogl_list_insert_list (CoglList *list,
> + CoglList *other)
> +{
> + if (_cogl_list_empty (other))
> + return;
> +
> + other->next->prev = list;
> + other->prev->next = list->next;
> + list->next->prev = other->prev;
> + list->next = other->next;
> +}
> diff --git a/cogl/cogl-list.h b/cogl/cogl-list.h
> new file mode 100644
> index 0000000..7d716a8
> --- /dev/null
> +++ b/cogl/cogl-list.h
> @@ -0,0 +1,123 @@
> +/*
> + * Copyright © 2008 Kristian Høgsberg
> + * Copyright © 2012, 2013 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission. The copyright holders make no representations
> + * about the suitability of this software for any purpose. It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +/* This list implementation is based on the Wayland source code */
> +
> +#ifndef COGL_LIST_H
> +#define COGL_LIST_H
> +
> +/**
> + * CoglList - linked list
> + *
> + * The list head is of "CoglList" type, and must be initialized
> + * using cogl_list_init(). All entries in the list must be of the same
> + * type. The item type must have a "CoglList" member. This
> + * member will be initialized by cogl_list_insert(). There is no need to
> + * call cogl_list_init() on the individual item. To query if the list is
> + * empty in O(1), use cogl_list_empty().
> + *
> + * Let's call the list reference "CoglList foo_list", the item type as
> + * "item_t", and the item member as "CoglList link". The following code
> + *
> + * The following code will initialize a list:
> + *
> + * cogl_list_init (foo_list);
> + * cogl_list_insert (foo_list, item1); Pushes item1 at the head
> + * cogl_list_insert (foo_list, item2); Pushes item2 at the head
> + * cogl_list_insert (item2, item3); Pushes item3 after item2
> + *
> + * The list now looks like [item2, item3, item1]
> + *
> + * Will iterate the list in ascending order:
> + *
> + * item_t *item;
> + * cogl_list_for_each(item, foo_list, link) {
> + * Do_something_with_item(item);
> + * }
> + */
> +
> +typedef struct _CoglList CoglList;
> +
> +struct _CoglList
> +{
> + CoglList *prev;
> + CoglList *next;
> +};
> +
> +void
> +_cogl_list_init (CoglList *list);
> +
> +void
> +_cogl_list_insert (CoglList *list,
> + CoglList *elm);
> +
> +void
> +_cogl_list_remove (CoglList *elm);
> +
> +int
> +_cogl_list_length (CoglList *list);
> +
> +int
> +_cogl_list_empty (CoglList *list);
> +
> +void
> +_cogl_list_insert_list (CoglList *list,
> + CoglList *other);
> +
> +#ifdef __GNUC__
> +#define _cogl_container_of(ptr, sample, member) \
> + (__typeof__(sample))((char *)(ptr) - \
> + ((char *)&(sample)->member - (char *)(sample)))
> +#else
> +#define _cogl_container_of(ptr, sample, member) \
> + (void *)((char *)(ptr) - \
> + ((char *)&(sample)->member - (char *)(sample)))
> +#endif
> +
> +#define _cogl_list_for_each(pos, head, member) \
> + for (pos = 0, pos = _cogl_container_of((head)->next, pos, member); \
> + &pos->member != (head); \
> + pos = _cogl_container_of(pos->member.next, pos, member))
> +
> +#define _cogl_list_for_each_safe(pos, tmp, head, member) \
> + for (pos = 0, tmp = 0, \
> + pos = _cogl_container_of((head)->next, pos, member), \
> + tmp = _cogl_container_of((pos)->member.next, tmp, member); \
> + &pos->member != (head); \
> + pos = tmp, \
> + tmp = _cogl_container_of(pos->member.next, tmp, member))
> +
> +#define _cogl_list_for_each_reverse(pos, head, member) \
> + for (pos = 0, pos = _cogl_container_of((head)->prev, pos, member); \
> + &pos->member != (head); \
> + pos = _cogl_container_of(pos->member.prev, pos, member))
> +
> +#define _cogl_list_for_each_reverse_safe(pos, tmp, head, member) \
> + for (pos = 0, tmp = 0, \
> + pos = _cogl_container_of((head)->prev, pos, member), \
> + tmp = _cogl_container_of((pos)->member.prev, tmp, member); \
> + &pos->member != (head); \
> + pos = tmp, \
> + tmp = _cogl_container_of(pos->member.prev, tmp, member))
> +
> +#endif /* COGL_LIST_H */
> diff --git a/cogl/cogl-memory-stack.c b/cogl/cogl-memory-stack.c
> index 5f4547e..2aefcc9 100644
> --- a/cogl/cogl-memory-stack.c
> +++ b/cogl/cogl-memory-stack.c
> @@ -53,26 +53,22 @@
> #endif
>
> #include "cogl-memory-stack-private.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
>
> #include <stdint.h>
>
> #include <glib.h>
>
> -typedef struct _CoglMemorySubStack CoglMemorySubStack;
> -
> -COGL_TAILQ_HEAD (CoglMemorySubStackList, CoglMemorySubStack);
> -
> -struct _CoglMemorySubStack
> +typedef struct _CoglMemorySubStack
> {
> - COGL_TAILQ_ENTRY (CoglMemorySubStack) list_node;
> + CoglList link;
> size_t bytes;
> uint8_t *data;
> -};
> +} CoglMemorySubStack;
>
> struct _CoglMemoryStack
> {
> - CoglMemorySubStackList sub_stacks;
> + CoglList sub_stacks;
>
> CoglMemorySubStack *sub_stack;
> size_t sub_stack_offset;
> @@ -93,7 +89,7 @@ _cogl_memory_stack_add_sub_stack (CoglMemoryStack *stack,
> {
> CoglMemorySubStack *sub_stack =
> _cogl_memory_sub_stack_alloc (sub_stack_bytes);
> - COGL_TAILQ_INSERT_TAIL (&stack->sub_stacks, sub_stack, list_node);
> + _cogl_list_insert (stack->sub_stacks.prev, &sub_stack->link);
> stack->sub_stack = sub_stack;
> stack->sub_stack_offset = 0;
> }
> @@ -103,7 +99,7 @@ _cogl_memory_stack_new (size_t initial_size_bytes)
> {
> CoglMemoryStack *stack = g_slice_new0 (CoglMemoryStack);
>
> - COGL_TAILQ_INIT (&stack->sub_stacks);
> + _cogl_list_init (&stack->sub_stacks);
>
> _cogl_memory_stack_add_sub_stack (stack, initial_size_bytes);
>
> @@ -128,9 +124,9 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
> * is made then we may need to skip over one or more of the
> * sub-stacks that are too small for the requested allocation
> * size... */
> - for (sub_stack = sub_stack->list_node.tqe_next;
> - sub_stack;
> - sub_stack = sub_stack->list_node.tqe_next)
> + for (sub_stack = _cogl_container_of (sub_stack->link.next, sub_stack, link);
> + &sub_stack->link != &stack->sub_stacks;
> + sub_stack = _cogl_container_of (sub_stack->link.next, sub_stack, link))
> {
> if (sub_stack->bytes >= bytes)
> {
> @@ -147,11 +143,11 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
> * requested allocation if that's bigger.
> */
>
> - sub_stack = COGL_TAILQ_LAST (&stack->sub_stacks, CoglMemorySubStackList);
> + sub_stack = _cogl_container_of (stack->sub_stacks.prev, sub_stack, link);
>
> _cogl_memory_stack_add_sub_stack (stack, MAX (sub_stack->bytes, bytes) * 2);
>
> - sub_stack = COGL_TAILQ_LAST (&stack->sub_stacks, CoglMemorySubStackList);
> + sub_stack = _cogl_container_of (stack->sub_stacks.prev, sub_stack, link);
>
> stack->sub_stack_offset += bytes;
>
> @@ -161,7 +157,9 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
> void
> _cogl_memory_stack_rewind (CoglMemoryStack *stack)
> {
> - stack->sub_stack = COGL_TAILQ_FIRST (&stack->sub_stacks);
> + stack->sub_stack = _cogl_container_of (stack->sub_stacks.next,
> + stack->sub_stack,
> + link);
> stack->sub_stack_offset = 0;
> }
>
> @@ -175,11 +173,12 @@ _cogl_memory_sub_stack_free (CoglMemorySubStack *sub_stack)
> void
> _cogl_memory_stack_free (CoglMemoryStack *stack)
> {
> - CoglMemorySubStack *sub_stack;
>
> - while ((sub_stack = COGL_TAILQ_FIRST (&stack->sub_stacks)))
> + while (!_cogl_list_empty (&stack->sub_stacks))
> {
> - COGL_TAILQ_REMOVE (&stack->sub_stacks, sub_stack, list_node);
> + CoglMemorySubStack *sub_stack =
> + _cogl_container_of (stack->sub_stacks.next, sub_stack, link);
> + _cogl_list_remove (&sub_stack->link);
> _cogl_memory_sub_stack_free (sub_stack);
> }
>
> diff --git a/cogl/cogl-node-private.h b/cogl/cogl-node-private.h
> index f1b505c..ee2246c 100644
> --- a/cogl/cogl-node-private.h
> +++ b/cogl/cogl-node-private.h
> @@ -29,12 +29,10 @@
> #define __COGL_NODE_PRIVATE_H
>
> #include "cogl-object-private.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
>
> typedef struct _CoglNode CoglNode;
>
> -COGL_LIST_HEAD (CoglNodeList, CoglNode);
> -
> /* Pipelines and layers represent their state in a tree structure where
> * some of the state relating to a given pipeline or layer may actually
> * be owned by one if is ancestors in the tree. We have a common data
> @@ -49,10 +47,10 @@ struct _CoglNode
> CoglNode *parent;
>
> /* The list entry here contains pointers to the node's siblings */
> - COGL_LIST_ENTRY (CoglNode) list_node;
> + CoglList link;
>
> /* List of children */
> - CoglNodeList children;
> + CoglList children;
>
> /* TRUE if the node took a strong reference on its parent. Weak
> * pipelines for instance don't take a reference on their parent. */
> diff --git a/cogl/cogl-node.c b/cogl/cogl-node.c
> index ab32e28..88bf991 100644
> --- a/cogl/cogl-node.c
> +++ b/cogl/cogl-node.c
> @@ -36,7 +36,7 @@ void
> _cogl_pipeline_node_init (CoglNode *node)
> {
> node->parent = NULL;
> - COGL_LIST_INIT (&node->children);
> + _cogl_list_init (&node->children);
> }
>
> void
> @@ -59,7 +59,7 @@ _cogl_pipeline_node_set_parent_real (CoglNode *node,
> if (node->parent)
> unparent (node);
>
> - COGL_LIST_INSERT_HEAD (&parent->children, node, list_node);
> + _cogl_list_insert (&parent->children, &node->link);
>
> node->parent = parent;
> node->has_parent_reference = take_strong_reference;
> @@ -80,9 +80,9 @@ _cogl_pipeline_node_unparent_real (CoglNode *node)
> if (parent == NULL)
> return;
>
> - _COGL_RETURN_IF_FAIL (!COGL_LIST_EMPTY (&parent->children));
> + _COGL_RETURN_IF_FAIL (!_cogl_list_empty (&parent->children));
>
> - COGL_LIST_REMOVE (node, list_node);
> + _cogl_list_remove (&node->link);
>
> if (node->has_parent_reference)
> cogl_object_unref (parent);
> @@ -97,7 +97,7 @@ _cogl_pipeline_node_foreach_child (CoglNode *node,
> {
> CoglNode *child, *next;
>
> - COGL_LIST_FOREACH_SAFE (child, &node->children, list_node, next)
> + _cogl_list_for_each_safe (child, next, &node->children, link)
> callback (child, user_data);
> }
>
> diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
> index e960dc3..1fd62ea 100644
> --- a/cogl/cogl-onscreen-private.h
> +++ b/cogl/cogl-onscreen-private.h
> @@ -26,8 +26,8 @@
>
> #include "cogl-onscreen.h"
> #include "cogl-framebuffer-private.h"
> -#include "cogl-queue.h"
> #include "cogl-closure-list-private.h"
> +#include "cogl-list.h"
>
> #include <glib.h>
>
> @@ -35,30 +35,22 @@
> #include <windows.h>
> #endif
>
> -typedef struct _CoglOnscreenEvent CoglOnscreenEvent;
> -
> -COGL_TAILQ_HEAD (CoglOnscreenEventList, CoglOnscreenEvent);
> -
> -struct _CoglOnscreenEvent
> +typedef struct _CoglOnscreenEvent
> {
> - COGL_TAILQ_ENTRY (CoglOnscreenEvent) list_node;
> + CoglList link;
>
> CoglOnscreen *onscreen;
> CoglFrameInfo *info;
> CoglFrameEvent type;
> -};
> +} CoglOnscreenEvent;
>
> -typedef struct _CoglOnscreenQueuedDirty CoglOnscreenQueuedDirty;
> -
> -COGL_TAILQ_HEAD (CoglOnscreenQueuedDirtyList, CoglOnscreenQueuedDirty);
> -
> -struct _CoglOnscreenQueuedDirty
> +typedef struct _CoglOnscreenQueuedDirty
> {
> - COGL_TAILQ_ENTRY (CoglOnscreenQueuedDirty) list_node;
> + CoglList link;
>
> CoglOnscreen *onscreen;
> CoglOnscreenDirtyInfo info;
> -};
> +} CoglOnscreenQueuedDirty;
>
> struct _CoglOnscreen
> {
> @@ -80,12 +72,12 @@ struct _CoglOnscreen
>
> CoglBool swap_throttled;
>
> - CoglClosureList frame_closures;
> + CoglList frame_closures;
>
> CoglBool resizable;
> - CoglClosureList resize_closures;
> + CoglList resize_closures;
>
> - CoglClosureList dirty_closures;
> + CoglList dirty_closures;
>
> int64_t frame_counter;
> int64_t swap_frame_counter; /* frame counter at last all to
> diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
> index f686b14..c115a6e 100644
> --- a/cogl/cogl-onscreen.c
> +++ b/cogl/cogl-onscreen.c
> @@ -47,9 +47,9 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
> {
> CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
>
> - COGL_LIST_INIT (&onscreen->frame_closures);
> - COGL_LIST_INIT (&onscreen->resize_closures);
> - COGL_LIST_INIT (&onscreen->dirty_closures);
> + _cogl_list_init (&onscreen->frame_closures);
> + _cogl_list_init (&onscreen->resize_closures);
> + _cogl_list_init (&onscreen->dirty_closures);
>
> framebuffer->config = onscreen_template->config;
> cogl_object_ref (framebuffer->config.swap_chain);
> @@ -122,23 +122,20 @@ static void
> _cogl_dispatch_onscreen_cb (CoglContext *context)
> {
> CoglOnscreenEvent *event, *tmp;
> - CoglOnscreenEventList queue;
> + CoglList queue;
>
> /* Dispatching the event callback may cause another frame to be
> * drawn which in may cause another event to be queued immediately.
> * To make sure this loop will only dispatch one set of events we'll
> * steal the queue and iterate that separately */
> - COGL_TAILQ_INIT (&queue);
> - COGL_TAILQ_CONCAT (&queue, &context->onscreen_events_queue, list_node);
> - COGL_TAILQ_INIT (&context->onscreen_events_queue);
> + _cogl_list_init (&queue);
> + _cogl_list_insert_list (&queue, &context->onscreen_events_queue);
> + _cogl_list_init (&context->onscreen_events_queue);
>
> _cogl_closure_disconnect (context->onscreen_dispatch_idle);
> context->onscreen_dispatch_idle = NULL;
>
> - COGL_TAILQ_FOREACH_SAFE (event,
> - &queue,
> - list_node,
> - tmp)
> + _cogl_list_for_each_safe (event, tmp, &queue, link)
> {
> CoglOnscreen *onscreen = event->onscreen;
> CoglFrameInfo *info = event->info;
> @@ -151,12 +148,12 @@ _cogl_dispatch_onscreen_cb (CoglContext *context)
> g_slice_free (CoglOnscreenEvent, event);
> }
>
> - while (!COGL_TAILQ_EMPTY (&context->onscreen_dirty_queue))
> + while (!_cogl_list_empty (&context->onscreen_dirty_queue))
> {
> CoglOnscreenQueuedDirty *qe =
> - COGL_TAILQ_FIRST (&context->onscreen_dirty_queue);
> + _cogl_container_of (context->onscreen_dirty_queue.next, qe, link);
>
> - COGL_TAILQ_REMOVE (&context->onscreen_dirty_queue, qe, list_node);
> + _cogl_list_remove (&qe->link);
>
> _cogl_closure_list_invoke (&qe->onscreen->dirty_closures,
> CoglOnscreenDirtyCallback,
> @@ -194,7 +191,7 @@ _cogl_onscreen_queue_dirty (CoglOnscreen *onscreen,
>
> qe->onscreen = cogl_object_ref (onscreen);
> qe->info = *info;
> - COGL_TAILQ_INSERT_TAIL (&ctx->onscreen_dirty_queue, qe, list_node);
> + _cogl_list_insert (ctx->onscreen_dirty_queue.prev, &qe->link);
>
> _cogl_onscreen_queue_dispatch_idle (onscreen);
> }
> @@ -226,7 +223,7 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
> event->info = cogl_object_ref (info);
> event->type = type;
>
> - COGL_TAILQ_INSERT_TAIL (&ctx->onscreen_events_queue, event, list_node);
> + _cogl_list_insert (ctx->onscreen_events_queue.prev, &event->link);
>
> _cogl_onscreen_queue_dispatch_idle (onscreen);
> }
> diff --git a/cogl/cogl-pipeline-layer.c b/cogl/cogl-pipeline-layer.c
> index bb77f6b..a401773 100644
> --- a/cogl/cogl-pipeline-layer.c
> +++ b/cogl/cogl-pipeline-layer.c
> @@ -346,7 +346,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
>
> /* Identify the case where the layer is new with no owner or
> * dependants and so we don't need to do anything. */
> - if (COGL_LIST_EMPTY (&COGL_NODE (layer)->children) &&
> + if (_cogl_list_empty (&COGL_NODE (layer)->children) &&
> layer->owner == NULL)
> goto init_layer_state;
>
> @@ -368,7 +368,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
> * they have dependants - either direct children, or another
> * pipeline as an owner.
> */
> - if (!COGL_LIST_EMPTY (&COGL_NODE (layer)->children) ||
> + if (!_cogl_list_empty (&COGL_NODE (layer)->children) ||
> layer->owner != required_owner)
> {
> CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
> diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
> index a185b3c..72917de 100644
> --- a/cogl/cogl-pipeline-private.h
> +++ b/cogl/cogl-pipeline-private.h
> @@ -34,7 +34,7 @@
> #include "cogl-matrix.h"
> #include "cogl-object-private.h"
> #include "cogl-profile.h"
> -#include "cogl-queue.h"
> +#include "cogl-list.h"
> #include "cogl-boxed-value.h"
> #include "cogl-pipeline-snippet-private.h"
> #include "cogl-pipeline-state.h"
> diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
> index b9264ed..19a8a19 100644
> --- a/cogl/cogl-pipeline.c
> +++ b/cogl/cogl-pipeline.c
> @@ -431,7 +431,7 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
> destroy_weak_children_cb,
> NULL);
>
> - g_assert (COGL_LIST_EMPTY (&COGL_NODE (pipeline)->children));
> + g_assert (_cogl_list_empty (&COGL_NODE (pipeline)->children));
>
> _cogl_pipeline_unparent (COGL_NODE (pipeline));
>
> @@ -1212,7 +1212,7 @@ _cogl_pipeline_pre_change_notify (CoglPipeline *pipeline,
> /* If there are still children remaining though we'll need to
> * perform a copy-on-write and reparent the dependants as children
> * of the copy. */
> - if (!COGL_LIST_EMPTY (&COGL_NODE (pipeline)->children))
> + if (!_cogl_list_empty (&COGL_NODE (pipeline)->children))
> {
> CoglPipeline *new_authority;
>
> diff --git a/cogl/cogl-poll.c b/cogl/cogl-poll.c
> index e29d997..c50d648 100644
> --- a/cogl/cogl-poll.c
> +++ b/cogl/cogl-poll.c
> @@ -57,7 +57,7 @@ cogl_poll_renderer_get_info (CoglRenderer *renderer,
> *n_poll_fds = renderer->poll_fds->len;
> *timeout = -1;
>
> - if (!COGL_LIST_EMPTY (&renderer->idle_closures))
> + if (!_cogl_list_empty (&renderer->idle_closures))
> {
> *timeout = 0;
> return renderer->poll_fds_age;
> diff --git a/cogl/cogl-queue.h b/cogl/cogl-queue.h
> deleted file mode 100644
> index 7020ae0..0000000
> --- a/cogl/cogl-queue.h
> +++ /dev/null
> @@ -1,647 +0,0 @@
> -/*-
> - * Copyright (c) 1991, 1993
> - * The Regents of the University of California. All rights reserved.
> - *
> - * Copyright (C) 2011 Intel Corporation.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - * 1. Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - * 2. Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in the
> - * documentation and/or other materials provided with the distribution.
> - * 4. Neither the name of the University nor the names of its contributors
> - * may be used to endorse or promote products derived from this software
> - * without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> - * SUCH DAMAGE.
> - *
> - * @(#)queue.h 8.5 (Berkeley) 8/20/94
> - * $FreeBSD$
> - */
> -
> -#ifndef _COGL_QUEUE_H_
> -#define _COGL_QUEUE_H_
> -
> -/*
> - * This file defines four types of data structures: singly-linked lists,
> - * singly-linked tail queues, lists and tail queues.
> - *
> - * A singly-linked list is headed by a single forward pointer. The elements
> - * are singly linked for minimum space and pointer manipulation overhead at
> - * the expense of O(n) removal for arbitrary elements. New elements can be
> - * added to the list after an existing element or at the head of the list.
> - * Elements being removed from the head of the list should use the explicit
> - * macro for this purpose for optimum efficiency. A singly-linked list may
> - * only be traversed in the forward direction. Singly-linked lists are ideal
> - * for applications with large datasets and few or no removals or for
> - * implementing a LIFO queue.
> - *
> - * A singly-linked tail queue is headed by a pair of pointers, one to the
> - * head of the list and the other to the tail of the list. The elements are
> - * singly linked for minimum space and pointer manipulation overhead at the
> - * expense of O(n) removal for arbitrary elements. New elements can be added
> - * to the list after an existing element, at the head of the list, or at the
> - * end of the list. Elements being removed from the head of the tail queue
> - * should use the explicit macro for this purpose for optimum efficiency.
> - * A singly-linked tail queue may only be traversed in the forward direction.
> - * Singly-linked tail queues are ideal for applications with large datasets
> - * and few or no removals or for implementing a FIFO queue.
> - *
> - * A list is headed by a single forward pointer (or an array of forward
> - * pointers for a hash table header). The elements are doubly linked
> - * so that an arbitrary element can be removed without a need to
> - * traverse the list. New elements can be added to the list before
> - * or after an existing element or at the head of the list. A list
> - * may only be traversed in the forward direction.
> - *
> - * A tail queue is headed by a pair of pointers, one to the head of the
> - * list and the other to the tail of the list. The elements are doubly
> - * linked so that an arbitrary element can be removed without a need to
> - * traverse the list. New elements can be added to the list before or
> - * after an existing element, at the head of the list, or at the end of
> - * the list. A tail queue may be traversed in either direction.
> - *
> - * For details on the use of these macros, see the queue(3) manual page.
> - *
> - *
> - * SLIST LIST STAILQ TAILQ
> - * _HEAD + + + +
> - * _HEAD_INITIALIZER + + + +
> - * _ENTRY + + + +
> - * _INIT + + + +
> - * _EMPTY + + + +
> - * _FIRST + + + +
> - * _NEXT + + + +
> - * _PREV - - - +
> - * _LAST - - + +
> - * _FOREACH + + + +
> - * _FOREACH_SAFE + + + +
> - * _FOREACH_REVERSE - - - +
> - * _FOREACH_REVERSE_SAFE - - - +
> - * _INSERT_HEAD + + + +
> - * _INSERT_BEFORE - + - +
> - * _INSERT_AFTER + + + +
> - * _INSERT_TAIL - - + +
> - * _CONCAT - - + +
> - * _REMOVE_AFTER + - + -
> - * _REMOVE_HEAD + - + -
> - * _REMOVE + + + +
> - * _SWAP + + + +
> - *
> - */
> -#ifdef COGL_QUEUE_MACRO_DEBUG
> -/* Store the last 2 places the queue element or head was altered */
> -struct cogl_qm_trace {
> - char * lastfile;
> - int lastline;
> - char * prevfile;
> - int prevline;
> -};
> -
> -#define COGL_TRACEBUF struct cogl_qm_trace trace;
> -#define COGL_TRASHIT(x) do {(x) = (void *)-1;} while (0)
> -#define COGL_QMD_SAVELINK(name, link) void **name = (void *)&(link)
> -
> -#define COGL_QMD_TRACE_HEAD(head) do { \
> - (head)->trace.prevline = (head)->trace.lastline; \
> - (head)->trace.prevfile = (head)->trace.lastfile; \
> - (head)->trace.lastline = __LINE__; \
> - (head)->trace.lastfile = __FILE__; \
> -} while (0)
> -
> -#define COGL_QMD_TRACE_ELEM(elem) do { \
> - (elem)->trace.prevline = (elem)->trace.lastline; \
> - (elem)->trace.prevfile = (elem)->trace.lastfile; \
> - (elem)->trace.lastline = __LINE__; \
> - (elem)->trace.lastfile = __FILE__; \
> -} while (0)
> -
> -#else
> -#define COGL_QMD_TRACE_ELEM(elem)
> -#define COGL_QMD_TRACE_HEAD(head)
> -#define COGL_QMD_SAVELINK(name, link)
> -#define COGL_TRACEBUF
> -#define COGL_TRASHIT(x)
> -#endif /* COGL_QUEUE_MACRO_DEBUG */
> -
> -/*
> - * Singly-linked List declarations.
> - */
> -#define COGL_SLIST_HEAD(name, type) \
> -typedef struct _ ## name { \
> - type *slh_first; /* first element */ \
> -} name
> -
> -#define COGL_SLIST_HEAD_INITIALIZER(head) \
> - { NULL }
> -
> -#define COGL_SLIST_ENTRY(type) \
> -struct { \
> - type *sle_next; /* next element */ \
> -}
> -
> -/*
> - * Singly-linked List functions.
> - */
> -#define COGL_SLIST_EMPTY(head) ((head)->slh_first == NULL)
> -
> -#define COGL_SLIST_FIRST(head) ((head)->slh_first)
> -
> -#define COGL_SLIST_FOREACH(var, head, field) \
> - for ((var) = COGL_SLIST_FIRST((head)); \
> - (var); \
> - (var) = COGL_SLIST_NEXT((var), field))
> -
> -#define COGL_SLIST_FOREACH_SAFE(var, head, field, tvar) \
> - for ((var) = COGL_SLIST_FIRST((head)); \
> - (var) && ((tvar) = COGL_SLIST_NEXT((var), field), 1); \
> - (var) = (tvar))
> -
> -#define COGL_SLIST_FOREACH_PREVPTR(var, varp, head, field) \
> - for ((varp) = &COGL_SLIST_FIRST((head)); \
> - ((var) = *(varp)) != NULL; \
> - (varp) = &COGL_SLIST_NEXT((var), field))
> -
> -#define COGL_SLIST_INIT(head) do { \
> - COGL_SLIST_FIRST((head)) = NULL; \
> -} while (0)
> -
> -#define COGL_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
> - COGL_SLIST_NEXT((elm), field) = COGL_SLIST_NEXT((slistelm), field); \
> - COGL_SLIST_NEXT((slistelm), field) = (elm); \
> -} while (0)
> -
> -#define COGL_SLIST_INSERT_HEAD(head, elm, field) do { \
> - COGL_SLIST_NEXT((elm), field) = COGL_SLIST_FIRST((head)); \
> - COGL_SLIST_FIRST((head)) = (elm); \
> -} while (0)
> -
> -#define COGL_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
> -
> -#define COGL_SLIST_REMOVE(head, elm, type, field) do { \
> - COGL_QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
> - if (COGL_SLIST_FIRST((head)) == (elm)) { \
> - COGL_SLIST_REMOVE_HEAD((head), field); \
> - } \
> - else { \
> - type *curelm = COGL_SLIST_FIRST((head)); \
> - while (COGL_SLIST_NEXT(curelm, field) != (elm)) \
> - curelm = COGL_SLIST_NEXT(curelm, field); \
> - COGL_SLIST_REMOVE_AFTER(curelm, field); \
> - } \
> - COGL_TRASHIT(*oldnext); \
> -} while (0)
> -
> -#define COGL_SLIST_REMOVE_AFTER(elm, field) do { \
> - COGL_SLIST_NEXT(elm, field) = \
> - COGL_SLIST_NEXT(COGL_SLIST_NEXT(elm, field), field); \
> -} while (0)
> -
> -#define COGL_SLIST_REMOVE_HEAD(head, field) do { \
> - COGL_SLIST_FIRST((head)) = \
> - COGL_SLIST_NEXT(COGL_SLIST_FIRST((head)), field); \
> -} while (0)
> -
> -#define COGL_SLIST_SWAP(head1, head2, type) do { \
> - type *swap_first = COGL_SLIST_FIRST(head1); \
> - COGL_SLIST_FIRST(head1) = COGL_SLIST_FIRST(head2); \
> - COGL_SLIST_FIRST(head2) = swap_first; \
> -} while (0)
> -
> -/*
> - * Singly-linked Tail queue declarations.
> - */
> -#define COGL_STAILQ_HEAD(name, type) \
> -typedef struct _ ## name { \
> - type *stqh_first;/* first element */ \
> - type **stqh_last;/* addr of last next element */ \
> -} name
> -
> -#define COGL_STAILQ_HEAD_INITIALIZER(head) \
> - { NULL, &(head).stqh_first }
> -
> -#define COGL_STAILQ_ENTRY(type) \
> -struct { \
> - type *stqe_next; /* next element */ \
> -}
> -
> -/*
> - * Singly-linked Tail queue functions.
> - */
> -#define COGL_STAILQ_CONCAT(head1, head2) do { \
> - if (!COGL_STAILQ_EMPTY((head2))) { \
> - *(head1)->stqh_last = (head2)->stqh_first; \
> - (head1)->stqh_last = (head2)->stqh_last; \
> - COGL_STAILQ_INIT((head2)); \
> - } \
> -} while (0)
> -
> -#define COGL_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
> -
> -#define COGL_STAILQ_FIRST(head) ((head)->stqh_first)
> -
> -#define COGL_STAILQ_FOREACH(var, head, field) \
> - for((var) = COGL_STAILQ_FIRST((head)); \
> - (var); \
> - (var) = COGL_STAILQ_NEXT((var), field))
> -
> -
> -#define COGL_STAILQ_FOREACH_SAFE(var, head, field, tvar) \
> - for ((var) = COGL_STAILQ_FIRST((head)); \
> - (var) && ((tvar) = COGL_STAILQ_NEXT((var), field), 1); \
> - (var) = (tvar))
> -
> -#define COGL_STAILQ_INIT(head) do { \
> - COGL_STAILQ_FIRST((head)) = NULL; \
> - (head)->stqh_last = &COGL_STAILQ_FIRST((head)); \
> -} while (0)
> -
> -#define COGL_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
> - if ((COGL_STAILQ_NEXT((elm), field) = \
> - COGL_STAILQ_NEXT((tqelm), field)) == NULL) \
> - (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field); \
> - COGL_STAILQ_NEXT((tqelm), field) = (elm); \
> -} while (0)
> -
> -#define COGL_STAILQ_INSERT_HEAD(head, elm, field) do { \
> - if ((COGL_STAILQ_NEXT((elm), field) = \
> - COGL_STAILQ_FIRST((head))) == NULL) \
> - (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field); \
> - COGL_STAILQ_FIRST((head)) = (elm); \
> - } while (0)
> -
> -#define COGL_STAILQ_INSERT_TAIL(head, elm, field) do { \
> - COGL_STAILQ_NEXT((elm), field) = NULL; \
> - *(head)->stqh_last = (elm); \
> - (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field); \
> -} while (0)
> -
> -#define COGL_STAILQ_LAST(head, type, field) \
> - (COGL_STAILQ_EMPTY((head)) ? \
> - NULL : \
> - ((type *)(void *) \
> - ((char *)((head)->stqh_last) - \
> - __offsetof(struct type, field))))
> -
> -#define COGL_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
> -
> -#define COGL_STAILQ_REMOVE(head, elm, type, field) do { \
> - COGL_QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
> - if (COGL_STAILQ_FIRST((head)) == (elm)) { \
> - COGL_STAILQ_REMOVE_HEAD((head), field); \
> - } \
> - else { \
> - type *curelm = COGL_STAILQ_FIRST((head)); \
> - while (COGL_STAILQ_NEXT(curelm, field) != (elm)) \
> - curelm = COGL_STAILQ_NEXT(curelm, field); \
> - COGL_STAILQ_REMOVE_AFTER(head, curelm, field); \
> - } \
> - COGL_TRASHIT(*oldnext); \
> -} while (0)
> -
> -#define COGL_STAILQ_REMOVE_AFTER(head, elm, field) do { \
> - if ((COGL_STAILQ_NEXT(elm, field) = \
> - COGL_STAILQ_NEXT(COGL_STAILQ_NEXT(elm, field), \
> - field)) == NULL) \
> - (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field); \
> -} while (0)
> -
> -#define COGL_STAILQ_REMOVE_HEAD(head, field) do { \
> - if ((COGL_STAILQ_FIRST((head)) = \
> - COGL_STAILQ_NEXT(COGL_STAILQ_FIRST((head)), field)) == NULL) \
> - (head)->stqh_last = &COGL_STAILQ_FIRST((head)); \
> -} while (0)
> -
> -#define COGL_STAILQ_SWAP(head1, head2, type) do { \
> - type *swap_first = COGL_STAILQ_FIRST(head1); \
> - type **swap_last = (head1)->stqh_last; \
> - COGL_STAILQ_FIRST(head1) = COGL_STAILQ_FIRST(head2); \
> - (head1)->stqh_last = (head2)->stqh_last; \
> - COGL_STAILQ_FIRST(head2) = swap_first; \
> - (head2)->stqh_last = swap_last; \
> - if (COGL_STAILQ_EMPTY(head1)) \
> - (head1)->stqh_last = &COGL_STAILQ_FIRST(head1); \
> - if (COGL_STAILQ_EMPTY(head2)) \
> - (head2)->stqh_last = &COGL_STAILQ_FIRST(head2); \
> -} while (0)
> -
> -
> -/*
> - * List declarations.
> - */
> -#define COGL_LIST_HEAD(name, type) \
> -typedef struct _ ## name { \
> - type *lh_first; /* first element */ \
> -} name
> -
> -#define COGL_LIST_HEAD_INITIALIZER(head) \
> - { NULL }
> -
> -#define COGL_LIST_ENTRY(type) \
> -struct { \
> - type *le_next; /* next element */ \
> - type **le_prev; /* address of previous next element */ \
> -}
> -
> -/*
> - * List functions.
> - */
> -
> -#if (defined(_KERNEL) && defined(INVARIANTS))
> -#define COGL_QMD_LIST_CHECK_HEAD(head, field) do { \
> - if (COGL_LIST_FIRST((head)) != NULL && \
> - COGL_LIST_FIRST((head))->field.le_prev != \
> - &COGL_LIST_FIRST((head))) \
> - panic("Bad list head %p first->prev != head", (head)); \
> -} while (0)
> -
> -#define COGL_QMD_LIST_CHECK_NEXT(elm, field) do { \
> - if (COGL_LIST_NEXT((elm), field) != NULL && \
> - COGL_LIST_NEXT((elm), field)->field.le_prev != \
> - &((elm)->field.le_next)) \
> - panic("Bad link elm %p next->prev != elm", (elm)); \
> -} while (0)
> -
> -#define COGL_QMD_LIST_CHECK_PREV(elm, field) do { \
> - if (*(elm)->field.le_prev != (elm)) \
> - panic("Bad link elm %p prev->next != elm", (elm)); \
> -} while (0)
> -#else
> -#define COGL_QMD_LIST_CHECK_HEAD(head, field)
> -#define COGL_QMD_LIST_CHECK_NEXT(elm, field)
> -#define COGL_QMD_LIST_CHECK_PREV(elm, field)
> -#endif /* (_KERNEL && INVARIANTS) */
> -
> -#define COGL_LIST_EMPTY(head) ((head)->lh_first == NULL)
> -
> -#define COGL_LIST_FIRST(head) ((head)->lh_first)
> -
> -#define COGL_LIST_FOREACH(var, head, field) \
> - for ((var) = COGL_LIST_FIRST((head)); \
> - (var); \
> - (var) = COGL_LIST_NEXT((var), field))
> -
> -#define COGL_LIST_FOREACH_SAFE(var, head, field, tvar) \
> - for ((var) = COGL_LIST_FIRST((head)); \
> - (var) && ((tvar) = COGL_LIST_NEXT((var), field), 1); \
> - (var) = (tvar))
> -
> -#define COGL_LIST_INIT(head) do { \
> - COGL_LIST_FIRST((head)) = NULL; \
> -} while (0)
> -
> -#define COGL_LIST_INSERT_AFTER(listelm, elm, field) do { \
> - COGL_QMD_LIST_CHECK_NEXT(listelm, field); \
> - if ((COGL_LIST_NEXT((elm), field) = \
> - COGL_LIST_NEXT((listelm), field)) != NULL) \
> - COGL_LIST_NEXT((listelm), field)->field.le_prev = \
> - &COGL_LIST_NEXT((elm), field); \
> - COGL_LIST_NEXT((listelm), field) = (elm); \
> - (elm)->field.le_prev = &COGL_LIST_NEXT((listelm), field); \
> -} while (0)
> -
> -#define COGL_LIST_INSERT_BEFORE(listelm, elm, field) do { \
> - COGL_QMD_LIST_CHECK_PREV(listelm, field); \
> - (elm)->field.le_prev = (listelm)->field.le_prev; \
> - COGL_LIST_NEXT((elm), field) = (listelm); \
> - *(listelm)->field.le_prev = (elm); \
> - (listelm)->field.le_prev = &COGL_LIST_NEXT((elm), field); \
> -} while (0)
> -
> -#define COGL_LIST_INSERT_HEAD(head, elm, field) do { \
> - COGL_QMD_LIST_CHECK_HEAD((head), field); \
> - if ((COGL_LIST_NEXT((elm), field) = \
> - COGL_LIST_FIRST((head))) != NULL) \
> - COGL_LIST_FIRST((head))->field.le_prev = \
> - &COGL_LIST_NEXT((elm), field); \
> - COGL_LIST_FIRST((head)) = (elm); \
> - (elm)->field.le_prev = &COGL_LIST_FIRST((head)); \
> -} while (0)
> -
> -#define COGL_LIST_NEXT(elm, field) ((elm)->field.le_next)
> -
> -#define COGL_LIST_REMOVE(elm, field) do { \
> - COGL_QMD_SAVELINK(oldnext, (elm)->field.le_next); \
> - COGL_QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
> - COGL_QMD_LIST_CHECK_NEXT(elm, field); \
> - COGL_QMD_LIST_CHECK_PREV(elm, field); \
> - if (COGL_LIST_NEXT((elm), field) != NULL) \
> - COGL_LIST_NEXT((elm), field)->field.le_prev = \
> - (elm)->field.le_prev; \
> - *(elm)->field.le_prev = COGL_LIST_NEXT((elm), field); \
> - COGL_TRASHIT(*oldnext); \
> - COGL_TRASHIT(*oldprev); \
> -} while (0)
> -
> -#define COGL_LIST_SWAP(head1, head2, type, field) do { \
> - type *swap_tmp = COGL_LIST_FIRST((head1)); \
> - COGL_LIST_FIRST((head1)) = COGL_LIST_FIRST((head2)); \
> - COGL_LIST_FIRST((head2)) = swap_tmp; \
> - if ((swap_tmp = COGL_LIST_FIRST((head1))) != NULL) \
> - swap_tmp->field.le_prev = &COGL_LIST_FIRST((head1)); \
> - if ((swap_tmp = COGL_LIST_FIRST((head2))) != NULL) \
> - swap_tmp->field.le_prev = &COGL_LIST_FIRST((head2)); \
> -} while (0)
> -
> -/*
> - * Tail queue declarations.
> - */
> -#define COGL_TAILQ_HEAD(name, type) \
> -typedef struct _ ## name { \
> - type *tqh_first; /* first element */ \
> - type **tqh_last; /* addr of last next element */ \
> - COGL_TRACEBUF \
> -} name
> -
> -#define COGL_TAILQ_HEAD_INITIALIZER(head) \
> - { NULL, &(head).tqh_first }
> -
> -#define COGL_TAILQ_ENTRY(type) \
> -struct { \
> - type *tqe_next; /* next element */ \
> - type **tqe_prev; /* address of previous next element */ \
> - COGL_TRACEBUF \
> -}
> -
> -/*
> - * Tail queue functions.
> - */
> -#if (defined(_KERNEL) && defined(INVARIANTS))
> -#define COGL_QMD_TAILQ_CHECK_HEAD(head, field) do { \
> - if (!COGL_TAILQ_EMPTY(head) && \
> - COGL_TAILQ_FIRST((head))->field.tqe_prev != \
> - &COGL_TAILQ_FIRST((head))) \
> - panic("Bad tailq head %p first->prev != head", (head)); \
> -} while (0)
> -
> -#define COGL_QMD_TAILQ_CHECK_TAIL(head, field) do { \
> - if (*(head)->tqh_last != NULL) \
> - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
> -} while (0)
> -
> -#define COGL_QMD_TAILQ_CHECK_NEXT(elm, field) do { \
> - if (COGL_TAILQ_NEXT((elm), field) != NULL && \
> - COGL_TAILQ_NEXT((elm), field)->field.tqe_prev != \
> - &((elm)->field.tqe_next)) \
> - panic("Bad link elm %p next->prev != elm", (elm)); \
> -} while (0)
> -
> -#define COGL_QMD_TAILQ_CHECK_PREV(elm, field) do { \
> - if (*(elm)->field.tqe_prev != (elm)) \
> - panic("Bad link elm %p prev->next != elm", (elm)); \
> -} while (0)
> -#else
> -#define COGL_QMD_TAILQ_CHECK_HEAD(head, field)
> -#define COGL_QMD_TAILQ_CHECK_TAIL(head, headname)
> -#define COGL_QMD_TAILQ_CHECK_NEXT(elm, field)
> -#define COGL_QMD_TAILQ_CHECK_PREV(elm, field)
> -#endif /* (_KERNEL && INVARIANTS) */
> -
> -#define COGL_TAILQ_CONCAT(head1, head2, field) do { \
> - if (!COGL_TAILQ_EMPTY(head2)) { \
> - *(head1)->tqh_last = (head2)->tqh_first; \
> - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
> - (head1)->tqh_last = (head2)->tqh_last; \
> - COGL_TAILQ_INIT((head2)); \
> - COGL_QMD_TRACE_HEAD(head1); \
> - COGL_QMD_TRACE_HEAD(head2); \
> - } \
> -} while (0)
> -
> -#define COGL_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
> -
> -#define COGL_TAILQ_FIRST(head) ((head)->tqh_first)
> -
> -#define COGL_TAILQ_FOREACH(var, head, field) \
> - for ((var) = COGL_TAILQ_FIRST((head)); \
> - (var); \
> - (var) = COGL_TAILQ_NEXT((var), field))
> -
> -#define COGL_TAILQ_FOREACH_SAFE(var, head, field, tvar) \
> - for ((var) = COGL_TAILQ_FIRST((head)); \
> - (var) && ((tvar) = COGL_TAILQ_NEXT((var), field), 1); \
> - (var) = (tvar))
> -
> -#define COGL_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
> - for ((var) = COGL_TAILQ_LAST((head), headname); \
> - (var); \
> - (var) = COGL_TAILQ_PREV((var), headname, field))
> -
> -#define COGL_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
> - for ((var) = COGL_TAILQ_LAST((head), headname); \
> - (var) && ((tvar) = COGL_TAILQ_PREV((var), headname, field), 1); \
> - (var) = (tvar))
> -
> -#define COGL_TAILQ_INIT(head) do { \
> - COGL_TAILQ_FIRST((head)) = NULL; \
> - (head)->tqh_last = &COGL_TAILQ_FIRST((head)); \
> - COGL_QMD_TRACE_HEAD(head); \
> -} while (0)
> -
> -#define COGL_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
> - COGL_QMD_TAILQ_CHECK_NEXT(listelm, field); \
> - if ((COGL_TAILQ_NEXT((elm), field) = \
> - COGL_TAILQ_NEXT((listelm), field)) != NULL) \
> - COGL_TAILQ_NEXT((elm), field)->field.tqe_prev = \
> - &COGL_TAILQ_NEXT((elm), field); \
> - else { \
> - (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field); \
> - COGL_QMD_TRACE_HEAD(head); \
> - } \
> - COGL_TAILQ_NEXT((listelm), field) = (elm); \
> - (elm)->field.tqe_prev = &COGL_TAILQ_NEXT((listelm), field); \
> - COGL_QMD_TRACE_ELEM(&(elm)->field); \
> - COGL_QMD_TRACE_ELEM(&listelm->field); \
> -} while (0)
> -
> -#define COGL_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
> - COGL_QMD_TAILQ_CHECK_PREV(listelm, field); \
> - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
> - COGL_TAILQ_NEXT((elm), field) = (listelm); \
> - *(listelm)->field.tqe_prev = (elm); \
> - (listelm)->field.tqe_prev = &COGL_TAILQ_NEXT((elm), field); \
> - COGL_QMD_TRACE_ELEM(&(elm)->field); \
> - COGL_QMD_TRACE_ELEM(&listelm->field); \
> -} while (0)
> -
> -#define COGL_TAILQ_INSERT_HEAD(head, elm, field) do { \
> - COGL_QMD_TAILQ_CHECK_HEAD(head, field); \
> - if ((COGL_TAILQ_NEXT((elm), field) = \
> - COGL_TAILQ_FIRST((head))) != NULL) \
> - COGL_TAILQ_FIRST((head))->field.tqe_prev = \
> - &COGL_TAILQ_NEXT((elm), field); \
> - else \
> - (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field); \
> - COGL_TAILQ_FIRST((head)) = (elm); \
> - (elm)->field.tqe_prev = &COGL_TAILQ_FIRST((head)); \
> - COGL_QMD_TRACE_HEAD(head); \
> - COGL_QMD_TRACE_ELEM(&(elm)->field); \
> -} while (0)
> -
> -#define COGL_TAILQ_INSERT_TAIL(head, elm, field) do { \
> - COGL_QMD_TAILQ_CHECK_TAIL(head, field); \
> - COGL_TAILQ_NEXT((elm), field) = NULL; \
> - (elm)->field.tqe_prev = (head)->tqh_last; \
> - *(head)->tqh_last = (elm); \
> - (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field); \
> - COGL_QMD_TRACE_HEAD(head); \
> - COGL_QMD_TRACE_ELEM(&(elm)->field); \
> -} while (0)
> -
> -#define COGL_TAILQ_LAST(head, headname) \
> - (*(((headname *)((head)->tqh_last))->tqh_last))
> -
> -#define COGL_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
> -
> -#define COGL_TAILQ_PREV(elm, headname, field) \
> - (*(((headname *)((elm)->field.tqe_prev))->tqh_last))
> -
> -#define COGL_TAILQ_REMOVE(head, elm, field) do { \
> - COGL_QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
> - COGL_QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
> - COGL_QMD_TAILQ_CHECK_NEXT(elm, field); \
> - COGL_QMD_TAILQ_CHECK_PREV(elm, field); \
> - if ((COGL_TAILQ_NEXT((elm), field)) != NULL) \
> - COGL_TAILQ_NEXT((elm), field)->field.tqe_prev = \
> - (elm)->field.tqe_prev; \
> - else { \
> - (head)->tqh_last = (elm)->field.tqe_prev; \
> - COGL_QMD_TRACE_HEAD(head); \
> - } \
> - *(elm)->field.tqe_prev = COGL_TAILQ_NEXT((elm), field); \
> - COGL_TRASHIT(*oldnext); \
> - COGL_TRASHIT(*oldprev); \
> - COGL_QMD_TRACE_ELEM(&(elm)->field); \
> -} while (0)
> -
> -#define COGL_TAILQ_SWAP(head1, head2, type, field) do { \
> - type *swap_first = (head1)->tqh_first; \
> - type **swap_last = (head1)->tqh_last; \
> - (head1)->tqh_first = (head2)->tqh_first; \
> - (head1)->tqh_last = (head2)->tqh_last; \
> - (head2)->tqh_first = swap_first; \
> - (head2)->tqh_last = swap_last; \
> - if ((swap_first = (head1)->tqh_first) != NULL) \
> - swap_first->field.tqe_prev = &(head1)->tqh_first; \
> - else \
> - (head1)->tqh_last = &(head1)->tqh_first; \
> - if ((swap_first = (head2)->tqh_first) != NULL) \
> - swap_first->field.tqe_prev = &(head2)->tqh_first; \
> - else \
> - (head2)->tqh_last = &(head2)->tqh_first; \
> -} while (0)
> -
> -#endif /* !_COGL_QUEUE_H_ */
> diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
> index 62aca7e..efc20a3 100644
> --- a/cogl/cogl-renderer-private.h
> +++ b/cogl/cogl-renderer-private.h
> @@ -56,7 +56,7 @@ struct _CoglRenderer
> int poll_fds_age;
> GList *poll_sources;
>
> - CoglClosureList idle_closures;
> + CoglList idle_closures;
>
> GList *outputs;
>
> diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
> index bfd91cd..6f978c6 100644
> --- a/cogl/cogl-renderer.c
> +++ b/cogl/cogl-renderer.c
> @@ -187,7 +187,7 @@ cogl_renderer_new (void)
>
> renderer->poll_fds = g_array_new (FALSE, TRUE, sizeof (CoglPollFD));
>
> - COGL_LIST_INIT (&renderer->idle_closures);
> + _cogl_list_init (&renderer->idle_closures);
>
> #ifdef COGL_HAS_XLIB_SUPPORT
> renderer->xlib_enable_event_retrieval = TRUE;
> diff --git a/cogl/cogl-sdl.c b/cogl/cogl-sdl.c
> index 602cac0..324bfd8 100644
> --- a/cogl/cogl-sdl.c
> +++ b/cogl/cogl-sdl.c
> @@ -100,6 +100,6 @@ cogl_sdl_idle (CoglContext *context)
> * to make sure the blocking returns immediately. We'll post our
> * dummy event to make sure that happens
> */
> - if (!COGL_LIST_EMPTY (&renderer->idle_closures))
> + if (!_cogl_list_empty (&renderer->idle_closures))
> _cogl_sdl_push_wakeup_event (context);
> }
> diff --git a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> index 0b06dd4..9fa9cbf 100644
> --- a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> +++ b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
> @@ -38,6 +38,7 @@
> #include "cogl-pipeline-layer-private.h"
> #include "cogl-blend-string.h"
> #include "cogl-snippet-private.h"
> +#include "cogl-list.h"
>
> #ifdef COGL_PIPELINE_FRAGEND_GLSL
>
> @@ -66,13 +67,9 @@ typedef struct _UnitState
> unsigned int combine_constant_used:1;
> } UnitState;
>
> -typedef struct _LayerData LayerData;
> -
> -COGL_LIST_HEAD (LayerDataList, LayerData);
> -
> -struct _LayerData
> +typedef struct _LayerData
> {
> - COGL_LIST_ENTRY (LayerData) list_node;
> + CoglList link;
>
> /* Layer index for the for the previous layer. This isn't
> necessarily the same as this layer's index - 1 because the
> @@ -81,7 +78,7 @@ struct _LayerData
> int previous_layer_index;
>
> CoglPipelineLayer *layer;
> -};
> +} LayerData;
>
> typedef struct
> {
> @@ -97,7 +94,7 @@ typedef struct
> in reverse order. As soon as we're about to generate code for
> layer we'll remove it from the list so we don't generate it
> again */
> - LayerDataList layers;
> + CoglList layers;
> } CoglPipelineShaderState;
>
> static CoglUserDataKey shader_state_key;
> @@ -349,7 +346,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
> g_string_set_size (ctx->codegen_source_buffer, 0);
> shader_state->header = ctx->codegen_header_buffer;
> shader_state->source = ctx->codegen_source_buffer;
> - COGL_LIST_INIT (&shader_state->layers);
> + _cogl_list_init (&shader_state->layers);
>
> add_layer_declarations (pipeline, shader_state);
> add_global_declarations (pipeline, shader_state);
> @@ -750,7 +747,7 @@ ensure_layer_generated (CoglPipeline *pipeline,
> LayerData *layer_data;
>
> /* Find the layer that corresponds to this layer_num */
> - COGL_LIST_FOREACH (layer_data, &shader_state->layers, list_node)
> + _cogl_list_for_each (layer_data, &shader_state->layers, link)
> {
> layer = layer_data->layer;
>
> @@ -765,7 +762,7 @@ ensure_layer_generated (CoglPipeline *pipeline,
> found:
>
> /* Remove the layer from the list so we don't generate it again */
> - COGL_LIST_REMOVE (layer_data, list_node);
> + _cogl_list_remove (&layer_data->link);
>
> combine_authority =
> _cogl_pipeline_layer_get_authority (layer,
> @@ -882,13 +879,18 @@ _cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline,
> layer_data = g_slice_new (LayerData);
> layer_data->layer = layer;
>
> - if (COGL_LIST_EMPTY (&shader_state->layers))
> - layer_data->previous_layer_index = -1;
> + if (_cogl_list_empty (&shader_state->layers))
> + {
> + layer_data->previous_layer_index = -1;
> + }
> else
> - layer_data->previous_layer_index
> - = COGL_LIST_FIRST (&shader_state->layers)->layer->index;
> + {
> + LayerData *first =
> + _cogl_container_of (shader_state->layers.next, first, link);
> + layer_data->previous_layer_index = first->layer->index;
> + }
>
> - COGL_LIST_INSERT_HEAD (&shader_state->layers, layer_data, list_node);
> + _cogl_list_insert (&shader_state->layers, &layer_data->link);
>
> return TRUE;
> }
> @@ -988,20 +990,25 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
> for the last layer. If the value of this layer depends on any
> previous layers then it will recursively generate the code
> for those layers */
> - if (!COGL_LIST_EMPTY (&shader_state->layers))
> + if (!_cogl_list_empty (&shader_state->layers))
> {
> CoglPipelineLayer *last_layer;
> LayerData *layer_data, *tmp;
>
> - last_layer = COGL_LIST_FIRST (&shader_state->layers)->layer;
> + layer_data = _cogl_container_of (shader_state->layers.next,
> + layer_data,
> + link);
> + last_layer = layer_data->layer;
>
> ensure_layer_generated (pipeline, last_layer->index);
> g_string_append_printf (shader_state->source,
> " cogl_color_out = cogl_layer%i;\n",
> last_layer->index);
>
> - COGL_LIST_FOREACH_SAFE (layer_data, &shader_state->layers,
> - list_node, tmp)
> + _cogl_list_for_each_safe (layer_data,
> + tmp,
> + &shader_state->layers,
> + link)
> g_slice_free (LayerData, layer_data);
> }
> else
> diff --git a/doc/reference/cogl2/Makefile.am b/doc/reference/cogl2/Makefile.am
> index e4556c3..9424c51 100644
> --- a/doc/reference/cogl2/Makefile.am
> +++ b/doc/reference/cogl2/Makefile.am
> @@ -78,7 +78,6 @@ IGNORE_HFILES=\
> cogl-gl-header.h \
> cogl-glsl-shader-boilerplate.h \
> cogl-profile.h \
> - cogl-queue.h \
> cogl-rectangle-map.h \
> cogl-spans.h \
> cogl-texture-driver.h \
> --
> 1.7.11.3.g3c3efa5
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl
More information about the Cogl
mailing list