(Atlas) Upload pixel data & Allow the difference in pixel format 02/50302/10
authorXiangyin Ma <x1.ma@samsung.com>
Tue, 27 Oct 2015 15:45:26 +0000 (15:45 +0000)
committerXiangyin Ma <x1.ma@samsung.com>
Mon, 2 Nov 2015 17:16:12 +0000 (09:16 -0800)
Change-Id: I09b649817d506a779379bd9c3ae10d1874f750c8

23 files changed:
automated-tests/src/dali-devel/CMakeLists.txt
automated-tests/src/dali-devel/utc-Dali-Atlas.cpp
automated-tests/src/dali-devel/utc-Dali-PixelData.cpp [new file with mode: 0644]
build/tizen/configure.ac
dali/devel-api/file.list
dali/devel-api/images/atlas.cpp
dali/devel-api/images/atlas.h
dali/devel-api/images/pixel-data.cpp [new file with mode: 0644]
dali/devel-api/images/pixel-data.h [new file with mode: 0644]
dali/integration-api/bitmap.cpp
dali/integration-api/bitmap.h
dali/internal/event/images/atlas-impl.cpp
dali/internal/event/images/atlas-impl.h
dali/internal/event/resources/resource-client.cpp
dali/internal/event/resources/resource-client.h
dali/internal/render/common/texture-cache-dispatcher.h
dali/internal/render/gl-resources/bitmap-texture.cpp
dali/internal/render/gl-resources/bitmap-texture.h
dali/internal/render/gl-resources/texture-cache.cpp
dali/internal/render/gl-resources/texture-cache.h
dali/internal/render/gl-resources/texture.h
dali/internal/update/resources/resource-manager.cpp
dali/internal/update/resources/resource-manager.h

index e291f77..d8e67d2 100644 (file)
@@ -18,6 +18,7 @@ SET(TC_SOURCES
         utc-Dali-HitTestAlgorithm.cpp
         utc-Dali-Material.cpp
         utc-Dali-Mutex.cpp
+        utc-Dali-PixelData.cpp
         utc-Dali-PropertyBuffer.cpp
         utc-Dali-Renderer.cpp
         utc-Dali-Sampler.cpp
index 7e033ab..549b058 100644 (file)
@@ -21,6 +21,7 @@
 #include <dali/public-api/dali-core.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/devel-api/images/atlas.h>
+#include <dali/devel-api/images/pixel-data.h>
 #include <dali-test-suite-utils.h>
 #include <test-native-image.h>
 
@@ -30,10 +31,10 @@ namespace
 {
 static const char* gTestImageFilename = "icon_wrt.png";
 
-void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat )
+void PrepareResourceImage( TestApplication& application, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat )
 {
   TestPlatformAbstraction& platform = application.GetPlatform();
-  platform.SetClosestImageSize(Vector2( 16, 16));
+  platform.SetClosestImageSize(Vector2( imageWidth, imageHeight));
 
   Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
   Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
@@ -45,6 +46,14 @@ void PrepareResourceImage( TestApplication& application, unsigned int imageHeigh
   platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
 }
 
+PixelDataPtr CreatePixelData(unsigned int width, unsigned int height, Pixel::Format pixelFormat)
+{
+  unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( pixelFormat );
+  unsigned char* buffer = new unsigned char [ bufferSize ];
+
+  return new PixelData( buffer, width, height, pixelFormat, PixelData::DELETE_ARRAY );
+}
+
 }
 
 void utc_dali_atlas_startup(void)
@@ -57,8 +66,7 @@ void utc_dali_atlas_cleanup(void)
   test_return_value = TET_PASS;
 }
 
-// 1.1
-int UtcDaliAtlasNew01(void)
+int UtcDaliAtlasNew(void)
 {
   TestApplication application;
 
@@ -74,118 +82,188 @@ int UtcDaliAtlasNew01(void)
   END_TEST;
 }
 
+int UtcDaliAtlasCopyConstructor(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 16, 16);
+  Atlas atlasCopy(atlas);
+
+
+  DALI_TEST_EQUALS( (bool)atlasCopy, true, TEST_LOCATION );
+  END_TEST;
+}
 
-// 1.2
-int UtcDaliAtlasUpload01(void)
+int UtcDaliAtlasAssignmentOperator(void)
 {
   TestApplication application;
 
-  Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( atlas );
+  Atlas atlas = Atlas::New( 16, 16);
 
-  // Using correct pixel format
-  PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
-  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+  Atlas atlas2;
+  DALI_TEST_EQUALS( (bool)atlas2, false, TEST_LOCATION );
 
-  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+  atlas2 = atlas;
+  DALI_TEST_EQUALS( (bool)atlas2, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliAtlasDownCast(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 16, 16);
+
+  BaseHandle handle(atlas);
+  Atlas atlasDowncast = Atlas::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)atlasDowncast, true, TEST_LOCATION );
+
+  Handle handle2 = Handle::New(); // Create a custom object
+  Atlas atlas2 = Atlas::DownCast(handle2);
+  DALI_TEST_EQUALS( (bool)atlas2, false, TEST_LOCATION );
 
   END_TEST;
 }
 
