Support offscreen rendering for TBM_FORMAT_ARGB8888 tbm buffer
authorbyungchul.so <byungchul.so@samsung.com>
Mon, 13 Dec 2021 03:05:48 +0000 (12:05 +0900)
committerbyungchul.so <byungchul.so@samsung.com>
Tue, 14 Dec 2021 03:27:15 +0000 (12:27 +0900)
- Assume below events:

  ...
  // Use TBM_FORMAT_ARGB8888 tbm buffer for offscreen rendering. The tbm buffer is used as
  // native buffer for an eglImage and the texture binded with the eglImage is attached to
  // framebuffer object.
  tbm_buffer = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
  EvasGLImage *evas_image = evasglCreateImageForContext(evas_gl, evas_gl_ctx,
  EVAS_GL_NATIVE_SURFACE_TIZEN, tbm_surface, attrs);
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glEvasGLImageTargetTexture2DOES(GL_TEXTURE_2D, evas_image);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

  Rendering something here...

  // Bind default framebuffer after rendering...
  glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer);
  ...

- The TBM_FORMAT_ARGB8888 tbm buffer should have rendering result after
  finishing rendering but it's not because offscreen rendering for TBM_FORMAT_ARGB8888
  tbm buffer not supported yet in the YAGL. This patch fixes this issue.

12 files changed:
EGL/yagl_context.c
EGL/yagl_context.h
EGL/yagl_egl_calls.c
EGL/yagl_onscreen_image_tizen_sfc.c
EGL/yagl_render.c
GLES_common/yagl_gles_calls.c
GLES_common/yagl_gles_image.c
GLES_common/yagl_gles_image.h
GLES_common/yagl_gles_texture.c
GLES_common/yagl_gles_texture.h
GLESv2/yagl_gles2_context.c
include/yagl_render.h

index 2e0feaeddf017235b0086d8747de45ebef99cfa0..e6c65a41b84a0a981d2a64fbff57f66d59b4a3db 100644 (file)
@@ -136,3 +136,8 @@ void yagl_context_finish(struct yagl_context *ctx)
 {
     yagl_display_finalize_images(ctx->dpy);
 }
+
+void yagl_context_flush(struct yagl_context *ctx)
+{
+    yagl_display_finalize_images(ctx->dpy);
+}
index 1ea2dd45388c905f649291df12725bd088c61911..809be4d91504b1f5edcbc271db7924c00c7cd2fc 100644 (file)
@@ -85,4 +85,6 @@ void yagl_context_release(struct yagl_context *ctx);
 
 void yagl_context_finish(struct yagl_context *ctx);
 
+void yagl_context_flush(struct yagl_context *ctx);
+
 #endif
index 66eb55bde9cb5fa097f8f20432b2f20fab10fd5d..2e7bf9959aaa81b6296a8a07ec8b7223b523dd96 100644 (file)
@@ -1638,6 +1638,8 @@ YAGL_API EGLBoolean eglSwapBuffers(EGLDisplay dpy_, EGLSurface surface_)
         goto out;
     }
 
+    yagl_render_flush();
+
     res = EGL_TRUE;
 
 #ifdef YAGL_PLATFORM_X11
index acd43d88135c5c475dba9d65e06e9bd3f8019a99..8c3dfa4327748deae97b648487c89e6a466f18eb 100644 (file)
@@ -293,27 +293,36 @@ static void yagl_onscreen_image_tizen_sfc_finalize(struct yagl_image *image)
         return;
     }
 
+    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;
+
     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,
+        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;
+    case TBM_FORMAT_ARGB8888:
+        /*
+         * No actual format conversion in ARGB8888 case. We just need to
+         * y-invert the image.
+         */
+        ret = !vigs_drm_surface_convert(tizen_sfc_image->drm_sfc,
+                                       DRM_FORMAT_ARGB8888,
+                                       dst,
+                                       DRM_FORMAT_ARGB8888,
+                                       true);
+        break;
+    default:
+        ret = yagl_onscreen_image_tizen_sfc_convert_back(tizen_sfc_image);
         break;
     }
 
-    yagl_onscreen_image_tizen_sfc_convert_back(tizen_sfc_image);
+    if (!ret) {
+        YAGL_LOG_ERROR("vigs_drm_surface_convert failed %s\n", strerror(-ret));
+    }
 }
 
 static void yagl_onscreen_image_tizen_sfc_destroy(struct yagl_ref *ref)
@@ -366,13 +375,13 @@ struct yagl_onscreen_image_tizen_sfc
             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_ARGB8888:
         case TBM_FORMAT_XBGR8888:
             need_convert = true;
             need_convert_back = true;
index e67925af6b3aa4d59ce182c838396855a09e385e..73e817c8348334f178b6c4624315450854bfe035 100644 (file)
@@ -79,3 +79,14 @@ void yagl_render_finish()
         yagl_context_finish(ctx);
     }
 }
