summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2014-03-26 16:46:55 +0100
committerJosep Torra <n770galaxy@gmail.com>2014-03-26 16:51:45 +0100
commitc5339b1dd002a95320f41855d652195bd48aee02 (patch)
treeba1164f8daa3b5350d31742ecc3ae4a4c65d7d0a
parent11a0fccf59774c6d927b6b299e87fee99cbdabac (diff)
Add egl mini library
Provides EGLDisplay, EGLMemory and EGLMemoryPool refcounted objects.
-rw-r--r--Makefile6
-rw-r--r--egl.c576
-rw-r--r--egl.h81
-rw-r--r--triangle.c44
4 files changed, 687 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index dce6341..3754505 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-OBJS=triangle.o video.o ilclient.o ilcore.o
+OBJS=triangle.o video.o ilclient.o ilcore.o egl.o
BIN=rpi_test_egl
CFLAGS+=-O0 -g3
@@ -8,8 +8,8 @@ LDFLAGS+=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos
INCLUDES+=-I$(SDKSTAGE)/opt/vc/include/ -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -I$(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux -I./
-CFLAGS += $(shell pkg-config --cflags glib-2.0)
-LDFLAGS += $(shell pkg-config --libs glib-2.0)
+CFLAGS += $(shell pkg-config --cflags glib-2.0 gobject-2.0)
+LDFLAGS += $(shell pkg-config --libs glib-2.0 gobject-2.0)
all: $(BIN) $(LIB)
diff --git a/egl.c b/egl.c
new file mode 100644
index 0000000..5acaa24
--- /dev/null
+++ b/egl.c
@@ -0,0 +1,576 @@
+/*
+ * Derived from GStreamer 0.10 EGL Library in gst-omx
+ * Copyright (C) 2014 Fluendo S.A.
+ * @author: Josep Torra <josep@fluendo.com>
+ * *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#define EGL_EGLEXT_PROTOTYPES
+#include "egl.h"
+
+#define DEBUG_MAGIC_CHECK 0
+
+#if DEBUG_MAGIC_CHECK
+#define EGLMEMORY_MAGIC 0x5fce5fce
+#define EGLMEMORY_POOL_MAGIC 0x5fce9001
+
+#define EGLMEMORY_POOL_MAGIC_ASSERT(pool) G_STMT_START { \
+ g_assert (pool->magic == EGLMEMORY_POOL_MAGIC); \
+} G_STMT_END
+#define EGLMEMORY_MAGIC_ASSERT(mem) G_STMT_START { \
+ g_assert (mem->magic == EGLMEMORY_MAGIC); \
+} G_STMT_END
+#else
+#define EGLMEMORY_POOL_MAGIC_ASSERT(pool) G_STMT_START{ }G_STMT_END
+#define EGLMEMORY_MAGIC_ASSERT(mem) G_STMT_START{ }G_STMT_END
+#endif
+
+struct _EGLImageMemory
+{
+ volatile gint refcount;
+
+#if DEBUG_MAGIC_CHECK
+ guint32 magic;
+#endif
+
+ EGLClientBuffer client_buffer;
+ EGLImageKHR image;
+
+ gpointer user_data;
+ GDestroyNotify destroy_data;
+
+ EGLImageMemoryPool *pool;
+};
+
+#define EGL_IMAGE_MEMORY(mem) ((EGLImageMemory *)(mem))
+
+struct _EGLImageMemoryPool
+{
+ volatile gint refcount;
+
+#if DEBUG_MAGIC_CHECK
+ guint32 magic;
+#endif
+
+ GMutex *lock;
+ GCond *cond;
+
+ EGLDisplayWrapper *display;
+ EGLImageMemory *memory;
+
+ gint size;
+ volatile gint unused;
+ volatile gint active;
+
+ gpointer user_data;
+ DestroyNotifyEGLImageMemoryPool destroy_data;
+};
+
+#define EGL_IMAGE_MEMORY_POOL_LOCK(pool) G_STMT_START { \
+ g_mutex_lock (pool->lock); \
+} G_STMT_END
+
+#define EGL_IMAGE_MEMORY_POOL_UNLOCK(pool) G_STMT_START { \
+ g_mutex_unlock (pool->lock); \
+} G_STMT_END
+
+#define EGL_IMAGE_MEMORY_POOL_WAIT_RELEASED(pool) G_STMT_START { \
+ g_cond_wait (pool->cond, pool->lock); \
+} G_STMT_END
+
+#define EGL_IMAGE_MEMORY_POOL_SIGNAL_UNUSED(pool) G_STMT_START { \
+ g_cond_signal (pool->cond); \
+} G_STMT_END
+
+#define EGL_IMAGE_MEMORY_POOL_IS_FULL(pool) (g_atomic_int_get (&pool->unused) == 0)
+#define EGL_IMAGE_MEMORY_POOL_IS_EMPTY(pool) (g_atomic_int_get (&pool->unused) == pool->size)
+
+#define EGL_IMAGE_MEMORY_POOL_SET_ACTIVE(pool,active) \
+ g_atomic_int_set (&pool->active, active)
+#define EGL_IMAGE_MEMORY_POOL_IS_ACTIVE(pool) (g_atomic_int_get (&pool->active) == TRUE)
+
+struct _EGLDisplayWrapper
+{
+ volatile gint refcount;
+
+ EGLDisplay display;
+
+ gpointer user_data;
+ GDestroyNotify destroy_data;
+};
+
+/**
+ * egl_image_memory_ref
+ * @mem: a #EGLImageMemory
+ *
+ * Increase the refcount of @mem.
+ *
+ */
+EGLImageMemory *
+egl_image_memory_ref (EGLImageMemory * mem)
+{
+ g_return_val_if_fail (mem != NULL, NULL);
+
+ EGLMEMORY_MAGIC_ASSERT (mem);
+
+ g_atomic_int_inc (&mem->refcount);
+
+ return mem;
+}
+
+static void
+egl_image_memory_free (EGLImageMemory * mem)
+{
+ EGLImageMemoryPool *pool = mem->pool;
+
+ /* We grab the pool lock as we will make changes to number of unused
+ * memories. */
+ EGL_IMAGE_MEMORY_POOL_LOCK (pool);
+
+ /* We have one more unused memory */
+ g_atomic_int_inc (&pool->unused);
+
+ /* Wake up potential waiters */
+ EGL_IMAGE_MEMORY_POOL_SIGNAL_UNUSED (pool);
+
+ EGL_IMAGE_MEMORY_POOL_UNLOCK (pool);
+
+ if (mem->destroy_data) {
+ mem->destroy_data (mem->user_data);
+ }
+
+ /* Remove our ref to the pool. That could destroy the pool so it is
+ * important to do that when we released the lock */
+ mem->pool = egl_image_memory_pool_unref (pool);
+}
+
+/**
+ * egl_image_memory_unref:
+ * @mem: a #EGLImageMemory
+ *
+ * Unref @mem and when the refcount reaches 0 frees the resources
+ * and return NULL.
+ *
+ */
+EGLImageMemory *
+egl_image_memory_unref (EGLImageMemory * mem)
+{
+ g_return_val_if_fail (mem != NULL, NULL);
+
+ EGLMEMORY_MAGIC_ASSERT (mem);
+
+ if (g_atomic_int_dec_and_test (&mem->refcount)) {
+ egl_image_memory_free (mem);
+ mem = NULL;
+ }
+
+ return mem;
+}
+
+/**
+ * egl_image_memory_get_image:
+ * @mem: a #EGLImageMemory
+ *
+ * Gives the #EGLImageKHR used by the #EGLImageMemory.
+ *
+ */
+EGLImageKHR
+egl_image_memory_get_image (EGLImageMemory * mem)
+{
+ return mem->image;
+}
+
+/**
+ * egl_image_memory_pool_new:
+ * @size: a number of memories managed by the pool
+ * @display: a #EGLDisplayWrapper display
+ * @user_data: user data passed to the callback
+ * @destroy_data: #DestroyNotifyEGLImageMemoryPool for user_data
+ *
+ * Create a new EGLImageMemoryPool instance with the provided images.
+ *
+ * Returns: a new #EGLImageMemoryPool
+ *
+ */
+EGLImageMemoryPool *
+egl_image_memory_pool_new (gint size, EGLDisplayWrapper * display,
+ gpointer user_data, DestroyNotifyEGLImageMemoryPool destroy_data)
+{
+ EGLImageMemoryPool *pool;
+
+ pool = g_new0 (EGLImageMemoryPool, 1);
+
+ pool->refcount = 1;
+ pool->lock = g_mutex_new ();
+ pool->cond = g_cond_new ();
+ pool->display = egl_display_ref (display);
+ pool->memory = (EGLImageMemory *) g_new0 (EGLImageMemory, size);
+ pool->size = pool->unused = size;
+ pool->user_data = user_data;
+ pool->destroy_data = destroy_data;
+
+#if DEBUG_MAGIC_CHECK
+ {
+ gint i;
+ pool->magic = EGLMEMORY_POOL_MAGIC;
+ for (i = 0; i < size; i++) {
+ EGLImageMemory *mem = &pool->memory[i];
+ mem->magic = EGLMEMORY_MAGIC;
+ }
+ }
+#endif
+
+ return pool;
+}
+
+/**
+ * egl_image_memory_pool_ref:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Increase the refcount of @pool.
+ *
+ */
+EGLImageMemoryPool *
+egl_image_memory_pool_ref (EGLImageMemoryPool * pool)
+{
+ g_return_val_if_fail (pool != NULL, NULL);
+
+ EGLMEMORY_POOL_MAGIC_ASSERT (pool);
+
+ g_atomic_int_inc (&pool->refcount);
+
+ return pool;
+}
+
+static void
+egl_image_memory_pool_free (EGLImageMemoryPool * pool)
+{
+ if (g_atomic_int_get (&pool->unused) != pool->size) {
+ g_critical ("refcounting problem detected, some memory is still in use");
+ }
+
+ if (pool->destroy_data) {
+ pool->destroy_data (pool, pool->user_data);
+ }
+
+ egl_display_unref (pool->display);
+ g_mutex_free (pool->lock);
+ g_cond_free (pool->cond);
+
+ g_free (pool->memory);
+ g_free (pool);
+}
+
+/**
+ * egl_image_memory_pool_unref:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Unref @pool and when the refcount reaches 0 frees the resources
+ * and return NULL.
+ *
+ */
+EGLImageMemoryPool *
+egl_image_memory_pool_unref (EGLImageMemoryPool * pool)
+{
+ g_return_val_if_fail (pool != NULL, NULL);
+
+ EGLMEMORY_POOL_MAGIC_ASSERT (pool);
+
+ if (g_atomic_int_dec_and_test (&pool->refcount)) {
+ egl_image_memory_pool_free (pool);
+ pool = NULL;
+ }
+ return pool;
+}
+
+/**
+ * egl_image_memory_pool_get_size:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Gives the number of memories that are managed by the pool.
+ *
+ */
+gint
+egl_image_memory_pool_get_size (EGLImageMemoryPool * pool)
+{
+ g_return_val_if_fail (pool != NULL, 0);
+
+ return pool->size;
+}
+
+/**
+ * egl_image_memory_pool_set_resources:
+ * @pool: a #EGLImageMemoryPool
+ * @idx: memory index
+ * @client_buffer: an #EGLClientBuffer to store in the pool
+ * @image: an #EGLImageKHR to store in the pool.
+ *
+ * Stores @client_buffer and @image at @idx memory slot.
+ *
+ */
+gboolean
+egl_image_memory_pool_set_resources (EGLImageMemoryPool * pool, gint idx,
+ EGLClientBuffer client_buffer, EGLImageKHR image)
+{
+ EGLImageMemory *mem;
+
+ g_return_val_if_fail (pool != NULL, FALSE);
+ g_return_val_if_fail (idx >= 0 && idx < pool->size, FALSE);
+
+ mem = &pool->memory[idx];
+ mem->client_buffer = client_buffer;
+ mem->image = image;
+
+ return TRUE;
+}
+
+/**
+ * egl_image_memory_pool_get_resources:
+ * @pool: a #EGLImageMemoryPool
+ * @idx: memory index
+ * @client_buffer: (out) (allow-none): the #EGLClientBuffer at @idx
+ * @image: (out) (allow-none): the #EGLImageKHR at @idx
+ *
+ * Retrieves @client_buffer and @image at @idx memory slot.
+ *
+ */
+gboolean
+egl_image_memory_pool_get_resources (EGLImageMemoryPool * pool, gint idx,
+ EGLClientBuffer * client_buffer, EGLImageKHR * image)
+{
+ EGLImageMemory *mem;
+
+ g_return_val_if_fail (pool != NULL, FALSE);
+ g_return_val_if_fail (idx >= 0 && idx < pool->size, FALSE);
+
+ mem = &pool->memory[idx];
+
+ if (client_buffer)
+ *client_buffer = mem->client_buffer;
+
+ if (image)
+ *image = mem->image;
+
+ return TRUE;
+}
+
+/**
+ * egl_image_memory_pool_get_display:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Provides a reference to the #EGLDisplayWrapper used by the pool
+ */
+EGLDisplayWrapper *
+egl_image_memory_pool_get_display (EGLImageMemoryPool * pool)
+{
+ g_return_val_if_fail (pool != NULL, NULL);
+
+ EGLMEMORY_POOL_MAGIC_ASSERT (pool);
+
+ g_return_val_if_fail (pool->display != NULL, NULL);
+
+ return egl_display_ref (pool->display);
+}
+
+/**
+ * egl_image_memory_pool_get_images:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Provides a #GList of EGL images
+ */
+GList *
+egl_image_memory_pool_get_images (EGLImageMemoryPool * pool)
+{
+ gint i;
+ GList *images = NULL;
+
+ g_return_val_if_fail (pool != NULL, NULL);
+
+ for (i = 0; i < pool->size; i++) {
+ EGLImageMemory *mem = &pool->memory[i];
+ images = g_list_append (images, mem->image);
+ }
+
+ return images;
+}
+
+/**
+ * egl_image_memory_pool_set_active:
+ * @pool: a #EGLImageMemoryPool
+ * @active: a #gboolean that indicates the pool is active
+ *
+ * Change @pool active state and unblocks any wait condition if needed.
+ *
+ */
+void
+egl_image_memory_pool_set_active (EGLImageMemoryPool * pool,
+ gboolean active)
+{
+ g_return_if_fail (pool != NULL);
+
+ EGLMEMORY_POOL_MAGIC_ASSERT (pool);
+
+ EGL_IMAGE_MEMORY_POOL_SET_ACTIVE (pool, active);
+
+ if (!active) {
+ EGL_IMAGE_MEMORY_POOL_SIGNAL_UNUSED (pool);
+ }
+}
+
+/**
+ * egl_image_memory_pool_wait_released:
+ * @pool: a #EGLImageMemoryPool
+ *
+ * Waits until none of the memory is in use.
+ *
+ */
+void
+egl_image_memory_pool_wait_released (EGLImageMemoryPool * pool)
+{
+ g_return_if_fail (pool != NULL);
+
+ EGLMEMORY_POOL_MAGIC_ASSERT (pool);
+
+ EGL_IMAGE_MEMORY_POOL_LOCK (pool);
+ while (!EGL_IMAGE_MEMORY_POOL_IS_EMPTY (pool)) {
+ EGL_IMAGE_MEMORY_POOL_WAIT_RELEASED (pool);
+ }
+ EGL_IMAGE_MEMORY_POOL_UNLOCK (pool);
+}
+
+/**
+ * egl_image_memory_pool_acquire_memory:
+ * @pool: a #EGLImageMemoryPool
+ * @idx: ordinal that specifies a #EGLImageMemory in the pool
+ * @user_data: user data passed to the callback
+ * @destroy_data: #GDestroyNotify for user_data
+ *
+ * Provides an specified #EGLImageMemory.
+ *
+ */
+EGLImageMemory *
+egl_image_memory_pool_acquire_memory (EGLImageMemoryPool * pool,
+ gint idx, gpointer user_data, GDestroyNotify destroy_data)
+{
+ EGLImageMemory *mem;
+
+ g_return_val_if_fail (pool != NULL, NULL);
+ g_return_val_if_fail (idx >= 0 && idx < pool->size, NULL);
+
+ EGL_IMAGE_MEMORY_POOL_LOCK (pool);
+ if (!EGL_IMAGE_MEMORY_POOL_IS_ACTIVE (pool)) {
+ EGL_IMAGE_MEMORY_POOL_UNLOCK (pool);
+ return NULL;
+ }
+
+ mem = &pool->memory[idx];
+
+ g_atomic_int_add (&pool->unused, -1);
+ g_atomic_int_set (&mem->refcount, 1);
+ mem->pool = egl_image_memory_pool_ref (pool);
+ mem->user_data = user_data;
+ mem->destroy_data = destroy_data;
+
+ EGL_IMAGE_MEMORY_POOL_UNLOCK (pool);
+
+ return mem;
+}
+
+G_DEFINE_BOXED_TYPE (EGLImageMemoryPool, egl_image_memory_pool,
+ (GBoxedCopyFunc) egl_image_memory_pool_ref,
+ (GBoxedFreeFunc) egl_image_memory_pool_unref);
+
+/**
+ * egl_display_new:
+ * @display: a #EGLDisplayWrapper display
+ * @user_data: user data passed to the callback
+ * @destroy_data: #GDestroyNotify for user_data
+ *
+ * Create a new #EGLDisplayWrapper that wraps and refcount @display.
+ *
+ * Returns: a new #EGLDisplayWrapper
+ *
+ */
+EGLDisplayWrapper *
+egl_display_new (EGLDisplay display, gpointer user_data,
+ GDestroyNotify destroy_data)
+{
+ EGLDisplayWrapper *gdisplay;
+
+ gdisplay = g_slice_new (EGLDisplayWrapper);
+ gdisplay->refcount = 1;
+ gdisplay->display = display;
+ gdisplay->user_data = user_data;
+ gdisplay->destroy_data = destroy_data;
+
+ return gdisplay;
+}
+
+/**
+ * egl_display_ref
+ * @display: a #EGLDisplayWrapper
+ *
+ * Increase the refcount of @display.
+ *
+ */
+EGLDisplayWrapper *
+egl_display_ref (EGLDisplayWrapper * display)
+{
+ g_return_val_if_fail (display != NULL, NULL);
+
+ g_atomic_int_inc (&display->refcount);
+
+ return display;
+}
+
+/**
+ * egl_display_unref:
+ * @display: a #EGLDisplayWrapper
+ *
+ * Decrease the refcount of @display and calls provided destroy function on
+ * last reference.
+ *
+ */
+void
+egl_display_unref (EGLDisplayWrapper * display)
+{
+ g_return_if_fail (display != NULL);
+
+ if (g_atomic_int_dec_and_test (&display->refcount)) {
+ if (display->destroy_data) {
+ display->destroy_data (display->user_data);
+ }
+ g_slice_free (EGLDisplayWrapper, display);
+ }
+}
+
+/**
+ * egl_display_get
+ * @display: a #EGLDisplayWrapper
+ *
+ * Gives the #EGLDisplay wrapped.
+ *
+ */
+EGLDisplay
+egl_display_get (EGLDisplayWrapper * display)
+{
+ g_return_val_if_fail (display != NULL, EGL_NO_DISPLAY);
+
+ return display->display;
+}
+
diff --git a/egl.h b/egl.h
new file mode 100644
index 0000000..22074da
--- /dev/null
+++ b/egl.h
@@ -0,0 +1,81 @@
+/*
+ * Derived from GStreamer 0.10 EGL Library in gst-omx
+ * Copyright (C) 2014 Fluendo S.A.
+ * @author: Josep Torra <josep@fluendo.com>
+ * *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MY_EGL_H__
+#define __MY_EGL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EGLImageMemory EGLImageMemory;
+typedef struct _EGLImageMemoryPool EGLImageMemoryPool;
+typedef struct _EGLDisplayWrapper EGLDisplayWrapper;
+typedef void (*DestroyNotifyEGLImageMemoryPool) (EGLImageMemoryPool *
+ pool, gpointer user_data);
+
+/* EGLImageMemory handling */
+EGLImageMemory *egl_image_memory_ref (EGLImageMemory * mem);
+EGLImageMemory *egl_image_memory_unref (EGLImageMemory * mem);
+EGLImageKHR egl_image_memory_get_image (EGLImageMemory * mem);
+
+/* EGLImageMemoryPool handling */
+#define TYPE_EGL_IMAGE_MEMORY_POOL (egl_image_memory_pool_get_type())
+GType egl_image_memory_pool_get_type (void);
+
+EGLImageMemoryPool *egl_image_memory_pool_new (gint size,
+ EGLDisplayWrapper * display, gpointer user_data,
+ DestroyNotifyEGLImageMemoryPool destroy_data);
+EGLImageMemoryPool *egl_image_memory_pool_ref (EGLImageMemoryPool *
+ pool);
+EGLImageMemoryPool *egl_image_memory_pool_unref (EGLImageMemoryPool *
+ pool);
+gint egl_image_memory_pool_get_size (EGLImageMemoryPool * pool);
+
+gboolean egl_image_memory_pool_set_resources (EGLImageMemoryPool * pool,
+ gint idx, EGLClientBuffer client_buffer, EGLImageKHR image);
+
+gboolean egl_image_memory_pool_get_resources (EGLImageMemoryPool * pool,
+ gint idx, EGLClientBuffer * client_buffer, EGLImageKHR * image);
+
+EGLDisplayWrapper *egl_image_memory_pool_get_display (EGLImageMemoryPool *
+ pool);
+GList *egl_image_memory_pool_get_images (EGLImageMemoryPool * pool);
+void egl_image_memory_pool_set_active (EGLImageMemoryPool * pool,
+ gboolean active);
+void egl_image_memory_pool_wait_released (EGLImageMemoryPool * pool);
+EGLImageMemory *egl_image_memory_pool_acquire_memory (EGLImageMemoryPool *
+ pool, gint idx, gpointer user_data, GDestroyNotify destroy_data);
+
+/* EGLDisplay wrapper with refcount, connection is closed after last ref is gone */
+EGLDisplayWrapper * egl_display_new (EGLDisplay display, gpointer user_data,
+ GDestroyNotify destroy_data);
+EGLDisplayWrapper *egl_display_ref (EGLDisplayWrapper * display);
+void egl_display_unref (EGLDisplayWrapper * display);
+EGLDisplay egl_display_get (EGLDisplayWrapper * display);
+
+G_END_DECLS
+
+#endif /* __MY_EGL_H__ */
diff --git a/triangle.c b/triangle.c
index 4fd3ffc..552f05f 100644
--- a/triangle.c
+++ b/triangle.c
@@ -50,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "cube_texture_and_coords.h"
#include "triangle.h"
+#include "egl.h"
#define PATH "./"
@@ -71,18 +72,21 @@ typedef struct
gboolean animate;
/* OpenGL|ES objects */
- EGLDisplay display;
+ EGLDisplayWrapper *display;
EGLSurface surface;
EGLContext context;
GLuint tex;
+
/* model rotation vector and direction */
GLfloat rot_angle_x_inc;
GLfloat rot_angle_y_inc;
GLfloat rot_angle_z_inc;
+
/* current model rotation angles */
GLfloat rot_angle_x;
GLfloat rot_angle_y;
GLfloat rot_angle_z;
+
/* current distance from camera */
GLfloat distance;
GLfloat distance_inc;
@@ -123,6 +127,7 @@ init_ogl (AppState * state)
int32_t success = 0;
EGLBoolean result;
EGLint num_config;
+ EGLDisplay display;
static EGL_DISPMANX_WINDOW_T nativewindow;
@@ -145,24 +150,26 @@ init_ogl (AppState * state)
EGLConfig config;
/* get an EGL display connection */
- state->display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
- assert (state->display != EGL_NO_DISPLAY);
+ display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+ assert (display != EGL_NO_DISPLAY);
+ state->display = egl_display_new (display, display,
+ (GDestroyNotify) eglTerminate);
/* initialize the EGL display connection */
- result = eglInitialize (state->display, NULL, NULL);
+ result = eglInitialize (display, NULL, NULL);
assert (EGL_FALSE != result);
/* get an appropriate EGL frame buffer configuration
* this uses a BRCM extension that gets the closest match, rather
* than standard which returns anything that matches. */
result =
- eglSaneChooseConfigBRCM (state->display, attribute_list, &config, 1,
+ eglSaneChooseConfigBRCM (display, attribute_list, &config, 1,
&num_config);
assert (EGL_FALSE != result);
/* create an EGL rendering context */
state->context =
- eglCreateContext (state->display, config, EGL_NO_CONTEXT, NULL);
+ eglCreateContext (display, config, EGL_NO_CONTEXT, NULL);
assert (state->context != EGL_NO_CONTEXT);
/* Open display */
@@ -200,12 +207,12 @@ init_ogl (AppState * state)
vc_dispmanx_update_submit_sync (dispman_update);
state->surface =
- eglCreateWindowSurface (state->display, config, &nativewindow, NULL);
+ eglCreateWindowSurface (display, config, &nativewindow, NULL);
assert (state->surface != EGL_NO_SURFACE);
/* connect the context to the surface */
result =
- eglMakeCurrent (state->display, state->surface, state->surface,
+ eglMakeCurrent (display, state->surface, state->surface,
state->context);
assert (EGL_FALSE != result);
@@ -388,6 +395,7 @@ inc_and_clip_distance (GLfloat distance, GLfloat distance_inc)
static void
redraw_scene (AppState * state)
{
+ EGLDisplay display = egl_display_get (state->display);
/* Start with a clear screen */
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -413,7 +421,7 @@ redraw_scene (AppState * state)
glRotatef (90.f, 0.f, 1.f, 0.f); /* bottom face normal along y axis */
glDrawArrays (GL_TRIANGLE_STRIP, 20, 4);
- eglSwapBuffers (state->display, state->surface);
+ eglSwapBuffers (display, state->surface);
}
/***********************************************************
@@ -431,6 +439,7 @@ redraw_scene (AppState * state)
static void
init_textures (AppState * state)
{
+ EGLDisplay display = egl_display_get (state->display);
glGenTextures (1, &state->tex);
glBindTexture (GL_TEXTURE_2D, state->tex);
@@ -450,7 +459,7 @@ init_textures (AppState * state)
/* Create EGL Image */
- state->ipc.eglImage = eglCreateImageKHR (state->display,
+ state->ipc.eglImage = eglCreateImageKHR (display,
state->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) state->tex, 0);
if (state->ipc.eglImage == EGL_NO_IMAGE_KHR) {
@@ -474,22 +483,23 @@ static void
close_ogl (void)
{
DISPMANX_UPDATE_HANDLE_T dispman_update;
-
+ EGLDisplay display = egl_display_get (state->display);
+
if (state->ipc.eglImage != 0) {
- if (!eglDestroyImageKHR (state->display, (EGLImageKHR) state->ipc.eglImage))
+ if (!eglDestroyImageKHR (display, (EGLImageKHR) state->ipc.eglImage))
g_print ("eglDestroyImageKHR failed.");
}
/* clear screen */
glClear (GL_COLOR_BUFFER_BIT);
- eglSwapBuffers (state->display, state->surface);
+ eglSwapBuffers (display, state->surface);
/* Release OpenGL resources */
- eglMakeCurrent (state->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ eglMakeCurrent (display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
- eglDestroySurface (state->display, state->surface);
- eglDestroyContext (state->display, state->context);
- eglTerminate (state->display);
+ eglDestroySurface (display, state->surface);
+ eglDestroyContext (display, state->context);
+ egl_display_unref (state->display);
dispman_update = vc_dispmanx_update_start (0);
vc_dispmanx_element_remove (dispman_update, state->dispman_element);