[M108 Migration][MM] Migrate Tbm feature for Tizen Multimedia 41/286841/8
authorSuhaspoornachandra <s.poornachan@samsung.com>
Wed, 25 Jan 2023 09:22:59 +0000 (14:52 +0530)
committerDae-Hyun Ko <dhyuna.ko@samsung.com>
Fri, 27 Jan 2023 14:20:42 +0000 (14:20 +0000)
This commit migrates below patches and their fixup's
1) Add Tbm Surface support
2) Add support for tbm buffer handling
3) [MM] Handle TBM on video frame drop
4) [MM] Fix memory leak during playing video using TBM
5) [MM] Fix the crash when player is destroyed before tbm media
   packet (partial)

Reference:
https://review.tizen.org/gerrit/269846/
https://review.tizen.org/gerrit/270726/
https://review.tizen.org/gerrit/272817/
https://review.tizen.org/gerrit/273650/
https://review.tizen.org/gerrit/274633/
https://review.tizen.org/gerrit/279208/
https://review.tizen.org/gerrit/282988/

Change-Id: Id65cfea36a7469c81c764d5d84d0ff9f84013244
Signed-off-by: Suhaspoornachandra <s.poornachan@samsung.com>
62 files changed:
cc/layers/video_layer_impl.cc
cc/layers/video_layer_impl.h
components/cast_streaming/public/remoting_proto_enum_utils.cc
components/viz/common/features.cc
content/renderer/render_thread_impl.cc
gpu/GLES2/gl2chromium_autogen.h
gpu/command_buffer/build_gles2_cmd_buffer.py
gpu/command_buffer/client/gles2_c_lib_autogen.h
gpu/command_buffer/client/gles2_implementation.cc
gpu/command_buffer/client/gles2_implementation.h
gpu/command_buffer/client/gles2_implementation_autogen.h
gpu/command_buffer/client/gles2_interface.h
gpu/command_buffer/client/gles2_interface_autogen.h
gpu/command_buffer/client/gles2_interface_stub_autogen.h
gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
gpu/command_buffer/client/gles2_trace_implementation_autogen.h
gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
gpu/command_buffer/client/gpu_control.h
gpu/command_buffer/gles2_cmd_buffer_functions.txt
gpu/ipc/client/command_buffer_proxy_impl.cc
gpu/ipc/client/command_buffer_proxy_impl.h
gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
media/base/video_frame.cc
media/base/video_frame.h
media/base/video_frame_layout.cc
media/base/video_types.cc
media/base/video_types.h
media/capture/mojom/BUILD.gn
media/capture/mojom/video_capture_types.mojom
media/capture/mojom/video_capture_types_mojom_traits.cc
media/mojo/mojom/renderer_extensions.mojom
media/renderers/paint_canvas_video_renderer.cc
media/renderers/video_resource_updater.cc
media/renderers/video_resource_updater.h
media/video/gpu_memory_buffer_video_frame_pool.cc
services/viz/public/mojom/BUILD.gn
third_party/openscreen/src/cast/streaming/remoting.proto
tizen_src/build/config/BUILD.gn
tizen_src/build/gn_chromiumefl.sh
tizen_src/chromium_impl/content/browser/browser_efl.gni
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h
tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc
tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h
tizen_src/chromium_impl/media/filters/media_player_registry.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/filters/media_player_registry.h [new file with mode: 0644]
tizen_src/chromium_impl/media/media_efl.gni
tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h [new file with mode: 0644]
tizen_src/chromium_impl/ui/ui_efl.gni
ui/gfx/gpu_memory_buffer.h
ui/gfx/mojom/BUILD.gn
ui/gfx/mojom/buffer_types.mojom
ui/gfx/mojom/buffer_types_mojom_traits.cc
ui/gfx/mojom/buffer_types_mojom_traits.h
ui/gl/gl_image_egl.cc
ui/gl/gl_image_egl.h
ui/gl/gl_image_native_pixmap.cc
ui/gl/gl_image_native_pixmap.h

index a6ced88..96080d7 100644 (file)
 #include "media/renderers/video_resource_updater.h"
 #include "ui/gfx/color_space.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/service/display/skia_renderer.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#endif
+
 namespace cc {
 
 // static
@@ -57,6 +63,9 @@ VideoLayerImpl::VideoLayerImpl(
 }
 
 VideoLayerImpl::~VideoLayerImpl() {
+#if defined(TIZEN_TBM_SUPPORT)
+  ReleaseResources();
+#endif
   if (!provider_client_impl_->Stopped()) {
     // In impl side painting, we may have a pending and active layer
     // associated with the video provider at the same time. Both have a ref
@@ -107,6 +116,63 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
     return false;
   }
 
+#if defined(TIZEN_TBM_SUPPORT)
+  if (frame_->IsTBMBackend()) {
+    context_provider_ = layer_tree_impl()->context_provider();
+    if (!context_provider_)
+      return false;
+    // Pass a VideoFrame reference to OnVideoCompositingFinished() callback to
+    // ensure that VideoFrame object is valid.
+    // OnVideoCompositingFinished() callback is invoked when finish to use the
+    // resource on browser process.
+    // After OnVideoCompositingFinished() is invoked, VideoFrame object can be
+    // destroyed.
+    frame_->SetContextProvider(context_provider_);
+    gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+    frame_->CreateTbmTextureIfNeeded(gl);
+    const gpu::MailboxHolder& mailbox_holder = frame_->mailbox_holder(0);
+    auto transferable_resource = viz::TransferableResource::MakeGpu(
+        mailbox_holder.mailbox, GL_LINEAR, mailbox_holder.texture_target,
+        mailbox_holder.sync_token, frame_->visible_rect().size(),
+        viz::RGBA_8888, false);
+    resource_id_ = resource_provider->ImportResource(
+        transferable_resource,
+        base::BindOnce(&VideoLayerImpl::OnVideoCompositingFinished,
+                       base::Unretained(this), frame_));
+#if defined(_DEBUG_TBM_VIDEO_RENDERING) && _DEBUG_TBM_VIDEO_RENDERING
+    LOG(INFO) << " Video frame > "
+              << ", texture_id:" << frame_->GetTbmTexture()
+              << ", resource_id:" << resource_id_
+              << ", size:" << frame_->visible_rect().size().ToString();
+#endif
+
+#if defined(_DEBUG_TBM_VIDEO_RENDERING_FPS) && _DEBUG_TBM_VIDEO_RENDERING_FPS
+    static media::VideoFrame* prev_frame = 0;
+    static int new_frame_cnt = 0;
+    static int frame_cnt = 0;
+    static base::TimeTicks last_tick = base::TimeTicks::Now();
+    const base::TimeTicks now = base::TimeTicks::Now();
+    const base::TimeDelta interval = now - last_tick;
+
+    if (prev_frame != frame_.get())
+      new_frame_cnt++;
+    prev_frame = frame_.get();
+    frame_cnt++;
+    if (interval >= base::TimeDelta::FromSeconds(1)) {
+      printf("VideoTBM[Draw] > [FPS]%.1f/%.1f\n",
+             new_frame_cnt / interval.InSecondsF(),
+             frame_cnt / interval.InSecondsF());
+      LOG(INFO) << "VideoTBM[Draw] > [FPS]"
+                << (new_frame_cnt / interval.InSecondsF()) << "/"
+                << (frame_cnt / interval.InSecondsF());
+      last_tick = now;
+      frame_cnt = 0;
+      new_frame_cnt = 0;
+    }
+#endif
+  }
+#endif
+
   if (!updater_) {
     const LayerTreeSettings& settings = layer_tree_impl()->settings();
     // TODO(sergeyu): Pass RasterContextProvider when it's available. Then
@@ -121,7 +187,11 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
         settings.resource_settings.use_r16_texture,
         layer_tree_impl()->max_texture_size());
   }
+#if defined(TIZEN_TBM_SUPPORT)
+  updater_->ObtainFrameResources(frame_, resource_id_);
+#else
   updater_->ObtainFrameResources(frame_);
+#endif
   return true;
 }
 
