e06af8eeba6cf95034db056667b36cb9c8bc4d5e
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / android / native-image-source-impl-android.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #define EGL_EGLEXT_PROTOTYPES
19 #if __ANDROID_API__ < 26
20 #error "Unsupported Android API version, must be >= 26"
21 #endif
22
23 // CLASS HEADER
24 #include <dali/internal/imaging/android/native-image-source-impl-android.h>
25
26 // EXTERNAL INCLUDES
27 #include <EGL/egl.h>
28 #include <dali/integration-api/debug.h>
29 #include <include/EGL/eglext.h>
30
31 // INTERNAL INCLUDES
32 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
33 #include <dali/internal/adaptor/common/adaptor-impl.h>
34 #include <dali/internal/graphics/common/egl-image-extensions.h>
35 #include <dali/internal/graphics/gles/egl-graphics.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace Adaptor
42 {
43 using Dali::Integration::PixelBuffer;
44
45 NativeImageSourceAndroid* NativeImageSourceAndroid::New(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
46 {
47   NativeImageSourceAndroid* image = new NativeImageSourceAndroid(width, height, depth, nativeImageSource);
48   DALI_ASSERT_DEBUG(image && "NativeImageSource allocation failed.");
49
50   // 2nd phase construction
51   if(image) //< Defensive in case we ever compile without exceptions.
52   {
53     image->Initialize();
54   }
55
56   return image;
57 }
58
59 NativeImageSourceAndroid::NativeImageSourceAndroid(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
60 : mWidth(width),
61   mHeight(height),
62   mOwnPixmap(true),
63   mPixmap(NULL),
64   mBlendingRequired(false),
65   mColorDepth(depth),
66   mEglImageKHR(NULL),
67   mEglImageExtensions(NULL)
68 {
69   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
70
71   GraphicsInterface* graphics    = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
72   auto               eglGraphics = static_cast<EglGraphics*>(graphics);
73
74   mEglImageExtensions = eglGraphics->GetImageExtensions();
75
76   DALI_ASSERT_DEBUG(mEglImageExtensions);
77
78   // assign the pixmap
79   mPixmap = static_cast<AHardwareBuffer*>(GetPixmapFromAny(nativeImageSource));
80   if(!mPixmap)
81   {
82     AHardwareBuffer_Desc bufferDescription;
83     memset(&bufferDescription, 0, sizeof(AHardwareBuffer_Desc));
84     bufferDescription.width  = width;
85     bufferDescription.height = height;
86     bufferDescription.layers = 1;
87     bufferDescription.usage  = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
88     switch(mColorDepth)
89     {
90       case Dali::NativeImageSource::COLOR_DEPTH_32:
91       case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
92         bufferDescription.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
93         break;
94       case Dali::NativeImageSource::COLOR_DEPTH_24:
95         bufferDescription.format = AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
96         break;
97       case Dali::NativeImageSource::COLOR_DEPTH_16:
98         bufferDescription.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
99         break;
100       case Dali::NativeImageSource::COLOR_DEPTH_8:
101         bufferDescription.format = AHARDWAREBUFFER_FORMAT_BLOB;
102         break;
103     }
104
105     int ret = AHardwareBuffer_allocate(&bufferDescription, &mPixmap);
106     if(ret)
107     {
108       DALI_LOG_ERROR("Failed to allocate AHardwareBuffer %d", ret);
109     }
110
111     mOwnPixmap = true;
112   }
113 }
114
115 void NativeImageSourceAndroid::Initialize()
116 {
117   if(mPixmap && !mOwnPixmap)
118   {
119     AHardwareBuffer_acquire(mPixmap);
120
121     // find out the pixmap width / height and color depth
122     GetPixmapDetails();
123   }
124 }
125
126 NativeImageSourceAndroid::~NativeImageSourceAndroid()
127 {
128   AHardwareBuffer_release(mPixmap);
129   mPixmap = NULL;
130 }
131
132 Any NativeImageSourceAndroid::GetNativeImageSource() const
133 {
134   return Any(mPixmap);
135 }
136
137 bool NativeImageSourceAndroid::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
138 {
139   DALI_ASSERT_DEBUG(sizeof(unsigned) == 4);
140   bool success = false;
141
142   width  = mWidth;
143   height = mHeight;
144
145   AHardwareBuffer_Desc bufferDescription;
146   memset(&bufferDescription, 0, sizeof(AHardwareBuffer_Desc));
147   AHardwareBuffer_describe(mPixmap, &bufferDescription);
148   switch(bufferDescription.format)
149   {
150     case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
151       pixelFormat = Pixel::Format::RGBA8888;
152       break;
153     case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
154       pixelFormat = Pixel::Format::RGB8888;
155       break;
156     case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
157       pixelFormat = Pixel::Format::RGB888;
158       break;
159     case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
160       pixelFormat = Pixel::Format::RGB565;
161       break;
162     case AHARDWAREBUFFER_FORMAT_BLOB:
163     default:
164       pixelFormat = Pixel::Format::A8;
165       break;
166   }
167
168   void* buffer = NULL;
169   int   ret    = AHardwareBuffer_lock(mPixmap, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL, &buffer);
170   if(ret != 0)
171   {
172     DALI_LOG_ERROR("Failed to AHardwareBuffer_lock %d", ret);
173     return success;
174   }
175
176   uint32_t pixelBytes = GetBytesPerPixel(pixelFormat);
177   if(bufferDescription.stride < (pixelBytes * bufferDescription.width))
178   {
179     //On Android device, bufferDescription.stride doesn't seem to mean (width * pixelbytes)
180     //in an actual case, (AHardwareBuffer_Desc) bufferDescription = (width = 1080, height = 1060, layers = 1, format = 1, usage = 306, stride = 1088, rfu0 = 0, rfu1 = 0)
181     //deal with situation
182     uint32_t dstStride = pixelBytes * bufferDescription.width;
183     uint32_t srcStride = pixelBytes * bufferDescription.stride;
184     uint32_t size      = dstStride * bufferDescription.height;
185     pixbuf.resize(size);
186     //copy each row over
187     const unsigned char* ptrSrc = reinterpret_cast<const unsigned char*>(buffer);
188     unsigned char*       ptrDst = pixbuf.data();
189     for(int y = 0; y < bufferDescription.height; y++, ptrSrc += srcStride, ptrDst += dstStride)
190     {
191       memcpy(ptrDst, ptrSrc, dstStride);
192     }
193   }
194   else
195   {
196     uint32_t size = bufferDescription.stride * bufferDescription.height;
197     pixbuf.resize(size);
198     memcpy(pixbuf.data(), buffer, size);
199   }
200
201   ret = AHardwareBuffer_unlock(mPixmap, NULL);
202   if(ret != 0)
203   {
204     DALI_LOG_ERROR("failed to AHardwareBuffer_unlock %d", ret);
205     return success;
206   }
207   success = true;
208
209   return success;
210 }
211
212 void NativeImageSourceAndroid::SetSource(Any source)
213 {
214   if(mPixmap)
215   {
216     mOwnPixmap = false;
217
218     AHardwareBuffer_release(mPixmap);
219     mPixmap = NULL;
220   }
221
222   mPixmap = static_cast<AHardwareBuffer*>(GetPixmapFromAny(source));
223
224   if(mPixmap)
225   {
226     // we don't own the pixmap
227     mOwnPixmap = false;
228
229     // find out the pixmap width / height and color depth
230     GetPixmapDetails();
231   }
232 }
233
234 bool NativeImageSourceAndroid::IsColorDepthSupported(Dali::NativeImageSource::ColorDepth colorDepth)
235 {
236   return true;
237 }
238
239 bool NativeImageSourceAndroid::CreateResource()
240 {
241   // if the image existed previously delete it.
242   if(mEglImageKHR != NULL)
243   {
244     DestroyResource();
245   }
246
247   DALI_ASSERT_ALWAYS(mPixmap);
248   EGLClientBuffer eglBuffer = eglGetNativeClientBufferANDROID(mPixmap);
249   switch(eglGetError())
250   {
251     case EGL_SUCCESS:
252     {
253       break;
254     }
255     case EGL_BAD_PARAMETER:
256     {
257       DALI_LOG_ERROR("EGL_BAD_PARAMETER: bad pixmap parameter\n");
258       break;
259     }
260     case EGL_BAD_ACCESS:
261     {
262       DALI_LOG_ERROR("EGL_BAD_ACCESS: bad access to pixmap\n");
263       break;
264     }
265     case EGL_BAD_ALLOC:
266     {
267       DALI_LOG_ERROR("EGL_BAD_ALLOC: Insufficient memory is available\n");
268       break;
269     }
270     default:
271     {
272       DALI_LOG_ERROR("eglGetNativeClientBufferANDROID error\n");
273       break;
274     }
275   }
276
277   DALI_ASSERT_ALWAYS(eglBuffer);
278   mEglImageKHR = mEglImageExtensions->CreateImageKHR(eglBuffer);
279
280   return mEglImageKHR != NULL;
281 }
282
283 void NativeImageSourceAndroid::DestroyResource()
284 {
285   mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
286
287   mEglImageKHR = NULL;
288 }
289
290 uint32_t NativeImageSourceAndroid::TargetTexture()
291 {
292   mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
293
294   return 0;
295 }
296
297 void NativeImageSourceAndroid::PrepareTexture()
298 {
299 }
300
301 int NativeImageSourceAndroid::GetTextureTarget() const
302 {
303   return GL_TEXTURE_2D;
304 }
305
306 bool NativeImageSourceAndroid::ApplyNativeFragmentShader(std::string& shader)
307 {
308   return false;
309 }
310
311 const char* NativeImageSourceAndroid::GetCustomSamplerTypename() const
312 {
313   return nullptr;
314 }
315
316 void* NativeImageSourceAndroid::GetPixmapFromAny(Any pixmap) const
317 {
318   if(pixmap.Empty())
319   {
320     return 0;
321   }
322
323   return AnyCast<void*>(pixmap);
324 }
325
326 void NativeImageSourceAndroid::GetPixmapDetails()
327 {
328   // get the width, height and depth
329   mBlendingRequired = false;
330
331   AHardwareBuffer_Desc bufferDescription;
332   memset(&bufferDescription, 0, sizeof(AHardwareBuffer_Desc));
333   AHardwareBuffer_describe(mPixmap, &bufferDescription);
334
335   mWidth  = bufferDescription.width;
336   mHeight = bufferDescription.height;
337   switch(bufferDescription.format)
338   {
339     case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
340       mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_32;
341       break;
342     case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
343       mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_24;
344       break;
345     case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
346       mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_16;
347       break;
348     case AHARDWAREBUFFER_FORMAT_BLOB:
349     default:
350       mColorDepth = Dali::NativeImageSource::COLOR_DEPTH_8;
351   }
352 }
353
354 uint8_t* NativeImageSourceAndroid::AcquireBuffer(uint16_t& width, uint16_t& height, uint16_t& stride)
355 {
356   if(mPixmap)
357   {
358     AHardwareBuffer_Desc bufferDescription;
359     memset(&bufferDescription, 0, sizeof(AHardwareBuffer_Desc));
360     AHardwareBuffer_describe(mPixmap, &bufferDescription);
361
362     void* buffer = NULL;
363     if(AHardwareBuffer_lock(mPixmap, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL, &buffer) != 0)
364     {
365       DALI_LOG_ERROR("Failed to AHardwareBuffer_lock\n");
366       return NULL;
367     }
368
369     stride = bufferDescription.stride;
370     width  = bufferDescription.width;
371     height = bufferDescription.height;
372
373     return static_cast<uint8_t*>(buffer);
374   }
375
376   return NULL;
377 }
378
379 bool NativeImageSourceAndroid::ReleaseBuffer()
380 {
381   if(mPixmap)
382   {
383     if(AHardwareBuffer_unlock(mPixmap, NULL) != 0)
384     {
385       DALI_LOG_ERROR("failed to AHardwareBuffer_unlock\n");
386       return false;
387     }
388     return true;
389   }
390   return false;
391 }
392
393 } // namespace Adaptor
394
395 } // namespace Internal
396
397 } // namespace Dali