[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 be7a0c3..1f8979f 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 b89fa31..956fd2a 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 addd1ad..e38c3cd 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 6695fbf..b811c2b 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 430b395..18e31f9 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 7cf2aec..56ef77f 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;