From 3639edafe715673a090150b7e93ce53b3a4b2f0e Mon Sep 17 00:00:00 2001 From: Vladislav Andresov Date: Thu, 31 May 2018 07:43:52 +0300 Subject: Add handling of new format XBGR Currently this format can be used only for output images which would be product of rendering. Change-Id: Ic3a7c5fe2e2c528059dc41a4df868268720c94a9 Signed-off-by: Vladislav Andresov --- EGL/yagl_context.c | 5 ++ EGL/yagl_context.h | 2 + EGL/yagl_display.c | 28 +++++++++ EGL/yagl_display.h | 1 + EGL/yagl_image.h | 2 + EGL/yagl_onscreen_image_tizen_sfc.c | 112 ++++++++++++++++++++++++++++++++++++ EGL/yagl_onscreen_image_tizen_sfc.h | 2 + EGL/yagl_render.c | 3 + GLES_common/yagl_gles_framebuffer.c | 2 + GLES_common/yagl_gles_framebuffer.h | 2 + GLESv2/yagl_gles2_context.c | 48 ++++++++++++++++ include/yagl_client_image.h | 2 + 12 files changed, 209 insertions(+) diff --git a/EGL/yagl_context.c b/EGL/yagl_context.c index 81ef29d..2e0feae 100644 --- a/EGL/yagl_context.c +++ b/EGL/yagl_context.c @@ -131,3 +131,8 @@ void yagl_context_release(struct yagl_context *ctx) yagl_resource_release(&ctx->res); } } + +void yagl_context_finish(struct yagl_context *ctx) +{ + yagl_display_finalize_images(ctx->dpy); +} diff --git a/EGL/yagl_context.h b/EGL/yagl_context.h index 4d11f76..1ea2dd4 100644 --- a/EGL/yagl_context.h +++ b/EGL/yagl_context.h @@ -83,4 +83,6 @@ void yagl_context_acquire(struct yagl_context *ctx); */ void yagl_context_release(struct yagl_context *ctx); +void yagl_context_finish(struct yagl_context *ctx); + #endif diff --git a/EGL/yagl_display.c b/EGL/yagl_display.c index 1433c8a..4aec282 100644 --- a/EGL/yagl_display.c +++ b/EGL/yagl_display.c @@ -42,6 +42,7 @@ #include "yagl_fence.h" #include "yagl_native_display.h" #include "yagl_native_platform.h" +#include "yagl_client_image.h" #include #include #include @@ -534,6 +535,33 @@ int yagl_display_image_remove(struct yagl_display *dpy, return 0; } +void yagl_display_finalize_images(struct yagl_display *dpy) +{ + struct yagl_resource *res; + + pthread_mutex_lock(&dpy->mutex); + + yagl_list_for_each(struct yagl_resource, res, &dpy->images, list) { + struct yagl_image *image = (struct yagl_image *)res; + int need_finalize; + + yagl_image_acquire(image); + + yagl_client_image_acquire(image->client_image); + need_finalize = image->client_image->need_finalize; + image->client_image->need_finalize = 0; + yagl_client_image_release(image->client_image); + + if (need_finalize && image->finalize) { + image->finalize(image); + } + + yagl_image_release(image); + } + + pthread_mutex_unlock(&dpy->mutex); +} + void yagl_display_fence_add(struct yagl_display *dpy, struct yagl_fence *fence) { diff --git a/EGL/yagl_display.h b/EGL/yagl_display.h index b1ee7b3..5aee5d0 100644 --- a/EGL/yagl_display.h +++ b/EGL/yagl_display.h @@ -179,6 +179,7 @@ struct yagl_image *yagl_display_image_acquire(struct yagl_display *dpy, int yagl_display_image_remove(struct yagl_display *dpy, EGLImageKHR handle); +void yagl_display_finalize_images(struct yagl_display *dpy); /* * @} */ diff --git a/EGL/yagl_image.h b/EGL/yagl_image.h index 7a63c79..2ab8e2b 100644 --- a/EGL/yagl_image.h +++ b/EGL/yagl_image.h @@ -56,6 +56,8 @@ struct yagl_image struct yagl_client_image *client_image; void (*update)(struct yagl_image */*image*/); + + void (*finalize)(struct yagl_image */*image*/); }; void yagl_image_init(struct yagl_image *image, diff --git a/EGL/yagl_onscreen_image_tizen_sfc.c b/EGL/yagl_onscreen_image_tizen_sfc.c index 4f33959..acd43d8 100644 --- a/EGL/yagl_onscreen_image_tizen_sfc.c +++ b/EGL/yagl_onscreen_image_tizen_sfc.c @@ -68,6 +68,15 @@ static inline uint32_t yuv2argb(float y, float u, float v) return (0xff000000 | (r << 16) | (g << 8) | b); } +static inline uint32_t argb2xbgr(uint32_t argb) +{ + uint32_t r = (argb & 0xff0000) >> 16; + uint32_t g = (argb & 0xff00) >> 8; + uint32_t b = (argb & 0xff); + + return (0xff000000) | (b << 16) | (g << 8) | (r); +} + static bool yagl_onscreen_image_tizen_sfc_convert(struct yagl_onscreen_image_tizen_sfc *image) { uint32_t *dst; @@ -150,6 +159,60 @@ static bool yagl_onscreen_image_tizen_sfc_convert(struct yagl_onscreen_image_tiz return true; } +static bool yagl_onscreen_image_tizen_sfc_convert_back(struct yagl_onscreen_image_tizen_sfc *image) +{ + uint32_t *dst; + int i, j; + tbm_surface_info_s info; + int ret; + + YAGL_LOG_FUNC_SET(yagl_onscreen_image_tizen_sfc_convert_back); + + ret = tbm_surface_map(image->sfc, TBM_SURF_OPTION_WRITE, &info); + + if (ret != TBM_SURFACE_ERROR_NONE) { + YAGL_LOG_ERROR("tbm_surface_map failed: %d", ret); + return false; + } + + ret = vigs_drm_surface_start_access(image->drm_sfc, VIGS_DRM_SAF_READ); + + if (ret) { + YAGL_LOG_ERROR("vigs_drm_surface_start_access failed: %s", strerror(-ret)); + tbm_surface_unmap(image->sfc); + return false; + } + + dst = image->drm_sfc->gem.vaddr; + dst += info.width * info.height - info.width; + + switch (info.format) { + case TBM_FORMAT_XBGR8888: + for (i = 0; i < info.height; i++) { + for (j = 0; j < info.width; j++) { + uint32_t argb = *(dst - i * info.width + j); + ((uint32_t *)info.planes[0].ptr)[i * info.width + j] = argb2xbgr(argb); + } + } + + YAGL_LOG_ERROR("cpu converting: %p[0] = 0x%x", info.planes[0].ptr, + ((uint32_t *)info.planes[0].ptr)[0]); + + break; + } + + ret = vigs_drm_surface_end_access(image->drm_sfc, 1); + + if (ret) { + YAGL_LOG_ERROR("vigs_drm_surface_end_access failed: %s", strerror(-ret)); + return false; + } + + tbm_surface_unmap(image->sfc); + + return true; +} + static void yagl_onscreen_image_tizen_sfc_update(struct yagl_image *image) { struct yagl_onscreen_image_tizen_sfc *tizen_sfc_image = @@ -213,6 +276,46 @@ static void yagl_onscreen_image_tizen_sfc_update(struct yagl_image *image) yagl_onscreen_image_tizen_sfc_convert(tizen_sfc_image); } +static void yagl_onscreen_image_tizen_sfc_finalize(struct yagl_image *image) +{ + struct yagl_onscreen_image_tizen_sfc *tizen_sfc_image = + (struct yagl_onscreen_image_tizen_sfc *)image; + + tbm_bo bo; + struct vigs_drm_surface *dst; + int ret; + + YAGL_LOG_FUNC_SET(yagl_onscreen_image_tizen_sfc_finalize); + + vigs_drm_surface_set_gpu_dirty(tizen_sfc_image->drm_sfc); + + if (!tizen_sfc_image->need_convert_back) { + return; + } + + switch (tizen_sfc_image->format) { + case TBM_FORMAT_XBGR8888: + bo = tbm_surface_internal_get_bo(tizen_sfc_image->sfc, 0); + dst = bo ? (struct vigs_drm_surface *)tbm_bo_get_handle(bo, TBM_DEVICE_3D).ptr : NULL; + + ret = vigs_drm_surface_convert(tizen_sfc_image->drm_sfc, + DRM_FORMAT_ARGB8888, + dst, + DRM_FORMAT_XBGR8888, + true); + + if (ret == 0) { + return; + } + + YAGL_LOG_ERROR("vigs_drm_surface_convert failed %s\n", strerror(-ret)); + + break; + } + + yagl_onscreen_image_tizen_sfc_convert_back(tizen_sfc_image); +} + static void yagl_onscreen_image_tizen_sfc_destroy(struct yagl_ref *ref) { struct yagl_onscreen_image_tizen_sfc *image = (struct yagl_onscreen_image_tizen_sfc *)ref; @@ -240,6 +343,7 @@ struct yagl_onscreen_image_tizen_sfc tbm_bo bo; tbm_surface_info_s info; bool need_convert; + bool need_convert_back; int ret; YAGL_LOG_FUNC_SET(yagl_onscreen_image_tizen_sfc_create); @@ -260,12 +364,18 @@ struct yagl_onscreen_image_tizen_sfc case TBM_FORMAT_RGB888: case TBM_FORMAT_XRGB8888: need_convert = false; + need_convert_back = false; break; case TBM_FORMAT_ARGB8888: case TBM_FORMAT_RGBA8888: case TBM_FORMAT_NV21: case TBM_FORMAT_YUV420: need_convert = true; + need_convert_back = false; + break; + case TBM_FORMAT_XBGR8888: + need_convert = true; + need_convert_back = true; break; default: YAGL_LOG_ERROR("bad format: 0x%X", info.format); @@ -344,8 +454,10 @@ struct yagl_onscreen_image_tizen_sfc yagl_client_image_release(client_image); image->base.update = &yagl_onscreen_image_tizen_sfc_update; + image->base.finalize = &yagl_onscreen_image_tizen_sfc_finalize; image->sfc = sfc; image->need_convert = need_convert; + image->need_convert_back = need_convert_back; image->drm_sfc = drm_sfc; image->format = info.format; diff --git a/EGL/yagl_onscreen_image_tizen_sfc.h b/EGL/yagl_onscreen_image_tizen_sfc.h index e7af41b..f7332dc 100644 --- a/EGL/yagl_onscreen_image_tizen_sfc.h +++ b/EGL/yagl_onscreen_image_tizen_sfc.h @@ -49,6 +49,8 @@ struct yagl_onscreen_image_tizen_sfc bool need_convert; + bool need_convert_back; + struct vigs_drm_surface *drm_sfc; uint32_t format; diff --git a/EGL/yagl_render.c b/EGL/yagl_render.c index 0bcf932..de117b1 100644 --- a/EGL/yagl_render.c +++ b/EGL/yagl_render.c @@ -62,6 +62,7 @@ void yagl_render_invalidate(int throttle) void yagl_render_finish() { struct yagl_surface *draw_sfc = yagl_get_draw_surface(); + struct yagl_context *ctx = yagl_get_context(); if (draw_sfc) { draw_sfc->wait_gl(draw_sfc); @@ -73,4 +74,6 @@ void yagl_render_finish() */ yagl_transport_flush(yagl_get_transport(), NULL); } + + yagl_context_finish(ctx); } diff --git a/GLES_common/yagl_gles_framebuffer.c b/GLES_common/yagl_gles_framebuffer.c index a1c2235..954e9da 100644 --- a/GLES_common/yagl_gles_framebuffer.c +++ b/GLES_common/yagl_gles_framebuffer.c @@ -219,6 +219,8 @@ void yagl_gles_framebuffer_bind(struct yagl_gles_framebuffer *fb, yagl_host_glBindFramebuffer(target, fb->global_name); fb->was_bound = 1; + + fb->target = target; } int yagl_gles_framebuffer_was_bound(struct yagl_gles_framebuffer *fb) diff --git a/GLES_common/yagl_gles_framebuffer.h b/GLES_common/yagl_gles_framebuffer.h index 8a3e3da..0ed6e2f 100644 --- a/GLES_common/yagl_gles_framebuffer.h +++ b/GLES_common/yagl_gles_framebuffer.h @@ -72,6 +72,8 @@ struct yagl_gles_framebuffer GLenum read_buffer; int was_bound; + + GLenum target; }; int yagl_gles_framebuffer_attachment_internalformat(struct yagl_gles_framebuffer_attachment_state *attachment_state, diff --git a/GLESv2/yagl_gles2_context.c b/GLESv2/yagl_gles2_context.c index 46e3991..8eec42d 100644 --- a/GLESv2/yagl_gles2_context.c +++ b/GLESv2/yagl_gles2_context.c @@ -42,6 +42,8 @@ #include "yagl_gles_texture_unit.h" #include "yagl_gles_vertex_array.h" #include "yagl_gles_utils.h" +#include "yagl_gles_framebuffer.h" +#include "yagl_gles_image.h" #include "yagl_log.h" #include "yagl_malloc.h" #include "yagl_state.h" @@ -237,6 +239,50 @@ static int yagl_gles2_context_pre_link_program(struct yagl_gles2_context *ctx, return 1; } +static void yagl_gles2_context_prepare_framebuffer(struct yagl_gles2_context *ctx, + struct yagl_gles_framebuffer *fb) +{ + int i = 0; + struct yagl_gles_framebuffer_attachment_state state; + + if (fb == NULL) { + return; + } + + yagl_gles_framebuffer_acquire(fb); + + /* + * Currently we don't support depth and stencil attachments for + * texture images + */ + + for (i = 0; i < YAGL_MAX_GLES_FRAMEBUFFER_COLOR_ATTACHMENTS; i++) { + state = fb->attachment_states[yagl_gles_framebuffer_attachment_color0 + i]; + + if (state.type == GL_TEXTURE && state.texture) { + yagl_gles_texture_acquire(state.texture); + + if (state.texture->image) { + yagl_gles_image_acquire(state.texture->image); + state.texture->image->base.need_finalize = 1; + yagl_gles_image_release(state.texture->image); + + yagl_gles_framebuffer_texture2d(fb, + fb->target, + GL_COLOR_ATTACHMENT0 + i, + yagl_gles_framebuffer_attachment_color0, + state.textarget, + 0, + state.texture); + } + + yagl_gles_texture_release(state.texture); + } + } + + yagl_gles_framebuffer_release(fb); +} + void yagl_gles2_context_init(struct yagl_gles2_context *ctx, yagl_client_api client_api, struct yagl_sharegroup *sg) @@ -431,6 +477,8 @@ void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx, { YAGL_LOG_FUNC_SET(yagl_gles2_context_pre_draw); + yagl_gles2_context_prepare_framebuffer(ctx, ctx->base.fbo_draw); + /* * 'count' can be <= 0 in case of integer overflows, this is * typically user problem, just don't simulate vertex attribute array 0 diff --git a/include/yagl_client_image.h b/include/yagl_client_image.h index 08c979c..15e42b6 100644 --- a/include/yagl_client_image.h +++ b/include/yagl_client_image.h @@ -42,6 +42,8 @@ struct yagl_client_image { struct yagl_object base; + int need_finalize; + void (*update)(struct yagl_client_image */*image*/, uint32_t /*width*/, uint32_t /*height*/, -- cgit v1.2.3