[Tizen] Support to get raw pixel informations of framebuffer for old driver device 57/306157/2 accepted/tizen/7.0/unified/20240219.160851
authorEunki, Hong <eunkiki.hong@samsung.com>
Fri, 16 Feb 2024 07:41:20 +0000 (16:41 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 16 Feb 2024 09:32:25 +0000 (18:32 +0900)
Let we use Framebuffer capture feature when we use Capture API.

It will be used if gles version is low, so
let we allow to FBO use targe as native image not working devices.

Change-Id: Ica70aff76f5469c7683b486e66d7e85bce313842
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.h
dali/internal/system/common/capture-impl.cpp

index be7a0c398ca06d79bf684baee38218d6d0be6a2a..1f8979f0dda6c9a131339a7ed3b607925cf43a51 100644 (file)
@@ -885,4 +885,9 @@ GLES::PipelineCache& EglGraphicsController::GetPipelineCache() const
   return *mPipelineCache;
 }
 
+void EglGraphicsController::CaptureRenderingResult(Graphics::Framebuffer& framebuffer, CallbackBase* capturedCallback, uint8_t* capturedBuffer)
+{
+  static_cast<GLES::Framebuffer*>(&framebuffer)->CaptureRenderingResult(capturedCallback, capturedBuffer);
+}
+
 } // namespace Dali::Graphics
index b89fa31ba0a44b51c518f8e3c83269c97a1be3a2..956fd2a46c102d9bafc58b6d6630d33bb5387d6a 100644 (file)
@@ -313,6 +313,10 @@ public:
     return {};
   }
 
