/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/event/rendering/texture-impl.h> // Dali::Internal::Texture
// INTERNAL INCLUDES
-#include <dali/internal/update/manager/update-manager.h>
+#include <dali/integration-api/render-controller.h>
#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+// EXTERNAL INCLUDES
+#include <cstring>
+
+namespace
+{
+const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
+} // namespace
namespace Dali
{
namespace Internal
{
-
-NewTexturePtr NewTexture::New(TextureType::Type type, Pixel::Format format, unsigned int width, unsigned int height )
+TexturePtr Texture::New(TextureType::Type type, Pixel::Format format, unsigned int width, unsigned int height)
{
- NewTexturePtr texture( new NewTexture( type, format, width, height ) );
+ constexpr auto max_value = std::numeric_limits<uint16_t>::max();
+ DALI_ASSERT_ALWAYS((width < max_value) && (height < max_value) && "Size out of range");
+ TexturePtr texture(new Texture(type, format, ImageDimensions(width, height)));
texture->Initialize();
return texture;
}
-NewTexturePtr NewTexture::New( NativeImageInterface& nativeImageInterface )
+TexturePtr Texture::New(NativeImageInterface& nativeImageInterface)
{
- NewTexturePtr texture( new NewTexture( &nativeImageInterface ) );
+ TexturePtr texture(new Texture(&nativeImageInterface));
texture->Initialize();
+
+ // Request event processing and update forcely.
+ texture->mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
+ texture->mEventThreadServices.ForceNextUpdate();
return texture;
}
-Render::NewTexture* NewTexture::GetRenderObject() const
+Render::Texture* Texture::GetRenderObject() const
{
return mRenderObject;
}
-NewTexture::NewTexture(TextureType::Type type, Pixel::Format format, unsigned int width, unsigned int height )
-: mEventThreadServices( *Stage::GetCurrent() ),
- mRenderObject( NULL ),
+Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions size)
+: mEventThreadServices(EventThreadServices::Get()),
+ mRenderObject(nullptr),
mNativeImage(),
- mType( type ),
- mFormat( format ),
- mWidth( width ),
- mHeight( height )
+ mSize(size),
+ mType(type),
+ mFormat(format)
{
}
-NewTexture::NewTexture( NativeImageInterfacePtr nativeImageInterface )
-: mEventThreadServices( *Stage::GetCurrent() ),
- mRenderObject( NULL ),
- mNativeImage( nativeImageInterface ),
- mType( TextureType::TEXTURE_2D ),
- mFormat( Pixel::RGB888 ),
- mWidth( nativeImageInterface->GetWidth() ),
- mHeight( nativeImageInterface->GetHeight() )
+Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
+: mEventThreadServices(EventThreadServices::Get()),
+ mRenderObject(nullptr),
+ mNativeImage(nativeImageInterface),
+ mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
+ mType(TextureType::TEXTURE_2D),
+ mFormat(Pixel::RGB888)
{
}
-void NewTexture::Initialize()
+void Texture::Initialize()
{
- if( mNativeImage )
+ if(EventThreadServices::IsCoreRunning())
{
- mRenderObject = new Render::NewTexture( mNativeImage );
+ if(mNativeImage)
+ {
+ mRenderObject = new Render::Texture(mNativeImage);
+ }
+ else
+ {
+ mRenderObject = new Render::Texture(mType, mFormat, mSize);
+ }
+
+ OwnerPointer<Render::Texture> transferOwnership(mRenderObject);
+ AddTexture(mEventThreadServices.GetUpdateManager(), transferOwnership);
}
- else
+}
+
+Texture::~Texture()
+{
+ if(EventThreadServices::IsCoreRunning() && mRenderObject)
{
- mRenderObject = new Render::NewTexture( mType, mFormat, mWidth, mHeight );
+ RemoveTexture(mEventThreadServices.GetUpdateManager(), *mRenderObject);
}
+}
- AddTexture( mEventThreadServices.GetUpdateManager(), *mRenderObject );
+bool Texture::Upload(PixelDataPtr pixelData)
+{
+ return Upload(pixelData, 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
}
-NewTexture::~NewTexture()
+bool Texture::Upload(PixelDataPtr pixelData,
+ unsigned int layer,
+ unsigned int mipmap,
+ unsigned int xOffset,
+ unsigned int yOffset,
+ unsigned int width,
+ unsigned int height)
{
- if( EventThreadServices::IsCoreRunning() && mRenderObject )
+ constexpr auto max_value = std::numeric_limits<uint16_t>::max();
+ DALI_ASSERT_ALWAYS(layer < max_value &&
+ mipmap < max_value &&
+ xOffset < max_value &&
+ yOffset < max_value &&
+ width < max_value &&
+ height < max_value &&
+ "Parameter value out of range");
+
+ bool result(false);
+ if(EventThreadServices::IsCoreRunning() && mRenderObject)
{
- RemoveTexture( mEventThreadServices.GetUpdateManager(), *mRenderObject );
+ if(mNativeImage)
+ {
+ DALI_LOG_ERROR("OpenGL ES does not support uploading data to native texture\n");
+ }
+ else
+ {
+ unsigned int pixelDataSize = pixelData->GetWidth() * pixelData->GetHeight();
+ if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0)
+ {
+ DALI_LOG_ERROR("PixelData is empty\n");
+ }
+ else
+ {
+ Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
+ if((pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
+ {
+ if(pixelDataSize < width * height)
+ {
+ DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n");
+ }
+ else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) ||
+ (yOffset + height > (mSize.GetHeight() / (1u << mipmap))))
+ {
+ DALI_LOG_ERROR("Texture update area out of bounds\n");
+ }
+ else
+ {
+ //Parameters are correct. Send message to upload data to the texture
+ UploadParams params = {static_cast<uint16_t>(layer),
+ static_cast<uint16_t>(mipmap),
+ static_cast<uint16_t>(xOffset),
+ static_cast<uint16_t>(yOffset),
+ static_cast<uint16_t>(width),
+ static_cast<uint16_t>(height)};
+ UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, pixelData, params);
+
+ // Request event processing and update forcely
+ mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
+ mEventThreadServices.ForceNextUpdate();
+
+ result = true;
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR("Bad format\n");
+ }
+ }
+ }
}
+
+ return result;
}
-bool NewTexture::CheckUploadParametres( const Vector<unsigned char>& buffer, const UploadParams& parameters ) const
+void Texture::GenerateMipmaps()
{
- if( mNativeImage )
- {
- DALI_LOG_ERROR( "Error: Uploading data to a native texture");
- return false;
- }
- else if( buffer.Size() < GetBytesPerPixel( mFormat ) * parameters.width * parameters.height )
+ if(EventThreadServices::IsCoreRunning() && mRenderObject)
{
- DALI_LOG_ERROR( "Error: Buffer of an incorrect size when trying to update texture");
- return false;
- }
- else if( ( parameters.xOffset + parameters.width > static_cast<unsigned int>( mWidth/(1<<parameters.mipmap ))) ||
- ( parameters.yOffset + parameters.height > static_cast<unsigned int>( mHeight/(1<<parameters.mipmap ))))
- {
- DALI_LOG_ERROR( "Error: Out of bounds texture update");
- return false;
- }
- else
- {
- return true;
+ GenerateMipmapsMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject);
}
}
-void NewTexture::Upload( Vector<unsigned char>& buffer,
- unsigned int layer, unsigned int mipmap,
- unsigned int xOffset, unsigned int yOffset,
- unsigned int width, unsigned int height )
+unsigned int Texture::GetWidth() const
{
- UploadParams params = { layer, mipmap, xOffset, yOffset, width, height };
- if( CheckUploadParametres( buffer, params ) )
- {
- UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, buffer, params );
- }
+ return mSize.GetWidth();
}
-void NewTexture::Upload( Vector<unsigned char>& buffer )
+unsigned int Texture::GetHeight() const
{
- UploadParams params = {0u,0u,0u,0u,mWidth,mHeight};
- if( CheckUploadParametres( buffer, params ) )
- {
- UploadTextureMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, buffer, params );
- }
+ return mSize.GetHeight();
}
-void NewTexture::GenerateMipmaps()
+bool Texture::IsNative() const
{
- GenerateMipmapsMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject );
+ return mNativeImage != nullptr;
}
-unsigned int NewTexture::GetWidth() const
+bool Texture::ApplyNativeFragmentShader(std::string& shader)
{
- return mWidth;
+ std::string fragmentShader;
+ bool modified = false;
+ if(mNativeImage != nullptr && !shader.empty())
+ {
+ const char* fragmentPrefix = mNativeImage->GetCustomFragmentPrefix();
+ const char* customSamplerTypename = mNativeImage->GetCustomSamplerTypename();
+
+ if(fragmentPrefix != nullptr)
+ {
+ modified = true;
+ fragmentShader = fragmentPrefix;
+ fragmentShader += "\n";
+ }
+ fragmentShader += shader;
+
+ if(customSamplerTypename != nullptr)
+ {
+ modified = true;
+ size_t pos = fragmentShader.find(DEFAULT_SAMPLER_TYPENAME);
+ if(pos < fragmentShader.length())
+ {
+ fragmentShader.replace(pos, strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename);
+ }
+ }
+ }
+
+ if(modified)
+ {
+ shader = fragmentShader;
+ }
+
+ return modified;
}
-unsigned int NewTexture::GetHeight() const
+bool Texture::IsUploaded()
{
- return mHeight;
+ if(EventThreadServices::IsCoreRunning() && mRenderObject)
+ {
+ return mRenderObject->IsUploaded();
+ }
+ return false;
}
} // namespace Internal