@@ -195,6 +265,23 @@ void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {
   provider_client_impl_->ReleaseLock();
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+void VideoLayerImpl::OnVideoCompositingFinished(
+    const scoped_refptr<media::VideoFrame> video_frame,
+    const gpu::SyncToken& sync_token,
+    bool lost_resource) {
+#if defined(USE_TTRACE)
+  TTRACE_WEB("VideoLayerImpl::OnVideoCompositingFinished");
+#endif
+#if defined(_DEBUG_TBM_VIDEO_RENDERING) && _DEBUG_TBM_VIDEO_RENDERING
+  LOG(INFO)
+      << "OnVideoCompositingFinished > resource was removed in ResourceProvider"
+      << ", tbm:" << video_frame->GetTbmBuffer().tbm_surface
+      << ", txt:" << video_frame->GetTbmTexture();
+#endif
+}
+#endif
+
 SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const {
   // If we don't have a frame yet, then we don't have an opaque region.
   if (!provider_client_impl_->HasCurrentFrame())
@@ -203,6 +290,16 @@ SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const {
 }
 
 void VideoLayerImpl::ReleaseResources() {
+#if defined(TIZEN_TBM_SUPPORT)
+  scoped_refptr<media::VideoFrame> last_frame = frame_;
+  if (!frame_)
+    last_frame = provider_client_impl_->AcquireLockAndCurrentFrame();
+  if (last_frame)
+    last_frame->ReleaseTbm();
+  last_frame = nullptr;
+  if (!frame_)
+    provider_client_impl_->ReleaseLock();
+#endif
   updater_ = nullptr;
 }
 
index 3bad972..99c89dc 100644 (file)
 #include "components/viz/common/resources/release_callback.h"
 #include "media/base/video_transformation.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "components/viz/common/gpu/context_provider.h"
+#endif
+
 namespace media {
 class VideoFrame;
 class VideoResourceUpdater;
@@ -64,12 +68,24 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
 
   const char* LayerTypeAsString() const override;
 
+#if defined(TIZEN_TBM_SUPPORT)
+  void OnVideoCompositingFinished(
+      const scoped_refptr<media::VideoFrame> video_frame,
+      const gpu::SyncToken& sync_token,
+      bool lost_resource);
+#endif
+
   scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl_;
 
   scoped_refptr<media::VideoFrame> frame_;
 
   media::VideoTransformation video_transform_;
 
+#if defined(TIZEN_TBM_SUPPORT)
+  scoped_refptr<viz::ContextProvider> context_provider_;
+  viz::ResourceId resource_id_;
+#endif
+
   std::unique_ptr<media::VideoResourceUpdater> updater_;
 };
 
index 9a173e6..98af814 100644 (file)
@@ -374,6 +374,9 @@ absl::optional<media::VideoPixelFormat> ToMediaVideoPixelFormat(
     CASE_RETURN_OTHER(PIXEL_FORMAT_P016LE);
     CASE_RETURN_OTHER(PIXEL_FORMAT_XR30);
     CASE_RETURN_OTHER(PIXEL_FORMAT_XB30);
+#if defined(TIZEN_TBM_SUPPORT)
+    CASE_RETURN_OTHER(PIXEL_FORMAT_TBM_SURFACE);
+#endif
     // PIXEL_FORMAT_UYVY, PIXEL_FORMAT_RGB32 and PIXEL_FORMAT_Y8 are deprecated.
     case openscreen::cast::VideoDecoderConfig_Format_PIXEL_FORMAT_RGB32:
       return absl::nullopt;
index dbd3021..4d16116 100644 (file)
@@ -331,6 +331,8 @@ bool UseSurfaceLayerForVideo() {
     return true;
   }
   return base::FeatureList::IsEnabled(kUseSurfaceLayerForVideoDefault);
+#elif defined(TIZEN_MULTIMEDIA)
+  return false;
 #else
   return true;
 #endif
index 17b6280..617b57f 100644 (file)
@@ -1147,6 +1147,9 @@ RenderThreadImpl::SharedMainThreadContextProvider() {
           .status_values[gpu::GPU_FEATURE_TYPE_CANVAS_OOP_RASTERIZATION] ==
       gpu::kGpuFeatureStatusEnabled;
   bool support_gles2_interface = false;
+#if defined(TIZEN_TBM_SUPPORT)
+  support_gles2_interface = true;
+#endif
   bool support_grcontext = !support_oop_rasterization;
   // Enable automatic flushes to improve canvas throughput.
   // See https://crbug.com/880901
index efcb0d3..014d040 100644 (file)
 #define glCoverageModulationCHROMIUM GLES2_GET_FUN(CoverageModulationCHROMIUM)
 #define glGetGraphicsResetStatusKHR GLES2_GET_FUN(GetGraphicsResetStatusKHR)
 #define glBlendBarrierKHR GLES2_GET_FUN(BlendBarrierKHR)
+#define glCreateTizenImageCHROMIUM GLES2_GET_FUN(CreateTizenImageCHROMIUM)
+#define glDestroyTizenImageCHROMIUM GLES2_GET_FUN(DestroyTizenImageCHROMIUM)
 #define glBindFragDataLocationIndexedEXT \
   GLES2_GET_FUN(BindFragDataLocationIndexedEXT)
 #define glBindFragDataLocationEXT GLES2_GET_FUN(BindFragDataLocationEXT)
index b8bef5e..849dc9b 100755 (executable)
@@ -3958,6 +3958,17 @@ _FUNCTION_INFO = {
     'extension': True,
     'trace_level': 2,
   },
+ 'CreateTizenImageCHROMIUM': {
+   'type': 'NoCommand',
+   'cmd_args':'gfx::TbmBufferHandle handle, GLsizei width,'
+   ' GLsizei height, GLenum internalformat',
+   'result': ['GLuint'],
+   'extension': True,
+  },
+  'DestroyTizenImageCHROMIUM': {
+  'type': 'NoCommand',
+  'extension': True,
+  },
   'InitializeDiscardableTextureCHROMIUM': {
     'type': 'Custom',
     'cmd_args': 'GLuint texture_id, uint32_t shm_id, '
index 7114150..dc682bd 100644 (file)
@@ -1601,6 +1601,16 @@ GLenum GL_APIENTRY GLES2GetGraphicsResetStatusKHR() {
 void GL_APIENTRY GLES2BlendBarrierKHR() {
   gles2::GetGLContext()->BlendBarrierKHR();
 }
+GLuint GL_APIENTRY GLES2CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle,
+                                                 GLsizei width,
+                                                 GLsizei height,
+                                                 GLenum internalformat) {
+  return gles2::GetGLContext()->CreateTizenImageCHROMIUM(handle, width, height,
+                                                         internalformat);
+}
+void GL_APIENTRY GLES2DestroyTizenImageCHROMIUM(GLuint image_id) {
+  gles2::GetGLContext()->DestroyTizenImageCHROMIUM(image_id);
+}
 void GL_APIENTRY GLES2BindFragDataLocationIndexedEXT(GLuint program,
                                                      GLuint colorNumber,
                                                      GLuint index,
@@ -2986,6 +2996,14 @@ extern const NameToFunc g_gles2_function_table[] = {
         reinterpret_cast<GLES2FunctionPointer>(glBlendBarrierKHR),
     },
     {
+        "glCreateTizenImageCHROMIUM",
+        reinterpret_cast<GLES2FunctionPointer>(glCreateTizenImageCHROMIUM),
+    },
+    {
+        "glDestroyTizenImageCHROMIUM",
+        reinterpret_cast<GLES2FunctionPointer>(glDestroyTizenImageCHROMIUM),
+    },
+    {
         "glBindFragDataLocationIndexedEXT",
         reinterpret_cast<GLES2FunctionPointer>(
             glBindFragDataLocationIndexedEXT),
index 9aed697..d66cb81 100644 (file)
       !ptr ||                                                             \
       (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1)));
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "base/logging.h"
+#endif
+
 namespace gpu {
 namespace gles2 {
 
@@ -244,7 +248,9 @@ GLES2Implementation::GLES2Implementation(
       aggressively_free_resources_(false),
       cached_extension_string_(nullptr) {
   DCHECK(helper);
-
+#if defined(TIZEN_TBM_SUPPORT)
+  LOG(INFO) << __FUNCTION__ << "  " << this;
+#endif
   std::stringstream ss;
   ss << std::hex << this;
   this_in_hex_ = ss.str();
@@ -324,6 +330,9 @@ GLES2Implementation::~GLES2Implementation() {
   // shared memory (mapped_memory_) which will free the memory used
   // by the queries. The GPU process when validating that memory is still
   // shared will fail and abort (ie, it will stop running).
+#if defined(TIZEN_TBM_SUPPORT)
+  LOG(INFO) << __FUNCTION__ << "  " << this;
+#endif
   WaitForCmd();
 
   query_tracker_.reset();
@@ -6899,6 +6908,65 @@ bool GLES2Implementation::CanDecodeWithHardwareAcceleration(
   return false;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+GLuint GLES2Implementation::CreateTizenImageCHROMIUMHelper(
+    gfx::TbmBufferHandle buffer_handle,
+    GLsizei width,
+    GLsizei height,
+    GLenum internalformat) {
+  if (width <= 0) {
+    SetGLError(GL_INVALID_VALUE, "glCreateTizenImageCHROMIUM", "width <= 0");
+    return 0;
+  }
+
+  if (height <= 0) {
+    SetGLError(GL_INVALID_VALUE, "glCreateTizenImageCHROMIUM", "height <= 0");
+    return 0;
+  }
+
+  int32_t image_id = gpu_control_->CreateEGLImage(buffer_handle, width, height,
+                                                  internalformat);
+  if (image_id < 0) {
+    SetGLError(GL_OUT_OF_MEMORY, "glCreateTizenImageCHROMIUM", "image_id < 0");
+    return 0;
+  }
+  return image_id;
+}
+#endif
+
+GLuint GLES2Implementation::CreateTizenImageCHROMIUM(
+    gfx::TbmBufferHandle buffer_handle,
+    GLsizei width,
+    GLsizei height,
+    GLenum internalformat) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG(
+      "[" << GetLogPrefix() << "] glCreateTizenImageCHROMIUM(" << buffer_handle
+          << ", " << width << ", " << height << ", "
+          << GLES2Util::GetStringTextureInternalFormat(internalformat) << ")");
+#if defined(TIZEN_TBM_SUPPORT)
+  GLuint image_id = CreateTizenImageCHROMIUMHelper(buffer_handle, width, height,
+                                                   internalformat);
+  CheckGLError();
+  return image_id;
+#else
+  return 0;
+#endif
+}
+
+void GLES2Implementation::DestroyTizenImageCHROMIUM(GLuint image_id) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyTizenImageCHROMIUM("
+                     << image_id << ")");
+#if defined(TIZEN_TBM_SUPPORT)
+  // Flush the command stream to make sure all pending commands
+  // that may refer to the image_id are executed on the service side.
+  helper_->CommandBufferHelper::Flush();
+  gpu_control_->DestroyEGLImage(image_id);
+  CheckGLError();
+#endif
+}
+
 bool GLES2Implementation::ValidateSize(const char* func, GLsizeiptr size) {
   if (size < 0) {
     SetGLError(GL_INVALID_VALUE, func, "size < 0");
index cf8daae..24934f9 100644 (file)
@@ -523,6 +523,13 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface,
       const GLuint* baseInstances,
       GLsizei drawcount);
 
+#if defined(TIZEN_TBM_SUPPORT)
+  GLuint CreateTizenImageCHROMIUMHelper(gfx::TbmBufferHandle buffer_handle,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLenum internalformat);
+#endif
+
   // Helper for GetVertexAttrib
   bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32_t* param);
 
index f1c6a51..7e96128 100644 (file)
@@ -1127,6 +1127,13 @@ GLenum GetGraphicsResetStatusKHR() override;
 
 void BlendBarrierKHR() override;
 
+GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle,
+                                GLsizei width,
+                                GLsizei height,
+                                GLenum internalformat) override;
+
+void DestroyTizenImageCHROMIUM(GLuint image_id) override;
+
 void BindFragDataLocationIndexedEXT(GLuint program,
                                     GLuint colorNumber,
                                     GLuint index,
index bcc3cd1..aa59036 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "gpu/command_buffer/client/interface_base.h"
+#include "ui/gfx/tbm_buffer_handle.h"
 
 namespace cc {
 class ClientTransferCacheEntry;
index d24bf67..ab5f1ca 100644 (file)
@@ -835,6 +835,11 @@ virtual void ContextVisibilityHintCHROMIUM(GLboolean visibility) = 0;
 virtual void CoverageModulationCHROMIUM(GLenum components) = 0;
 virtual GLenum GetGraphicsResetStatusKHR() = 0;
 virtual void BlendBarrierKHR() = 0;
+virtual GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle,
+                                        GLsizei width,
+                                        GLsizei height,
+                                        GLenum internalformat) = 0;
+virtual void DestroyTizenImageCHROMIUM(GLuint image_id) = 0;
 virtual void BindFragDataLocationIndexedEXT(GLuint program,
                                             GLuint colorNumber,
                                             GLuint index,
index c799d22..cb8e5d0 100644 (file)
@@ -811,6 +811,11 @@ void ContextVisibilityHintCHROMIUM(GLboolean visibility) override;
 void CoverageModulationCHROMIUM(GLenum components) override;
 GLenum GetGraphicsResetStatusKHR() override;
 void BlendBarrierKHR() override;
+GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle,
+                                GLsizei width,
+                                GLsizei height,
+                                GLenum internalformat) override;
+void DestroyTizenImageCHROMIUM(GLuint image_id) override;
 void BindFragDataLocationIndexedEXT(GLuint program,
                                     GLuint colorNumber,
                                     GLuint index,
index 0dc071a..2dd74a0 100644 (file)
@@ -1088,6 +1088,14 @@ GLenum GLES2InterfaceStub::GetGraphicsResetStatusKHR() {
   return 0;
 }
 void GLES2InterfaceStub::BlendBarrierKHR() {}
+GLuint GLES2InterfaceStub::CreateTizenImageCHROMIUM(
+    gfx::TbmBufferHandle /* handle */,
+    GLsizei /* width */,
+    GLsizei /* height */,
+    GLenum /* internalformat */) {
+  return 0;
+}
+void GLES2InterfaceStub::DestroyTizenImageCHROMIUM(GLuint /* image_id */) {}
 void GLES2InterfaceStub::BindFragDataLocationIndexedEXT(
     GLuint /* program */,
     GLuint /* colorNumber */,
index 2103e9e..63b3b61 100644 (file)
@@ -811,6 +811,11 @@ void ContextVisibilityHintCHROMIUM(GLboolean visibility) override;
 void CoverageModulationCHROMIUM(GLenum components) override;
 GLenum GetGraphicsResetStatusKHR() override;
 void BlendBarrierKHR() override;
+GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle,
+                                GLsizei width,
+                                GLsizei height,
+                                GLenum internalformat) override;
+void DestroyTizenImageCHROMIUM(GLuint image_id) override;
 void BindFragDataLocationIndexedEXT(GLuint program,
                                     GLuint colorNumber,
                                     GLuint index,
index e22cb21..1a6c4c5 100644 (file)
@@ -2313,6 +2313,20 @@ void GLES2TraceImplementation::BlendBarrierKHR() {
   gl_->BlendBarrierKHR();
 }
 
+GLuint GLES2TraceImplementation::CreateTizenImageCHROMIUM(
+    gfx::TbmBufferHandle handle,
+    GLsizei width,
+    GLsizei height,
+    GLenum internalformat) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateTizenImageCHROMIUM");
+  return gl_->CreateTizenImageCHROMIUM(handle, width, height, internalformat);
+}
+
+void GLES2TraceImplementation::DestroyTizenImageCHROMIUM(GLuint image_id) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DestroyTizenImageCHROMIUM");
+  gl_->DestroyTizenImageCHROMIUM(image_id);
+}
+
 void GLES2TraceImplementation::BindFragDataLocationIndexedEXT(
     GLuint program,
     GLuint colorNumber,
index eadc592..a45ac1a 100644 (file)
 #include "gpu/gpu_export.h"
 #include "ui/gfx/overlay_transform.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "ui/gfx/tbm_buffer_handle.h"
+#endif
+
 extern "C" typedef struct _ClientBuffer* ClientBuffer;
 extern "C" typedef struct _ClientGpuFence* ClientGpuFence;
 
@@ -47,6 +51,16 @@ class GPU_EXPORT GpuControl {
 
   virtual const Capabilities& GetCapabilities() const = 0;
 
+#if defined(TIZEN_TBM_SUPPORT)
+  virtual int32_t CreateEGLImage(gfx::TbmBufferHandle buffer_handle,
+                                 size_t width,
+                                 size_t height,
+                                 unsigned internalformat) {
+    return -1;
+  }
+  virtual void DestroyEGLImage(int32_t image_id) {}
+#endif
+
   // Runs |callback| when a query created via glCreateQueryEXT() has cleared
   // passed the glEndQueryEXT() point.
   virtual void SignalQuery(uint32_t query, base::OnceClosure callback) = 0;
index a2801cd..15dae8d 100644 (file)
@@ -348,6 +348,10 @@ GL_APICALL GLenum       GL_APIENTRY glGetGraphicsResetStatusKHR (void);
 // Extension KHR_blend_equation_advanced
 GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void);
 
+// for tizen
+GL_APICALL GLuint GL_APIENTRY glCreateTizenImageCHROMIUM (gfx::TbmBufferHandle handle, GLsizei width, GLsizei height, GLenum internalformat);
+GL_APICALL void GL_APIENTRY glDestroyTizenImageCHROMIUM (GLuint image_id);
+
 // Extension EXT_blend_func_extended
 GL_APICALL void         GL_APIENTRY glBindFragDataLocationIndexedEXT (GLidProgram program, GLuint colorNumber, GLuint index, const char* name);
 GL_APICALL void         GL_APIENTRY glBindFragDataLocationEXT (GLidProgram program, GLuint colorNumber, const char* name);
index 682ed9f..a6af84d 100644 (file)
@@ -415,6 +415,55 @@ const gpu::Capabilities& CommandBufferProxyImpl::GetCapabilities() const {
   return capabilities_;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+int32_t CommandBufferProxyImpl::CreateEGLImage(
+    gfx::TbmBufferHandle buffer_handle,
+    size_t width,
+    size_t height,
+    unsigned internalformat) {
+  CheckLock();
+  base::AutoLock lock(last_state_lock_);
+  if (last_state_.error != gpu::error::kNoError)
+    return -1;
+
+  int32_t new_id = channel_->ReserveImageId();
+
+  auto params = mojom::CreateImageParams::New();
+  params->id = new_id;
+  params->size = gfx::Size(width, height);
+  params->format = gfx::BufferFormat::RGBA_8888;
+  params->plane = gfx::BufferPlane::DEFAULT;
+  params->image_release_count = 0;
+
+  gfx::GpuMemoryBufferHandle handle;
+  handle.type = gfx::NATIVE_PIXMAP;
+  handle.tbm_surface = reinterpret_cast<uintptr_t>(buffer_handle.tbm_surface);
+  handle.media_packet = reinterpret_cast<uintptr_t>(buffer_handle.media_packet);
+  handle.player_id = buffer_handle.player_id;
+  handle.key_num = buffer_handle.key_num;
+  for (int i = 0; i < handle.key_num; ++i) {
+    handle.key[i] = buffer_handle.key[i];
+    handle.strides[i] = buffer_handle.strides[i];
+    LOG(ERROR) << "exported key values " << handle.key[i];
+  }
+  handle.width = width;
+  handle.height = height;
+
+  params->gpu_memory_buffer = std::move(handle);
+  command_buffer_->CreateImage(std::move(params));
+  return new_id;
+}
+
+void CommandBufferProxyImpl::DestroyEGLImage(int32_t image_id) {
+  CheckLock();
+  base::AutoLock lock(last_state_lock_);
+  if (last_state_.error != gpu::error::kNoError)
+    return;
+
+  command_buffer_->DestroyImage(image_id);
+}
+#endif
+
 void CommandBufferProxyImpl::SetLock(base::Lock* lock) {
   lock_ = lock;
 }
index 80369c9..969320f 100644 (file)
@@ -163,6 +163,14 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer,
     return shared_state_shm_;
   }
 
+#if defined(TIZEN_TBM_SUPPORT)
+  int32_t CreateEGLImage(gfx::TbmBufferHandle buffer_handle,
+                         size_t width,
+                         size_t height,
+                         unsigned internalformat) override;
+  void DestroyEGLImage(int32_t image_id) override;
+#endif
+
  private:
   typedef std::map<int32_t, scoped_refptr<gpu::Buffer>> TransferBufferMap;
   typedef std::unordered_map<uint32_t, base::OnceClosure> SignalTaskMap;
index 2dff68b..cdd61b8 100644 (file)
@@ -129,7 +129,15 @@ GpuMemoryBufferFactoryNativePixmap::CreateImageForGpuMemoryBuffer(
     SurfaceHandle surface_handle) {
   if (handle.type != gfx::NATIVE_PIXMAP)
     return nullptr;
-
+#if defined(TIZEN_TBM_SUPPORT)
+  scoped_refptr<gl::GLImageNativePixmap> image(
+      new gl::GLImageNativePixmap(size, format));
+  if (!image->Initialize(handle)) {
+    LOG(ERROR) << "Failed to create GLImage";
+    return nullptr;
+  }
+  return image;
+#else
   scoped_refptr<gfx::NativePixmap> pixmap;
 
   // If CreateGpuMemoryBuffer was used to allocate this buffer then avoid
@@ -180,6 +188,7 @@ GpuMemoryBufferFactoryNativePixmap::CreateImageForGpuMemoryBuffer(
       NOTREACHED();
       return nullptr;
   }
+#endif
 }
 
 bool GpuMemoryBufferFactoryNativePixmap::SupportsCreateAnonymousImage() const {
index 4aa077a..ef1213f 100644 (file)
 #if BUILDFLAG(IS_MAC)
 #include "ui/gfx/mac/io_surface.h"
 #endif
+#if defined(TIZEN_TBM_SUPPORT)
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "media/base/bind_to_current_loop.h"
+#endif
 
 namespace media {
 
@@ -79,6 +86,10 @@ std::string VideoFrame::StorageTypeToString(
     case VideoFrame::STORAGE_DMABUFS:
       return "DMABUFS";
 #endif
+#if defined(TIZEN_TBM_SUPPORT)
+    case VideoFrame::STORAGE_TBM_SURFACE:
+      return "TBM_SURFACE";
+#endif
     case VideoFrame::STORAGE_GPU_MEMORY_BUFFER:
       return "GPU_MEMORY_BUFFER";
   }
@@ -164,6 +175,9 @@ gfx::Size VideoFrame::SampleSize(VideoPixelFormat format, size_t plane) {
         case PIXEL_FORMAT_XB30:
         case PIXEL_FORMAT_BGRA:
         case PIXEL_FORMAT_RGBAF16:
+#if defined(TIZEN_TBM_SUPPORT)
+        case PIXEL_FORMAT_TBM_SURFACE:
+#endif
           break;
       }
   }
@@ -197,6 +211,9 @@ static bool RequiresEvenSizeAllocation(VideoPixelFormat format) {
     case PIXEL_FORMAT_XB30:
     case PIXEL_FORMAT_BGRA:
     case PIXEL_FORMAT_RGBAF16:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       return false;
     case PIXEL_FORMAT_NV12:
     case PIXEL_FORMAT_NV21:
@@ -354,6 +371,34 @@ scoped_refptr<VideoFrame> VideoFrame::CreateZeroInitializedFrame(
 }
 
 // static
+#if defined(TIZEN_TBM_SUPPORT)
+scoped_refptr<VideoFrame> VideoFrame::WrapTBMSurface(
+    const gfx::Size& size,
+    base::TimeDelta timestamp,
+    gfx::TbmBufferHandle handle) {
+  const VideoPixelFormat format = PIXEL_FORMAT_TBM_SURFACE;
+  const StorageType storage = STORAGE_TBM_SURFACE;
+  const gfx::Rect visible_rect = gfx::Rect(size);
+  if (!IsValidConfig(format, storage, size, visible_rect, size)) {
+    LOG(ERROR) << __FUNCTION__ << " WrapTBMSurface Invalid config."
+               << ConfigToString(format, storage, size, visible_rect, size);
+    return nullptr;
+  }
+
+  auto layout = VideoFrameLayout::Create(format, size);
+  if (!layout) {
+    LOG(ERROR) << "Invalid layout.";
+    return nullptr;
+  }
+
+  scoped_refptr<VideoFrame> frame(
+      new VideoFrame(*layout, storage, gfx::Rect(size), size, timestamp));
+  frame->buffer_handle_ = handle;
+  return frame;
+}
+#endif
+
+// static
 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTextures(
     VideoPixelFormat format,
     const gpu::MailboxHolder (&mailbox_holders)[kMaxPlanes],
@@ -1086,6 +1131,9 @@ int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) {
       return 1;
     case PIXEL_FORMAT_MJPEG:
       return 0;
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
     case PIXEL_FORMAT_UNKNOWN:
       break;
   }
@@ -1269,7 +1317,11 @@ uint8_t* VideoFrame::GetWritableVisibleData(size_t plane) {
 
 const gpu::MailboxHolder& VideoFrame::mailbox_holder(
     size_t texture_index) const {
+#if defined(TIZEN_TBM_SUPPORT)
+  DCHECK(IsTBMBackend() || HasTextures());
+#else
   DCHECK(HasTextures());
+#endif
   DCHECK(IsValidPlane(format(), texture_index));
   return wrapped_frame_ ? wrapped_frame_->mailbox_holder(texture_index)
                         : mailbox_holders_[texture_index];
@@ -1330,7 +1382,11 @@ void VideoFrame::AddDestructionObserver(base::OnceClosure callback) {
 }
 
 gpu::SyncToken VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) {
+#if defined(TIZEN_TBM_SUPPORT)
+  DCHECK(IsTBMBackend() || HasTextures());
+#else
   DCHECK(HasTextures());
+#endif
   if (wrapped_frame_) {
     return wrapped_frame_->UpdateReleaseSyncToken(client);
   }
@@ -1390,6 +1446,11 @@ VideoFrame::VideoFrame(const VideoFrameLayout& layout,
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
       dmabuf_fds_(base::MakeRefCounted<DmabufHolder>()),
 #endif
+#if defined(TIZEN_TBM_SUPPORT)
+      texture_id_(0),
+      gl_(nullptr),
+      image_id_(0),
+#endif
       timestamp_(timestamp),
       unique_id_(g_unique_id_generator.GetNext()) {
   DCHECK(IsValidConfigInternal(format(), frame_control_type, coded_size(),
@@ -1631,4 +1692,81 @@ std::vector<size_t> VideoFrame::CalculatePlaneSize() const {
   return plane_size;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+void ReleaseTbmTexture(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                       gpu::gles2::GLES2Interface* gl,
+                       uint32_t texture,
+                       uint32_t image,
+                       scoped_refptr<viz::ContextProvider> context_provider,
+                       const gpu::SyncToken& release_sync_point) {
+#if defined(USE_TTRACE)
+  TTRACE(TTRACE_TAG_WEB, "ReleaseTbmTexture");
+#endif
+  DCHECK(task_runner->BelongsToCurrentThread());
+  const uint32_t target = GL_TEXTURE_EXTERNAL_OES;
+  LOG(INFO) << "VideoFrame > --ReleaseTbmTexture >"
+            << ", img:" << image << ", txt:" << texture;
+  if (release_sync_point.HasData())
+    gl->WaitSyncTokenCHROMIUM(release_sync_point.GetConstData());
+  if (image) {
+    gl->BindTexture(target, texture);
+    gl->ReleaseTexImage2DCHROMIUM(target, image);
+    gl->DestroyTizenImageCHROMIUM(image);
+  }
+  gl->DeleteTextures(1, &texture);
+}
+
+void VideoFrame::ReleaseTbm() {
+  if (mailbox_holders_and_gmb_release_cb_) {
+    gpu::SyncToken release_sync_token;
+    {
+      // To ensure that changes to |release_sync_token_| are visible on this
+      // thread (imply a memory barrier).
+      base::AutoLock locker(release_sync_token_lock_);
+      release_sync_token = release_sync_token_;
+    }
+    std::move(mailbox_holders_and_gmb_release_cb_)
+        .Run(release_sync_token, std::move(gpu_memory_buffer_));
+  }
+}
+
+unsigned VideoFrame::CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl) {
+#if defined(USE_TTRACE)
+  TTRACE(TTRACE_TAG_WEB, "VideoFrameCompositor::CreateTbmTextureIfNeeded");
+#endif
+  base::AutoLock autolock(tbm_lock_);
+  if (!gl || texture_id_)
+    return (gl_ == gl) ? texture_id_ : 0;
+
+  gl_ = gl;
+  unsigned image = gl->CreateTizenImageCHROMIUM(
+      buffer_handle_, visible_rect().width(), visible_rect().height(), GL_RGBA);
+  gl->GenTextures(1, &texture_id_);
+  gl->BindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
+  gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
+                    GL_CLAMP_TO_EDGE);
+  gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
+                    GL_CLAMP_TO_EDGE);
+  gl->BindTexImage2DCHROMIUM(GL_TEXTURE_EXTERNAL_OES, image);
+
+  LOG(INFO) << "CreateTbmTextureIfNeeded img:" << image
+            << ", txt:" << texture_id_;
+
+  gpu::Mailbox mailbox;
+  gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox.name);
+  gl->ShallowFlushCHROMIUM();
+  gpu::SyncToken sync_token;
+  gl->GenSyncTokenCHROMIUM(sync_token.GetData());
+  mailbox_holders_[kARGBPlane] =
+      gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_EXTERNAL_OES);
+
+  SetReleaseMailboxCB(base::BindOnce(ReleaseTbmTexture,
+                                     base::ThreadTaskRunnerHandle::Get(), gl,
+                                     texture_id_, image, context_provider_));
+  return texture_id_;
+}
+#endif
+
 }  // namespace media
index 8c6d873..ffeb81e 100644 (file)
@@ -50,8 +50,25 @@ class GpuMemoryBuffer;
 struct GpuMemoryBufferHandle;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include "components/viz/common/gpu/context_provider.h"
+#include "ui/gfx/tbm_buffer_handle.h"
+#define _DEBUG_TBM_VIDEO_RENDERING 0
+#define _DEBUG_TBM_VIDEO_RENDERING_FPS 0
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}  // namespace gpu
+#endif
+
 namespace media {
 
+constexpr auto TBM_BO_NUM_MAX = 4;
+
 class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
  public:
   static constexpr size_t kFrameSizeAlignment = 16;
@@ -92,7 +109,12 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
     STORAGE_DMABUFS = 5,  // Each plane is stored into a DmaBuf.
 #endif
     STORAGE_GPU_MEMORY_BUFFER = 6,
+#if defined(TIZEN_TBM_SUPPORT)
+    STORAGE_TBM_SURFACE = 7,
+    STORAGE_MAX = STORAGE_TBM_SURFACE,
+#else
     STORAGE_MAX = STORAGE_GPU_MEMORY_BUFFER,
+#endif
   };
 
   // CB to be called on the mailbox backing this frame and its GpuMemoryBuffers
@@ -330,6 +352,25 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
       const gfx::Rect& visible_rect,
       const gfx::Size& natural_size);
 
+#if defined(TIZEN_TBM_SUPPORT)
+  // Needed when we have video-frame content in tbm surface.
+  static scoped_refptr<VideoFrame> WrapTBMSurface(const gfx::Size& size,
+                                                  base::TimeDelta timestamp,
+                                                  gfx::TbmBufferHandle handle);
+  bool IsTBMBackend() const { return storage_type_ == STORAGE_TBM_SURFACE; }
+  unsigned GetTbmTexture() { return texture_id_; }
+  unsigned CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl);
+  void ReleaseTbm();
+  void SetTbmTexture(unsigned texture) { texture_id_ = texture; }
+  gfx::TbmBufferHandle GetTbmBuffer() { return buffer_handle_; }
+  unsigned GetImageID() { return image_id_; }
+  void SetImageID(unsigned image_id) { image_id_ = image_id; }
+  void SetContextProvider(
+      scoped_refptr<viz::ContextProvider> context_provider) {
+    context_provider_ = context_provider;
+  }
+#endif
+
   // Creates a frame which indicates end-of-stream.
   static scoped_refptr<VideoFrame> CreateEOSFrame();
 
@@ -776,6 +817,16 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
 
   std::vector<base::OnceClosure> done_callbacks_;
 
+#if defined(TIZEN_TBM_SUPPORT)
+  base::Lock tbm_lock_;
+  mutable base::Lock tbm_map_lock_;
+  gfx::TbmBufferHandle buffer_handle_;
+  unsigned texture_id_;
+  gpu::gles2::GLES2Interface* gl_;
+  unsigned image_id_;
+  scoped_refptr<viz::ContextProvider> context_provider_;
+#endif
+
   base::TimeDelta timestamp_;
 
   base::Lock release_sync_token_lock_;
index b3307c3..47bbbff 100644 (file)
@@ -85,6 +85,9 @@ size_t VideoFrameLayout::NumPlanes(VideoPixelFormat format) {
     case PIXEL_FORMAT_UNKNOWN:
       // Note: PIXEL_FORMAT_UNKNOWN is used for end-of-stream frame.
       // Set its NumPlanes() to zero to avoid NOTREACHED().
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       return 0;
   }
   NOTREACHED() << "Unsupported video frame format: " << format;
index ea148df..4edcc27 100644 (file)
@@ -85,6 +85,10 @@ std::string VideoPixelFormatToString(VideoPixelFormat format) {
       return "PIXEL_FORMAT_YUV422AP10";
     case PIXEL_FORMAT_YUV444AP10:
       return "PIXEL_FORMAT_YUV444AP10";
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+      return "PIXEL_FORMAT_TBM_SURFACE";
+#endif
   }
   NOTREACHED() << "Invalid VideoPixelFormat provided: " << format;
   return "";
@@ -161,6 +165,9 @@ bool IsYuvPlanar(VideoPixelFormat format) {
     case PIXEL_FORMAT_XB30:
     case PIXEL_FORMAT_BGRA:
     case PIXEL_FORMAT_RGBAF16:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       return false;
   }
   return false;
@@ -239,6 +246,9 @@ bool IsOpaque(VideoPixelFormat format) {
     case PIXEL_FORMAT_P016LE:
     case PIXEL_FORMAT_XR30:
     case PIXEL_FORMAT_XB30:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       return true;
     case PIXEL_FORMAT_I420A:
     case PIXEL_FORMAT_ARGB:
@@ -258,6 +268,9 @@ bool IsOpaque(VideoPixelFormat format) {
 size_t BitDepth(VideoPixelFormat format) {
   switch (format) {
     case PIXEL_FORMAT_UNKNOWN:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       NOTREACHED();
       [[fallthrough]];
     case PIXEL_FORMAT_I420:
index 7f44dbf..d7dad6d 100644 (file)
@@ -88,9 +88,14 @@ enum VideoPixelFormat {
   PIXEL_FORMAT_YUV422AP10 = 37,
   PIXEL_FORMAT_YUV444AP10 = 38,
 
-  // Please update UMA histogram enumeration when adding new formats here.
+// Please update UMA histogram enumeration when adding new formats here.
+#if defined(TIZEN_TBM_SUPPORT)
+  PIXEL_FORMAT_TBM_SURFACE = 39,
+  PIXEL_FORMAT_MAX = PIXEL_FORMAT_TBM_SURFACE,
+#else
   PIXEL_FORMAT_MAX =
       PIXEL_FORMAT_YUV444AP10,  // Must always be equal to largest entry logged.
+#endif
 };
 
 // These values are persisted to logs. Entries should not be renumbered and
index db44033..65cd420 100644 (file)
@@ -4,6 +4,15 @@
 
 import("//mojo/public/tools/bindings/mojom.gni")
 
+if (use_aura) {
+  import("//tizen_src/build/config/tizen_features.gni")
+}
+
+enabled_features = []
+if (tizen_tbm_support) {
+  enabled_features += [ "tizen_tbm_support" ]
+}
+
 mojom("video_capture") {
   generate_java = true
   sources = [ "video_capture.mojom" ]
index d8814af..e58304e 100644 (file)
@@ -44,6 +44,9 @@ enum VideoCapturePixelFormat {
   [MinVersion=1] YUV420AP10,
   [MinVersion=1] YUV422AP10,
   [MinVersion=1] YUV444AP10,
+
+  [EnableIf=tizen_tbm_support]
+  TBM_SURFACE,
 };
 
 [Stable, Extensible]
index 2dd7014..aa05fa7 100644 (file)
@@ -159,6 +159,10 @@ EnumTraits<media::mojom::VideoCapturePixelFormat,
       return media::mojom::VideoCapturePixelFormat::YUV422AP10;
     case media::VideoPixelFormat::PIXEL_FORMAT_YUV444AP10:
       return media::mojom::VideoCapturePixelFormat::YUV444AP10;
+#if defined(TIZEN_TBM_SUPPORT)
+    case media::VideoPixelFormat::PIXEL_FORMAT_TBM_SURFACE:
+      return media::mojom::VideoCapturePixelFormat::TBM_SURFACE;
+#endif
   }
   NOTREACHED();
   return media::mojom::VideoCapturePixelFormat::I420;
@@ -278,6 +282,11 @@ bool EnumTraits<media::mojom::VideoCapturePixelFormat,
     case media::mojom::VideoCapturePixelFormat::YUV444AP10:
       *output = media::PIXEL_FORMAT_YUV444AP10;
       return true;
+#if defined(TIZEN_TBM_SUPPORT)
+    case media::mojom::VideoCapturePixelFormat::TBM_SURFACE:
+      *output = media::PIXEL_FORMAT_TBM_SURFACE;
+      return true;
+#endif
   }
   NOTREACHED();
   return false;
index 2d66c33..4dd4ebd 100644 (file)
@@ -9,6 +9,7 @@ import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/shared_memory.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
+import "ui/gfx/mojom/buffer_types.mojom";
 
 [EnableIf=is_win]
 import "ui/gfx/mojom/buffer_types.mojom";
@@ -33,6 +34,11 @@ interface MediaPlayerRendererClientExtension {
                       mojo_base.mojom.TimeDelta timestamp,
                       uint32 width,
                       uint32 height);
+
+  [EnableIf=tizen_multimedia]
+  OnNewTbmFrameAvailable(uint32 playerId,
+                         gfx.mojom.TbmBufferHandle tbm_buffer_handle,
+                         mojo_base.mojom.TimeDelta timestamp);
 };
 
 // Extension of the mojo::Renderer communication layer for HLS and Android
@@ -47,6 +53,9 @@ interface MediaPlayerRendererExtension {
   // StreamTexture's set-up.
   InitiateScopedSurfaceRequest()
       => (mojo_base.mojom.UnguessableToken request_token);
+
+  [EnableIf=tizen_multimedia]
+  OnTbmBufferExhausted(gfx.mojom.TbmBufferHandle tbm_buffer_handle);
 };
 
 // Extension of the mojo::RendererClient communication layer for media flinging,
index ce72cf6..c2c53c0 100644 (file)
@@ -982,6 +982,9 @@ void PaintCanvasVideoRenderer::Paint(
   if (!video_frame.get() || video_frame->natural_size().IsEmpty() ||
       !(media::IsYuvPlanar(video_frame->format()) ||
         video_frame->format() == PIXEL_FORMAT_Y16 ||
+#if defined(TIZEN_TBM_SUPPORT)
+        video_frame->IsTBMBackend() ||
+#endif
         video_frame->format() == PIXEL_FORMAT_ARGB ||
         video_frame->format() == PIXEL_FORMAT_XRGB ||
         video_frame->format() == PIXEL_FORMAT_ABGR ||
@@ -1873,7 +1876,11 @@ bool PaintCanvasVideoRenderer::UpdateLastImage(
   // |video_frame| is software.
   // Holding |video_frame| longer than this call when using GPUVideoDecoder
   // could cause problems since the pool of VideoFrames has a fixed size.
-  if (video_frame->HasTextures()) {
+  if (video_frame->HasTextures()
+#if defined(TIZEN_TBM_SUPPORT)
+      && !video_frame->IsTBMBackend()
+#endif
+  ) {
     DCHECK(raster_context_provider);
     bool supports_oop_raster =
         raster_context_provider->ContextCapabilities().supports_oop_raster;
@@ -2003,8 +2010,38 @@ bool PaintCanvasVideoRenderer::UpdateLastImage(
                                             cc::PaintImage::GetNextContentId());
   } else {
     cache_.emplace(video_frame->unique_id());
+#if defined(TIZEN_TBM_SUPPORT)
+    gpu::gles2::GLES2Interface* gl = raster_context_provider->ContextGL();
+    unsigned source_texture = 0;
+    gl->GenTextures(1, &source_texture);
+    DCHECK(source_texture);
+    gl->BindTexture(GL_TEXTURE_2D, source_texture);
+
+    CopyMailboxToTexture(
+        gl, video_frame->coded_size(), video_frame->visible_rect(),
+        video_frame->mailbox_holder(0).mailbox,
+        video_frame->mailbox_holder(0).sync_token, GL_TEXTURE_2D,
+        source_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 0, false, false);
+
+    GrGLTextureInfo source_texture_info;
+    source_texture_info.fID = source_texture;
+    source_texture_info.fTarget = GL_TEXTURE_2D;
+    source_texture_info.fFormat = GL_RGBA8_OES;
+    GrBackendTexture source_backend_texture(
+        video_frame->coded_size().width(), video_frame->coded_size().height(),
+        GrMipMapped::kNo, source_texture_info);
+
+    paint_image_builder.set_image(
+        SkImage::MakeFromAdoptedTexture(
+            raster_context_provider->GrContext(), source_backend_texture,
+            kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
+            kPremul_SkAlphaType, video_frame->ColorSpace().ToSkColorSpace()),
+        cc::PaintImage::GetNextContentId());
+
+#else
     paint_image_builder.set_paint_image_generator(
         sk_make_sp<VideoImageGenerator>(video_frame));
+#endif
   }
 
   cache_->paint_image = paint_image_builder.TakePaintImage();
index 7ded363..9b419ca 100644 (file)
@@ -207,6 +207,9 @@ VideoFrameResourceType ExternalResourceTypeForHardwarePlanes(
     case PIXEL_FORMAT_YUV422AP10:
     case PIXEL_FORMAT_YUV444AP10:
     case PIXEL_FORMAT_UNKNOWN:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       break;
   }
   return VideoFrameResourceType::NONE;
@@ -550,7 +553,16 @@ VideoResourceUpdater::~VideoResourceUpdater() {
 }
 
 void VideoResourceUpdater::ObtainFrameResources(
-    scoped_refptr<VideoFrame> video_frame) {
+    scoped_refptr<VideoFrame> video_frame,
+    viz::ResourceId external_resource_id) {
+#if defined(TIZEN_TBM_SUPPORT)
+  if (video_frame->IsTBMBackend()) {
+    frame_resources_.emplace_back(external_resource_id,
+                                  video_frame->coded_size());
+    frame_resource_type_ = VideoFrameResourceType::RGBA;
+    return;
+  }
+#endif
   if (video_frame->metadata().overlay_plane_id.has_value()) {
     // This is a hole punching VideoFrame, there is nothing to display.
     overlay_plane_id_ = *video_frame->metadata().overlay_plane_id;
index 9ada870..e3a0783 100644 (file)
@@ -108,7 +108,9 @@ class MEDIA_EXPORT VideoResourceUpdater
   // 2. AppendQuads(): Add DrawQuads to CompositorFrame for video.
   // 3. ReleaseFrameResources(): After the CompositorFrame has been submitted,
   //    remove imported resources from viz::ClientResourceProvider.
-  void ObtainFrameResources(scoped_refptr<VideoFrame> video_frame);
+  void ObtainFrameResources(
+      scoped_refptr<VideoFrame> video_frame,
+      viz::ResourceId resource_id = viz::kInvalidResourceId);
   void ReleaseFrameResources();
   // Appends a quad representing |frame| to |render_pass|.
   // At most one quad is expected to be appended, this is enforced by the users
index 098650d..d402e0f 100644 (file)
@@ -790,6 +790,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
     case PIXEL_FORMAT_YUV422AP10:
     case PIXEL_FORMAT_YUV444AP10:
     case PIXEL_FORMAT_UNKNOWN:
+#if defined(TIZEN_TBM_SUPPORT)
+    case PIXEL_FORMAT_TBM_SURFACE:
+#endif
       if (is_software_backed_video_frame) {
         UMA_HISTOGRAM_ENUMERATION(
             "Media.GpuMemoryBufferVideoFramePool.UnsupportedFormat",
index d0884a9..b71d563 100644 (file)
@@ -3,6 +3,11 @@
 # found in the LICENSE file.
 import("//build/config/chromeos/ui_mode.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
+
+if (use_efl) {
+  import("//tizen_src/build/config/tizen_features.gni")
+}
+
 mojom("mojom") {
   generate_java = true
   sources = [
@@ -607,6 +612,11 @@ mojom("mojom") {
       ]
     },
   ]
+
+  enabled_features = []
+  if (tizen_tbm_support) {
+    enabled_features += [ "tizen_tbm_support" ]
+  }
 }
 mojom("resource_format") {
   generate_java = true
index 399c97b..af8bbfa 100644 (file)
@@ -231,6 +231,7 @@ message VideoDecoderConfig {
     PIXEL_FORMAT_P016LE = 29;
     PIXEL_FORMAT_XR30 = 30;
     PIXEL_FORMAT_XB30 = 31;
+    PIXEL_FORMAT_TBM_SURFACE = 32;
   };
 
   // Proto version of Chrome's media::ColorSpace.
index eb89768..c8ad9c5 100644 (file)
@@ -17,9 +17,6 @@ config("tizen_feature_flags") {
       defines += [ "EFL_BETA_API_SUPPORT" ]
     }
   }
-  if (tizen_tbm_support) {
-    defines += [ "TIZEN_TBM_SUPPORT" ]
-  }
   if (ewk_bringup) {
     defines += [ "EWK_BRINGUP" ]
   }
@@ -33,6 +30,9 @@ config("tizen_feature_flags") {
     if (use_wayland) {
       defines += [ "USE_WAYLAND" ]
     }
+    if (tizen_tbm_support) {
+      defines += [ "TIZEN_TBM_SUPPORT" ]
+    }
     if (tizen_multimedia_support) {
       defines += [
         "TIZEN_MULTIMEDIA_SUPPORT",
index fd9662f..275bef8 100755 (executable)
@@ -222,7 +222,7 @@ add_tizen_flags() {
   ADDITIONAL_GN_PARAMETERS+="tizen_multimedia=true
                              proprietary_codecs=true
                              tizen_web_speech_recognition=true
-                             tizen_tbm_support=false
+                             tizen_tbm_support=true
                             "
 }
 
index 2586fa5..260330f 100644 (file)
@@ -155,13 +155,6 @@ if (tizen_multimedia) {
   ]
 }
 
-if (tizen_tbm_support) {
-  external_content_browser_efl_sources += [
-    "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.cc",
-    "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.h",
-  ]
-}
-
 if (tizen_web_speech_recognition) {
   external_content_browser_efl_sources += [
     "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc",
index 35b74aa..e5d1313 100644 (file)
 #include "tizen_src/chromium_impl/content/browser/media/media_player_renderer_web_contents_observer.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h"
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+namespace media {
+void DestroyMediaPacket(void* media_packet, int player_id) {
+  MediaPlayerTizen* player =
+      MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+  if (!player) {
+    // TODO: All media packets should be removed before player is destroyed.
+    LOG(WARNING) << __func__
+                 << " player already destroyed. player_id: " << player_id;
+    return;
+  }
+  player->DestroyMediaPacket(media_packet);
+}
+}  // namespace media
+#endif
 namespace content {
 
 class TizenRendererImpl::RendererClientInternal final
@@ -100,6 +116,14 @@ class TizenRendererImpl::RendererClientInternal final
     renderer_->OnBufferUpdate(time);
   }
 
+#if defined(TIZEN_TBM_SUPPORT)
+  void OnNewTbmFrameAvailable(uint32_t player_id,
+                              const gfx::TbmBufferHandle& tbm_handle,
+                              base::TimeDelta timestamp) override {
+    DCHECK(type_ == media::DemuxerStream::VIDEO);
+    renderer_->OnNewTbmFrameAvailable(player_id, tbm_handle, timestamp);
+  }
+#else
   void OnNewFrameAvailable(uint32_t playerId,
                            base::UnsafeSharedMemoryRegion frame,
                            uint32_t size,
@@ -109,6 +133,7 @@ class TizenRendererImpl::RendererClientInternal final
     renderer_->OnNewFrameAvailable(playerId, std::move(frame), size, timestamp,
                                    width, height);
   }
+#endif
 
  private:
   media::DemuxerStream::Type type_;
@@ -242,11 +267,17 @@ void TizenRendererImpl::SetStreamInfo() {
         media::DemuxerStream::VIDEO, this);
     GetPlayer()->SetStreamInfo(media::DemuxerStream::VIDEO, video_stream_,
                                video_renderer_client_.get());
-
+#if defined(TIZEN_TBM_SUPPORT)
+    media::MediaPlayerESPlusPlayer::GetMediaPlayerESPlusPlayer()
+        ->SetFrameAvailableCallback(
+            base::BindRepeating(&TizenRendererImpl::OnNewTbmFrameAvailable,
+                                base::Unretained(this)));
+#else
     // Will be removed later by using |ClientExtention| interface.
     media::MediaPlayerESPlusPlayer::GetMediaPlayerESPlusPlayer()
         ->SetFrameAvailableCallback(base::BindRepeating(
             &TizenRendererImpl::OnNewFrameAvailable, base::Unretained(this)));
+#endif
   }
 }
 
@@ -451,4 +482,18 @@ void TizenRendererImpl::OnBufferUpdate(base::TimeDelta time) {
   client_extension_->OnBufferUpdate(time);
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+void TizenRendererImpl::OnNewTbmFrameAvailable(uint32_t player_id,
+                                               gfx::TbmBufferHandle tbm_handle,
+                                               base::TimeDelta timestamp) {
+  client_extension_->OnNewTbmFrameAvailable(player_id, tbm_handle, timestamp);
+}
+
+void TizenRendererImpl::OnTbmBufferExhausted(
+    const gfx::TbmBufferHandle& tbm_handle) {
+  media_player_->DestroyMediaPacket(
+      reinterpret_cast<void*>(tbm_handle.media_packet));
+}
+#endif
+
 }  // namespace content
index f7c469f..fbb96a8 100644 (file)
@@ -98,6 +98,13 @@ class CONTENT_EXPORT TizenRendererImpl
                            uint32_t width,
                            uint32_t height);
 
+#if defined(TIZEN_TBM_SUPPORT)
+  void OnNewTbmFrameAvailable(uint32_t player_id,
+                              gfx::TbmBufferHandle tbm_handle,
+                              base::TimeDelta timestamp);
+  void OnTbmBufferExhausted(const gfx::TbmBufferHandle& tbm_handle) override;
+#endif
+
  private:
   class RendererClientInternal;
   const float kDefaultVolume = 1.0;
index 4756451..0ae0b6c 100644 (file)
@@ -134,4 +134,32 @@ void MediaPlayerRendererClient::OnBufferUpdate(base::TimeDelta time) {
 }
 #endif
 
+#if defined(TIZEN_TBM_SUPPORT)
+void MediaPlayerRendererClient::OnTbmBufferExhausted(
+    media::VideoFrame* video_frame,
+    void* media_packet,
+    int player_id) {
+  gfx::TbmBufferHandle tbm_handle;
+  tbm_handle.media_packet = reinterpret_cast<uintptr_t>(media_packet);
+  tbm_handle.player_id = player_id;
+  renderer_extension_remote_->OnTbmBufferExhausted(tbm_handle);
+}
+
+void MediaPlayerRendererClient::OnNewTbmFrameAvailable(
+    uint32_t playerId,
+    const gfx::TbmBufferHandle& tbm_buffer_handle,
+    base::TimeDelta timestamp) {
+  gfx::Size size(tbm_buffer_handle.width, tbm_buffer_handle.height);
+  scoped_refptr<media::VideoFrame> video_frame =
+      media::VideoFrame::WrapTBMSurface(size, timestamp, tbm_buffer_handle);
+  video_frame->AddDestructionObserver(base::BindOnce(
+      &MediaPlayerRendererClient::OnTbmBufferExhausted,
+      weak_factory_.GetWeakPtr(), base::Unretained(video_frame.get()),
+      const_cast<void*>((const void*)tbm_buffer_handle.media_packet),
+      tbm_buffer_handle.player_id));
+
+  sink_->PaintSingleFrame(std::move(video_frame));
+}
+#endif
+
 }  // namespace content
index 930fbb6..f601a44 100644 (file)
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h"
+#endif
+
 namespace content {
 
 // MediaPlayerRendererClient lives in Renderer process and mirrors a
@@ -69,6 +73,14 @@ class CONTENT_EXPORT MediaPlayerRendererClient
                            base::TimeDelta timestamp,
                            uint32_t width,
                            uint32_t height) override;
+#if defined(TIZEN_TBM_SUPPORT)
+  void OnNewTbmFrameAvailable(uint32_t playerId,
+                              const gfx::TbmBufferHandle& tbm_buffer_handle,
+                              base::TimeDelta timestamp) override;
+  void OnTbmBufferExhausted(media::VideoFrame* video_frame,
+                            void* media_packet,
+                            int player_id);
+#endif
 
  private:
   void OnRemoteRendererInitialized(media::PipelineStatus status);
index a122ed2..45e9b99 100644 (file)
@@ -9,14 +9,21 @@
 #include "base/logging.h"
 #include "media/base/renderer_client.h"
 #include "media/base/tizen/media_player_bridge_capi.h"
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 
 namespace media {
 
 MediaPlayerBridgeCapiAdapter::MediaPlayerBridgeCapiAdapter(const GURL& url,
                                                            double volume)
-    : url_(url), volume_(volume) {}
+    : url_(url), volume_(volume) {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+  player_id_ = MediaPlayerRegistry::GetInstance()->RegisterMediaPlayer(this);
+}
 
-MediaPlayerBridgeCapiAdapter::~MediaPlayerBridgeCapiAdapter() {}
+MediaPlayerBridgeCapiAdapter::~MediaPlayerBridgeCapiAdapter() {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+  MediaPlayerRegistry::GetInstance()->UnregisterMediaPlayer(player_id_);
+}
 
 bool MediaPlayerBridgeCapiAdapter::CreatePlayer() {
   if (media_player_)
@@ -193,7 +200,7 @@ void MediaPlayerBridgeCapiAdapter::OnNewTbmBufferAvailable(
 
   void* media_packet = reinterpret_cast<void*>(tbm_handle.media_packet);
   tbm_handle.media_packet = reinterpret_cast<uint64_t>(media_packet);
-  tbm_handle.player_handle = reinterpret_cast<uint64_t>(this);
+  tbm_handle.player_id = player_id_;
   tbm_handle.width = width_;
   tbm_handle.height = height_;
 
index 3b348fe..26df8d0 100644 (file)
@@ -112,6 +112,8 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiAdapter : public MediaPlayerTizen,
   bool is_initialized_ = false;
   bool is_prepared_ = false;
 
+  int player_id_ = 0;
+
   int width_ = 0;
   int height_ = 0;
 };
index b5f83e3..baab703 100644 (file)
@@ -14,6 +14,7 @@
 #include "media/base/decoder_buffer.h"
 #include "media/base/renderer_client.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 
 namespace media {
 using player_buffer_size_t = unsigned long long;
@@ -125,6 +126,8 @@ MediaPlayerESPlusPlayer::~MediaPlayerESPlusPlayer() {
   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
   weak_factory_.InvalidateWeakPtrs();
 
+  MediaPlayerRegistry::GetInstance()->UnregisterMediaPlayer(player_id_);
+
   int error = esplusplayer_destroy(esplayer_);
   if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
     LOG(ERROR) << "esplusplayer_destroy failed, error #"
@@ -181,6 +184,8 @@ void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) {
     return;
   }
 
+  player_id_ = MediaPlayerRegistry::GetInstance()->RegisterMediaPlayer(this);
+
   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
             << " state:" << GetString(GetPlayerState());
 
@@ -506,6 +511,20 @@ base::TimeDelta MediaPlayerESPlusPlayer::GetCurrentTime() {
   return current_position_;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+void MediaPlayerESPlusPlayer::DestroyMediaPacket(void* media_packet) {
+  if (!task_runner_->BelongsToCurrentThread()) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::DestroyMediaPacket,
+                                  weak_factory_.GetWeakPtr(), media_packet));
+    return;
+  }
+
+  esplusplayer_decoded_buffer_destroy(
+      esplayer_, static_cast<esplusplayer_decoded_video_packet*>(media_packet));
+}
+#endif
+
 esplusplayer_state MediaPlayerESPlusPlayer::GetPlayerState() {
   return (esplayer_ ? esplusplayer_get_state(esplayer_)
                     : ESPLUSPLAYER_STATE_NONE);
@@ -911,6 +930,15 @@ void MediaPlayerESPlusPlayer::OnFrameReady(
              << ", duration:" << packet->duration << ", Player(" << esplayer_
              << ", state:" << GetString(GetPlayerState());
 
+#if defined(TIZEN_TBM_SUPPORT)
+  gfx::TbmBufferHandle tbm_handle;
+  tbm_handle.tbm_surface = reinterpret_cast<uint64_t>(tbm_surface);
+  tbm_handle.media_packet = reinterpret_cast<uint64_t>(packet);
+  tbm_handle.player_id = player_id_;
+  tbm_handle.width = width;
+  tbm_handle.height = height;
+  data_cb_.Run(0, tbm_handle, timestamp);
+#else
   base::UnsafeSharedMemoryRegion shared_memory;
   uint32_t shared_memory_size =
       suf_info.planes[0].size + (suf_info.planes[0].size / 2);
@@ -994,6 +1022,7 @@ void MediaPlayerESPlusPlayer::OnFrameReady(
 
     sink_->PaintSingleFrame(video_frame);
   }
+#endif
 }
 
 void MediaPlayerESPlusPlayer::OnFlushComplete() {
index a557153..3992847 100644 (file)
@@ -31,6 +31,10 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
  public:
   static MediaPlayerESPlusPlayer* GetMediaPlayerESPlusPlayer();
 
+#if defined(TIZEN_TBM_SUPPORT)
+  using DataRequestCB = base::RepeatingCallback<
+      void(uint32_t, gfx::TbmBufferHandle, base::TimeDelta)>;
+#else
   using DataRequestCB =
       base::RepeatingCallback<void(uint32_t,
                                    base::UnsafeSharedMemoryRegion,
@@ -38,6 +42,8 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
                                    base::TimeDelta,
                                    uint32_t,
                                    uint32_t)>;
+#endif
+
   bool CreatePlayer() override;
   void Initialize(VideoRendererSink* sink) override;
   bool IsInitialized() override;
@@ -65,6 +71,10 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
 
   void SetFrameAvailableCallback(const DataRequestCB& datacb) override;
 
+#if defined(TIZEN_TBM_SUPPORT)
+  void DestroyMediaPacket(void* media_packet) override;
+#endif
+
   // Callback handler
   void OnReadyToPrepare(const esplusplayer_stream_type stream_type);
   void OnPrepareComplete(bool result);
@@ -157,6 +167,9 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
   bool should_set_playback_rate_ = false;
 
   base::OnceClosure flush_cb_;
+
+  int player_id_ = 0;
+
   DataRequestCB data_cb_;
 
   VideoRendererSink* sink_;
diff --git a/tizen_src/chromium_impl/media/filters/media_player_registry.cc b/tizen_src/chromium_impl/media/filters/media_player_registry.cc
new file mode 100644 (file)
index 0000000..0f21b49
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2022 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
+
+#include "base/logging.h"
+#include "base/process/process_handle.h"
+
+namespace media {
+
+MediaPlayerRegistry* MediaPlayerRegistry::GetInstance() {
+  return base::Singleton<MediaPlayerRegistry>::get();
+}
+
+MediaPlayerRegistry::MediaPlayerRegistry() {
+  next_media_player_id_ = base::GetCurrentProcId();
+}
+
+MediaPlayerRegistry::~MediaPlayerRegistry() {}
+
+int MediaPlayerRegistry::RegisterMediaPlayer(MediaPlayerTizen* player) {
+  LOG(INFO) << __func__ << " player id: " << next_media_player_id_;
+  media_players_[next_media_player_id_] = player;
+  return next_media_player_id_++;
+}
+
+void MediaPlayerRegistry::UnregisterMediaPlayer(int player_id) {
+  LOG(INFO) << __func__ << " player id: " << player_id;
+  media_players_.erase(player_id);
+}
+
+MediaPlayerTizen* MediaPlayerRegistry::GetMediaPlayer(int player_id) {
+  std::map<int, MediaPlayerTizen*>::iterator iter =
+      media_players_.find(player_id);
+  if (iter != media_players_.end())
+    return iter->second;
+  return nullptr;
+}
+
+}  // namespace media
diff --git a/tizen_src/chromium_impl/media/filters/media_player_registry.h b/tizen_src/chromium_impl/media/filters/media_player_registry.h
new file mode 100644 (file)
index 0000000..0576fba
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2022 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_
+#define MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_
+
+#include <map>
+
+#include "base/memory/singleton.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class MediaPlayerTizen;
+
+class MEDIA_EXPORT MediaPlayerRegistry {
+ public:
+  static MediaPlayerRegistry* GetInstance();
+
+  int RegisterMediaPlayer(MediaPlayerTizen* player);
+  void UnregisterMediaPlayer(int player_id);
+
+  MediaPlayerTizen* GetMediaPlayer(int player_id);
+
+ private:
+  MediaPlayerRegistry();
+  ~MediaPlayerRegistry();
+
+  MediaPlayerRegistry(const MediaPlayerRegistry&) = delete;
+  MediaPlayerRegistry& operator=(const MediaPlayerRegistry&) = delete;
+
+  int next_media_player_id_;
+
+  std::map<int, MediaPlayerTizen*> media_players_;
+
+  friend struct base::DefaultSingletonTraits<MediaPlayerRegistry>;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_
index e158e8a..ff1ba71 100644 (file)
@@ -104,6 +104,8 @@ if (tizen_multimedia) {
     "//tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h",
     "//tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc",
     "//tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h",
+    "//tizen_src/chromium_impl/media/filters/media_player_registry.cc",
+    "//tizen_src/chromium_impl/media/filters/media_player_registry.h",
     "//tizen_src/chromium_impl/media/filters/media_player_tizen.h",
   ]
 
diff --git a/tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h b/tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h
new file mode 100644 (file)
index 0000000..4e82dcd
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_TBM_BUFFER_HANDLE_H
+#define UI_GFX_TBM_BUFFER_HANDLE_H
+
+#include <stddef.h>
+#include "ui/gfx/gfx_export.h"
+
+#if defined(TIZEN_TBM_SUPPORT)
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#endif
+
+namespace gfx {
+
+struct GFX_EXPORT TbmBufferHandle {
+  TbmBufferHandle() {}
+#if defined(TIZEN_TBM_SUPPORT)
+  uint32_t tbm_surface{0};
+  uint32_t media_packet{0};
+  int32_t player_id = 0;
+  int32_t key_num = 0;
+  int32_t key[4];
+  int32_t strides[4];
+  int32_t width = 0;
+  int32_t height = 0;
+#endif
+};
+
+}  // namespace gfx
+
+#endif
index bb54b8b..3f2beaa 100644 (file)
@@ -62,6 +62,7 @@ external_ui_gfx_sources = [
   "//tizen_src/chromium_impl/ui/display/device_display_info_efl.cc",
   "//tizen_src/chromium_impl/ui/display/device_display_info_efl.h",
   "//tizen_src/chromium_impl/ui/display/device_display_info_observer_efl.h",
+  "//tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h",
 ]
 
 # For //ui/gfx/x target
index 8ad8af9..13b77ba 100644 (file)
@@ -85,6 +85,16 @@ struct GFX_EXPORT GpuMemoryBufferHandle {
 #elif BUILDFLAG(IS_ANDROID)
   base::android::ScopedHardwareBufferHandle android_hardware_buffer;
 #endif
+#if defined(TIZEN_TBM_SUPPORT)
+  uint32_t tbm_surface{0};
+  uint32_t media_packet{0};
+  int32_t player_id = 0;
+  int32_t key_num = 0;
+  int32_t key[4];
+  int32_t strides[4];
+  int32_t width = 0;
+  int32_t height = 0;
+#endif
 };
 
 // This interface typically correspond to a type of shared memory that is also
index 3c8d0eb..91a2f6e 100644 (file)
@@ -4,6 +4,9 @@
 
 import("//build/config/ozone.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
+if (use_efl) {
+  import("//tizen_src/build/config/tizen_features.gni")
+}
 
 mojom("mojom") {
   generate_java = true
@@ -49,6 +52,9 @@ mojom("mojom") {
   if (ozone_platform_x11) {
     enabled_features += [ "enable_x11_params" ]
   }
+  if (tizen_tbm_support) {
+    enabled_features += [ "tizen_tbm_support" ]
+  }
 
   shared_cpp_typemaps = [
     {
@@ -84,6 +90,10 @@ mojom("mojom") {
           mojom = "gfx.mojom.GpuMemoryBufferType"
           cpp = "::gfx::GpuMemoryBufferType"
         },
+        {
+          mojom = "gfx.mojom.TbmBufferHandle"
+          cpp = "::gfx::TbmBufferHandle"
+        },
       ]
 
       traits_headers = [ "buffer_types_mojom_traits.h" ]
index 4fa5ca2..4e989d4 100644 (file)
@@ -65,5 +65,57 @@ struct GpuMemoryBufferHandle {
   GpuMemoryBufferId id;
   uint32 offset;
   uint32 stride;
+
+  [EnableIf=tizen_tbm_support]
+  uint32 tbm_surface;
+
+  [EnableIf=tizen_tbm_support]
+  uint32 media_packet;
+
+  [EnableIf=tizen_tbm_support]
+  int32 player_id;
+
+  [EnableIf=tizen_tbm_support]
+  int32 key_num;
+
+  [EnableIf=tizen_tbm_support]
+  array<int32, 4> key;
+
+  [EnableIf=tizen_tbm_support]
+  array<int32, 4> strides;
+
+  [EnableIf=tizen_tbm_support]
+  int32 width;
+
+  [EnableIf=tizen_tbm_support]
+  int32 height;
+
   GpuMemoryBufferPlatformHandle? platform_handle;
 };
+
+// gfx::TbmBufferHandle
+struct TbmBufferHandle {
+  [EnableIf=tizen_tbm_support]
+  uint32 tbm_surface;
+
+  [EnableIf=tizen_tbm_support]
+  uint32 media_packet;
+
+  [EnableIf=tizen_tbm_support]
+  int32 player_id;
+
+  [EnableIf=tizen_tbm_support]
+  int32 key_num;
+
+  [EnableIf=tizen_tbm_support]
+  array<int32, 4> key;
+
+  [EnableIf=tizen_tbm_support]
+  array<int32, 4> strides;
+
+  [EnableIf=tizen_tbm_support]
+  int32 width;
+
+  [EnableIf=tizen_tbm_support]
+  int32 height;
+};
index 0f6ffe1..9b7d0e4 100644 (file)
@@ -98,7 +98,21 @@ bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
 
   out->offset = data.offset();
   out->stride = data.stride();
+#if defined(TIZEN_TBM_SUPPORT)
+  out->tbm_surface = data.tbm_surface();
+  out->media_packet = data.media_packet();
+  out->player_id = data.player_id();
+  out->key_num = data.key_num();
+  out->width = data.width();
+  out->height = data.height();
+  base::span<int32_t> key(out->key);
+  if (!data.ReadKey(&key))
+    return false;
 
+  base::span<int32_t> strides(out->strides);
+  if (!data.ReadStrides(&strides))
+    return false;
+#endif
   gfx::mojom::GpuMemoryBufferPlatformHandlePtr platform_handle;
   if (!data.ReadPlatformHandle(&platform_handle)) {
     return false;
@@ -168,4 +182,53 @@ bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
   return false;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+// static
+base::span<const int32_t> StructTraits<
+    gfx::mojom::GpuMemoryBufferHandleDataView,
+    gfx::GpuMemoryBufferHandle>::key(const gfx::GpuMemoryBufferHandle& input) {
+  return input.key;
+}
+
+// static
+base::span<const int32_t> StructTraits<
+    gfx::mojom::GpuMemoryBufferHandleDataView,
+    gfx::GpuMemoryBufferHandle>::strides(const gfx::GpuMemoryBufferHandle&
+                                             input) {
+  return input.strides;
+}
+
+bool StructTraits<gfx::mojom::TbmBufferHandleDataView, gfx::TbmBufferHandle>::
+    Read(gfx::mojom::TbmBufferHandleDataView data, gfx::TbmBufferHandle* out) {
+  out->tbm_surface = data.tbm_surface();
+  out->media_packet = data.media_packet();
+  out->player_id = data.player_id();
+  out->key_num = data.key_num();
+  out->width = data.width();
+  out->height = data.height();
+  base::span<int32_t> key(out->key);
+  if (!data.ReadKey(&key))
+    return false;
+
+  base::span<int32_t> strides(out->strides);
+  if (!data.ReadStrides(&strides))
+    return false;
+  return true;
+}
+
+// static
+base::span<const int32_t>
+StructTraits<gfx::mojom::TbmBufferHandleDataView, gfx::TbmBufferHandle>::key(
+    const gfx::TbmBufferHandle& input) {
+  return input.key;
+}
+
+// static
+base::span<const int32_t>
+StructTraits<gfx::mojom::TbmBufferHandleDataView,
+             gfx::TbmBufferHandle>::strides(const gfx::TbmBufferHandle& input) {
+  return input.strides;
+}
+#endif
+
 }  // namespace mojo
index fc160f3..0f62f6c 100644 (file)
 #include "ui/gfx/mojom/buffer_types.mojom-shared.h"
 #include "ui/gfx/mojom/native_handle_types.mojom.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h"
+#endif
+
 namespace mojo {
 
 template <>
@@ -233,6 +237,31 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
   static uint32_t stride(const gfx::GpuMemoryBufferHandle& handle) {
     return handle.stride;
   }
+#if defined(TIZEN_TBM_SUPPORT)
+  static uint32_t tbm_surface(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.tbm_surface;
+  }
+  static uint32_t media_packet(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.media_packet;
+  }
+  static int32_t player_id(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.player_id;
+  }
+
+  static int32_t key_num(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.key_num;
+  }
+  static base::span<const int32_t> key(const gfx::GpuMemoryBufferHandle& input);
+  static base::span<const int32_t> strides(
+      const gfx::GpuMemoryBufferHandle& input);
+
+  static int32_t width(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.width;
+  }
+  static int32_t height(const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.height;
+  }
+#endif
   static mojo::StructPtr<gfx::mojom::GpuMemoryBufferPlatformHandle>
   platform_handle(gfx::GpuMemoryBufferHandle& handle);
 
@@ -240,6 +269,38 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
                    gfx::GpuMemoryBufferHandle* handle);
 };
 
+#if defined(TIZEN_TBM_SUPPORT)
+template <>
+struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
+    StructTraits<gfx::mojom::TbmBufferHandleDataView, gfx::TbmBufferHandle> {
+  static uint32_t tbm_surface(const gfx::TbmBufferHandle& handle) {
+    return handle.tbm_surface;
+  }
+  static uint32_t media_packet(const gfx::TbmBufferHandle& handle) {
+    return handle.media_packet;
+  }
+  static int32_t player_id(const gfx::TbmBufferHandle& handle) {
+    return handle.player_id;
+  }
+
+  static int32_t key_num(const gfx::TbmBufferHandle& handle) {
+    return handle.key_num;
+  }
+  static base::span<const int32_t> key(const gfx::TbmBufferHandle& input);
+  static base::span<const int32_t> strides(const gfx::TbmBufferHandle& input);
+
+  static int32_t width(const gfx::TbmBufferHandle& handle) {
+    return handle.width;
+  }
+  static int32_t height(const gfx::TbmBufferHandle& handle) {
+    return handle.height;
+  }
+
+  static bool Read(gfx::mojom::TbmBufferHandleDataView data,
+                   gfx::TbmBufferHandle* handle);
+};
+#endif
+
 template <>
 struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
     EnumTraits<gfx::mojom::BufferPlane, gfx::BufferPlane> {
index 84635e5..d72f414 100644 (file)
@@ -9,6 +9,12 @@
 #include "ui/gl/gl_enums.h"
 #include "ui/gl/gl_surface_egl.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+namespace media {
+void DestroyMediaPacket(void* media_packet_handle, int player_id);
+}
+#endif
+
 namespace gl {
 
 GLImageEGL::GLImageEGL(const gfx::Size& size)
@@ -23,6 +29,10 @@ GLImageEGL::~GLImageEGL() {
       GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay(), egl_image_);
   if (result == EGL_FALSE)
     DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString();
+
+#if defined(TIZEN_TBM_SUPPORT)
+  media::DestroyMediaPacket(media_packet_, player_id_);
+#endif
 }
 
 bool GLImageEGL::Initialize(EGLContext context,
@@ -39,6 +49,29 @@ bool GLImageEGL::Initialize(EGLContext context,
   return success;
 }
 
+#if defined(TIZEN_TBM_SUPPORT)
+bool GLImageEGL::Initialize(EGLenum target,
+                            EGLClientBuffer buffer,
+                            const EGLint* attrs,
+                            void* media_packet,
+                            int player_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
+  media_packet_ = media_packet;
+  player_id_ = player_id;
+
+  egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay(),
+                                 EGL_NO_CONTEXT, target, buffer, attrs);
+  if (egl_image_ == EGL_NO_IMAGE_KHR) {
+    DLOG(ERROR) << "Error creating EGLImage: " << ui::GetLastEGLErrorString();
+    media::DestroyMediaPacket(media_packet_, player_id_);
+    return false;
+  }
+
+  return true;
+}
+#endif
+
 gfx::Size GLImageEGL::GetSize() {
   return size_;
 }
index 0afd7d4..d46ae79 100644 (file)
@@ -18,6 +18,13 @@ namespace gl {
 class GL_EXPORT GLImageEGL : public GLImage {
  public:
   explicit GLImageEGL(const gfx::Size& size);
+#if defined(TIZEN_TBM_SUPPORT)
+  bool Initialize(unsigned target,
+                  void* buffer,
+                  const EGLint* attrs,
+                  void* media_packet,
+                  int player_id);
+#endif
 
   GLImageEGL(const GLImageEGL&) = delete;
   GLImageEGL& operator=(const GLImageEGL&) = delete;
@@ -47,6 +54,10 @@ class GL_EXPORT GLImageEGL : public GLImage {
                   const EGLint* attrs);
 
   raw_ptr<void> egl_image_ /* EGLImageKHR */;
+#if defined(TIZEN_TBM_SUPPORT)
+  void* media_packet_;
+  int player_id_;
+#endif
   const gfx::Size size_;
   base::ThreadChecker thread_checker_;
 };
index e48a7d5..72b5fca 100644 (file)
 #include "ui/gl/gl_enums.h"
 #include "ui/gl/gl_surface_egl.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "ui/gfx/gpu_memory_buffer.h"
+#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
+#endif
+
 #define FOURCC(a, b, c, d)                                        \
   ((static_cast<uint32_t>(a)) | (static_cast<uint32_t>(b) << 8) | \
    (static_cast<uint32_t>(c) << 16) | (static_cast<uint32_t>(d) << 24))
@@ -138,6 +143,21 @@ GLImageNativePixmap::GLImageNativePixmap(const gfx::Size& size,
 
 GLImageNativePixmap::~GLImageNativePixmap() {}
 
+#if defined(TIZEN_TBM_SUPPORT)
+bool GLImageNativePixmap::Initialize(const gfx::GpuMemoryBufferHandle& handle) {
+  EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+  tbm_surface_h surface = reinterpret_cast<tbm_surface_h>(handle.tbm_surface);
+  if (!GLImageEGL::Initialize(EGL_NATIVE_SURFACE_TIZEN,
+                              static_cast<EGLClientBuffer>(surface), attrs,
+                              reinterpret_cast<void*>(handle.media_packet),
+                              handle.player_id)) {
+    return false;
+  }
+
+  return true;
+}
+#endif
+
 bool GLImageNativePixmap::Initialize(scoped_refptr<gfx::NativePixmap> pixmap) {
   DCHECK(!pixmap_);
   if (GLInternalFormat(format_) == GL_NONE) {
index ea5c883..fbe3dfc 100644 (file)
 #include "ui/gl/gl_export.h"
 #include "ui/gl/gl_image_egl.h"
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+namespace gfx {
+struct GpuMemoryBufferHandle;
+}
+#endif
+
 namespace gl {
 
 class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL {
@@ -21,6 +30,9 @@ class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL {
                       gfx::BufferFormat format,
                       gfx::BufferPlane plane = gfx::BufferPlane::DEFAULT);
 
+#if defined(TIZEN_TBM_SUPPORT)
+  bool Initialize(const gfx::GpuMemoryBufferHandle& handle);
+#endif
   // Create an EGLImage from a given NativePixmap.
   bool Initialize(scoped_refptr<gfx::NativePixmap> pixmap);
   bool InitializeForOverlay(scoped_refptr<gfx::NativePixmap> pixmap);
@@ -53,6 +65,12 @@ class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL {
   bool has_image_flush_external_;
   bool has_image_dma_buf_export_;
   bool did_initialize_;
+#if defined(TIZEN_TBM_SUPPORT)
+  tbm_bufmgr bufmgr_;
+  tbm_surface_h tbm_surf_;
+  tbm_bo bos_[4] = {0};
+  tbm_surface_info_s tbmsi_;
+#endif
 };
 
 }  // namespace gl