-// 1.3
-int UtcDaliAtlasUpload02(void)
+int UtcDaliAtlasClear(void)
 {
   TestApplication application;
 
-  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  Atlas atlas = Atlas::New( 16, 32, Pixel::RGBA8888 );
   DALI_TEST_CHECK( atlas );
 
-  // Using INCORRECT pixel format
-  PixelBuffer* buffer = new PixelBuffer[16 * 16];
-  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 );
-  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+  atlas.Clear(Color::TRANSPARENT);
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  callStack.Reset();
+  callStack.Enable(true);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  callStack.Enable(false);
 
-  PrepareResourceImage( application, 16, 16, Pixel::A8 );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 32") );
 
   END_TEST;
 }
 
-// 1.4
-int UtcDaliAtlasUpload03(void)
+
+// Upload resource image, buffer image & pixel data with same pixel format
+int UtcDaliAtlasUpload01P(void)
 {
   TestApplication application;
 
-  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  Atlas atlas = Atlas::New( 16, 40, Pixel::RGBA8888 );
   DALI_TEST_CHECK( atlas );
 
-  // Using image too big for atlas
+  // Using same pixel format
   PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
   BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+  DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
 
   PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 16 ) );
+
+  PixelDataPtr pixelData = CreatePixelData( 6,8,Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( pixelData, 2, 32 ) );
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  callStack.Reset();
+  callStack.Enable(true);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  callStack.Enable(false);
+
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 16") );
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 16, 16, 16") );
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "2, 32, 6, 8") );
 
   END_TEST;
 }
 
-// 1.5
-int UtcDaliAtlasUpload04(void)
+// Upload resource image, buffer image & pixel data with different pixel format
+int UtcDaliAtlasUpload02P(void)
 {
   TestApplication application;
 
-  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  Atlas atlas = Atlas::New( 20, 20, Pixel::RGBA8888 );
   DALI_TEST_CHECK( atlas );
 
-  // Using valid offsets
-  PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
-  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+  // Using different pixel format
+  PixelBuffer* buffer = new PixelBuffer[16 * 16 * 3];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGB888 );
+  DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
 
-  DALI_TEST_CHECK( atlas.Upload( image,  0,  0 ) );
-  DALI_TEST_CHECK( atlas.Upload( image, 16,  0 ) );
-  DALI_TEST_CHECK( atlas.Upload( image,  0, 16 ) );
-  DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+  PrepareResourceImage( application, 12, 12, Pixel::A8 );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 6, 6 ) );
 
-  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
-  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0,  0 ) );
-  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16,  0 ) );
-  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0, 16 ) );
-  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) );
+  PixelDataPtr pixelData = CreatePixelData( 8,8,Pixel::LA88 );
+  DALI_TEST_CHECK( atlas.Upload( pixelData, 10, 10 ) );
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  callStack.Reset();
+  callStack.Enable(true);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  callStack.Enable(false);
+
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 16, 16") );
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "6, 6, 12, 12") );
+  DALI_TEST_CHECK( callStack.FindMethodAndParams("TexSubImage2D", "10, 10, 8, 8") );
 
   END_TEST;
 }
 
-// 1.6
-int UtcDaliAtlasUpload05(void)
+// Upload resource image, buffer image & pixel data which cannot fit into the atlas with given offset
+int UtcDaliAtlasUploadN(void)
 {
   TestApplication application;
 
-  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
   DALI_TEST_CHECK( atlas );
 
-  // Using invalid offsets
-  PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
-  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
-  DALI_TEST_CHECK( !atlas.Upload( image,  0, 17 ) );
-  DALI_TEST_CHECK( !atlas.Upload( image, 17,  0 ) );
-  DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) );
-  DALI_TEST_CHECK( !atlas.Upload( image, 99,  0 ) );
-  DALI_TEST_CHECK( !atlas.Upload( image,  0, 99 ) );
-  DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+  // Using image cannot fit into atlas at the given offsets
+  PixelBuffer* buffer = new PixelBuffer[24 * 24 * 4];
+  BufferImage image = BufferImage::New( buffer, 24, 24, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
 
   PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
-
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 17 ) );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17,  0 ) );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99,  0 ) );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 99 ) );
-  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 10, 10 ) );
+
+  PixelDataPtr pixelData = CreatePixelData( 6,6,Pixel::RGBA8888 );
+  DALI_TEST_CHECK( !atlas.Upload( pixelData, 11, 11 ) );
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  callStack.Reset();
+  callStack.Enable(true);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  callStack.Enable(false);
+
+  // none of these three upload() call sends texture to GPU
+  DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "0, 0, 24, 24") );
+  DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "10, 10, 16, 16") );
+  DALI_TEST_CHECK( ! callStack.FindMethodAndParams("TexSubImage2D", "11, 11, 6, 6") );
 
   END_TEST;
 }
 
