2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #define EGL_EGLEXT_PROTOTYPES
19 #if __ANDROID_API__ < 26
20 #error "Unsupported Android API version, must be >= 26"
24 #include <dali/internal/imaging/android/native-image-source-impl-android.h>
28 #include <include/EGL/eglext.h>
29 #include <dali/integration-api/debug.h>
32 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
33 #include <dali/internal/graphics/common/egl-image-extensions.h>
34 #include <dali/internal/graphics/gles/egl-graphics.h>
35 #include <dali/internal/adaptor/common/adaptor-impl.h>
40 const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
41 const char* SAMPLER_TYPE = "samplerExternalOES";
53 using Dali::Integration::PixelBuffer;
55 NativeImageSourceAndroid* NativeImageSourceAndroid::New( uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
57 NativeImageSourceAndroid* image = new NativeImageSourceAndroid( width, height, depth, nativeImageSource );
58 DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );
60 // 2nd phase construction
61 if( image ) //< Defensive in case we ever compile without exceptions.
69 NativeImageSourceAndroid::NativeImageSourceAndroid( uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
74 mBlendingRequired( false ),
77 mEglImageExtensions( NULL ),
78 mResourceDestructionCallback()
80 DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
82 GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
83 auto eglGraphics = static_cast<EglGraphics*>( graphics );
85 mEglImageExtensions = eglGraphics->GetImageExtensions();
87 DALI_ASSERT_DEBUG( mEglImageExtensions );
90 mPixmap = static_cast<AHardwareBuffer*>( GetPixmapFromAny( nativeImageSource ) );
93 AHardwareBuffer_Desc bufferDescription;
94 memset( &bufferDescription, 0, sizeof( AHardwareBuffer_Desc ) );
95 bufferDescription.width = width;
96 bufferDescription.height = height;
97 bufferDescription.layers = 1;
98 bufferDescription.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
101 case Dali::NativeImageSource::COLOR_DEPTH_32:
102 case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
103 bufferDescription.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
105 case Dali::NativeImageSource::COLOR_DEPTH_24:
106 bufferDescription.format = AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
108 case Dali::NativeImageSource::COLOR_DEPTH_16:
109 bufferDescription.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
111 case Dali::NativeImageSource::COLOR_DEPTH_8:
112 bufferDescription.format = AHARDWAREBUFFER_FORMAT_BLOB;
116 int ret = AHardwareBuffer_allocate( &bufferDescription, &mPixmap );
119 DALI_LOG_ERROR("Failed to allocate AHardwareBuffer %d", ret);
126 void NativeImageSourceAndroid::Initialize()
128 if( mPixmap && !mOwnPixmap )
130 AHardwareBuffer_acquire( mPixmap ) ;
132 // find out the pixmap width / height and color depth
137 NativeImageSourceAndroid::~NativeImageSourceAndroid()
139 AHardwareBuffer_release( mPixmap );
143 Any NativeImageSourceAndroid::GetNativeImageSource() const
145 return Any( mPixmap );
148 bool NativeImageSourceAndroid::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
150 DALI_ASSERT_DEBUG( sizeof(unsigned) == 4 );
151 bool success = false;
156 AHardwareBuffer_Desc bufferDescription;
157 memset( &bufferDescription, 0, sizeof( AHardwareBuffer_Desc ) );
158 AHardwareBuffer_describe( mPixmap, &bufferDescription );
159 switch( bufferDescription.format )
161 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
162 pixelFormat = Pixel::Format::RGBA8888;
164 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
165 pixelFormat = Pixel::Format::RGB8888;
167 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
168 pixelFormat = Pixel::Format::RGB888;
170 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
171 pixelFormat = Pixel::Format::RGB565;
173 case AHARDWAREBUFFER_FORMAT_BLOB:
175 pixelFormat = Pixel::Format::A8;
180 int ret = AHardwareBuffer_lock( mPixmap, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL, &buffer );
183 DALI_LOG_ERROR("Failed to AHardwareBuffer_lock %d", ret);
187 uint32_t size = bufferDescription.stride * bufferDescription.height;
188 pixbuf.resize( size );
189 memcpy( pixbuf.data(), buffer, size );
191 ret = AHardwareBuffer_unlock( mPixmap, NULL );
194 DALI_LOG_ERROR("failed to AHardwareBuffer_unlock %d", ret);
202 void NativeImageSourceAndroid::SetSource( Any source )
208 AHardwareBuffer_release( mPixmap );
212 mPixmap = static_cast<AHardwareBuffer*>( GetPixmapFromAny( source ) );
216 // we don't own the pixmap
219 // find out the pixmap width / height and color depth
224 bool NativeImageSourceAndroid::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
229 bool NativeImageSourceAndroid::CreateResource()
231 // if the image existed previously delete it.
232 if( mEglImageKHR != NULL )
237 DALI_ASSERT_ALWAYS( mPixmap );
238 EGLClientBuffer eglBuffer = eglGetNativeClientBufferANDROID( mPixmap );
239 switch( eglGetError() )
245 case EGL_BAD_PARAMETER:
247 DALI_LOG_ERROR( "EGL_BAD_PARAMETER: bad pixmap parameter\n" );
252 DALI_LOG_ERROR( "EGL_BAD_ACCESS: bad access to pixmap\n" );
257 DALI_LOG_ERROR( "EGL_BAD_ALLOC: Insufficient memory is available\n" );
262 DALI_LOG_ERROR( "eglGetNativeClientBufferANDROID error\n" );
267 DALI_ASSERT_ALWAYS( eglBuffer );
268 mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );
270 return mEglImageKHR != NULL;
273 void NativeImageSourceAndroid::DestroyResource()
275 mEglImageExtensions->DestroyImageKHR( mEglImageKHR );
280 uint32_t NativeImageSourceAndroid::TargetTexture()
282 mEglImageExtensions->TargetTextureKHR( mEglImageKHR );
287 void NativeImageSourceAndroid::PrepareTexture()
291 int NativeImageSourceAndroid::GetTextureTarget() const
293 return GL_TEXTURE_2D;
296 const char* NativeImageSourceAndroid::GetCustomFragmentPrefix() const
301 const char* NativeImageSourceAndroid::GetCustomSamplerTypename() const
307 void* NativeImageSourceAndroid::GetPixmapFromAny(Any pixmap) const
314 return AnyCast<void*>( pixmap );
317 void NativeImageSourceAndroid::GetPixmapDetails()
319 // get the width, height and depth
320 mBlendingRequired = false;
322 AHardwareBuffer_Desc bufferDescription;
323 memset( &bufferDescription, 0, sizeof( AHardwareBuffer_Desc ) );
324 AHardwareBuffer_describe( mPixmap, &bufferDescription );
326 mWidth = bufferDescription.width;
327 mHeight = bufferDescription.height;
328 switch (bufferDescription.format)
330 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
331 mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_32;
333 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
334 mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_24;
336 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
337 mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_16;
339 case AHARDWAREBUFFER_FORMAT_BLOB:
341 mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_8;
345 uint8_t* NativeImageSourceAndroid::AcquireBuffer( uint16_t& width, uint16_t& height, uint16_t& stride )
349 AHardwareBuffer_Desc bufferDescription;
350 memset( &bufferDescription, 0, sizeof( AHardwareBuffer_Desc ) );
351 AHardwareBuffer_describe( mPixmap, &bufferDescription );
354 if( AHardwareBuffer_lock( mPixmap, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL, &buffer ) != 0 )
356 DALI_LOG_ERROR( "Failed to AHardwareBuffer_lock\n" );
360 stride = bufferDescription.stride;
361 width = bufferDescription.width;
362 height = bufferDescription.height;
364 return static_cast< uint8_t* >( buffer );
371 bool NativeImageSourceAndroid::ReleaseBuffer()
375 if( AHardwareBuffer_unlock( mPixmap, NULL ) != 0 )
377 DALI_LOG_ERROR( "failed to AHardwareBuffer_unlock\n" );
385 void NativeImageSourceAndroid::SetResourceDestructionCallback(EventThreadCallback* callback)
387 mResourceDestructionCallback = std::unique_ptr<EventThreadCallback>(callback);
390 } // namespace Adaptor
392 } // namespace internal