diff options
author | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2013-07-04 14:24:26 +0400 |
---|---|---|
committer | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2013-07-04 14:51:02 +0400 |
commit | 1ffb232808c23e30b9e44fc6011ef3ed97d7748d (patch) | |
tree | 06096144907fed90f9cb84146864a28ab3a9bb52 /hw | |
parent | 1aac667b899131b126eece73ceccd75f22669342 (diff) | |
download | qemu-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.c | 9 | ||||
-rw-r--r-- | hw/yagl_apis/egl/yagl_host_egl_calls.c | 114 | ||||
-rw-r--r-- | hw/yagl_apis/egl/yagl_host_egl_calls.h | 8 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_gles_context.c | 24 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_gles_tex_image.c | 68 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_gles_tex_image.h | 39 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_gles_texture.c | 82 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_gles_texture.h | 22 | ||||
-rw-r--r-- | hw/yagl_apis/gles/yagl_host_gles_calls.c | 12 | ||||
-rw-r--r-- | hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c | 20 | ||||
-rw-r--r-- | hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c | 9 | ||||
-rw-r--r-- | hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c | 83 | ||||
-rw-r--r-- | hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h | 6 | ||||
-rw-r--r-- | hw/yagl_client_context.h | 7 | ||||
-rw-r--r-- | hw/yagl_client_tex_image.c | 32 | ||||
-rw-r--r-- | hw/yagl_client_tex_image.h | 41 | ||||
-rw-r--r-- | hw/yagl_egl_native_config.c | 2 | ||||
-rw-r--r-- | hw/yagl_egl_native_config.h | 2 | ||||
-rw-r--r-- | hw/yagl_eglb_surface.h | 11 |
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*/); }; |