+
+
+
diff --git a/automated-tests/src/dali-devel/utc-Dali-PixelData.cpp b/automated-tests/src/dali-devel/utc-Dali-PixelData.cpp
new file mode 100644 (file)
index 0000000..e22f41b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <cstdlib>
+#include <dali-test-suite-utils.h>
+
+#include <dali/devel-api/images/pixel-data.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/common/dali-vector.h>
+
+using namespace Dali;
+
+int UtcDaliPixelData01(void)
+{
+  TestApplication application;
+
+  unsigned int width = 10u;
+  unsigned int height = 10u;
+  unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::RGB888 );
+
+  unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( bufferSize ) );
+  PixelDataPtr pixelData = PixelData::New( buffer, width, height, Pixel::RGB888, PixelData::FREE );
+
+  DALI_TEST_CHECK( pixelData );
+  DALI_TEST_CHECK( pixelData->GetWidth() == width );
+  DALI_TEST_CHECK( pixelData->GetHeight() == height );
+  DALI_TEST_CHECK( pixelData->GetPixelFormat() == Pixel::RGB888 );
+  DALI_TEST_CHECK( pixelData->GetBuffer() == buffer );
+
+  END_TEST;
+}
+
+int UtcDaliPixelData02(void)
+{
+  TestApplication application;
+
+  unsigned int width = 10u;
+  unsigned int height = 10u;
+  unsigned int bufferSize = width*height*Pixel::GetBytesPerPixel( Pixel::L8 );
+  unsigned char* buffer = new unsigned char [ bufferSize ];
+  buffer[0] = 'a';
+
+  PixelDataPtr pixelData2 = PixelData::New( buffer, width, height, Pixel::L8, PixelData::DELETE_ARRAY );
+
+  DALI_TEST_CHECK( pixelData2 );
+  DALI_TEST_CHECK( pixelData2->GetBuffer()[0] == 'a' );
+
+  buffer[0] = 'b';
+  DALI_TEST_CHECK( pixelData2->GetBuffer()[0] == 'b' );
+
+  END_TEST;
+}
+
+int UtcDaliPixelDataNonCopyable(void)
+{
+  // we want to make sure that PixelData is not copyable (its copy constructor is not defined)
+  // this test will stop compiling if PixelData has compiler generated copy constructor
+  DALI_COMPILE_TIME_ASSERT( !__has_trivial_copy( PixelData ) );
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
index 6398a82..ae2b942 100644 (file)
@@ -60,6 +60,14 @@ AC_ARG_ENABLE([lock_backtrace],
               [enable_lock_backtrace=$enableval],
               [enable_lock_backtrace=no])
 
+AC_ARG_ENABLE([gles],
+              [AC_HELP_STRING([--enable-gles],
+                              [Specify the OpenGL ES version for backwards compatibility])],
+              [enable_gles=$enableval],
+              [enable_gles=20])
+
+DALI_CFLAGS="$DALI_CFLAGS -DDALI_GLES_VERSION=${enable_gles}"
+
 if test "x$enable_debug" = "xyes"; then
   DALI_CFLAGS="$DALI_CFLAGS -DDEBUG_ENABLED"
 fi
index 7528fe1..a277021 100644 (file)
@@ -7,6 +7,7 @@ devel_api_src_files = \
   $(devel_api_src_dir)/events/hit-test-algorithm.cpp \
   $(devel_api_src_dir)/images/atlas.cpp \
   $(devel_api_src_dir)/images/distance-field.cpp \
+  $(devel_api_src_dir)/images/pixel-data.cpp \
   $(devel_api_src_dir)/object/property-buffer.cpp \
   $(devel_api_src_dir)/object/weak-handle.cpp \
   $(devel_api_src_dir)/rendering/cull-face.cpp \
@@ -39,7 +40,8 @@ devel_api_core_events_header_files = \
 
 devel_api_core_images_header_files = \
   $(devel_api_src_dir)/images/atlas.h \
-  $(devel_api_src_dir)/images/distance-field.h
+  $(devel_api_src_dir)/images/distance-field.h \
+  $(devel_api_src_dir)/images/pixel-data.h
 
 devel_api_core_object_header_files = \
   $(devel_api_src_dir)/object/property-buffer.h \
index f7f96d1..cc0357b 100644 (file)
@@ -59,6 +59,13 @@ bool Atlas::Upload( const std::string& url,
   return GetImplementation(*this).Upload( url, xOffset, yOffset );
 }
 
+bool Atlas::Upload( PixelDataPtr pixelData,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  return GetImplementation(*this).Upload( pixelData, xOffset, yOffset );
+}
+
 Atlas Atlas::DownCast( BaseHandle handle )
 {
   return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
index 025b9ad..caa785d 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/images/image.h>
 #include <dali/public-api/images/buffer-image.h>
+#include <dali/devel-api/images/pixel-data.h>
 
 namespace Dali
 {
@@ -41,6 +42,9 @@ class Atlas;
  * Images must be uploaded at a specified position, to populate the Atlas.
  * The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas.
  *
+ * @note For gles 2.0, matched pixel format is demanded to ensure the correct atlasing.
+ *       The only exception supported is uploading image of RGB888 to atlas of RGBA8888 format which is converted manually before pushing to GPU.
+ *
  * For context recovery after loss:
  * By default, the atlas will re-upload the resource images automatically,
  * while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal().
@@ -113,6 +117,17 @@ public:
   bool Upload( const std::string& url,
                SizeType xOffset,
                SizeType yOffset );
+
+  /**
+   * @brief Upload a pixel buffer to atlas
+   *
+   * @param [in] pixelData      The pixel data.
+   * @param [in] xOffset        Specifies an offset in the x direction within the atlas.
+   * @param [in] yOffset        Specifies an offset in the y direction within the atlas.
+   */
+  bool Upload( PixelDataPtr pixelData,
+               SizeType xOffset,
+               SizeType yOffset );
   /**
    * @brief Downcast an Object handle to Atlas.
    *
diff --git a/dali/devel-api/images/pixel-data.cpp b/dali/devel-api/images/pixel-data.cpp
new file mode 100644 (file)
index 0000000..7b426ce
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "pixel-data.h"
+
+// EXTERNAL INLCUDES
+#include <stdlib.h>
+
+namespace Dali
+{
+
+PixelData::PixelData( unsigned char* buffer,
+                      unsigned int width,
+                      unsigned int height,
+                      Pixel::Format pixelFormat,
+                      ReleaseFunction releaseFunction )
+: mBuffer( buffer ),
+  mWidth( width ),
+  mHeight( height ),
+  mPixelFormat( pixelFormat ),
+  mReleaseFunction( releaseFunction )
+{
+}
+
+PixelData::~PixelData()
+{
+  if( mBuffer )
+  {
+    if( mReleaseFunction == FREE)
+    {
+      free( mBuffer );
+    }
+    else
+    {
+      delete[] mBuffer;
+    }
+  }
+ }
+
+PixelDataPtr PixelData::New(unsigned char* buffer,
+                            unsigned int width,
+                            unsigned int height,
+                            Pixel::Format pixelFormat,
+                            ReleaseFunction releaseFunction)
+{
+  return new PixelData( buffer, width, height, pixelFormat, releaseFunction );
+}
+
+unsigned int PixelData::GetWidth() const
+{
+  return mWidth;
+}
+
+unsigned int PixelData::GetHeight() const
+{
+  return mHeight;
+}
+
+Pixel::Format PixelData::GetPixelFormat() const
+{
+  return mPixelFormat;
+}
+
+unsigned char* PixelData::GetBuffer() const
+{
+  return mBuffer;
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/images/pixel-data.h b/dali/devel-api/images/pixel-data.h
new file mode 100644 (file)
index 0000000..0a8d349
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __DALI_PIXEL_DATA_H__
+#define __DALI_PIXEL_DATA_H__
+
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+class PixelData;
+typedef IntrusivePtr<PixelData> PixelDataPtr;
+
+/**
+ * @brief Reference counted pixel data .
+ *
+ * The PixelData takes over the ownership of the pixel buffer.
+ * The buffer memory must NOT be released outside of this class, instead, the PixelData object will release it automatically when the reference count falls to zero.
+ */
+class DALI_IMPORT_API PixelData : public RefObject
+{
+public:
+
+  enum ReleaseFunction
+  {
+    FREE,          ///< Use free function to release the pixel buffer
+    DELETE_ARRAY,  ///< Use delete[] operator to release the pixel buffer
+  };
+
+  /**
+   * @brief Create a PixelData object.
+   *
+   * @param [in] buffer         The raw pixel data.
+   * @param [in] width          Buffer width in pixels
+   * @param [in] height         Buffer height in pixels
+   * @param [in] pixelFormat    The pixel format
+   * @param [in] release        The function used to release the memory.
+   */
+  static PixelDataPtr New( unsigned char* buffer,
+                           unsigned int width,
+                           unsigned int height,
+                           Pixel::Format pixelFormat,
+                           ReleaseFunction releaseFunction);
+
+  /**
+   * Get the width of the buffer in pixels.
+   * @return The width of the buffer in pixels
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * Get the height of the buffer in pixels
+   * @return The height of the buffer in pixels
+   */
+  unsigned int GetHeight() const;
+
+  /**
+   * Get the pixel format
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const;
+
+  /**
+   * Get the pixel buffer if it's present.
+   * @return The buffer if exits, or NULL if there is no pixel buffer.
+   */
+  unsigned char* GetBuffer() const;
+
+public:
+
+  /**
+   * @brief Constructor.
+   *
+   * @param [in] buffer         The raw pixel data.
+   * @param [in] width          Buffer width in pixels
+   * @param [in] height         Buffer height in pixels
+   * @param [in] pixelFormat    The pixel format
+   * @param [in] release        The function used to release the memory.
+   */
+  PixelData( unsigned char* buffer,
+             unsigned int width,
+             unsigned int height,
+             Pixel::Format pixelFormat,
+             ReleaseFunction releaseFunction );
+
+  /**
+   * @brief Destructor.
+   *
+   * Release the pixel buffer if exists.
+   */
+  ~PixelData();
+
+
+private:
+
+  /*
+   * Undefined copy constructor.
+   */
+  PixelData(const PixelData& other);
+
+  /*
+   * Undefined assignment operator.
+   */
+  PixelData& operator = (const PixelData& other);
+
+private:
+
+  unsigned char* mBuffer;           ///< The raw pixel data.
+  unsigned int   mWidth;            ///< Buffer width in pixels.
+  unsigned int   mHeight;           ///< Buffer height in pixels.
+  Pixel::Format  mPixelFormat;      ///< Pixel format
+  ReleaseFunction mReleaseFunction;  ///< Function for releasing memory
+};
+
+
+} //namespace Dali
+
+#endif // __DALI_PIXEL_DATA_H__
index 56d58c5..6527067 100644 (file)
@@ -279,6 +279,13 @@ Bitmap::Bitmap( ResourcePolicy::Discardable discardable, Dali::Integration::Pixe
 {
 }
 
+PixelBuffer* Bitmap::GetBufferOwnership()
+{
+  PixelBuffer* buffer = mData;
+  mData = NULL;
+  return buffer;
+}
+
 void Bitmap::DiscardBuffer()
 {
   if( mDiscardable == ResourcePolicy::OWNED_DISCARD )
index a6a2523..7518fe9 100644 (file)
@@ -142,6 +142,13 @@ public:
   }
 
   /**
+   * Get the pixel buffer if it's present and take over the ownership.
+   * @note With this function called, the bitmap loses the ownership and is no longer responsible for the release of pixel buffer.
+   * @return The raw pointer pointing to the pixel buffer
+   */
+  PixelBuffer* GetBufferOwnership();
+
+  /**
    * Get the pixel buffer size in bytes
    * @return The buffer size in bytes.
    * @sa ReserveBuffer GetBuffer
index d84c3b5..8cc3163 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/public-api/object/type-registry.h>
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/images/bitmap-packed-pixel.h>
 #include <dali/internal/event/resources/resource-client.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/integration-api/platform-abstraction.h>
@@ -61,9 +62,7 @@ bool Atlas::Upload( BufferImage& bufferImage,
 {
   bool uploadSuccess( false );
 
-  if( Compatible(bufferImage.GetPixelFormat(),
-                 xOffset + bufferImage.GetWidth(),
-                 yOffset + bufferImage.GetHeight() ) )
+  if( IsInside( xOffset + bufferImage.GetWidth(),  yOffset + bufferImage.GetHeight() ) )
   {
     AllocateAtlas();
     ResourceId destId = GetResourceId();
@@ -86,7 +85,7 @@ bool Atlas::Upload( const std::string& url,
 
   Integration::BitmapPtr bitmap = LoadBitmap( url );
 
-  if( bitmap && Compatible(bitmap->GetPixelFormat(), xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
+  if( bitmap && IsInside( xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
   {
     AllocateAtlas();
     ResourceId destId = GetResourceId();
@@ -104,6 +103,26 @@ bool Atlas::Upload( const std::string& url,
   return uploadSuccess;
 }
 
+bool Atlas::Upload( PixelDataPtr pixelData,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  bool uploadSuccess( false );
+  if( IsInside( xOffset + pixelData->GetWidth(),  yOffset + pixelData->GetHeight() ) )
+  {
+    AllocateAtlas();
+    ResourceId destId = GetResourceId();
+
+    if( destId )
+    {
+      mResourceClient.UploadBitmap( destId, pixelData, xOffset, yOffset  );
+      uploadSuccess = true;
+    }
+  }
+
+  return uploadSuccess;
+}
+
 void Atlas::RecoverFromContextLoss()
 {
   ResourceId destId = GetResourceId();
@@ -171,29 +190,20 @@ void Atlas::Disconnect()
   }
 }
 
-bool Atlas::Compatible( Pixel::Format pixelFormat,
-                        SizeType x,
-                        SizeType y )
+bool Atlas::IsInside( SizeType x, SizeType y )
 {
-  bool Compatible(false);
+  bool fit(false);
 
-  if( mPixelFormat != pixelFormat )
+  if( x <= mWidth  && y <= mHeight )
   {
-    DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", pixelFormat, mPixelFormat );
+    fit = true;
   }
   else
   {
-    if( x <= mWidth  && y <= mHeight )
-    {
-      Compatible = true;
-    }
-    else
-    {
-      DALI_LOG_ERROR( "image does not fit within the atlas \n" );
-    }
+    DALI_LOG_ERROR( "image does not fit within the atlas \n" );
   }
 
-  return Compatible;
+  return fit;
 }
 
 void Atlas::AllocateAtlas()
@@ -256,12 +266,10 @@ void Atlas::ClearBackground(const Vector4& color )
       }
     }
 
-    RectArea area;
-    imageData->Update(area);
-
     mClearColor = color;
     mClear = true;
-    mResourceClient.UploadBitmap( destId, imageData->GetResourceId(), 0, 0 );
+
+    imageData->UploadBitmap( destId, 0, 0 );
   }
 }
 
index ae767f3..68caeb3 100644 (file)
@@ -64,20 +64,27 @@ public:
   void Clear( const Vector4& color  );
 
   /**
-   * @copydoc Dali::Atlas::Upload( const BufferImage&, unsigned int, unsigned int )
+   * @copydoc Dali::Atlas::Upload( const BufferImage&, uint32_t, uint32_t )
    */
   bool Upload( BufferImage& bufferImage,
                SizeType xOffset,
                SizeType yOffset );
 
   /**
-   * @copydoc Dali::Atlas::Upload( const std::string&, unsigned int, unsigned int )
+   * @copydoc Dali::Atlas::Upload( const std::string&, uint32_t, uint32_t )
    */
   bool Upload( const std::string& url,
                SizeType xOffset,
                SizeType yOffset );
 
   /**
+   * @copydoc Dali::Atlas::Upload( Dali::Atlas::PixelDataPtr, uint32_t )
+   */
+  bool Upload( PixelDataPtr pixelData,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
    * @copydoc ContextRecoveryInterface::RecoverFromContextLoss
    */
   virtual void RecoverFromContextLoss();
@@ -118,11 +125,10 @@ private:
 
   /**
    * Helper for Upload methods
-   * @return True if the bitmap has the same pixel format and its size fits within the atlas at the specified offset
+   * @return True if the size of the bitmap fits within the atlas at the specified offset
    */
-  bool Compatible( Pixel::Format pixelFormat,
-                   SizeType x,
-                   SizeType y );
+  bool IsInside( SizeType x, SizeType y );
+
   /**
    * Helper to create the Atlas resource
    */
index 3b68bcf..2d4f2f1 100644 (file)
@@ -347,6 +347,16 @@ void ResourceClient::UploadBitmap( ResourceId destId,Integration::BitmapPtr bitm
                               yOffset );
 }
 
+void ResourceClient::UploadBitmap( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset)
+{
+  RequestUploadBitmapMessage( mEventThreadServices,
+                              mResourceManager,
+                              destId,
+                              pixelData,
+                              xOffset,
+                              yOffset );
+}
+
 void ResourceClient::CreateGlTexture( ResourceId id )
 {
   RequestCreateGlTextureMessage( mEventThreadServices, mResourceManager, id );
index 57a00bb..1037d68 100644 (file)
@@ -23,8 +23,9 @@
 
 // INTERNAL INCLUDES
 #include <dali/public-api/images/frame-buffer-image.h>
-#include <dali/devel-api/common/ref-counted-dali-vector.h>
 #include <dali/public-api/images/native-image-interface.h>
+#include <dali/devel-api/common/ref-counted-dali-vector.h>
+#include <dali/devel-api/images/pixel-data.h>
 #include <dali/internal/event/resources/resource-client-declarations.h>
 #include <dali/internal/event/resources/image-ticket.h>
 #include <dali/internal/event/resources/resource-ticket-lifetime-observer.h>
@@ -205,6 +206,15 @@ public:
   void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
 
   /**
+   * Upload a pixel buffer to a texture
+   * @param[in] destId The destination texture ID
+   * @param[in] bitmap The pointer pointing to the pixel data
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UploadBitmap( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset);
+
+  /**
    * @brief Trigger asynchronous creation of GL texture to back resource immediately.
    * @param[in] id The resource ID to allocate a GL texture for.
    */
index 6ef3c22..d2e6842 100644 (file)
 #include <stdint.h>
 
 // INTERNAL INCLUDES
-#include <dali/public-api/images/native-image-interface.h>
 #include <dali/public-api/images/buffer-image.h>
-#include <dali/public-api/images/pixel.h>
 #include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/devel-api/images/pixel-data.h>
 #include <dali/internal/common/message.h>
 #include <dali/internal/update/common/scene-graph-buffers.h>
 #include <dali/integration-api/resource-declarations.h>
@@ -154,6 +155,16 @@ public:
   virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset ) = 0;
 
   /**
+   * Dispatch a message to update the part of a texture with the pixel data.
+   * May be called from Update thread
+   * @param[in] destId The ID of the texture to update
+   * @param[in] pixelData The pointer pointing to the pixel data to upload.
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+  /**
    * Dispatch a message to update the texture area
    * May be called from the Update thread
    * @param[in] id Resource Id of the texture
index 9432bd4..be7421a 100644 (file)
 #include <dali/internal/render/gl-resources/bitmap-texture.h>
 
 // INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
 #include <dali/integration-api/debug.h>
 #include <dali/internal/render/common/vertex.h>
 #include <dali/internal/render/common/performance-monitor.h>
 #include <dali/internal/render/gl-resources/context.h>
 #include <dali/internal/render/gl-resources/texture-units.h>
 
+
 namespace Dali
 {
 
@@ -238,34 +240,82 @@ void BitmapTexture::Update( Integration::Bitmap* srcBitmap, std::size_t xOffset,
 {
   if( NULL != srcBitmap )
   {
-    GLenum pixelFormat   = GL_RGBA;
-    GLenum pixelDataType = GL_UNSIGNED_BYTE;
-    Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelFormat );
+    Update( srcBitmap->GetBuffer(), srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
+            srcBitmap->GetPixelFormat(), xOffset, yOffset);
+  }
+}
 
-    if( !mId )
-    {
-      mContext.GenTextures( 1, &mId );
+void BitmapTexture::Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset )
+{
+  if( NULL != srcPixelData )
+  {
+    Update( srcPixelData->GetBuffer(), srcPixelData->GetWidth(), srcPixelData->GetHeight(),
+            srcPixelData->GetPixelFormat(), xOffset, yOffset);
+  }
+}
 
-      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
-      mContext.Bind2dTexture( mId );
-      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+void BitmapTexture::Update( const unsigned char* pixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat, std::size_t xOffset, std::size_t yOffset )
+{
 
-      mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL );
-      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-    }
-    else
+  GLenum pixelGLFormat   = GL_RGBA;
+  GLenum pixelDataType = GL_UNSIGNED_BYTE;
+  Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelGLFormat );
+
+  if( !mId )
+  {
+    mContext.GenTextures( 1, &mId );
+
+    mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+    mContext.Bind2dTexture( mId );
+    mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+    mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelGLFormat, mWidth, mHeight, 0, pixelGLFormat, pixelDataType, NULL );
+    mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+  }
+  else
+  {
+    mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+    mContext.Bind2dTexture( mId );
+    mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+  }
+
+#if DALI_GLES_VERSION >= 30
+// for gles 3.0, uploading sub-image with different format is a valid operation
+  Integration::ConvertToGlFormat( srcBitmap->GetPixelFormat(), pixelDataType, pixelGLFormat );
+#else
+  // allows RGB888 source bitmap to be added to RGBA8888 texture, need to convert the bitmap format manually
+  if(pixelFormat == Pixel::RGB888 && mPixelFormat == Pixel::RGBA8888 )
+  {
+    std::size_t size = width * height;
+
+    Vector<PixelBuffer> tempBuffer;
+    tempBuffer.Reserve( size*4u );
+    PixelBuffer* data = tempBuffer.Begin();
+
+    for( std::size_t i=0u; i<size; i++ )
     {
-      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
-      mContext.Bind2dTexture( mId );
-      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+      data[i*4u] = pixels[i*3u];
+      data[i*4u+1] = pixels[i*3u+1];
+      data[i*4u+2] = pixels[i*3u+2];
+      data[i*4u+3] = 0xFF;
     }
 
     mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
                             xOffset, yOffset,
-                            srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
-                            pixelFormat, pixelDataType, srcBitmap->GetBuffer() );
+                            width, height,
+                            pixelGLFormat, pixelDataType,
+                            data );
+
+    return;
   }
+#endif
+
+  mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
+                          xOffset, yOffset,
+                          width, height,
+                          pixelGLFormat, pixelDataType,
+                          pixels );
 }
 
 void BitmapTexture::UpdateArea( const RectArea& updateArea )
index 2bcf6c3..c76a082 100644 (file)
@@ -122,6 +122,14 @@ public:
   virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset );
 
   /**
+   * Update part of the texture with a pixel buffer
+   * @param[in] srcPixelData The pixel data to copy from
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Bitmap area has been modified - update the texture appropriately.
    * @pre The bitmap hasn't been discarded (should be external type)
    * @param[in] area The updated area
@@ -163,6 +171,17 @@ private:
    */
   void DiscardBitmapBuffer();
 
+  /**
+   * Update part of the texture.
+   * @param [in] pixels The pixel buffer.
+   * @param [in] width  The buffer width in pixels
+   * @param [in] height The buffer height in pixels
+   * @param [in] pixelFormat The pixel format
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void Update( const unsigned char* pixels, std::size_t width, std::size_t height, Pixel::Format pixelFormat, std::size_t xOffset, std::size_t yOffset );
+
 private:
   Integration::BitmapPtr      mBitmap;          ///< The Bitmap the Texture was created from (may be NULL)
   bool                        mClearPixels:1;   ///< true if initial texture should be cleared on creation
index d11fac0..a735e99 100644 (file)
@@ -202,6 +202,24 @@ void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size
   }
 }
 
+void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
+
+  TextureIter textureIter = mTextures.find(id);
+  if( textureIter != mTextures.end() )
+  {
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->Update( pixelData.Get(), xOffset, yOffset );
+
+      ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+      mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+    }
+  }
+}
+
 void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
@@ -570,6 +588,21 @@ void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, s
   }
 }
 
+void TextureCache::DispatchUpdateTexture( ResourceId id, PixelDataPtr pixelData , std::size_t xOffset, std::size_t yOffset)
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue4< TextureCache, ResourceId, PixelDataPtr, std::size_t, std::size_t > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, pixelData, xOffset, yOffset );
+  }
+}
+
 void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
 {
   // NULL, means being shutdown, so ignore msgs
index 3165359..a2d5468 100644 (file)
@@ -164,6 +164,15 @@ public:
   void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
   /**
+   * Update the texture with a pixel buffer
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] pixelData The pixel data
+   * @param[in] xOffset Specifies an offset in the x direction within the texture
+   * @param[in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Update the area of the texture from the associated bitmap
    * @param[in] id Resource Id of the bitmap
    * @param[in] area The area of the bitmap that has changed
@@ -297,6 +306,11 @@ protected: // Implements TextureCacheDispatcher
   virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
   /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
+  virtual void DispatchUpdateTexture( ResourceId destId, PixelDataPtr srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * @copydoc TextureCacheDispatcher::DispatchUpdateTextureArea()
    */
   virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area );
index f356bd2..090f3f0 100644 (file)
  */
 
 // INTERNAL INCLUDES
+#include <dali/public-api/actors/sampling.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/native-image.h>
+#include <dali/public-api/math/rect.h>
 #include <dali/public-api/object/ref-object.h>
+#include <dali/devel-api/images/pixel-data.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/internal/render/common/uv-rect.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/internal/render/gl-resources/gl-resource-owner.h>
 #include <dali/internal/render/gl-resources/texture-units.h>
-#include <dali/public-api/images/image.h>
-#include <dali/public-api/images/pixel.h>
-#include <dali/public-api/images/native-image.h>
-#include <dali/public-api/math/rect.h>
-#include <dali/public-api/actors/sampling.h>
+
 
 namespace Dali
 {
@@ -87,6 +89,14 @@ public:
   virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset ) {}
 
   /**
+   * Update part of the texture with a pixel buffer
+   * @param[in] srcPixelData The pixel data to copy from
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void Update( PixelData* srcPixelData, std::size_t xOffset, std::size_t yOffset ) {}
+
+  /**
    * @return Return true if the texture should be updated on GL texture creation.
    */
   virtual bool UpdateOnCreate();
index 2d6a140..dc777ca 100644 (file)
@@ -349,6 +349,14 @@ void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId s
   }
 }
 
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
+{
+  if( destId && pixelData )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, pixelData, xOffset, yOffset );
+  }
+}
+
 void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
 {
   DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
index 8a28390..24421b2 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/public-api/images/native-image-interface.h>
 #include <dali/public-api/images/buffer-image.h>
 #include <dali/devel-api/common/ref-counted-dali-vector.h>
+#include <dali/devel-api/images/pixel-data.h>
 
 #include <dali/integration-api/bitmap.h>
 #include <dali/integration-api/platform-abstraction.h>
@@ -264,6 +265,15 @@ public: // Used by ResourceClient
   void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
   /**
+   * Upload a pixel buffer to a position within a specified texture
+   * @param[in] destId The destination texture ID
+   * @param[in] pixelData pointer pointing to the pixel data to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void HandleUploadBitmapRequest( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Request reloading a resource from the native filesystem.
    * @param[in] id The resource id
    * @param[in] typePath The type & path of the resource
@@ -524,6 +534,22 @@ inline void RequestUploadBitmapMessage( EventThreadServices& eventThreadServices
   new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, srcId, xOffset, yOffset );
 }
 
+inline void RequestUploadBitmapMessage(EventThreadServices& eventThreadServices,
+                                       ResourceManager& manager,
+                                       ResourceId destId,
+                                       PixelDataPtr pixelData,
+                                       std::size_t xOffset,
+                                       std::size_t yOffset)
+{
+  typedef MessageValue4< ResourceManager, ResourceId, PixelDataPtr , std::size_t, std::size_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, pixelData, xOffset, yOffset );
+}
+
 inline void RequestReloadResourceMessage( EventThreadServices& eventThreadServices,
                                           ResourceManager& manager,
                                           ResourceId id,