+public: // Framebuffer Capture
+  void CaptureRenderingResult(Graphics::Framebuffer& framebuffer, CallbackBase* capturedCallback, uint8_t* capturedBuffer) override;
+
+public:
   [[nodiscard]] Integration::GlAbstraction* GetGL() const
   {
     if(mIsShuttingDown)
index addd1addd0e0f8039de960bdfa0bddf627a90fc7..e38c3cdcc07ed7791945e4f073923bdfa88b60da 100644 (file)
@@ -765,6 +765,11 @@ void Context::EndRenderPass(GLES::TextureDependencyChecker& dependencyChecker)
       auto& gl = *mImpl->mController.GetGL();
       gl.Flush();
 
+      if(framebuffer->CaptureRequested())
+      {
+        framebuffer->DrawRenderedBuffer();
+      }
+
       /* @todo Full dependency checking would need to store textures in Begin, and create
        * fence objects here; but we're going to draw all fbos on shared context in serial,
        * so no real need (yet). Might want to consider ensuring order of render passes,
index 6695fbf7cfec87bc9631f7663ef9e4de438a57a0..b811c2b82fa6e1a46e9ded0362f68268206d8687 100644 (file)
@@ -202,6 +202,10 @@ void Framebuffer::DestroyResource()
 void Framebuffer::DiscardResource()
 {
   mController.DiscardResource(this);
+
+  mCaptureRenderedResult = false;
+  mCapturedBuffer = nullptr;
+  mCapturedCallback = nullptr;
 }
 
 void Framebuffer::Bind() const
@@ -248,4 +252,28 @@ uint32_t Framebuffer::GetGlStencilBufferId() const
   return mStencilBufferId;
 }
 
+void Framebuffer::CaptureRenderingResult(CallbackBase* capturedCallback, uint8_t* capturedBuffer)
+{
+  // Let we make to capture the result.
+  mCaptureRenderedResult = true;
+
+  mCapturedCallback = capturedCallback;
+  mCapturedBuffer   = capturedBuffer;
+}
+
+void Framebuffer::DrawRenderedBuffer()
+{
+  auto gl = mController.GetGL();
+  if(gl && mCaptureRenderedResult && mCapturedCallback && mCapturedBuffer != nullptr)
+  {
+    gl->ReadPixels(0, 0, mCreateInfo.size.width, mCreateInfo.size.height, GL_RGBA, GL_UNSIGNED_BYTE, mCapturedBuffer);
+
+    CallbackBase::Execute(*mCapturedCallback, mCapturedBuffer);
+
+    mCaptureRenderedResult = false;
+    mCapturedBuffer = nullptr;
+    mCapturedCallback = nullptr;
+  }
+}
+
 } //namespace Dali::Graphics::GLES
index 430b395f53c8990aaea2b18f20392522841fcaf3..18e31f99c6132eb009614450de9057a1a7ac16ed 100644 (file)
@@ -72,6 +72,15 @@ public:
 
   [[nodiscard]] uint32_t GetGlStencilBufferId() const;
 
+  void CaptureRenderingResult(CallbackBase* capturedCallback, uint8_t* capturedBuffer);
+
+  void DrawRenderedBuffer();
+
+  bool CaptureRequested() const
+  {
+    return mCaptureRenderedResult;
+  }
+
 private:
   /**
    * Attach a texture to the specified attachment point
@@ -88,6 +97,10 @@ private:
   uint32_t mStencilBufferId{0u};
   uint32_t mMultisamples{1u};
   bool     mInitialized{false};
+
+  uint8_t*            mCapturedBuffer{nullptr};   ///< not owned
+  Dali::CallbackBase* mCapturedCallback{nullptr}; ///< not owned
+  bool                mCaptureRenderedResult{false};
 };
 
 } // namespace Dali::Graphics::GLES
index 7cf2aecb5945009d2e19188b32cf1681d76ba10b..56ef77f3c3fa2974f45a5c7607f16fc3ca990719 100644 (file)
@@ -135,15 +135,37 @@ Dali::Devel::PixelBuffer Capture::GetCapturedBuffer()
 {
   if(!mPixelBuffer || (mPixelBuffer && !mPixelBuffer.GetBuffer()))
   {
-    std::vector<uint8_t> buffer;
     uint32_t             width, height;
     Dali::Pixel::Format  pixelFormat;
-    if(!mNativeImageSourcePtr->GetPixels(buffer, width, height, pixelFormat))
+    if(mIsNativeImageSourcePossible)
     {
-      return Dali::Devel::PixelBuffer();
+      std::vector<uint8_t> buffer;
+      if(!mNativeImageSourcePtr || !mNativeImageSourcePtr->GetPixels(buffer, width, height, pixelFormat))
+      {
+        return Dali::Devel::PixelBuffer();
+      }
+      mPixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+      memcpy(mPixelBuffer.GetBuffer(), &buffer[0], width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat));
+    }
+    else
+    {
+      if(!mFrameBuffer || !mTexture)
+      {
+        DALI_LOG_ERROR("Capture is not started yet.");
+        return Dali::Devel::PixelBuffer();
+      }
+      uint8_t* buffer = mFrameBuffer.GetRenderedBuffer();
+      if(buffer == nullptr)
+      {
+        DALI_LOG_ERROR("Capture is not finished.");
+        return Dali::Devel::PixelBuffer();
+      }
+      width = mTexture.GetWidth();
+      height = mTexture.GetHeight();
+      pixelFormat = mTexture.GetPixelFormat();
+      mPixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+      memcpy(mPixelBuffer.GetBuffer(), buffer, width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat));
     }
-    mPixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
-    memcpy(mPixelBuffer.GetBuffer(), &buffer[0], width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat));
   }
   return mPixelBuffer;
 }
@@ -165,7 +187,7 @@ void Capture::CreateTexture(const Vector2& size)
   }
   else
   {
-    mTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGB888, unsigned(size.width), unsigned(size.height));
+    mTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
   }
 }
 
@@ -260,6 +282,10 @@ void Capture::SetupRenderTask(const Dali::Vector2& position, const Dali::Vector2
   mRenderTask.SetProperty(Dali::RenderTask::Property::REQUIRES_SYNC, true);
   mRenderTask.FinishedSignal().Connect(this, &Capture::OnRenderFinished);
   mRenderTask.GetCameraActor().SetInvertYAxis(true);
+  if(!mIsNativeImageSourcePossible)
+  {
+    mFrameBuffer.CaptureRenderedResult();
+  }
 
   mTimer = Dali::Timer::New(TIME_OUT_DURATION);
   mTimer.TickSignal().Connect(this, &Capture::OnTimeOut);
@@ -378,7 +404,8 @@ bool Capture::SaveFile()
   }
   else
   {
-    DALI_LOG_ERROR("can't use Capture::SavceFile(). we don't support this function in gles 2.0 \n");
+    uint8_t* buffer = mFrameBuffer.GetRenderedBuffer();
+    return Dali::EncodeToFile(buffer, mPath, Dali::Pixel::RGBA8888, mTexture.GetWidth(), mTexture.GetHeight(), mQuality);
   }
 
   return false;