2 * Copyright (c) 2016 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 #include "emscripten-platform-abstraction.h"
24 #include <SDL_surface.h>
25 #include <SDL_image.h>
26 #include "emscripten/emscripten.h"
27 #include "emscripten-callbacks.h"
29 #define EM_LOG(x); // EM_ASM( console.log( x ) );
33 #include <dali/integration-api/platform-abstraction.h>
34 #include <dali/devel-api/common/ref-counted-dali-vector.h>
39 Dali::Integration::BitmapPtr LoadResourceEncodedImage( Dali::RefCountedVector<uint8_t>* encodedBlob )
41 Dali::Integration::BitmapPtr bitmapPtr = NULL;
43 if( encodedBlob != 0 )
45 const size_t blobSize = encodedBlob->GetVector().Size();
46 uint8_t * const blobBytes = &(encodedBlob->GetVector()[0]);
47 DALI_ASSERT_DEBUG( blobSize > 0U );
48 DALI_ASSERT_DEBUG( blobBytes != 0U );
50 if( blobBytes != 0 && blobSize > 0U )
53 SDL_RWops *memory = SDL_RWFromMem(blobBytes, blobSize);
57 printf(" Error Null pointer from SDL RW memory?\n");
60 SDL_Surface *surface = IMG_Load_RW(memory, 0);
64 bitmapPtr = Dali::Integration::Bitmap::New( Dali::Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,
65 Dali::ResourcePolicy::OWNED_DISCARD ); // DISCARD; Dali manages
67 Dali::Integration::Bitmap::PackedPixelsProfile* packedProfile = bitmapPtr->GetPackedPixelsProfile();
68 DALI_ASSERT_ALWAYS(packedProfile);
70 unsigned char bytesPerPixel = surface->format->BytesPerPixel;
72 Dali::Integration::PixelBuffer* pixels = NULL;
74 unsigned char targetBytesPerPixel = 3; // bytesPerPixel;
76 // SDL in emscripten returns us a 4byteperpixel image regardless of rgb/png etc
77 // Theres no apparent way to differentiate an image with an alpha channel
78 // In Dali if an image has an alpha channel it gets sorted. This introduces odd artifacts on rotation
79 // as the sorting algorithm presumes front on view.
80 // So here well just support pngs with an alpha channel.
81 // We're poking around in the format as emscripten currently lacks a file memory api where we could use
82 // Dali's machinery to read the format.
83 unsigned char *pBytes = blobBytes;
85 if( 0x89 == *(pBytes+0) && 0x50 == *(pBytes+1) ) // magic bytes for png_all_filters
87 pBytes+=8; // 8 bytes for header
88 pBytes+=4; // 4 bytes for chunk length
89 pBytes+=4; // 4 bytes for chunk type
90 // ihdr data (must be first chunk)
91 pBytes+=4; // 4 for width,height
93 pBytes+=1; // 1 for bit depth
94 unsigned char ihdr_colorType= *pBytes; // 1 for bit colorType
95 if( (4 == ihdr_colorType || // 4 is 8,16 bit depth with alpha LA
96 6 == ihdr_colorType) ) // 6 is 8,16 bit depth with alpha RGBA
98 targetBytesPerPixel = 4;
102 if(3 == targetBytesPerPixel)
104 pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGB888,
105 surface->w, surface->h,
106 surface->w, surface->h);
108 else if(4 == targetBytesPerPixel)
110 pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGBA8888,
111 surface->w, surface->h,
112 surface->w, surface->h);
116 DALI_ASSERT_ALWAYS(0 && "bad bytes per pixel");
119 unsigned char* fromPtr = static_cast<unsigned char*>(surface->pixels);
121 int stride = surface->pitch;
123 for(int h = 0; h < surface->h; ++h)
125 for(int w = 0; w < (surface->w*bytesPerPixel); w+=bytesPerPixel)
127 for(int j = 0; j < targetBytesPerPixel; ++j)
129 pixels[ index++ ] = *( (fromPtr + (h * stride) ) + w + j );
136 printf(" Error empty surface when decoding image? (SDL RW Memory ptr=%llx) %s. %d\n", (long long)(memory), SDL_GetError(), blobSize);
142 printf(" Error No bytes in image?\n");
148 printf(" Error Null pointer given for decoding image?\n");
154 EM_ASM( console.log( "LoadResourceEncodedImage: Image:-" ) );
156 console.log( $0 ) }, bitmapPtr->GetImageWidth() );
158 console.log( $0 ) }, bitmapPtr->GetImageHeight() );
160 console.log( $0 ) }, bitmapPtr->GetBufferSize() );
165 EM_ASM( console.log( "LoadResourceEncodedImage: no bitmap data?" ) );
176 EmscriptenPlatformAbstraction::EmscriptenPlatformAbstraction()
183 EmscriptenPlatformAbstraction::~EmscriptenPlatformAbstraction()
187 void EmscriptenPlatformAbstraction::GetTimeMicroseconds(unsigned int &seconds, unsigned int µSeconds)
189 double current = EM_ASM_DOUBLE_V({ return new Date().getTime(); }); // getTime() in ms
191 seconds = static_cast<unsigned int>(current/1000.0);
192 microSeconds = (static_cast<unsigned int>(current) - seconds*1000.0) * 1000;
195 void EmscriptenPlatformAbstraction::Suspend()
197 DALI_ASSERT_ALWAYS("!Not Implemented");
200 void EmscriptenPlatformAbstraction::Resume()
202 DALI_ASSERT_ALWAYS("!Not Implemented");
205 ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( const std::string& filename,
206 ImageDimensions size,
207 FittingMode::Type fittingMode,
208 SamplingMode::Type samplingMode,
209 bool orientationCorrection )
211 return Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
214 ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
215 ImageDimensions size,
216 FittingMode::Type fittingMode,
217 SamplingMode::Type samplingMode,
218 bool orientationCorrection )
221 return Dali::ImageDimensions(); // Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
224 Integration::ResourcePointer EmscriptenPlatformAbstraction::LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath )
226 Integration::ResourcePointer ret;
228 switch(resourceType.id)
230 case Integration::ResourceBitmap:
232 const Integration::BitmapResourceType& bitmapResource( static_cast<const Integration::BitmapResourceType&>(resourceType) );
234 Integration::BitmapPtr bitmapPtr = Dali::Internal::Emscripten::GetImage( bitmapResource.size,
235 bitmapResource.scalingMode,
236 bitmapResource.samplingMode,
237 bitmapResource.orientationCorrection,
243 case Integration::ResourceNativeImage:
247 case Integration::ResourceTargetImage:
251 } // switch(resourceType->id)
256 void EmscriptenPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request)
258 std::string path = request.GetPath();
260 Integration::ResourceType *type = request.GetType();
261 Integration::ResourceId resourceId = request.GetId();
262 Integration::ResourcePointer resourcePtr = request.GetResource();
268 case Integration::ResourceBitmap:
270 Integration::BitmapPtr bitmapPtr = NULL;
272 if( NULL == request.GetResource().Get() )
274 const Integration::BitmapResourceType& bitmapResource( static_cast<const Integration::BitmapResourceType&>(*type) );
276 Integration::BitmapPtr bitmapPtr = Dali::Internal::Emscripten::GetImage( bitmapResource.size,
277 bitmapResource.scalingMode,
278 bitmapResource.samplingMode,
279 bitmapResource.orientationCorrection,
287 // 2) load it (usually on worker thread)
288 // DALI_LOG_TRACE_METHOD( mLogFilter );
289 // DALI_LOG_INFO(mLogFilter, Debug::Verbose, "%s(%s)\n", __FUNCTION__, request.GetPath().c_str());
291 bitmapPtr = LoadResourceEncodedImage( reinterpret_cast<Dali::RefCountedVector<uint8_t>*>( request.GetResource().Get() ) );
296 mResourceQueue.push( ResourceIdBitmapPair( resourceId, bitmapPtr ) );
301 case Integration::ResourceNativeImage:
303 printf("EmscriptenPlatformAbstraction::LoadResource ResourceNativeImage\n");
306 case Integration::ResourceTargetImage:
308 printf("EmscriptenPlatformAbstraction::LoadResource ResourceTargetImage\n");
317 void EmscriptenPlatformAbstraction::SaveResource(const Integration::ResourceRequest& request)
319 DALI_ASSERT_ALWAYS("!Not Implemented");
322 Integration::BitmapPtr EmscriptenPlatformAbstraction::DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t bufferSize )
324 return Integration::BitmapPtr();
327 void EmscriptenPlatformAbstraction::CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId)
329 DALI_ASSERT_ALWAYS("!Not Implemented");
332 void EmscriptenPlatformAbstraction::GetResources(Integration::ResourceCache& cache)
334 while( !mResourceQueue.empty() )
336 Integration::ResourceId resourceId = mResourceQueue.front().first;
337 Integration::BitmapPtr bitmapPtr = mResourceQueue.front().second;
339 cache.LoadResponse( resourceId,
340 Integration::ResourceBitmap,
342 Integration::RESOURCE_COMPLETELY_LOADED );
343 mResourceQueue.pop();
347 bool EmscriptenPlatformAbstraction::IsLoading()
349 EM_LOG("EmscriptenPlatformAbstraction::IsLoading");
353 const std::string& EmscriptenPlatformAbstraction::GetDefaultFontFamily() const
355 EM_LOG("EmscriptenPlatformAbstraction::GetDefaultFontFamily");
356 DALI_ASSERT_ALWAYS("!Not Implemented");
357 return mGetDefaultFontFamilyResult;
360 int EmscriptenPlatformAbstraction::GetDefaultFontSize() const
362 EM_LOG("EmscriptenPlatformAbstraction::GetDefaultFontSize");
366 void EmscriptenPlatformAbstraction::SetDpi (unsigned int /* dpiHorizontal*/, unsigned int /* dpiVertical */)
372 bool EmscriptenPlatformAbstraction::LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
374 EM_LOG("EmscriptenPlatformAbstraction::LoadFile");
378 bool EmscriptenPlatformAbstraction::SaveFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const
380 EM_LOG("EmscriptenPlatformAbstraction::SaveFile");
382 DALI_ASSERT_ALWAYS("!Unimplemented");
386 bool EmscriptenPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
388 EM_LOG("EmscriptenPlatformAbstraction::LoadShaderBinaryFile");
392 bool EmscriptenPlatformAbstraction::SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const
394 EM_LOG("EmscriptenPlatformAbstraction::SaveShaderBinaryFile");
396 DALI_ASSERT_ALWAYS("!Unimplemented");
400 void EmscriptenPlatformAbstraction::JoinLoaderThreads()
402 DALI_ASSERT_ALWAYS("!Unimplemented");
405 void EmscriptenPlatformAbstraction::UpdateDefaultsFromDevice()
407 DALI_ASSERT_ALWAYS("!Unimplemented");
408 mGetDefaultFontFamilyResult+=1.0f;
411 void EmscriptenPlatformAbstraction::IncrementGetTimeResult(size_t milliseconds)