+
+void yagl_render_flush()
+{
+    struct yagl_context *ctx = yagl_get_context();
+
+    yagl_transport_flush(yagl_get_transport(), NULL);
+
+    if (ctx) {
+        yagl_context_flush(ctx);
+    }
+}
index 6181ff9c8a5864f27fcdb58df3075ffd105ceb26..7e5d7635fb46e9f93e2266c865447d969b59ab9b 100644 (file)
@@ -1259,7 +1259,16 @@ YAGL_API void glFinish()
     YAGL_LOG_FUNC_EXIT(NULL);
 }
 
-YAGL_IMPLEMENT_API_NORET0(glFlush)
+YAGL_API void glFlush()
+{
+    YAGL_LOG_FUNC_ENTER_SPLIT0(glFlush);
+
+    yagl_host_glFlush();
+
+    yagl_render_flush();
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
 
 void glFramebufferRenderbuffer(GLenum target,
                                GLenum attachment,
index 7139f36db05ada01ac57b667beae8f9f8106bbf1..c9f0944e8b6a066a89361834cb47638aaf075b81 100644 (file)
@@ -129,3 +129,10 @@ void yagl_gles_image_release(struct yagl_gles_image *image)
         yagl_client_image_release(&image->base);
     }
 }
+
+void yagl_gles_set_finalize(struct yagl_gles_image *image)
+{
+    if (image) {
+        image->base.need_finalize = 1;
+    }
+}
index 83436f40bb79928d34f885b5d91e21710ec1cf25..4dda60ec2a380207a7562a26a11e8a5a6cd40489 100644 (file)
@@ -67,4 +67,10 @@ void yagl_gles_image_acquire(struct yagl_gles_image *image);
  */
 void yagl_gles_image_release(struct yagl_gles_image *image);
 
+/*
+ * Set need_finalize flag to update original surface of drm surface.
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void yagl_gles_set_finalize(struct yagl_gles_image *image);
+
 #endif
index 0a20e56978fc39a3184b2cd8d46c4358c163b043..4a93ed4449cf5231559a24c268460ddef6607103 100644 (file)
@@ -340,3 +340,12 @@ void yagl_gles_texture_release_tex_image(struct yagl_gles_texture *texture)
      */
     yagl_host_glGenTextures(&texture->global_name, 1);
 }
+
+void yagl_gles_texture_set_finalize_image(struct yagl_gles_texture *texture)
+{
+    if (texture && texture->image) {
+        yagl_gles_image_acquire(texture->image);
+        yagl_gles_set_finalize(texture->image);
+        yagl_gles_image_release(texture->image);
+    }
+}
index bf5e1eb7d732dcb0bcb0cb93a1186b5faf9fa798..c5cd5016a752e5274d7154216271f794f2905c02 100644 (file)
@@ -116,4 +116,9 @@ void yagl_gles_texture_bind_tex_image(struct yagl_gles_texture *texture,
  */
 void yagl_gles_texture_release_tex_image(struct yagl_gles_texture *texture);
 
+/*
+ * Set finalize flag to image binded the texture.
+ */
+void yagl_gles_texture_set_finalize_image(struct yagl_gles_texture *texture);
+
 #endif
index 295930866f37918d53d1cf5e91304bc57c5a519b..fa67c7520517eebc6d230818e3c6dd463bdb17bf 100644 (file)
@@ -265,9 +265,7 @@ static void yagl_gles2_context_prepare_framebuffer(struct yagl_gles2_context *ct
             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_texture_set_finalize_image(state.texture);
 
                 yagl_gles_framebuffer_texture2d(fb,
                     fb->target,
index 244a513fb6f52b3b82d97d125800527e0dc5c143..eae10b773428cfb3224c21c9fee6f0bbb18308ab 100644 (file)
@@ -76,4 +76,16 @@ YAGL_API void yagl_render_invalidate(int throttle);
  */
 YAGL_API void yagl_render_finish();
 
+/*
+ * Some tbm buffers that has format such as TBM_FORMAT_ARGB8888 and TBM_FORMAT_XBGR8888
+ * are necessary to update original surface from drm surface after finishing rendering for
+ * consistency. YAGL already finalizes images by using yagl_render_finish() in glFinish()
+ * but if an application that uses eglimage binded with tbm buffer that created with
+ * TBM_FORMAT_ARGB8888 or TBM_FORMAT_XBGR8888 format doesn't invoke glFinish() in their
+ * source code then the consistency can be breaked. Therefore, it needs to finalize images
+ * additionally after flushing rendering commands. Callers of this should probably include
+ * glFlush, eglSwapBuffers, etc.
+ */
+YAGL_API void yagl_render_flush();
+
 #endif