mCallStack.PushCall("EndRenderPass", namedParams.str(), namedParams);
}
+ void ReadPixels(uint8_t* buffer) override
+ {
+ }
+
void ExecuteCommandBuffers(std::vector<const CommandBuffer*>&& commandBuffers) override
{
mCommands.emplace_back();
* @brief Get PixelBuffer of captured image.
*
* @return PixelBuffer Captured result
+ * @note GetCapturedBuffer is only available inside FinishedSignal, otherwise this returns empty handle.
*/
DALI_ADAPTOR_API Dali::Devel::PixelBuffer GetCapturedBuffer(Dali::Capture capture);
return Dali::Internal::Adaptor::NativeImageSource::GetImplementation(image).ReleaseBuffer(updatedArea);\r
}\r
\r
+bool SetPixels(NativeImageSource& image, uint8_t* pixbuf, const Pixel::Format& pixelFormat)\r
+{\r
+ return Dali::Internal::Adaptor::NativeImageSource::GetImplementation(image).SetPixels(pixbuf, pixelFormat);\r
+}\r
+\r
void SetResourceDestructionCallback(NativeImageSource& image, EventThreadCallback* callback)\r
{\r
return Dali::Internal::Adaptor::NativeImageSource::GetImplementation(image).SetResourceDestructionCallback(callback);\r
*/\r
DALI_ADAPTOR_API bool ReleaseBuffer(NativeImageSource& image, const Rect<uint32_t>& updatedArea);\r
\r
+/**\r
+ * @brief Sets PixelBuffers to NativeImageSource\r
+ *\r
+ * @param[in] image The instance of NativeImageSource.\r
+ * @param[in] pixbuf Pixel buffer to copy.\r
+ * @param[in] pixelFormat Pixel format of the pixel buffer\r
+ * @return @c true If the buffer is successfully set.\r
+ * @note The width and height of the input pixel buffer should be same with those of NativeImageSource.\r
+ * @note Only Pixel::Format::RGB888 and Pixel::Format::RGBA8888 are available as a input pixel format.\r
+ */\r
+DALI_ADAPTOR_API bool SetPixels(NativeImageSource& image, uint8_t* pixbuf, const Pixel::Format& pixelFormat);\r
+\r
/**\r
* @brief Set the Resource Destruction Callback object\r
*\r
fprintf(output, "{\"Cmd\":\"END_RENDER_PASS\"}\n");
break;
}
+ case GLES::CommandType::READ_PIXELS:
+ {
+ fprintf(output, "{\"Cmd\":\"READ_PIXELS\"}\n");
+ break;
+ }
case GLES::CommandType::PRESENT_RENDER_TARGET:
{
fprintf(output, "{\"Cmd\":\"PRESENT_RENDER_TARGET\"}\n");
}
break;
}
+ case GLES::CommandType::READ_PIXELS:
+ {
+ mCurrentContext->ReadPixels(cmd.readPixelsBuffer.buffer);
+ break;
+ }
case GLES::CommandType::PRESENT_RENDER_TARGET:
{
ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
}
}
+void Context::ReadPixels(uint8_t* buffer)
+{
+ if(mImpl->mCurrentRenderTarget)
+ {
+ GLES::Framebuffer* framebuffer = mImpl->mCurrentRenderTarget->GetFramebuffer();
+ auto* gl = mImpl->GetGL();
+ if(framebuffer && gl)
+ {
+ gl->Finish(); // To guarantee ReadPixels.
+ gl->ReadPixels(0, 0, framebuffer->GetCreateInfo().size.width, framebuffer->GetCreateInfo().size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ }
+ }
+}
+
+
void Context::ClearState()
{
mImpl->mCurrentTextureBindings.clear();
*/
void EndRenderPass(TextureDependencyChecker& checker);
+ /**
+ * @brief Request to read pixels
+ * @param[out] buffer to load pixel data.
+ */
+ void ReadPixels(uint8_t* buffer);
+
/**
* @brief Returns the cache of GL state in the context
* @return the reference of GL state cache (which can be modified)
command->endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
}
+void CommandBuffer::ReadPixels(uint8_t* buffer)
+{
+ auto command = mCommandPool->AllocateCommand(CommandType::READ_PIXELS);
+ command->readPixelsBuffer.buffer = buffer;
+}
+
void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
{
auto command = mCommandPool->AllocateCommand(CommandType::EXECUTE_COMMAND_BUFFERS);
SET_VIEWPORT,
BEGIN_RENDERPASS,
END_RENDERPASS,
+ READ_PIXELS,
EXECUTE_COMMAND_BUFFERS,
PRESENT_RENDER_TARGET,
SET_COLOR_MASK,
Graphics::SyncObject* syncObject;
} endRenderPass;
+ struct
+ {
+ uint8_t* buffer;
+ } readPixelsBuffer;
+
struct
{
IndirectPtr<const GLES::CommandBuffer*> buffers;
*/
void EndRenderPass(Graphics::SyncObject* syncObject) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::ReadPixels
+ */
+ void ReadPixels(uint8_t* buffer) override;
+
/**
* @copydoc Dali::Graphics::CommandBuffer::ExecuteCommandBuffers
*/
mCommandBuffer.endRenderPass();
}
+void CommandBufferImpl::ReadPixels(uint8_t* buffer)
+{
+}
+
void CommandBufferImpl::PipelineBarrier(
vk::PipelineStageFlags srcStageMask,
vk::PipelineStageFlags dstStageMask,
*/
void EndRenderPass();
+ /**
+ * Request to read pixels.
+ */
+ void ReadPixels(uint8_t* buffer);
+
void PipelineBarrier(vk::PipelineStageFlags srcStageMask,
vk::PipelineStageFlags dstStageMask,
vk::DependencyFlags dependencyFlags,
mCommandBufferImpl->EndRenderPass();
}
+void CommandBuffer::ReadPixels(uint8_t* buffer)
+{
+ mCommandBufferImpl->ReadPixels(buffer);
+}
+
void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& gfxCommandBuffers)
{
std::vector<vk::CommandBuffer> vkCommandBuffers;
*/
void EndRenderPass(Graphics::SyncObject* syncObject) override;
+ /**
+ * @copydoc Dali::Graphics::CommandBuffer::ReadPixels
+ */
+ void ReadPixels(uint8_t* buffer) override;
+
/**
* @brief Executes a list of secondary command buffers
*
return success;
}
+bool NativeImageSourceAndroid::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ return false;
+}
+
void NativeImageSourceAndroid::SetSource(Any source)
{
if(mPixmap)
*/
bool GetPixels(std::vector<uint8_t>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
*/
virtual bool GetPixels(std::vector<uint8_t>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const = 0;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ virtual bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) = 0;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
return true;
}
+bool NativeImageSourceCocoa::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ return false;
+}
+
void NativeImageSourceCocoa::SetSource(Any source)
{
}
uint32_t& height,
Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
return false;
}
+bool NativeImageSourceTizen::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ std::scoped_lock lock(mMutex);
+ if(mTbmSurface != NULL)
+ {
+ tbm_surface_info_s surface_info;
+
+ if(tbm_surface_map(mTbmSurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &surface_info) != TBM_SURFACE_ERROR_NONE)
+ {
+ DALI_LOG_ERROR("Fail to map tbm_surface\n");
+ return false;
+ }
+ tbm_surface_internal_ref(mTbmSurface);
+
+ if(pixelFormat != Pixel::Format::RGBA8888 && pixelFormat != Pixel::Format::RGB888)
+ {
+ DALI_LOG_ERROR("Not Supported PixelFormat\n");
+ return false;
+ }
+
+ tbm_format format = surface_info.format;
+ uint32_t stride = surface_info.planes[0].stride;
+ uint8_t* ptr = surface_info.planes[0].ptr;
+
+ size_t lineSize;
+ size_t inputBufferLinePixelSize = Dali::Pixel::GetBytesPerPixel(pixelFormat);
+
+ switch(format)
+ {
+ case TBM_FORMAT_RGB888:
+ {
+ lineSize = mWidth * inputBufferLinePixelSize;
+ uint8_t* bufptr = &pixbuf[0];
+
+ for(uint32_t r = 0; r < mHeight; ++r, bufptr += lineSize)
+ {
+ for(uint32_t c = 0; c < mWidth; ++c)
+ {
+ size_t sOffset = c * inputBufferLinePixelSize;
+ size_t dOffset = c * 3;
+ size_t offset = dOffset + r * stride;
+ ptr[offset + 2] = *(bufptr + sOffset);
+ ptr[offset + 1] = *(bufptr + sOffset + 1);
+ ptr[offset] = *(bufptr + sOffset + 2);
+ }
+ }
+ break;
+ }
+ case TBM_FORMAT_RGBA8888:
+ {
+ lineSize = mWidth * inputBufferLinePixelSize;
+ uint8_t* bufptr = &pixbuf[0];
+
+ for(uint32_t r = 0; r < mHeight; ++r, bufptr += lineSize)
+ {
+ for(uint32_t c = 0; c < mWidth; ++c)
+ {
+ size_t sOffset = c * inputBufferLinePixelSize;
+ size_t dOffset = c * 4;
+ size_t offset = dOffset + r * stride;
+ ptr[offset + 3] = *(bufptr + sOffset);
+ ptr[offset + 2] = *(bufptr + sOffset + 1);
+ ptr[offset + 1] = *(bufptr + sOffset + 2);
+ ptr[offset] = (inputBufferLinePixelSize == 4) ? *(bufptr + sOffset + 3) : 0xFF;
+ }
+ }
+ break;
+ }
+ case TBM_FORMAT_ARGB8888:
+ {
+ lineSize = mWidth * inputBufferLinePixelSize;
+ uint8_t* bufptr = &pixbuf[0];
+
+ for(uint32_t r = 0; r < mHeight; ++r, bufptr += lineSize)
+ {
+ for(uint32_t c = 0; c < mWidth; ++c)
+ {
+ size_t sOffset = c * inputBufferLinePixelSize;
+ size_t dOffset = c * 4;
+ size_t offset = dOffset + r * stride;
+ ptr[offset + 2] = *(bufptr + sOffset);
+ ptr[offset + 1] = *(bufptr + sOffset + 1);
+ ptr[offset] = *(bufptr + sOffset + 2);
+ ptr[offset + 3] = (inputBufferLinePixelSize == 4) ? *(bufptr + sOffset + 3) : 0xFF;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ DALI_ASSERT_ALWAYS(0 && "Tbm surface has unsupported pixel format.\n");
+
+ return false;
+ }
+ }
+
+ if(tbm_surface_unmap(mTbmSurface) != TBM_SURFACE_ERROR_NONE)
+ {
+ DALI_LOG_ERROR("Fail to unmap tbm_surface\n");
+ }
+ tbm_surface_internal_unref(mTbmSurface);
+
+ return true;
+ }
+
+ DALI_LOG_WARNING("TBM surface does not exist.\n");
+
+ return false;
+}
+
void NativeImageSourceTizen::SetSource(Any source)
{
std::scoped_lock lock(mMutex);
*/
bool GetPixels(std::vector<uint8_t>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
return success;
}
+bool NativeImageSourceX::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ return false;
+}
+
void NativeImageSourceX::SetSource(Any source)
{
mPixmap = GetPixmapFromAny(source);
*/
bool GetPixels(std::vector<uint8_t>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
return success;
}
+bool NativeImageSourceWin::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ return false;
+}
+
void NativeImageSourceWin::SetSource(Any source)
{
mPixmap = GetPixmapFromAny(source);
*/
bool GetPixels(std::vector<uint8_t>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
return success;
}
+bool NativeImageSourceX::SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat)
+{
+ return false;
+}
+
void NativeImageSourceX::SetSource(Any source)
{
mPixmap = GetPixmapFromAny(source);
*/
bool GetPixels(std::vector<unsigned char>& pixbuf, uint32_t& width, uint32_t& height, Pixel::Format& pixelFormat) const override;
+ /**
+ * @copydoc Dali::NativeImageSource::SetPixels()
+ */
+ bool SetPixels(uint8_t* pixbuf, const Pixel::Format& pixelFormat) override;
+
/**
* @copydoc Dali::NativeImageSource::SetSource( Any source )
*/
// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/pixel-data-integ.h>
#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/render-tasks/render-task-list.h>
#include <string.h>
namespace
{
static constexpr uint32_t ORDER_INDEX_CAPTURE_RENDER_TASK = 1000;
-constexpr int32_t SHADER_VERSION_NATIVE_IMAGE_SOURCE_AVAILABLE = 300;
constexpr uint32_t TIME_OUT_DURATION = 1000;
constexpr int32_t GL_VERSION_NATIVE_IMAGE_SOURCE_AVAILABLE = 30;
} // namespace
: mQuality(DEFAULT_QUALITY),
mTimer(),
mPath(),
- mNativeImageSourcePtr(NULL),
mFileSave(false),
mUseDefaultCamera(true),
mSceneOffCameraAfterCaptureFinished(false)
mCameraActor(cameraActor),
mTimer(),
mPath(),
- mNativeImageSourcePtr(NULL),
mFileSave(false),
mUseDefaultCamera(!cameraActor),
mSceneOffCameraAfterCaptureFinished(false)
{
Adaptor::Get().UnregisterProcessorOnce(*this, true);
}
- DeleteNativeImageSource();
mTexture.Reset();
}
// Increase the reference count focely to avoid application mistake.
Reference();
+ UnsetResources();
+ SetupResources(position, size, clearColor, source);
+
mPath = path;
if(!mPath.empty())
{
mFileSave = true;
}
-
- UnsetResources();
- SetupResources(position, size, clearColor, source);
+ mRenderTask.KeepRenderResult();
mInCapture = true;
Adaptor::Get().RegisterProcessorOnce(*this, true);
return mIsExclusive;
}
-Dali::NativeImageSourcePtr Capture::GetNativeImageSource() const
+Dali::NativeImageSourcePtr Capture::GetNativeImageSource()
{
- return mNativeImageSourcePtr;
+ Dali::NativeImageSourcePtr result;
+ if(mRenderTask)
+ {
+ Dali::PixelData pixelData = mRenderTask.GetRenderResult();
+ if(pixelData)
+ {
+ auto pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+ NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New(pixelData.GetWidth(), pixelData.GetHeight(), Dali::NativeImageSource::COLOR_DEPTH_32); // Texture pixel format is RGBA8888
+
+ if(Dali::DevelNativeImageSource::SetPixels(*nativeImageSourcePtr, pixelDataBuffer.buffer, pixelData.GetPixelFormat()))
+ {
+ result = nativeImageSourcePtr;
+ }
+ }
+ }
+ return result;
}
Dali::Texture Capture::GetTexture() const
Dali::Devel::PixelBuffer Capture::GetCapturedBuffer()
{
- if(!mPixelBuffer || (mPixelBuffer && !mPixelBuffer.GetBuffer()))
+ Devel::PixelBuffer pixelBuffer;
+ if(mRenderTask)
{
- std::vector<uint8_t> buffer;
- uint32_t width, height;
- Dali::Pixel::Format pixelFormat;
- if(!mNativeImageSourcePtr->GetPixels(buffer, width, height, pixelFormat))
+ Dali::PixelData pixelData = mRenderTask.GetRenderResult();
+ if(pixelData)
{
- return Dali::Devel::PixelBuffer();
+ auto pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+ pixelBuffer = Dali::Devel::PixelBuffer::New(pixelData.GetWidth(), pixelData.GetHeight(), pixelData.GetPixelFormat());
+ memcpy(pixelBuffer.GetBuffer(), pixelDataBuffer.buffer, pixelDataBuffer.bufferSize);
}
- mPixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
- memcpy(mPixelBuffer.GetBuffer(), &buffer[0], width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat));
}
- return mPixelBuffer;
+ return pixelBuffer;
}
Dali::Capture::CaptureFinishedSignalType& Capture::FinishedSignal()
void Capture::CreateTexture(const Vector2& size)
{
- if(!mNativeImageSourcePtr)
- {
- mNativeImageSourcePtr = Dali::NativeImageSource::New(size.width, size.height, Dali::NativeImageSource::COLOR_DEPTH_DEFAULT);
- mTexture = Dali::Texture::New(*mNativeImageSourcePtr);
- }
-}
-
-void Capture::DeleteNativeImageSource()
-{
- if(mNativeImageSourcePtr)
- {
- mNativeImageSourcePtr.Reset();
- }
+ mTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
}
void Capture::CreateFrameBuffer()
Dali::RenderTaskList taskList = sceneHolder.GetRenderTaskList();
taskList.RemoveTask(mRenderTask);
}
+ mRenderTask.ClearRenderResult();
mRenderTask.Reset();
mSource.Reset();
+ mTexture.Reset();
mSceneHolderHandle.Reset();
}
bool Capture::SaveFile()
{
- if(mNativeImageSourcePtr)
+ Dali::PixelData pixelData = mRenderTask.GetRenderResult();
+ if(pixelData)
{
- return Dali::DevelNativeImageSource::EncodeToFile(*mNativeImageSourcePtr, mPath, mQuality);
+ auto pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+ return Dali::EncodeToFile(pixelDataBuffer.buffer, mPath, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight(), mQuality);
}
return false;
/**
* @copydoc Dali::Capture::GetNativeImageSource
*/
- Dali::NativeImageSourcePtr GetNativeImageSource() const;
+ Dali::NativeImageSourcePtr GetNativeImageSource();
/**
* @copydoc Dali::Capture::GetCapturedBuffer
*/
void CreateTexture(const Dali::Vector2& size);
- /**
- * @brief Delete native image source.
- */
- void DeleteNativeImageSource();
-
/**
* @brief Create frame buffer.
*/
Dali::Timer mTimer; ///< For timeout.
Dali::Capture::CaptureFinishedSignalType mFinishedSignal;
std::string mPath;
- Dali::NativeImageSourcePtr mNativeImageSourcePtr; ///< pointer to surface image
- Dali::Devel::PixelBuffer mPixelBuffer;
bool mInCapture{false};
bool mIsExclusive{false};
bool mFileSave;
return GetImpl(*this).IsExclusive();
}
-Dali::NativeImageSourcePtr Capture::GetNativeImageSource() const
+Dali::NativeImageSourcePtr Capture::GetNativeImageSource()
{
return GetImpl(*this).GetNativeImageSource();
}
* @SINCE_1_9.10
*
* @return NativeImageSourcePtr Captured result that can be rendered with DALi
+ * @note GetNativeImageSource is only available inside FinishedSignal.
*/
- Dali::NativeImageSourcePtr GetNativeImageSource() const;
+ Dali::NativeImageSourcePtr GetNativeImageSource();
/**
* @brief Get Texture of captured image.
*
* @return Texture Captured result
+ * @note GetTexture is only available inside FinishedSignal.
*/
Dali::Texture GetTexture() const;