[dali_1.0.1] Merge branch 'tizen'
[platform/core/uifw/dali-adaptor.git] / adaptors / wayland / pixmap-image-impl-wl.cpp
1 /*
2  * Copyright (c) 2014 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 // CLASS HEADER
19 #include "pixmap-image-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <Ecore.h>
23 #include <Ecore_Wayland.h>
24 #include <dali/integration-api/debug.h>
25 #include <render-surface.h>
26
27 // INTERNAL INCLUDES
28 #include <gl/egl-image-extensions.h>
29 #include <gl/egl-factory.h>
30 #include <adaptor-impl.h>
31
32 // Allow this to be encoded and saved:
33 #include <platform-abstractions/slp/resource-loader/resource-loader.h>
34 #include <platform-abstractions/slp/resource-loader/loader-jpeg.h>
35 #include <platform-abstractions/slp/resource-loader/loader-png.h>
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 namespace Adaptor
44 {
45 using Dali::Integration::PixelBuffer;
46
47 // Pieces needed to save compressed images (temporary location while plumbing):
48 namespace
49 {
50
51   /**
52    * Simple function to tell intended image file format from filename
53    */
54   FileFormat GetFormatFromFileName( const std::string& filename )
55   {
56     if (filename.length() < 5)
57     {
58       DALI_LOG_WARNING("Invalid (short) filename.");
59     }
60     FileFormat format(INVALID_FORMAT);
61
62     const std::size_t filenameSize = filename.length();
63
64     if(filenameSize >= 4){ // Avoid throwing out_of_range or failing silently if exceptions are turned-off on the compare(). (http://www.cplusplus.com/reference/string/string/compare/)
65       if( !filename.compare( filenameSize - 4, 4, ".jpg" )
66        || !filename.compare( filenameSize - 4, 4, ".JPG" ) )
67       {
68         format = JPG_FORMAT;
69       }
70       else if( !filename.compare( filenameSize - 4, 4, ".png" )
71             || !filename.compare( filenameSize - 4, 4, ".PNG" ) )
72       {
73         format = PNG_FORMAT;
74       }
75       else if( !filename.compare( filenameSize - 4, 4, ".bmp" )
76             || !filename.compare( filenameSize - 4, 4, ".BMP" ) )
77       {
78         format = BMP_FORMAT;
79       }
80       else if( !filename.compare( filenameSize - 4, 4, ".gif" )
81             || !filename.compare( filenameSize - 4, 4, ".GIF" ) )
82       {
83         format = GIF_FORMAT;
84       }
85       else if( !filename.compare( filenameSize - 4, 4, ".ico" )
86             || !filename.compare( filenameSize - 4, 4, ".ICO" ) )
87       {
88         format = ICO_FORMAT;
89       }
90       else if(filenameSize >= 5){
91         if( !filename.compare( filenameSize - 5, 5, ".jpeg" )
92          || !filename.compare( filenameSize - 5, 5, ".JPEG" ) )
93         {
94           format = JPG_FORMAT;
95         }
96       }
97     }
98
99     return format;
100   }
101
102   bool EncodeToFormat( const PixelBuffer* pixelBuffer, std::vector< unsigned char >& encodedPixels, FileFormat formatEncoding, std::size_t width, std::size_t height, Pixel::Format pixelFormat )
103   {
104     switch( formatEncoding )
105     {
106       case JPG_FORMAT:
107       {
108         return SlpPlatform::EncodeToJpeg( pixelBuffer, encodedPixels, width, height, pixelFormat );
109         break;
110       }
111       case PNG_FORMAT:
112       {
113         return SlpPlatform::EncodeToPng( pixelBuffer, encodedPixels, width, height, pixelFormat );
114         break;
115       }
116       default:
117       {
118         DALI_LOG_ERROR("Format not supported for image encoding (supported formats are PNG and JPEG)");
119         break;
120       }
121     }
122     return false;
123   }
124
125   bool EncodeToFile(const PixelBuffer * const pixelBuffer, const std::string& filename, const Pixel::Format pixelFormat, const std::size_t width, const std::size_t height)
126   {
127     DALI_ASSERT_DEBUG(pixelBuffer != 0 && filename.size() > 4 && width > 0 && height > 0);
128     std::vector< unsigned char > pixbufEncoded;
129     const FileFormat format = GetFormatFromFileName( filename );
130     const bool encodeResult = EncodeToFormat( pixelBuffer, pixbufEncoded, format, width, height, pixelFormat );
131     if(!encodeResult)
132     {
133       DALI_LOG_ERROR("Encoding pixels failed");
134       return false;
135     }
136     return SlpPlatform::ResourceLoader::SaveFile( filename, pixbufEncoded );
137   }
138 }
139
140 PixmapImage* PixmapImage::New(unsigned int width, unsigned int height, Dali::PixmapImage::ColorDepth depth, Dali::Adaptor& adaptor,  Any pixmap )
141 {
142   PixmapImage* image = new PixmapImage( width, height, depth, adaptor, pixmap );
143   DALI_ASSERT_DEBUG( image && "PixmapImage allocation failed." );
144
145   // 2nd phase construction
146   if(image) //< Defensive in case we ever compile without exceptions.
147   {
148     image->Initialize();
149   }
150
151   return image;
152 }
153
154 PixmapImage::PixmapImage(unsigned int width, unsigned int height, Dali::PixmapImage::ColorDepth depth, Dali::Adaptor& adaptor, Any pixmap)
155 : mWidth(width),
156   mHeight(height),
157   mOwnPixmap(true),
158   mPixelFormat(Pixel::RGB888),
159   mColorDepth(depth),
160   mAdaptor(Internal::Adaptor::Adaptor::GetImplementation(adaptor)),
161   mEglImageKHR(NULL)
162 {
163 }
164
165 void PixmapImage::Initialize()
166 {
167 }
168
169 PixmapImage::~PixmapImage()
170 {
171   // Lost the opportunity to call GlExtensionDestroy() if Adaptor is destroyed first
172   if( Adaptor::IsAvailable() )
173   {
174     // GlExtensionDestroy() called from GLCleanup on the render thread. Checking this is done here.
175     // (mEglImageKHR is now read/written from different threads although ref counted destruction
176     //  should mean this isnt concurrent)
177     DALI_ASSERT_ALWAYS( NULL == mEglImageKHR && "NativeImage GL resources have not been properly cleaned up" );
178   }
179 }
180
181 Any PixmapImage::GetPixmap(Dali::PixmapImage::PixmapAPI api) const
182 {
183     return NULL;
184 }
185
186 Any PixmapImage::GetDisplay() const
187 {
188     return NULL;
189 }
190
191 bool PixmapImage::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
192 {
193     return false;
194 }
195
196 bool PixmapImage::EncodeToFile(const std::string& filename) const
197 {
198   std::vector< unsigned char > pixbuf;
199   unsigned int width(0), height(0);
200   Pixel::Format pixelFormat;
201
202   if(GetPixels(pixbuf, width, height, pixelFormat))
203   {
204     return Dali::Internal::Adaptor::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
205   }
206   return false;
207 }
208
209 bool PixmapImage::GlExtensionCreate()
210 {
211     return false;
212 }
213
214 void PixmapImage::GlExtensionDestroy()
215 {
216   EglImageExtensions* eglImageExtensions = GetEglImageExtensions();
217
218   eglImageExtensions->DestroyImageKHR(mEglImageKHR);
219
220   mEglImageKHR = NULL;
221 }
222
223 unsigned int PixmapImage::TargetTexture()
224 {
225   EglImageExtensions* eglImageExtensions = GetEglImageExtensions();
226
227   eglImageExtensions->TargetTextureKHR(mEglImageKHR);
228
229   return 0;
230 }
231
232 int PixmapImage::GetPixelDepth(Dali::PixmapImage::ColorDepth depth) const
233 {
234   switch (depth)
235   {
236     case Dali::PixmapImage::COLOR_DEPTH_8:
237     {
238       return 8;
239     }
240     case Dali::PixmapImage::COLOR_DEPTH_16:
241     {
242       return 16;
243     }
244     case Dali::PixmapImage::COLOR_DEPTH_24:
245     {
246       return 24;
247     }
248     case Dali::PixmapImage::COLOR_DEPTH_32:
249     {
250       return 32;
251     }
252     default:
253     {
254       DALI_ASSERT_DEBUG(0 && "unknown color enum");
255       return 0;
256     }
257   }
258 }
259
260 void PixmapImage::SetPixelFormat(int depth)
261 {
262   // store the pixel format based on the depth
263   switch (depth)
264   {
265     case 8:
266     {
267       mPixelFormat = Pixel::A8;
268       break;
269     }
270     case 16:
271     {
272       mPixelFormat = Pixel::RGB565;
273       break;
274     }
275     case 32:
276     {
277       mPixelFormat = Pixel::RGBA8888;
278       break;
279     }
280     case 24:
281     default:
282     {
283       mPixelFormat = Pixel::RGB888;
284       break;
285     }
286   }
287 }
288
289 void PixmapImage::GetPixmapDetails()
290 {
291 }
292
293 EglImageExtensions* PixmapImage::GetEglImageExtensions() const
294 {
295   EglFactory& factory = mAdaptor.GetEGLFactory();
296   EglImageExtensions* egl = factory.GetImageExtensions();
297   DALI_ASSERT_DEBUG( egl && "EGL Image Extensions not initialized" );
298   return egl;
299 }
300
301 } // namespace Adaptor
302
303 } // namespace internal
304
305 } // namespace Dali