*/
#include "vigs_gl_backend.h"
+#include "vigs_gl_pool.h"
#include "vigs_surface.h"
#include "vigs_plane.h"
#include "vigs_log.h"
* into front buffer.
*
* Allocated on first access.
- *
- * TODO: Make a global framebuffer pool and use framebuffers from
- * it. Framebuffer pool must contain one framebuffer per distinct
- * surface format.
*/
GLuint fb;
" FragColor = color;\n"
"}\n";
+static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format)
+{
+ struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
+ GLint tex_internalformat;
+ GLenum tex_format;
+ GLenum tex_type;
+ GLuint tex = 0, cur_tex = 0;
+
+ backend->GenTextures(1, &tex);
+
+ if (!tex) {
+ return 0;
+ }
+
+ switch (format) {
+ case vigsp_surface_bgrx8888:
+ case vigsp_surface_bgra8888:
+ tex_internalformat = GL_RGBA8;
+ tex_format = GL_BGRA;
+ tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ default:
+ assert(false);
+ return 0;
+ }
+
+ backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
+ backend->BindTexture(GL_TEXTURE_2D, tex);
+
+ /*
+ * Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3":
+ * These lines used to be in 'vigs_gl_backend_init', but it turned out that they must
+ * be called after 'glBindTexture'.
+ */
+ backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ backend->TexImage2D(GL_TEXTURE_2D, 0, tex_internalformat,
+ width, height, 0,
+ tex_format, tex_type,
+ NULL);
+ backend->BindTexture(GL_TEXTURE_2D, cur_tex);
+
+ return tex;
+}
+
+static void vigs_gl_backend_release_tmp_texture(void *user_data, GLuint id)
+{
+ struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
+
+ backend->DeleteTextures(1, &id);
+}
+
+static GLuint vigs_gl_backend_alloc_framebuffer(void *user_data,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format)
+{
+ struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
+ GLuint fb = 0;
+
+ backend->GenFramebuffers(1, &fb);
+
+ return fb;
+}
+
+static void vigs_gl_backend_release_framebuffer(void *user_data, GLuint id)
+{
+ struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
+
+ backend->DeleteFramebuffers(1, &id);
+}
+
static GLuint vigs_gl_create_shader(struct vigs_gl_backend *backend,
const char *source,
GLenum type)
}
}
-static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface *ws_sfc,
- GLuint *tex)
+static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface *ws_sfc)
{
GLuint cur_tex = 0;
- if (*tex) {
+ if (ws_sfc->tex) {
return true;
}
- ws_sfc->backend->GenTextures(1, tex);
+ ws_sfc->backend->GenTextures(1, &ws_sfc->tex);
- if (!*tex) {
- goto fail;
+ if (!ws_sfc->tex) {
+ return false;
}
ws_sfc->backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
- ws_sfc->backend->BindTexture(GL_TEXTURE_2D, *tex);
+ ws_sfc->backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
/*
* Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3":
ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex);
return true;
+}
-fail:
- return false;
+static bool vigs_gl_surface_create_tmp_texture(struct vigs_gl_surface *gl_sfc)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
+
+ if (gl_sfc->tmp_tex) {
+ return true;
+ }
+
+ gl_sfc->tmp_tex = vigs_gl_pool_alloc(gl_backend->tex_pool,
+ gl_sfc->base.ws_sfc->width,
+ gl_sfc->base.ws_sfc->height,
+ gl_sfc->base.format);
+
+ return gl_sfc->tmp_tex != 0;
}
static bool vigs_gl_surface_setup_framebuffer(struct vigs_gl_surface *gl_sfc,
struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
if (!gl_sfc->fb) {
- gl_backend->GenFramebuffers(1, &gl_sfc->fb);
+ gl_sfc->fb = vigs_gl_pool_alloc(gl_backend->fb_pool,
+ gl_sfc->base.ws_sfc->width,
+ gl_sfc->base.ws_sfc->height,
+ gl_sfc->base.format);
if (!gl_sfc->fb) {
return false;
(has_current ||
vigs_sfc->backend->make_current(vigs_sfc->backend, true))) {
- vigs_winsys_gl_surface_create_texture(vigs_sfc,
- &vigs_sfc->tex);
+ vigs_winsys_gl_surface_create_texture(vigs_sfc);
if (!has_current) {
vigs_sfc->backend->make_current(vigs_sfc->backend, false);
goto out;
}
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &ws_sfc->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
goto out;
}
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &gl_sfc->tmp_tex)) {
+ if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
goto out;
}
GLfloat *tex_coords;
uint32_t i;
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &ws_sfc->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
goto out;
}
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &gl_sfc->tmp_tex)) {
+ if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
goto out;
}
GLfloat *vert_coords;
GLfloat *tex_coords;
- if (!vigs_winsys_gl_surface_create_texture(ws_dst, &ws_dst->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_dst)) {
goto out;
}
VIGS_LOG_WARN("copying garbage ???");
}
- if (!vigs_winsys_gl_surface_create_texture(ws_src, &ws_src->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_src)) {
goto out;
}
* Feedback loop is possible, use 'tmp_tex' instead.
*/
- if (!vigs_winsys_gl_surface_create_texture(ws_dst, &gl_dst->tmp_tex)) {
+ if (!vigs_gl_surface_create_tmp_texture(gl_dst)) {
goto out;
}
GLfloat colorf[4];
GLfloat sfc_h;
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &ws_sfc->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
goto out;
}
vigs_winsys_gl_surface_orphan(ws_sfc);
if (gl_sfc->fb) {
- gl_backend->DeleteFramebuffers(1, &gl_sfc->fb);
+ vigs_gl_pool_release(gl_backend->fb_pool,
+ sfc->ws_sfc->width,
+ sfc->ws_sfc->height,
+ sfc->format);
}
if (gl_sfc->tmp_tex) {
- gl_backend->DeleteTextures(1, &gl_sfc->tmp_tex);
+ vigs_gl_pool_release(gl_backend->tex_pool,
+ sfc->ws_sfc->width,
+ sfc->ws_sfc->height,
+ sfc->format);
}
vigs_surface_cleanup(&gl_sfc->base);
VIGS_LOG_WARN("compositing garbage (root surface) ???");
}
- if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc, &ws_root_sfc->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc)) {
goto out;
}
}
- if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc, &gl_root_sfc->tmp_tex)) {
+ if (!vigs_gl_surface_create_tmp_texture(gl_root_sfc)) {
goto out;
}
VIGS_LOG_WARN("compositing garbage (plane %u) ???", i);
}
- if (!vigs_winsys_gl_surface_create_texture(ws_sfc, &ws_sfc->tex)) {
+ if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
goto out;
}
}
return false;
}
+ gl_backend->tex_pool = vigs_gl_pool_create("tmp_tex",
+ &vigs_gl_backend_alloc_tmp_texture,
+ &vigs_gl_backend_release_tmp_texture,
+ gl_backend);
+ gl_backend->fb_pool = vigs_gl_pool_create("fb",
+ &vigs_gl_backend_alloc_framebuffer,
+ &vigs_gl_backend_release_framebuffer,
+ gl_backend);
+
if (gl_backend->is_gl_2) {
const char *tmp = (const char*)gl_backend->GetString(GL_EXTENSIONS);
gl_backend->DeleteVertexArrays(1, &gl_backend->vao);
}
+ vigs_gl_pool_destroy(gl_backend->fb_pool);
+ vigs_gl_pool_destroy(gl_backend->tex_pool);
+
gl_backend->make_current(gl_backend, false);
}
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "vigs_gl_pool.h"
+#include "vigs_log.h"
+
+struct vigs_gl_pool_key
+{
+ uint32_t width;
+ uint32_t height;
+ vigsp_surface_format format;
+};
+
+struct vigs_gl_pool_value
+{
+ struct vigs_gl_pool *pool;
+
+ GLuint id;
+
+ /*
+ * We don't want to use struct vigs_ref here since
+ * these objects are owned by hash table, i.e. destruction
+ * must be performed from outside when needed.
+ */
+ uint32_t user_count;
+};
+
+static guint vigs_gl_pool_hash(gconstpointer a)
+{
+ const struct vigs_gl_pool_key *key = a;
+
+ return (key->width |
+ (key->height << 13) |
+ ((uint32_t)key->format << 26));
+}
+
+static gboolean vigs_gl_pool_equal(gconstpointer a, gconstpointer b)
+{
+ const struct vigs_gl_pool_key *left = a;
+ const struct vigs_gl_pool_key *right = b;
+
+ if (left->width != right->width) {
+ return FALSE;
+ }
+
+ if (left->height != right->height) {
+ return FALSE;
+ }
+
+ if (left->format != right->format) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void vigs_gl_pool_key_destroy(gpointer data)
+{
+ struct vigs_gl_pool_key *key = data;
+
+ g_free(key);
+}
+
+static void vigs_gl_pool_value_destroy(gpointer data)
+{
+ struct vigs_gl_pool_value *value = data;
+
+ assert(value->user_count == 0);
+
+ value->pool->release_func(value->pool->user_data, value->id);
+
+ g_free(value);
+}
+
+struct vigs_gl_pool
+ *vigs_gl_pool_create(const char *name,
+ vigs_gl_pool_alloc_func alloc_func,
+ vigs_gl_pool_release_func release_func,
+ void *user_data)
+{
+ struct vigs_gl_pool *pool;
+
+ pool = g_malloc0(sizeof(*pool));
+
+ strncpy(pool->name, name, sizeof(pool->name)/sizeof(pool->name[0]));
+ pool->name[sizeof(pool->name)/sizeof(pool->name[0]) - 1] = '\0';
+
+ pool->entries = g_hash_table_new_full(vigs_gl_pool_hash,
+ vigs_gl_pool_equal,
+ vigs_gl_pool_key_destroy,
+ vigs_gl_pool_value_destroy);
+
+ pool->alloc_func = alloc_func;
+ pool->release_func = release_func;
+ pool->user_data = user_data;
+
+ return pool;
+}
+
+void vigs_gl_pool_destroy(struct vigs_gl_pool *pool)
+{
+ g_hash_table_destroy(pool->entries);
+
+ g_free(pool);
+}
+
+GLuint vigs_gl_pool_alloc(struct vigs_gl_pool *pool,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format)
+{
+ struct vigs_gl_pool_key tmp_key;
+ GLuint id;
+ struct vigs_gl_pool_key *key;
+ struct vigs_gl_pool_value *value;
+
+ tmp_key.width = width;
+ tmp_key.height = height;
+ tmp_key.format = format;
+
+ value = g_hash_table_lookup(pool->entries, &tmp_key);
+
+ if (value) {
+ ++value->user_count;
+
+ return value->id;
+ }
+
+ id = pool->alloc_func(pool->user_data, width, height, format);
+
+ if (!id) {
+ return id;
+ }
+
+ key = g_malloc0(sizeof(*key));
+
+ key->width = width;
+ key->height = height;
+ key->format = format;
+
+ value = g_malloc0(sizeof(*value));
+
+ value->pool = pool;
+ value->id = id;
+ value->user_count = 1;
+
+ g_hash_table_insert(pool->entries, key, value);
+
+ VIGS_LOG_TRACE("pool %s: num_entries = %u",
+ pool->name,
+ g_hash_table_size(pool->entries));
+
+ return value->id;
+}
+
+void vigs_gl_pool_release(struct vigs_gl_pool *pool,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format)
+{
+ struct vigs_gl_pool_key tmp_key;
+ struct vigs_gl_pool_value *value;
+
+ tmp_key.width = width;
+ tmp_key.height = height;
+ tmp_key.format = format;
+
+ value = g_hash_table_lookup(pool->entries, &tmp_key);
+
+ assert(value);
+
+ if (!value) {
+ return;
+ }
+
+ assert(value->user_count > 0);
+
+ if (--value->user_count == 0) {
+ g_hash_table_remove(pool->entries, &tmp_key);
+
+ VIGS_LOG_TRACE("pool %s: num_entries = %u",
+ pool->name,
+ g_hash_table_size(pool->entries));
+ }
+}
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef _QEMU_VIGS_GL_POOL_H
+#define _QEMU_VIGS_GL_POOL_H
+
+#include "vigs_types.h"
+#include <glib.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+typedef GLuint (*vigs_gl_pool_alloc_func)(void */*user_data*/,
+ uint32_t /*width*/,
+ uint32_t /*height*/,
+ vigsp_surface_format /*format*/);
+
+typedef void (*vigs_gl_pool_release_func)(void */*user_data*/,
+ GLuint /*id*/);
+
+struct vigs_gl_pool
+{
+ char name[255];
+
+ GHashTable *entries;
+
+ vigs_gl_pool_alloc_func alloc_func;
+
+ vigs_gl_pool_release_func release_func;
+
+ void *user_data;
+};
+
+struct vigs_gl_pool
+ *vigs_gl_pool_create(const char *name,
+ vigs_gl_pool_alloc_func alloc_func,
+ vigs_gl_pool_release_func release_func,
+ void *user_data);
+
+void vigs_gl_pool_destroy(struct vigs_gl_pool *pool);
+
+GLuint vigs_gl_pool_alloc(struct vigs_gl_pool *pool,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format);
+
+void vigs_gl_pool_release(struct vigs_gl_pool *pool,
+ uint32_t width,
+ uint32_t height,
+ vigsp_surface_format format);
+
+#endif