summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorStanislav Vorobiov <s.vorobiov@samsung.com>2013-07-04 14:24:26 +0400
committerStanislav Vorobiov <s.vorobiov@samsung.com>2013-07-04 14:51:02 +0400
commit1ffb232808c23e30b9e44fc6011ef3ed97d7748d (patch)
tree06096144907fed90f9cb84146864a28ab3a9bb52 /hw
parent1aac667b899131b126eece73ceccd75f22669342 (diff)
downloadqemu-1ffb232808c23e30b9e44fc6011ef3ed97d7748d.tar.gz
qemu-1ffb232808c23e30b9e44fc6011ef3ed97d7748d.tar.bz2
qemu-1ffb232808c23e30b9e44fc6011ef3ed97d7748d.zip
YaGL: eglBindTexImage/eglReleaseTexImage implemented
YaGL: memory leak fixed in onscreen EGLImageKHR eglBindTexImage/eglReleaseTexImage implemented for onscreen via texture redirection. For offscreen it's left unimplemented Onscreen EGLImageKHR creation code didn't release reference to image data, this is fixed
Diffstat (limited to 'hw')
-rw-r--r--hw/yagl_apis/egl/yagl_egl_config.c9
-rw-r--r--hw/yagl_apis/egl/yagl_host_egl_calls.c114
-rw-r--r--hw/yagl_apis/egl/yagl_host_egl_calls.h8
-rw-r--r--hw/yagl_apis/gles/yagl_gles_context.c24
-rw-r--r--hw/yagl_apis/gles/yagl_gles_tex_image.c68
-rw-r--r--hw/yagl_apis/gles/yagl_gles_tex_image.h39
-rw-r--r--hw/yagl_apis/gles/yagl_gles_texture.c82
-rw-r--r--hw/yagl_apis/gles/yagl_gles_texture.h22
-rw-r--r--hw/yagl_apis/gles/yagl_host_gles_calls.c12
-rw-r--r--hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c20
-rw-r--r--hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c9
-rw-r--r--hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c83
-rw-r--r--hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h6
-rw-r--r--hw/yagl_client_context.h7
-rw-r--r--hw/yagl_client_tex_image.c32
-rw-r--r--hw/yagl_client_tex_image.h41
-rw-r--r--hw/yagl_egl_native_config.c2
-rw-r--r--hw/yagl_egl_native_config.h2
-rw-r--r--hw/yagl_eglb_surface.h11
19 files changed, 566 insertions, 25 deletions
diff --git a/hw/yagl_apis/egl/yagl_egl_config.c b/hw/yagl_apis/egl/yagl_egl_config.c
index 32f7852bbf..86cf6339b8 100644
--- a/hw/yagl_apis/egl/yagl_egl_config.c
+++ b/hw/yagl_apis/egl/yagl_egl_config.c
@@ -164,6 +164,9 @@ static struct yagl_egl_config
cfg->native.sample_buffers_num = (cfg->native.samples_per_pixel > 0) ? 1 : 0;
+ cfg->native.bind_to_texture_rgb = EGL_TRUE;
+ cfg->native.bind_to_texture_rgba = EGL_TRUE;
+
return cfg;
}
@@ -279,6 +282,8 @@ bool yagl_egl_config_is_chosen_by(const struct yagl_egl_config *cfg,
YAGL_CHECK_ATTRIB_CAST(caveat, !=);
YAGL_CHECK_ATTRIB_CAST(native_renderable, !=);
YAGL_CHECK_ATTRIB_CAST(transparent_type, !=);
+ YAGL_CHECK_ATTRIB_CAST(bind_to_texture_rgb, !=);
+ YAGL_CHECK_ATTRIB_CAST(bind_to_texture_rgba, !=);
/*
* Mask.
@@ -332,10 +337,10 @@ bool yagl_egl_config_get_attrib(const struct yagl_egl_config *cfg,
*value = cfg->native.alpha_size;
break;
case EGL_BIND_TO_TEXTURE_RGB:
- *value = EGL_FALSE;
+ *value = cfg->native.bind_to_texture_rgb;
break;
case EGL_BIND_TO_TEXTURE_RGBA:
- *value = EGL_FALSE;
+ *value = cfg->native.bind_to_texture_rgba;
break;
case EGL_CONFIG_CAVEAT:
*value = cfg->native.caveat;
diff --git a/hw/yagl_apis/egl/yagl_host_egl_calls.c b/hw/yagl_apis/egl/yagl_host_egl_calls.c
index a9415cf887..56a4d81b1c 100644
--- a/hw/yagl_apis/egl/yagl_host_egl_calls.c
+++ b/hw/yagl_apis/egl/yagl_host_egl_calls.c
@@ -529,6 +529,8 @@ bool yagl_host_eglChooseConfig(EGLBoolean* retval,
dummy.trans_blue_val = EGL_DONT_CARE;
dummy.transparent_type = EGL_NONE;
dummy.match_format_khr = EGL_DONT_CARE;
+ dummy.bind_to_texture_rgb = EGL_DONT_CARE;
+ dummy.bind_to_texture_rgba = EGL_DONT_CARE;
if (!yagl_egl_is_attrib_list_empty(attrib_list)) {
bool has_config_id = false;
@@ -540,8 +542,12 @@ bool yagl_host_eglChooseConfig(EGLBoolean* retval,
case EGL_MAX_PBUFFER_HEIGHT:
case EGL_MAX_PBUFFER_PIXELS:
case EGL_NATIVE_VISUAL_ID:
+ break;
case EGL_BIND_TO_TEXTURE_RGB:
+ dummy.bind_to_texture_rgb = attrib_list[i + 1];
+ break;
case EGL_BIND_TO_TEXTURE_RGBA:
+ dummy.bind_to_texture_rgba = attrib_list[i + 1];
break;
case EGL_SURFACE_TYPE:
dummy.surface_type = attrib_list[i + 1];
@@ -1071,19 +1077,115 @@ out:
}
bool yagl_host_eglBindTexImage(EGLBoolean* retval,
- yagl_host_handle dpy,
- yagl_host_handle surface,
+ yagl_host_handle dpy_,
+ yagl_host_handle surface_,
EGLint buffer)
{
- YAGL_UNIMPLEMENTED(eglBindTexImage, EGL_FALSE);
+ struct yagl_egl_display *dpy = NULL;
+ struct yagl_egl_surface *surface = NULL;
+
+ YAGL_LOG_FUNC_SET(eglBindTexImage);
+
+ if (!egl_api_ts->context) {
+ YAGL_LOG_WARN("No context");
+ *retval = EGL_TRUE;
+ goto out;
+ }
+
+ *retval = EGL_FALSE;
+
+ if (!yagl_validate_display(dpy_, &dpy)) {
+ goto out;
+ }
+
+ if (!yagl_validate_surface(dpy, surface_, &surface)) {
+ goto out;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ YAGL_SET_ERR(EGL_BAD_PARAMETER);
+ goto out;
+ }
+
+ if (surface->backend_sfc->type != EGL_PBUFFER_BIT) {
+ YAGL_SET_ERR(EGL_BAD_SURFACE);
+ goto out;
+ }
+
+ if (surface->backend_sfc->attribs.pbuffer.tex_format == EGL_NO_TEXTURE) {
+ YAGL_SET_ERR(EGL_BAD_MATCH);
+ goto out;
+ }
+
+ if (surface->backend_sfc->attribs.pbuffer.tex_target == EGL_NO_TEXTURE) {
+ YAGL_SET_ERR(EGL_BAD_MATCH);
+ goto out;
+ }
+
+ if (!surface->backend_sfc->bind_tex_image(surface->backend_sfc)) {
+ YAGL_SET_ERR(EGL_BAD_ACCESS);
+ goto out;
+ }
+
+ *retval = EGL_TRUE;
+
+out:
+ yagl_egl_surface_release(surface);
+
+ return true;
}
bool yagl_host_eglReleaseTexImage(EGLBoolean* retval,
- yagl_host_handle dpy,
- yagl_host_handle surface,
+ yagl_host_handle dpy_,
+ yagl_host_handle surface_,
EGLint buffer)
{
- YAGL_UNIMPLEMENTED(eglReleaseTexImage, EGL_FALSE);
+ struct yagl_egl_display *dpy = NULL;
+ struct yagl_egl_surface *surface = NULL;
+
+ YAGL_LOG_FUNC_SET(eglReleaseTexImage);
+
+ *retval = EGL_FALSE;
+
+ if (!yagl_validate_display(dpy_, &dpy)) {
+ goto out;
+ }
+
+ if (!yagl_validate_surface(dpy, surface_, &surface)) {
+ goto out;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ YAGL_SET_ERR(EGL_BAD_PARAMETER);
+ goto out;
+ }
+
+ if (surface->backend_sfc->type != EGL_PBUFFER_BIT) {
+ YAGL_SET_ERR(EGL_BAD_SURFACE);
+ goto out;
+ }
+
+ if (surface->backend_sfc->attribs.pbuffer.tex_format == EGL_NO_TEXTURE) {
+ YAGL_SET_ERR(EGL_BAD_MATCH);
+ goto out;
+ }
+
+ if (surface->backend_sfc->attribs.pbuffer.tex_target == EGL_NO_TEXTURE) {
+ YAGL_SET_ERR(EGL_BAD_MATCH);
+ goto out;
+ }
+
+ if (!surface->backend_sfc->release_tex_image(surface->backend_sfc)) {
+ YAGL_SET_ERR(EGL_BAD_ACCESS);
+ goto out;
+ }
+
+ *retval = EGL_TRUE;
+
+out:
+ yagl_egl_surface_release(surface);
+
+ return true;
}
bool yagl_host_eglCreateContext(yagl_host_handle* retval,
diff --git a/hw/yagl_apis/egl/yagl_host_egl_calls.h b/hw/yagl_apis/egl/yagl_host_egl_calls.h
index de12ed0eb5..fa335e7666 100644
--- a/hw/yagl_apis/egl/yagl_host_egl_calls.h
+++ b/hw/yagl_apis/egl/yagl_host_egl_calls.h
@@ -55,12 +55,12 @@ bool yagl_host_eglSurfaceAttrib(EGLBoolean* retval,
EGLint attribute,
EGLint value);
bool yagl_host_eglBindTexImage(EGLBoolean* retval,
- yagl_host_handle dpy,
- yagl_host_handle surface,
+ yagl_host_handle dpy_,
+ yagl_host_handle surface_,
EGLint buffer);
bool yagl_host_eglReleaseTexImage(EGLBoolean* retval,
- yagl_host_handle dpy,
- yagl_host_handle surface,
+ yagl_host_handle dpy_,
+ yagl_host_handle surface_,
EGLint buffer);
bool yagl_host_eglCreateContext(yagl_host_handle* retval,
yagl_host_handle dpy_,
diff --git a/hw/yagl_apis/gles/yagl_gles_context.c b/hw/yagl_apis/gles/yagl_gles_context.c
index f76e36f10b..3565f2680f 100644
--- a/hw/yagl_apis/gles/yagl_gles_context.c
+++ b/hw/yagl_apis/gles/yagl_gles_context.c
@@ -7,6 +7,7 @@
#include "yagl_gles_texture_unit.h"
#include "yagl_gles_validate.h"
#include "yagl_gles_image.h"
+#include "yagl_gles_tex_image.h"
#include "yagl_gles_texture.h"
#include "yagl_log.h"
#include "yagl_process.h"
@@ -171,6 +172,28 @@ static struct yagl_client_image
return image ? &image->base : NULL;
}
+static struct yagl_client_tex_image
+ *yagl_gles_context_create_tex_image(struct yagl_client_context *ctx,
+ yagl_object_name tex_global_name,
+ struct yagl_ref *tex_data)
+{
+ struct yagl_gles_context *gles_ctx = (struct yagl_gles_context*)ctx;
+ struct yagl_gles_texture_target_state *texture_target_state =
+ yagl_gles_context_get_active_texture_target_state(gles_ctx,
+ yagl_gles_texture_target_2d);
+
+ if (!texture_target_state->texture) {
+ return NULL;
+ }
+
+ yagl_gles_tex_image_create(tex_global_name,
+ tex_data,
+ texture_target_state->texture);
+
+ return texture_target_state->texture->tex_image ?
+ &texture_target_state->texture->tex_image->base : NULL;
+}
+
void yagl_gles_context_init(struct yagl_gles_context *ctx,
struct yagl_gles_driver *driver)
{
@@ -178,6 +201,7 @@ void yagl_gles_context_init(struct yagl_gles_context *ctx,
ctx->base.finish = &yagl_gles_context_finish;
ctx->base.read_pixels = &yagl_gles_context_read_pixels;
ctx->base.create_image = &yagl_gles_context_create_image;
+ ctx->base.create_tex_image = &yagl_gles_context_create_tex_image;
ctx->driver = driver;
diff --git a/hw/yagl_apis/gles/yagl_gles_tex_image.c b/hw/yagl_apis/gles/yagl_gles_tex_image.c
new file mode 100644
index 0000000000..7d14afe678
--- /dev/null
+++ b/hw/yagl_apis/gles/yagl_gles_tex_image.c
@@ -0,0 +1,68 @@
+#include <GL/gl.h>
+#include "yagl_gles_tex_image.h"
+#include "yagl_gles_texture.h"
+
+static void yagl_gles_tex_image_unbind(struct yagl_client_tex_image *tex_image)
+{
+ struct yagl_gles_tex_image *gles_tex_image =
+ (struct yagl_gles_tex_image*)tex_image;
+ struct yagl_ref *data = tex_image->data;
+
+ assert(gles_tex_image->bound_texture);
+
+ yagl_gles_texture_unset_tex_image(gles_tex_image->bound_texture);
+
+ gles_tex_image->tex_global_name = 0;
+ gles_tex_image->bound_texture = NULL;
+
+ tex_image->data = NULL;
+ yagl_ref_release(data);
+}
+
+static void yagl_gles_tex_image_destroy(struct yagl_ref *ref)
+{
+ struct yagl_gles_tex_image *tex_image = (struct yagl_gles_tex_image*)ref;
+
+ /*
+ * Can't get here if bound to texture.
+ */
+ assert(!tex_image->bound_texture);
+
+ yagl_client_tex_image_cleanup(&tex_image->base);
+
+ g_free(tex_image);
+}
+
+void yagl_gles_tex_image_create(yagl_object_name tex_global_name,
+ struct yagl_ref *tex_data,
+ struct yagl_gles_texture *bound_texture)
+{
+ struct yagl_gles_tex_image *tex_image;
+
+ tex_image = g_malloc0(sizeof(*tex_image));
+
+ yagl_client_tex_image_init(&tex_image->base,
+ &yagl_gles_tex_image_destroy,
+ tex_data);
+
+ tex_image->base.unbind = &yagl_gles_tex_image_unbind;
+
+ tex_image->tex_global_name = tex_global_name;
+ tex_image->bound_texture = bound_texture;
+
+ yagl_gles_texture_set_tex_image(bound_texture, tex_image);
+}
+
+void yagl_gles_tex_image_acquire(struct yagl_gles_tex_image *tex_image)
+{
+ if (tex_image) {
+ yagl_client_tex_image_acquire(&tex_image->base);
+ }
+}
+
+void yagl_gles_tex_image_release(struct yagl_gles_tex_image *tex_image)
+{
+ if (tex_image) {
+ yagl_client_tex_image_release(&tex_image->base);
+ }
+}
diff --git a/hw/yagl_apis/gles/yagl_gles_tex_image.h b/hw/yagl_apis/gles/yagl_gles_tex_image.h
new file mode 100644
index 0000000000..9efa6569f8
--- /dev/null
+++ b/hw/yagl_apis/gles/yagl_gles_tex_image.h
@@ -0,0 +1,39 @@
+#ifndef _QEMU_YAGL_GLES_TEX_IMAGE_H
+#define _QEMU_YAGL_GLES_TEX_IMAGE_H
+
+#include "yagl_types.h"
+#include "yagl_client_tex_image.h"
+
+struct yagl_gles_driver;
+struct yagl_gles_texture;
+
+struct yagl_gles_tex_image
+{
+ struct yagl_client_tex_image base;
+
+ yagl_object_name tex_global_name;
+
+ /*
+ * Weak pointer, no ref.
+ */
+ struct yagl_gles_texture *bound_texture;
+};
+
+/*
+ * Does NOT take ownership of 'bound_texture'.
+ */
+void yagl_gles_tex_image_create(yagl_object_name tex_global_name,
+ struct yagl_ref *tex_data,
+ struct yagl_gles_texture *bound_texture);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void yagl_gles_tex_image_acquire(struct yagl_gles_tex_image *tex_image);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void yagl_gles_tex_image_release(struct yagl_gles_tex_image *tex_image);
+
+#endif
diff --git a/hw/yagl_apis/gles/yagl_gles_texture.c b/hw/yagl_apis/gles/yagl_gles_texture.c
index e1499cc592..e0a8c2e3f3 100644
--- a/hw/yagl_apis/gles/yagl_gles_texture.c
+++ b/hw/yagl_apis/gles/yagl_gles_texture.c
@@ -1,15 +1,34 @@
#include <GL/gl.h>
#include "yagl_gles_texture.h"
#include "yagl_gles_image.h"
+#include "yagl_gles_tex_image.h"
#include "yagl_gles_driver.h"
+static bool yagl_gles_texture_unset_internal(struct yagl_gles_texture *texture)
+{
+ bool ret = false;
+
+ if (texture->image) {
+ yagl_gles_image_release(texture->image);
+ texture->image = NULL;
+ ret = true;
+ }
+
+ if (texture->tex_image) {
+ texture->tex_image->base.unbind(&texture->tex_image->base);
+ assert(!texture->tex_image);
+ texture->tex_image = NULL;
+ ret = true;
+ }
+
+ return ret;
+}
+
static void yagl_gles_texture_destroy(struct yagl_ref *ref)
{
struct yagl_gles_texture *texture = (struct yagl_gles_texture*)ref;
- yagl_gles_image_release(texture->image);
-
- if (!texture->image) {
+ if (!yagl_gles_texture_unset_internal(texture)) {
yagl_ensure_ctx();
texture->driver->DeleteTextures(1, &texture->global_name);
yagl_unensure_ctx();
@@ -84,9 +103,8 @@ void yagl_gles_texture_set_image(struct yagl_gles_texture *texture,
}
yagl_gles_image_acquire(image);
- yagl_gles_image_release(texture->image);
- if (!texture->image) {
+ if (!yagl_gles_texture_unset_internal(texture)) {
texture->driver->DeleteTextures(1, &texture->global_name);
}
@@ -102,8 +120,7 @@ void yagl_gles_texture_unset_image(struct yagl_gles_texture *texture)
if (texture->image) {
GLuint global_name = 0;
- yagl_gles_image_release(texture->image);
- texture->image = NULL;
+ yagl_gles_texture_unset_internal(texture);
texture->driver->GenTextures(1, &global_name);
@@ -113,3 +130,54 @@ void yagl_gles_texture_unset_image(struct yagl_gles_texture *texture)
texture->global_name);
}
}
+
+void yagl_gles_texture_set_tex_image(struct yagl_gles_texture *texture,
+ struct yagl_gles_tex_image *tex_image)
+{
+ assert(texture->target);
+ assert(tex_image);
+
+ yagl_gles_tex_image_acquire(tex_image);
+
+ if (!yagl_gles_texture_unset_internal(texture)) {
+ texture->driver->DeleteTextures(1, &texture->global_name);
+ }
+
+ texture->global_name = tex_image->tex_global_name;
+ texture->tex_image = tex_image;
+
+ texture->driver->BindTexture(texture->target,
+ texture->global_name);
+}
+
+void yagl_gles_texture_unset_tex_image(struct yagl_gles_texture *texture)
+{
+ GLuint global_name = 0;
+
+ assert(texture->tex_image);
+
+ yagl_gles_tex_image_release(texture->tex_image);
+ texture->tex_image = NULL;
+
+ /*
+ * Should ensure context here since this function
+ * can be called when no context is active.
+ */
+ yagl_ensure_ctx();
+ texture->driver->GenTextures(1, &global_name);
+ yagl_unensure_ctx();
+
+ texture->global_name = global_name;
+}
+
+void yagl_gles_texture_release_tex_image(struct yagl_gles_texture *texture)
+{
+ if (texture->tex_image) {
+ yagl_gles_texture_unset_internal(texture);
+
+ assert(texture->global_name);
+
+ texture->driver->BindTexture(texture->target,
+ texture->global_name);
+ }
+}
diff --git a/hw/yagl_apis/gles/yagl_gles_texture.h b/hw/yagl_apis/gles/yagl_gles_texture.h
index fc4196bef5..7395ff9e94 100644
--- a/hw/yagl_apis/gles/yagl_gles_texture.h
+++ b/hw/yagl_apis/gles/yagl_gles_texture.h
@@ -8,6 +8,7 @@
struct yagl_gles_driver;
struct yagl_gles_image;
+struct yagl_gles_tex_image;
struct yagl_gles_texture
{
@@ -23,6 +24,11 @@ struct yagl_gles_texture
* Non-NULL if it's an EGLImage target.
*/
struct yagl_gles_image *image;
+
+ /*
+ * Non-NULL if eglBindTexImage bound.
+ */
+ struct yagl_gles_tex_image *tex_image;
};
struct yagl_gles_texture
@@ -44,8 +50,22 @@ bool yagl_gles_texture_bind(struct yagl_gles_texture *texture,
GLenum yagl_gles_texture_get_target(struct yagl_gles_texture *texture);
void yagl_gles_texture_set_image(struct yagl_gles_texture *texture,
- struct yagl_gles_image *image);
+ struct yagl_gles_image *image);
void yagl_gles_texture_unset_image(struct yagl_gles_texture *texture);
+/*
+ * Helpers for use in yagl_gles_tex_image only.
+ * @{
+ */
+void yagl_gles_texture_set_tex_image(struct yagl_gles_texture *texture,
+ struct yagl_gles_tex_image *tex_image);
+
+void yagl_gles_texture_unset_tex_image(struct yagl_gles_texture *texture);
+/*
+ * @}
+ */
+
+void yagl_gles_texture_release_tex_image(struct yagl_gles_texture *texture);
+
#endif
diff --git a/hw/yagl_apis/gles/yagl_host_gles_calls.c b/hw/yagl_apis/gles/yagl_host_gles_calls.c
index 257f5b3729..632ac0a2b8 100644
--- a/hw/yagl_apis/gles/yagl_host_gles_calls.c
+++ b/hw/yagl_apis/gles/yagl_host_gles_calls.c
@@ -519,6 +519,12 @@ bool yagl_host_glCompressedTexImage2D(GLenum target,
* to OES_EGL_image specs.
*/
yagl_gles_texture_unset_image(tex_target_state->texture);
+
+ /*
+ * This operation should release TexImage according
+ * to eglBindTexImage spec.
+ */
+ yagl_gles_texture_release_tex_image(tex_target_state->texture);
}
}
@@ -1534,6 +1540,12 @@ bool yagl_host_glTexImage2D(GLenum target,
* to OES_EGL_image specs.
*/
yagl_gles_texture_unset_image(tex_target_state->texture);
+
+ /*
+ * This operation should release TexImage according
+ * to eglBindTexImage spec.
+ */
+ yagl_gles_texture_release_tex_image(tex_target_state->texture);
}
}
diff --git a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c
index ea78cdc3c9..277f3aca4a 100644
--- a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c
+++ b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c
@@ -139,6 +139,24 @@ static bool yagl_egl_offscreen_surface_copy_buffers(struct yagl_eglb_surface *sf
return true;
}
+static bool yagl_egl_offscreen_surface_bind_tex_image(struct yagl_eglb_surface *sfc)
+{
+ YAGL_LOG_FUNC_SET(eglBindTexImage);
+
+ YAGL_LOG_WARN("Not supported!");
+
+ return false;
+}
+
+static bool yagl_egl_offscreen_surface_release_tex_image(struct yagl_eglb_surface *sfc)
+{
+ YAGL_LOG_FUNC_SET(eglReleaseTexImage);
+
+ YAGL_LOG_WARN("Not supported!");
+
+ return false;
+}
+
static void yagl_egl_offscreen_surface_destroy(struct yagl_eglb_surface *sfc)
{
struct yagl_egl_offscreen_surface *egl_offscreen_sfc =
@@ -234,6 +252,8 @@ struct yagl_egl_offscreen_surface
sfc->base.query = &yagl_egl_offscreen_surface_query;
sfc->base.swap_buffers = &yagl_egl_offscreen_surface_swap_buffers;
sfc->base.copy_buffers = &yagl_egl_offscreen_surface_copy_buffers;
+ sfc->base.bind_tex_image = &yagl_egl_offscreen_surface_bind_tex_image;
+ sfc->base.release_tex_image = &yagl_egl_offscreen_surface_release_tex_image;
sfc->base.destroy = &yagl_egl_offscreen_surface_destroy;
YAGL_LOG_FUNC_EXIT(NULL);
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c
index f4368f234c..33e6152339 100644
--- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c
+++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c
@@ -73,20 +73,19 @@ struct yagl_egl_onscreen_image
image_data = g_malloc0(sizeof(*image_data));
yagl_ref_init(&image_data->ref, &yagl_egl_onscreen_image_data_destroy);
+ ws_sfc->base.acquire(&ws_sfc->base);
+ image_data->ws_sfc = ws_sfc;
glegl_image = client_iface->create_image(client_iface,
ws_sfc->get_texture(ws_sfc),
&image_data->ref);
+ yagl_ref_release(&image_data->ref);
+
if (!glegl_image) {
- yagl_ref_cleanup(&image_data->ref);
- g_free(image_data);
goto out;
}
- ws_sfc->base.acquire(&ws_sfc->base);
- image_data->ws_sfc = ws_sfc;
-
image = g_malloc0(sizeof(*image));
yagl_eglb_image_init(&image->base, buffer, &dpy->base);
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c
index f029c19411..cad9ba2b33 100644
--- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c
+++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c
@@ -8,10 +8,34 @@
#include "yagl_process.h"
#include "yagl_thread.h"
#include "yagl_gles_driver.h"
+#include "yagl_client_tex_image.h"
+#include "yagl_client_context.h"
#include "winsys_gl.h"
YAGL_DECLARE_TLS(struct yagl_egl_onscreen_ts*, egl_onscreen_ts);
+struct yagl_egl_onscreen_surface_data
+{
+ struct yagl_ref ref;
+
+ struct yagl_egl_onscreen_surface *sfc;
+};
+
+static void yagl_egl_onscreen_surface_data_destroy(struct yagl_ref *ref)
+{
+ struct yagl_egl_onscreen_surface_data *surface_data =
+ (struct yagl_egl_onscreen_surface_data*)ref;
+
+ if (surface_data->sfc->tex_image) {
+ yagl_client_tex_image_release(surface_data->sfc->tex_image);
+ surface_data->sfc->tex_image = NULL;
+ }
+
+ yagl_ref_cleanup(ref);
+
+ g_free(surface_data);
+}
+
static void yagl_egl_onscreen_surface_invalidate(struct yagl_eglb_surface *sfc,
yagl_winsys_id id)
{
@@ -96,6 +120,53 @@ static bool yagl_egl_onscreen_surface_copy_buffers(struct yagl_eglb_surface *sfc
return true;
}
+static bool yagl_egl_onscreen_surface_bind_tex_image(struct yagl_eglb_surface *sfc)
+{
+ struct yagl_egl_onscreen_surface *osfc =
+ (struct yagl_egl_onscreen_surface*)sfc;
+ struct yagl_eglb_context *ctx =
+ (egl_onscreen_ts->ctx ? &egl_onscreen_ts->ctx->base : NULL);
+ struct yagl_egl_onscreen_surface_data *surface_data = NULL;
+
+ if (osfc->tex_image) {
+ return false;
+ }
+
+ if (!ctx) {
+ return true;
+ }
+
+ surface_data = g_malloc0(sizeof(*surface_data));
+
+ yagl_ref_init(&surface_data->ref, &yagl_egl_onscreen_surface_data_destroy);
+ surface_data->sfc = osfc;
+
+ osfc->tex_image =
+ ctx->client_ctx->create_tex_image(ctx->client_ctx,
+ osfc->ws_sfc->get_texture(osfc->ws_sfc),
+ &surface_data->ref);
+
+ yagl_ref_release(&surface_data->ref);
+
+ return osfc->tex_image != NULL;
+}
+
+static bool yagl_egl_onscreen_surface_release_tex_image(struct yagl_eglb_surface *sfc)
+{
+ struct yagl_egl_onscreen_surface *osfc =
+ (struct yagl_egl_onscreen_surface*)sfc;
+
+ if (!osfc->tex_image) {
+ return true;
+ }
+
+ osfc->tex_image->unbind(osfc->tex_image);
+ assert(!osfc->tex_image);
+ osfc->tex_image = NULL;
+
+ return true;
+}
+
static void yagl_egl_onscreen_surface_destroy(struct yagl_eglb_surface *sfc)
{
struct yagl_egl_onscreen_surface *osfc =
@@ -105,6 +176,12 @@ static void yagl_egl_onscreen_surface_destroy(struct yagl_eglb_surface *sfc)
YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_destroy, NULL);
+ if (osfc->tex_image) {
+ osfc->tex_image->unbind(osfc->tex_image);
+ assert(!osfc->tex_image);
+ osfc->tex_image = NULL;
+ }
+
egl_onscreen->egl_driver->pbuffer_surface_destroy(
egl_onscreen->egl_driver,
((struct yagl_egl_onscreen_display*)sfc->dpy)->native_dpy,
@@ -178,6 +255,8 @@ struct yagl_egl_onscreen_surface
sfc->base.query = &yagl_egl_onscreen_surface_query;
sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+ sfc->base.bind_tex_image = &yagl_egl_onscreen_surface_bind_tex_image;
+ sfc->base.release_tex_image = &yagl_egl_onscreen_surface_release_tex_image;
sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
YAGL_LOG_FUNC_EXIT(NULL);
@@ -243,6 +322,8 @@ struct yagl_egl_onscreen_surface
sfc->base.query = &yagl_egl_onscreen_surface_query;
sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+ sfc->base.bind_tex_image = &yagl_egl_onscreen_surface_bind_tex_image;
+ sfc->base.release_tex_image = &yagl_egl_onscreen_surface_release_tex_image;
sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
YAGL_LOG_FUNC_EXIT(NULL);
@@ -308,6 +389,8 @@ struct yagl_egl_onscreen_surface
sfc->base.query = &yagl_egl_onscreen_surface_query;
sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+ sfc->base.bind_tex_image = &yagl_egl_onscreen_surface_bind_tex_image;
+ sfc->base.release_tex_image = &yagl_egl_onscreen_surface_release_tex_image;
sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
YAGL_LOG_FUNC_EXIT(NULL);
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h
index fe1a4249d0..ae826fad74 100644
--- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h
+++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h
@@ -6,6 +6,7 @@
struct yagl_egl_onscreen_display;
struct yagl_egl_native_config;
+struct yagl_client_tex_image;
struct winsys_gl_surface;
@@ -29,6 +30,11 @@ struct yagl_egl_onscreen_surface
* when this surface is made current for the first time.
*/
GLuint rb;
+
+ /*
+ * eglBindTexImage result.
+ */
+ struct yagl_client_tex_image *tex_image;
};
struct yagl_egl_onscreen_surface
diff --git a/hw/yagl_client_context.h b/hw/yagl_client_context.h
index 4c8b2c0d1c..c97f94c8b4 100644
--- a/hw/yagl_client_context.h
+++ b/hw/yagl_client_context.h
@@ -3,8 +3,10 @@
#include "yagl_types.h"
+struct yagl_ref;
struct yagl_sharegroup;
struct yagl_client_image;
+struct yagl_client_tex_image;
struct yagl_client_context
{
@@ -37,6 +39,11 @@ struct yagl_client_context
struct yagl_client_image
*(*create_image)(struct yagl_client_context */*ctx*/);
+ struct yagl_client_tex_image
+ *(*create_tex_image)(struct yagl_client_context */*ctx*/,
+ yagl_object_name /*tex_global_name*/,
+ struct yagl_ref */*tex_data*/);
+
/*
* 'deactivate' is called whenever this context resigns
* current state for the thread. This is the last
diff --git a/hw/yagl_client_tex_image.c b/hw/yagl_client_tex_image.c
new file mode 100644
index 0000000000..9c8740c12c
--- /dev/null
+++ b/hw/yagl_client_tex_image.c
@@ -0,0 +1,32 @@
+#include "yagl_client_tex_image.h"
+
+void yagl_client_tex_image_init(struct yagl_client_tex_image *tex_image,
+ yagl_ref_destroy_func destroy_func,
+ struct yagl_ref *data)
+{
+ yagl_object_init(&tex_image->base, destroy_func);
+ yagl_ref_acquire(data);
+ tex_image->data = data;
+}
+
+void yagl_client_tex_image_cleanup(struct yagl_client_tex_image *tex_image)
+{
+ if (tex_image->data) {
+ yagl_ref_release(tex_image->data);
+ }
+ yagl_object_cleanup(&tex_image->base);
+}
+
+void yagl_client_tex_image_acquire(struct yagl_client_tex_image *tex_image)
+{
+ if (tex_image) {
+ yagl_object_acquire(&tex_image->base);
+ }
+}
+
+void yagl_client_tex_image_release(struct yagl_client_tex_image *tex_image)
+{
+ if (tex_image) {
+ yagl_object_release(&tex_image->base);
+ }
+}
diff --git a/hw/yagl_client_tex_image.h b/hw/yagl_client_tex_image.h
new file mode 100644
index 0000000000..53d8565a48
--- /dev/null
+++ b/hw/yagl_client_tex_image.h
@@ -0,0 +1,41 @@
+#ifndef _QEMU_YAGL_CLIENT_TEX_IMAGE_H
+#define _QEMU_YAGL_CLIENT_TEX_IMAGE_H
+
+#include "yagl_types.h"
+#include "yagl_object.h"
+
+struct yagl_client_tex_image
+{
+ struct yagl_object base;
+
+ struct yagl_ref *data;
+
+ void (*unbind)(struct yagl_client_tex_image */*tex_image*/);
+};
+
+void yagl_client_tex_image_init(struct yagl_client_tex_image *tex_image,
+ yagl_ref_destroy_func destroy_func,
+ struct yagl_ref *data);
+
+void yagl_client_tex_image_cleanup(struct yagl_client_tex_image *tex_image);
+
+/*
+ * Helper functions that simply acquire/release yagl_client_tex_image::ref
+ * @{
+ */
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void yagl_client_tex_image_acquire(struct yagl_client_tex_image *tex_image);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void yagl_client_tex_image_release(struct yagl_client_tex_image *tex_image);
+
+/*
+ * @}
+ */
+
+#endif
diff --git a/hw/yagl_egl_native_config.c b/hw/yagl_egl_native_config.c
index 3669ee2883..facf648b2c 100644
--- a/hw/yagl_egl_native_config.c
+++ b/hw/yagl_egl_native_config.c
@@ -16,4 +16,6 @@ void yagl_egl_native_config_init(struct yagl_egl_native_config *cfg)
cfg->trans_green_val = EGL_DONT_CARE;
cfg->trans_blue_val = EGL_DONT_CARE;
cfg->match_format_khr = EGL_DONT_CARE;
+ cfg->bind_to_texture_rgb = EGL_DONT_CARE;
+ cfg->bind_to_texture_rgba = EGL_DONT_CARE;
}
diff --git a/hw/yagl_egl_native_config.h b/hw/yagl_egl_native_config.h
index 4f402c3afd..88cee2b3f7 100644
--- a/hw/yagl_egl_native_config.h
+++ b/hw/yagl_egl_native_config.h
@@ -45,6 +45,8 @@ struct yagl_egl_native_config
EGLenum conformant;
EGLint sample_buffers_num;
EGLint match_format_khr;
+ EGLBoolean bind_to_texture_rgb;
+ EGLBoolean bind_to_texture_rgba;
};
/*
diff --git a/hw/yagl_eglb_surface.h b/hw/yagl_eglb_surface.h
index 229d7ccf01..2c4ee4f15f 100644
--- a/hw/yagl_eglb_surface.h
+++ b/hw/yagl_eglb_surface.h
@@ -46,6 +46,17 @@ struct yagl_eglb_surface
bool (*copy_buffers)(struct yagl_eglb_surface */*sfc*/);
+ /*
+ * Can be called even when this surface is not current!
+ * @{
+ */
+ bool (*bind_tex_image)(struct yagl_eglb_surface */*sfc*/);
+
+ bool (*release_tex_image)(struct yagl_eglb_surface */*sfc*/);
+ /*
+ * @}
+ */
+
void (*destroy)(struct yagl_eglb_surface */*sfc*/);
};