Updates to handle context loss and regain 69/27369/18
authorDavid Steele <david.steele@partner.samsung.com>
Wed, 10 Sep 2014 17:59:50 +0000 (18:59 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Wed, 5 Nov 2014 11:39:25 +0000 (11:39 +0000)
[Problem]  Dali doesn't handle context loss
[Cause]    Context loss code, e.g. ReplaceSurface(), has never been tested,
but is required for new platforms.

[Solution] Allow the application to choose either to handle context
loss itself (i.e.  it should connect to the new stage signals
ContextLost and ContextRegained), or to let Dali handle context loss
( which means it needs to retain bitmap data and mesh data, adding a
memory overhead )

For Tizen, if the application doesn't handle context loss, DALi only
actually needs to retain the mesh data, as it can reload bitmaps from
file based images (No other bitmap type is discardable).

It also triggers a reload of the font atlas, although that should be
relatively quick, as the glyphs have already been cached, so it should
be as quick as resizing texture atlas.

It also triggers a refresh of all render tasks with framebuffers and RefreshOnce.

For controls and applications that delete their render tasks after they have finished
rendering, they will need to listen for ContextRegained in order to re-run them to
recreate the resultant framebuffer.

Added tests for mesh data discard using public meshes and meshes loaded via model.

Change-Id: I0d89f0dee2dfcf79fcabce19c36ac129de077fa8
Signed-off-by: David Steele <david.steele@partner.samsung.com>
75 files changed:
automated-tests/src/dali-internal/CMakeLists.txt
automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp
automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp
automated-tests/src/dali-internal/utc-Dali-Internal-Material.cpp
automated-tests/src/dali-internal/utc-Dali-Internal-Mesh.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp
automated-tests/src/dali-unmanaged/dali-test-suite-utils/test-platform-abstraction.cpp
automated-tests/src/dali-unmanaged/dali-test-suite-utils/test-platform-abstraction.h
automated-tests/src/dali-unmanaged/utc-Dali-NinePatchImages.cpp
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali/dali-test-suite-utils/test-application.h
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp
automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h
automated-tests/src/dali/utc-Dali-Image.cpp
automated-tests/src/dali/utc-Dali-ImageActor.cpp
automated-tests/src/dali/utc-Dali-Material.cpp
automated-tests/src/dali/utc-Dali-RenderTask.cpp
automated-tests/src/dali/utc-Dali-Stage.cpp
dali/integration-api/bitmap.cpp
dali/integration-api/bitmap.h
dali/integration-api/context-notifier.h [new file with mode: 0644]
dali/integration-api/core.cpp
dali/integration-api/core.h
dali/integration-api/file.list
dali/integration-api/platform-abstraction.h
dali/integration-api/resource-policies.h [new file with mode: 0644]
dali/internal/common/core-impl.cpp
dali/internal/common/core-impl.h
dali/internal/event/common/stage-impl.cpp
dali/internal/event/common/stage-impl.h
dali/internal/event/images/bitmap-compressed.cpp
dali/internal/event/images/bitmap-compressed.h
dali/internal/event/images/bitmap-external.cpp
dali/internal/event/images/bitmap-packed-pixel.cpp
dali/internal/event/images/bitmap-packed-pixel.h
dali/internal/event/images/image-factory.cpp
dali/internal/event/images/image-factory.h
dali/internal/event/modeling/mesh-impl.cpp
dali/internal/event/modeling/model-data-impl.cpp
dali/internal/event/render-tasks/render-task-list-impl.cpp
dali/internal/event/render-tasks/render-task-list-impl.h
dali/internal/event/resources/resource-client.cpp
dali/internal/event/resources/resource-client.h
dali/internal/event/text/atlas/glyph-atlas-manager.cpp
dali/internal/event/text/atlas/glyph-atlas-manager.h
dali/internal/event/text/font-factory.cpp
dali/internal/event/text/font-factory.h
dali/internal/event/text/font-impl.cpp
dali/internal/render/common/render-manager.cpp
dali/internal/render/gl-resources/bitmap-texture.cpp
dali/internal/render/gl-resources/bitmap-texture.h
dali/internal/render/gl-resources/compressed-bitmap-texture.cpp
dali/internal/render/gl-resources/compressed-bitmap-texture.h
dali/internal/render/gl-resources/context.cpp
dali/internal/render/gl-resources/context.h
dali/internal/render/gl-resources/texture-cache.cpp
dali/internal/render/gl-resources/texture-cache.h
dali/internal/render/gl-resources/texture-factory.cpp
dali/internal/render/gl-resources/texture-factory.h
dali/internal/render/gl-resources/texture.cpp
dali/internal/render/gl-resources/texture.h
dali/internal/render/renderers/scene-graph-image-renderer.cpp
dali/internal/render/shaders/program.cpp
dali/internal/render/shaders/program.h
dali/internal/render/shaders/shader.cpp
dali/internal/update/modeling/internal-mesh-data.cpp
dali/internal/update/modeling/internal-mesh-data.h
dali/internal/update/modeling/scene-graph-mesh.cpp
dali/internal/update/modeling/scene-graph-mesh.h
dali/internal/update/node-attachments/scene-graph-image-attachment.cpp
dali/internal/update/resources/resource-manager.cpp
dali/internal/update/resources/resource-manager.h
dali/public-api/common/stage.cpp
dali/public-api/common/stage.h

index 39598b8..c41360e 100644 (file)
@@ -11,6 +11,7 @@ SET(TC_SOURCES
         utc-Dali-Internal-Handles.cpp
         utc-Dali-Internal-ImageFactory.cpp
         utc-Dali-Internal-Material.cpp
+        utc-Dali-Internal-Mesh.cpp
         utc-Dali-Internal-Text.cpp
         utc-Dali-Internal-ResourceClient.cpp
         utc-Dali-Internal-Image-Culling.cpp
index 95edd19..8945a75 100644 (file)
@@ -65,7 +65,7 @@ Image LoadImage( TestApplication& application, GLuint textureId, int width, int
   ids.push_back( textureId );
   application.GetGlAbstraction().SetNextTextureIds( ids );
 
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, width, height, width, height);
   DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
index 93648bf..59bc9ad 100644 (file)
@@ -42,7 +42,7 @@ static void EmulateImageLoaded( TestApplication& application, unsigned int width
 {
   // emulate load success
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  true  );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource( bitmap );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, width, height, width, height );
   if( request )
index 01190b5..f0446fd 100644 (file)
@@ -184,7 +184,7 @@ Internal::ResourceTicketPtr CheckLoadBitmap(TestApplication& application, const
   application.SendNotification(); // Flush update messages
   application.Render();           // Process resource request
   Integration::ResourceRequest*   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, w, h, w, h );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
   application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
@@ -206,7 +206,7 @@ Internal::ImagePtr LoadImage(TestApplication& application, const char* name)
   application.SendNotification(); // Flush update messages
   application.Render();           // Process resource request
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80,80,80,80 );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
 
@@ -338,7 +338,7 @@ int UtcDaliMaterialUnreadyTextureOffstage(void)
   DALI_TEST_CHECK( textureId == textureId2 );
 
   Integration::ResourceRequest*   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
   application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
@@ -569,7 +569,7 @@ int UtcDaliMaterialSetUnreadyTextureWhilstStaged(void)
   DALI_TEST_EQUALS( boundTextures.GetNumBoundTextures(), 0u, TEST_LOCATION );
 
   Integration::ResourceRequest*   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
   application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Mesh.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Mesh.cpp
new file mode 100644 (file)
index 0000000..637f2f1
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2014 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 <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/update/modeling/scene-graph-mesh.h>
+
+using namespace Dali;
+#include "mesh-builder.h"
+
+void utc_dali_mesh_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_mesh_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+unsigned int GetNextResourceId(TestApplication& application)
+{
+  // Attempt to determine what the next resource ID will be
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ResourceTicketPtr resourceTicket = resourceClient.AllocateTexture( 80, 80, Pixel::RGBA8888 );
+  unsigned int nextResourceId = resourceTicket->GetId();
+  nextResourceId++;
+
+  // Clear allocation request through the system
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  return nextResourceId;
+}
+
+Mesh CreateMesh( TestApplication& application )
+{
+  Dali::MeshData publicMeshData;
+  {
+    MeshData::VertexContainer    publicVertices;
+    MeshData::FaceIndices        publicFaces;
+    BoneContainer                bones;
+    ConstructVertices(publicVertices, 60);
+    ConstructFaces(publicVertices, publicFaces);
+    Dali::Material material  = ConstructMaterial();
+    publicMeshData.SetData(publicVertices, publicFaces, bones, material);
+  }
+  Mesh publicMesh = Mesh::New(publicMeshData); // Will generate new request
+
+  application.SendNotification();
+  application.Render(); // Should allocate mesh, pass ownership to ResourceManager
+  application.SendNotification();
+  return publicMesh;
+}
+
+Model CreateModel(TestApplication& application)
+{
+  TestPlatformAbstraction& platform = application.GetPlatform();
+
+  // Raise a request
+  Model model = Model::New("Tree");
+
+  application.SendNotification();
+  application.Render();
+
+  Dali::ModelData modelData = BuildTreeModel();
+  Integration::ResourceRequest* request = platform.GetRequest(); // Return modelData
+  if(request)
+  {
+    platform.SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(&(modelData.GetBaseObject())));
+  }
+  application.Render();           // This will perform the GetResources() to get the model data
+  application.SendNotification(); // This will handle model loaded (triggering mesh allocation)
+  application.Render();           // This will allocate meshes in update manager
+  application.SendNotification();
+
+  return model;
+}
+
+
+Internal::MeshData& GetStagedMeshData( unsigned int resourceId )
+{
+    // ResourceManager::GetMesh() will give us the scene graph mesh from resource id
+  Internal::ResourceManager& resourceManager  = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Internal::SceneGraph::Mesh* internalMesh = resourceManager.GetMesh(resourceId);
+  DALI_TEST_CHECK( internalMesh != NULL );
+  return internalMesh->GetMeshData(Internal::SceneGraph::Mesh::UPDATE_THREAD);
+}
+
+
+void TestMeshDiscard( ResourcePolicy::DataRetention policy, bool expectedDiscardResult )
+{
+  TestApplication application( TestApplication::DEFAULT_SURFACE_WIDTH,
+                               TestApplication::DEFAULT_SURFACE_HEIGHT,
+                               TestApplication::DEFAULT_HORIZONTAL_DPI,
+                               TestApplication::DEFAULT_VERTICAL_DPI,
+                               policy );
+
+  // run through startup, clearing all requests/messages
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  unsigned int nextResourceId = GetNextResourceId(application);
+  Mesh publicMesh = CreateMesh(application);
+  Internal::MeshData& meshData = GetStagedMeshData(nextResourceId);
+
+  // Check that the vertex data is allocated
+  const Internal::MeshData::VertexContainer& internalVertices = meshData.GetVertices();
+  const Internal::MeshData::FaceIndices& internalFaces = meshData.GetFaces();
+  DALI_TEST_CHECK( meshData.GetVertexCount() > 0 );
+  DALI_TEST_CHECK( meshData.GetFaceCount() > 0 );
+  DALI_TEST_CHECK( internalVertices.size() > 0 );
+  DALI_TEST_CHECK( internalFaces.size() > 0 );
+
+  // Create an actor that will render the mesh
+  MeshActor actor = MeshActor::New( publicMesh );
+  std::string name = "AMeshActor";
+  actor.SetName(name);
+  actor.SetAffectedByLighting(false);
+  Stage::GetCurrent().Add(actor);
+
+  // render it
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  // Check that the vertex data has been discarded
+  DALI_TEST_CHECK( meshData.GetVertexCount() > 0 );
+  DALI_TEST_CHECK( meshData.GetFaceCount() > 0 );
+  if( expectedDiscardResult == false )
+  {
+    DALI_TEST_CHECK( internalVertices.size() > 0 );
+    DALI_TEST_CHECK( internalFaces.size() > 0 );
+  }
+  else
+  {
+    DALI_TEST_CHECK( internalVertices.size() == 0 );
+    DALI_TEST_CHECK( internalFaces.size() == 0 );
+  }
+}
+
+
+
+void TestModelDiscard( ResourcePolicy::DataRetention policy, bool expectedDiscardResult )
+{
+  TestApplication application( TestApplication::DEFAULT_SURFACE_WIDTH,
+                               TestApplication::DEFAULT_SURFACE_HEIGHT,
+                               TestApplication::DEFAULT_HORIZONTAL_DPI,
+                               TestApplication::DEFAULT_VERTICAL_DPI,
+                               policy );
+
+  // run through startup, clearing all requests/messages
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  unsigned int nextResourceId = GetNextResourceId(application);
+  Model model = CreateModel(application);
+
+  // 2 resource id's should be generated, 1st for the model, 2nd for the only mesh
+  Internal::MeshData& meshData = GetStagedMeshData(nextResourceId+1);
+
+  // Check that the vertex data is allocated
+  const Internal::MeshData::VertexContainer& internalVertices = meshData.GetVertices();
+  const Internal::MeshData::FaceIndices& internalFaces = meshData.GetFaces();
+  DALI_TEST_CHECK( meshData.GetVertexCount() > 0 );
+  DALI_TEST_CHECK( meshData.GetFaceCount() > 0 );
+  DALI_TEST_CHECK( internalVertices.size() > 0 );
+  DALI_TEST_CHECK( internalFaces.size() > 0 );
+
+  // Create an actor that will render the mesh
+  Actor actor = ModelActorFactory::BuildActorTree(model, ""); // model should be loaded
+  Light light = Light::New("KeyLight");
+  light.SetFallOff(Vector2(10000.0f, 10000.0f));
+  LightActor keyLightActor = LightActor::New();
+  keyLightActor.SetParentOrigin(ParentOrigin::CENTER);
+  keyLightActor.SetPosition(200.0f, 500.0f, 300.0f);
+  keyLightActor.SetName(light.GetName());
+  keyLightActor.SetLight(light);
+  keyLightActor.SetActive(true);
+  Stage::GetCurrent().Add(keyLightActor);
+  Stage::GetCurrent().Add(actor);
+
+  // render it
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  // Check that the vertex data has been discarded
+  DALI_TEST_CHECK( meshData.GetVertexCount() > 0 );
+  DALI_TEST_CHECK( meshData.GetFaceCount() > 0 );
+  if( expectedDiscardResult == false )
+  {
+    DALI_TEST_CHECK( internalVertices.size() > 0 );
+    DALI_TEST_CHECK( internalFaces.size() > 0 );
+  }
+  else
+  {
+    DALI_TEST_CHECK( internalVertices.size() == 0 );
+    DALI_TEST_CHECK( internalFaces.size() == 0 );
+  }
+}
+
+
+} // anon namespace
+
+
+int utcDaliInternalMeshDiscard01(void)
+{
+  tet_infoline("Test that internal mesh data is discarded after rendering with policy=DISCARD_ALL");
+  TestMeshDiscard( ResourcePolicy::DALI_DISCARDS_ALL_DATA, true /* Not discarded */);
+  END_TEST;
+}
+
+int utcDaliInternalMeshDiscard02(void)
+{
+  tet_infoline("Test that internal mesh data is not discarded after rendering with policy=RETAIN_ALL");
+  TestMeshDiscard( ResourcePolicy::DALI_RETAINS_ALL_DATA, false /* Not discarded */);
+  END_TEST;
+}
+
+int utcDaliInternalMeshDiscard03(void)
+{
+  tet_infoline("Test that internal mesh data is not discarded after rendering with policy=RETAIN_MESH");
+  TestMeshDiscard( ResourcePolicy::DALI_RETAINS_MESH_DATA, false /* Not discarded */);
+  END_TEST;
+}
+
+int utcDaliInternalModelDiscard01(void)
+{
+  tet_infoline("Test that model's internal mesh data is discarded after rendering with policy=DISCARD_ALL");
+  TestModelDiscard( ResourcePolicy::DALI_DISCARDS_ALL_DATA, true /* Not discarded */);
+  END_TEST;
+}
+
+int utcDaliInternalModelDiscard02(void)
+{
+  tet_infoline("Test that model's internal mesh data is not discarded after rendering with policy=RETAIN_ALL");
+  TestModelDiscard( ResourcePolicy::DALI_RETAINS_ALL_DATA, false /* Not discarded */);
+  END_TEST;
+}
+
+int utcDaliInternalModelDiscard03(void)
+{
+  tet_infoline("Test that model's internal mesh data is not discarded after rendering with policy=RETAIN_MESH");
+  TestModelDiscard( ResourcePolicy::DALI_RETAINS_MESH_DATA, false /* Not discarded */);
+  END_TEST;
+}
index c93981c..0fb9244 100644 (file)
@@ -121,7 +121,7 @@ Internal::ImagePtr LoadImage(TestApplication& application, char* name)
   application.SendNotification(); // Flush update messages
   application.Render();           // Process resource request
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80,80,80,80 );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
   application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
@@ -144,7 +144,7 @@ Internal::ResourceTicketPtr CheckLoadBitmap(TestApplication& application, const
   application.SendNotification(); // Flush update messages
   application.Render();           // Process resource request
   Integration::ResourceRequest*   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, w, h, w, h );
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
   application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
@@ -234,7 +234,7 @@ int UtcDaliInternalRequestResourceBitmapRequests01(void)
 
     // Create a resource
     Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
     bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
     Integration::ResourcePointer resourcePtr(bitmap); // reference it
 
@@ -449,7 +449,7 @@ int UtcDaliInternalRequestReloadBitmapRequests01(void)
 
     // Create a new resource - the image size could have changed in the meantime
     Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
     bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 );
     Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
     DALI_TEST_CHECK( req->GetId() == ticket->GetId() );
@@ -548,7 +548,7 @@ int UtcDaliInternalRequestReloadBitmapRequests02(void)
     DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
     // Create a resource
     Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
     bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
     Integration::ResourcePointer resourcePtr(bitmap); // reference it
 
@@ -658,7 +658,7 @@ int UtcDaliInternalRequestReloadBitmapRequests03(void)
 
     // Create a resource
     Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
     bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
     Integration::ResourcePointer resourcePtr(bitmap); // reference it
 
@@ -702,7 +702,7 @@ int UtcDaliInternalRequestReloadBitmapRequests03(void)
 
     // Create a new resource - the image size could have changed in the meantime
     req = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
     bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 );
     Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
     DALI_TEST_CHECK( req->GetId() == id );
@@ -1119,7 +1119,7 @@ int UtcDaliInternalAddBitmapImage01(void)
   tet_infoline("Testing AddBitmap with reserved buffer()");
   testTicketObserver.Reset();
   Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  false  );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::RETAIN  );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGB565, 80, 80, 80, 80 );
 
   Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
@@ -1158,7 +1158,7 @@ int UtcDaliInternalAddBitmapImage02(void)
   tet_infoline("Testing AddBitmap without reserved buffer()");
   testTicketObserver.Reset();
   Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  false  );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::RETAIN  );
 
   Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
   DALI_TEST_CHECK( imageTicket );
@@ -1225,7 +1225,7 @@ int UtcDaliInternalGetBitmapImage01(void)
   testTicketObserver.Reset();
 
   Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  false  );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::RETAIN  );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 20, 20, 80, 80 );
   Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
 
@@ -1404,7 +1404,7 @@ int UtcDaliInternalAllocateMesh01(void)
 
   testTicketObserver.Reset();
   Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
-  Internal::OwnerPointer<Internal::MeshData> meshDataPtr( new Internal::MeshData( publicMeshData, true, true ) );
+  Internal::OwnerPointer<Internal::MeshData> meshDataPtr( new Internal::MeshData( publicMeshData, ResourcePolicy::DISCARD, true ) );
   Internal::ResourceTicketPtr meshTicket = resourceClient.AllocateMesh(meshDataPtr);
   DALI_TEST_CHECK( meshTicket );
   meshTicket->AddObserver( testTicketObserver );
index 22b0466..d5f24ab 100644 (file)
@@ -217,7 +217,7 @@ Integration::GlyphSet* TestPlatformAbstraction::GetGlyphData ( const Integration
 
       if( getBitmap )
       {
-        bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true);
+        bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD);
         bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64);
         PixelBuffer* pixelBuffer = bitmapData->GetBuffer();
         memset( pixelBuffer, it->character, 64*64 );
@@ -258,7 +258,7 @@ Integration::GlyphSet* TestPlatformAbstraction::GetCachedGlyphData( const Integr
       characters.insert( it->character );
       Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::HIGH_QUALITY,  10.0f,  10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition };
 
-      bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true);
+      bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD);
       bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64);
       PixelBuffer* pixelBuffer = bitmapData->GetBuffer();
       memset( pixelBuffer, it->character, 64*64 );
@@ -447,7 +447,7 @@ void TestPlatformAbstraction::GetFileNamesFromDirectory( const std::string& dire
 
 Integration::BitmapPtr TestPlatformAbstraction::GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const
 {
-  Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   image->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 1, 1 );
 
   mTrace.PushCall("GetGlyphImage", "");
@@ -455,7 +455,6 @@ Integration::BitmapPtr TestPlatformAbstraction::GetGlyphImage( const std::string
   return image;
 }
 
-
 /** Call this every test */
 void TestPlatformAbstraction::Initialize()
 {
index 6ecfe07..e8614ec 100644 (file)
@@ -235,7 +235,6 @@ public:
 
   virtual Integration::BitmapPtr GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const;
 
-
 public: // TEST FUNCTIONS
 
   // Enumeration of Platform Abstraction methods
@@ -323,7 +322,6 @@ public: // TEST FUNCTIONS
 
   void SetReadMetricsResult( bool success, std::vector<Integration::GlyphMetrics>& glyphMetricsContainer );
 
-
 private:
   mutable TraceCallStack        mTrace;
   size_t                        mSeconds;
index 9f1b8fd..bd2560b 100644 (file)
@@ -27,7 +27,7 @@ namespace {
 
 Integration::Bitmap* CreateBitmap( unsigned int imageHeight, unsigned int imageWidth, unsigned int initialColor, Pixel::Format pixelFormat )
 {
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat,  imageWidth,imageHeight,imageWidth,imageHeight );
   unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
 
index c2680b2..ff8ec11 100644 (file)
@@ -24,13 +24,15 @@ namespace Dali
 TestApplication::TestApplication( size_t surfaceWidth,
                                   size_t surfaceHeight,
                                   float  horizontalDpi,
-                                  float  verticalDpi)
+                                  float  verticalDpi,
+                                  ResourcePolicy::DataRetention policy)
 : mCore( NULL ),
   mSurfaceWidth( surfaceWidth ),
   mSurfaceHeight( surfaceHeight ),
   mFrame( 0u ),
   mDpi( horizontalDpi, verticalDpi ),
-  mLastVSyncTime(0u)
+  mLastVSyncTime(0u),
+  mDataRetentionPolicy(policy)
 {
   Initialize();
 }
@@ -39,12 +41,15 @@ TestApplication::TestApplication( bool   initialize,
                                   size_t surfaceWidth,
                                   size_t surfaceHeight,
                                   float  horizontalDpi,
-                                  float  verticalDpi )
+                                  float  verticalDpi,
+                                  ResourcePolicy::DataRetention policy)
 : mCore( NULL ),
   mSurfaceWidth( surfaceWidth ),
   mSurfaceHeight( surfaceHeight ),
   mFrame( 0u ),
-  mDpi( horizontalDpi, verticalDpi )
+  mDpi( horizontalDpi, verticalDpi ),
+  mLastVSyncTime(0u),
+  mDataRetentionPolicy( policy )
 {
   if ( initialize )
   {
@@ -59,7 +64,8 @@ void TestApplication::Initialize()
     mPlatformAbstraction,
     mGlAbstraction,
     mGlSyncAbstraction,
-    mGestureManager );
+    mGestureManager,
+    mDataRetentionPolicy);
 
   mCore->ContextCreated();
   mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
@@ -190,7 +196,7 @@ bool TestApplication::RenderOnly( )
 
 void TestApplication::ResetContext()
 {
-  mCore->ContextToBeDestroyed();
+  mCore->ContextDestroyed();
   mCore->ContextCreated();
 }
 
index bcc2dd8..c91086e 100644 (file)
@@ -25,6 +25,7 @@
 #include "test-gl-abstraction.h"
 #include "test-render-controller.h"
 #include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/resource-policies.h>
 
 namespace Dali
 {
@@ -50,13 +51,15 @@ public:
   TestApplication( size_t surfaceWidth  = DEFAULT_SURFACE_WIDTH,
                    size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
                    float  horizontalDpi = DEFAULT_HORIZONTAL_DPI,
-                   float  verticalDpi   = DEFAULT_VERTICAL_DPI );
+                   float  verticalDpi   = DEFAULT_VERTICAL_DPI,
+                   ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA);
 
   TestApplication( bool   initialize,
                    size_t surfaceWidth  = DEFAULT_SURFACE_WIDTH,
                    size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
                    float  horizontalDpi = DEFAULT_HORIZONTAL_DPI,
-                   float  verticalDpi   = DEFAULT_VERTICAL_DPI );
+                   float  verticalDpi   = DEFAULT_VERTICAL_DPI,
+                   ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA);
 
   void Initialize();
   virtual ~TestApplication();
@@ -97,6 +100,7 @@ protected:
 
   Vector2 mDpi;
   unsigned int mLastVSyncTime;
+  ResourcePolicy::DataRetention mDataRetentionPolicy;
 };
 
 } // Dali
index b094fde..52ab7a6 100644 (file)
@@ -489,7 +489,7 @@ public:
         out << ", ";
       }
     }
-    mTextureTrace.PushCall("GenTexture", out.str());
+    mTextureTrace.PushCall("GenTextures", out.str());
   }
 
   inline void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
index ef3eb77..779fd2a 100644 (file)
@@ -227,7 +227,7 @@ Integration::GlyphSet* TestPlatformAbstraction::GetGlyphData ( const Integration
 
       if( getBitmap )
       {
-        bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true);
+        bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD);
         bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64);
         PixelBuffer* pixelBuffer = bitmapData->GetBuffer();
         memset( pixelBuffer, it->character, 64*64 );
@@ -268,7 +268,7 @@ Integration::GlyphSet* TestPlatformAbstraction::GetCachedGlyphData( const Integr
       characters.insert( it->character );
       Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::HIGH_QUALITY,  10.0f,  10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition };
 
-      bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true);
+      bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD);
       bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64);
       PixelBuffer* pixelBuffer = bitmapData->GetBuffer();
       memset( pixelBuffer, it->character, 64*64 );
@@ -455,7 +455,7 @@ void TestPlatformAbstraction::GetFileNamesFromDirectory( const std::string& dire
 
 Integration::BitmapPtr TestPlatformAbstraction::GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const
 {
-  Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   image->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 1, 1 );
 
   mTrace.PushCall("GetGlyphImage", "");
@@ -645,4 +645,5 @@ void TestPlatformAbstraction::SetReadMetricsResult( bool success, std::vector<In
   mReadMetrics = glyphMetricsContainer; // copy
 }
 
+
 } // namespace Dali
index 2d4c38c..f3f22ac 100644 (file)
@@ -325,8 +325,6 @@ public: // TEST FUNCTIONS
   void SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics );
 
   void SetReadMetricsResult( bool success, std::vector<Integration::GlyphMetrics>& glyphMetricsContainer );
-
-
 private:
   mutable TraceCallStack        mTrace;
   size_t                        mSeconds;
index f070c16..491f618 100644 (file)
@@ -131,7 +131,7 @@ int UtcDaliImageNewWithPolicies01(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -189,7 +189,7 @@ int UtcDaliImageNewWithPolicies02(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -245,7 +245,7 @@ int UtcDaliImageNewWithPolicies03(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -311,7 +311,7 @@ int UtcDaliImageNewWithPolicies04(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -398,7 +398,7 @@ int UtcDaliImageNewDistanceFieldWithPolicies01(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -457,7 +457,7 @@ int UtcDaliImageNewDistanceFieldWithPolicies02(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -513,7 +513,7 @@ int UtcDaliImageNewDistanceFieldWithPolicies03(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -579,7 +579,7 @@ int UtcDaliImageNewDistanceFieldWithPolicies04(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -671,7 +671,7 @@ int UtcDaliImageNewDistanceFieldWithAttrandPol(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -769,7 +769,7 @@ int UtcDaliImageGetLoadingState01(void)
 
   // simulate load success
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
@@ -886,7 +886,7 @@ int UtcDaliImageSignalLoadingFinished(void)
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
   if(request)
   {
-    application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true)));
+    application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD)));
   }
 
   application.Render(16);
@@ -916,7 +916,7 @@ int UtcDaliImageSignalUploaded(void)
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
   if(request)
@@ -983,7 +983,7 @@ int UtcDaliImageDiscard01(void)
     ids.push_back( 23 );
     application.GetGlAbstraction().SetNextTextureIds( ids );
     Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
     Integration::ResourcePointer resource(bitmap);
     bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
     if(request)
@@ -1032,7 +1032,7 @@ int UtcDaliImageDiscard02(void)
         application.GetGlAbstraction().SetNextTextureIds( ids );
 
         Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-        Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+        Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
         Integration::ResourcePointer resource(bitmap);
         bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
         if(request)
@@ -1086,7 +1086,8 @@ int UtcDaliImageDiscard03(void)
   application.GetGlAbstraction().SetNextTextureIds( ids );
 
   Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
+
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
   if(request)
@@ -1113,3 +1114,97 @@ int UtcDaliImageDiscard03(void)
 
   END_TEST;
 }
+
+
+namespace
+{
+void LoadBitmapResource(TestPlatformAbstraction& platform)
+{
+  Integration::ResourceRequest* request = platform.GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
+
+  if(request)
+  {
+    platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource);
+  }
+}
+
+}
+
+int UtcDaliImageContextLoss(void)
+{
+  TestApplication application; // Default config: DALI_DISCARDS_ALL_DATA
+
+  const Vector2 closestImageSize( 80, 80 );
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  platform.SetClosestImageSize(closestImageSize);
+
+  tet_infoline("UtcDaliImageContextLoss - Load image with LoadPolicy::Immediate, ReleasePolicy::Never, bitmap discard. Check that the image is re-requested on context regain\n");
+
+  Image image = Image::New("image.png", Image::Immediate, Image::Never);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading immediately
+
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  LoadBitmapResource(platform);
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") );
+
+  textureTrace.Reset();
+  textureTrace.Enable(true);
+  platform.ResetTrace();
+  platform.EnableTrace(true);
+
+  // Lose & regain context (in render 'thread')
+  application.ResetContext();
+
+  application.GetCore().RecoverFromContextLoss(); // start the recovery process
+  application.SendNotification();
+
+  // Run update/render loop
+  application.Render(16);
+  application.SendNotification();
+
+  // Expect new load request
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  // Finish loading image
+  LoadBitmapResource(platform);
+  ids.clear();
+  ids.push_back( 57 );
+  glAbstraction.SetNextTextureIds(ids);
+
+  // Run update/render loop
+  application.Render(16);
+  application.SendNotification();
+
+  // Expect new GenTextures
+  DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") );
+
+  END_TEST;
+}
index 42c4846..25342cc 100644 (file)
@@ -240,7 +240,7 @@ int UtcDaliImageActorGetCurrentSize02(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  initialImageSize.width,initialImageSize.height, initialImageSize.width,initialImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -292,7 +292,7 @@ int UtcDaliImageActorGetCurrentSize03(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -343,7 +343,7 @@ int UtcDaliImageActorGetCurrentSize04(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -383,7 +383,7 @@ int UtcDaliImageActorGetCurrentSize04(void)
 
   // Now complete the image load
   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height );
 
   Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
@@ -427,7 +427,7 @@ int UtcDaliImageActorGetCurrentSize05(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -459,7 +459,7 @@ int UtcDaliImageActorGetCurrentSize05(void)
 
   // Now complete the image load
   req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height );
 
   Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
@@ -506,7 +506,7 @@ int UtcDaliImageActorNaturalPixelAreaSize01(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -569,7 +569,7 @@ int UtcDaliImageActorNaturalPixelAreaSize02(void)
 
   // Now complete the image load
   Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
 
   Integration::ResourcePointer resourcePtr(bitmap); // reference it
@@ -914,7 +914,7 @@ int UtcDaliImageActorNinePatch01(void)
   tet_infoline("Test the successful loading of a nine-patch image\n");
 
   platform.SetClosestImageSize(Vector2(4, 4));
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  4,4,4,4 );
   memset( pixels, 0, 64 );
 
@@ -1007,7 +1007,7 @@ int UtcDaliImageActorNinePatch03(void)
   tet_infoline("Test the successful loading of a nine-patch image added using ImageActor::SetImage()\n");
 
   platform.SetClosestImageSize(Vector2(4, 4));
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, false );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  4,4,4,4 );
   memset( pixels, 0, 64 );
 
index 77c8eac..1c0d9e2 100644 (file)
@@ -183,7 +183,7 @@ int UtcDaliMaterialStage01(void)
     std::vector<GLuint> ids;
     ids.push_back( 23 );
     application.GetGlAbstraction().SetNextTextureIds( ids );
-    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
     Integration::ResourcePointer resource(bitmap);
     bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
     DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
@@ -295,7 +295,7 @@ int UtcDaliMaterialStage02(void)
       Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
       DALI_TEST_CHECK( request != NULL );
 
-      Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+      Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
       Integration::ResourcePointer resource(bitmap);
       bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
       if(request)
index 0e2b2ba..899853c 100644 (file)
@@ -201,7 +201,7 @@ void CompleteImageLoad(TestApplication& application, Integration::ResourceId res
   ids.push_back( 23 );
   application.GetGlAbstraction().SetNextTextureIds( ids );
 
-  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, true );
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
   Integration::ResourcePointer resource(bitmap);
   bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
 
index 1ab4559..57c730f 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include <dali/public-api/dali-core.h>
+#include <dali/integration-api/context-notifier.h>
 #include <dali/integration-api/events/key-event-integ.h>
 #include <dali/integration-api/events/touch-event-integ.h>
 
@@ -135,6 +136,26 @@ bool DummyTouchCallback( Actor actor, const TouchEvent& touch )
   return true;
 }
 
+
+struct ContextStatusFunctor
+{
+  ContextStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag )
+  {
+    mCalledFlag = false;
+  }
+
+  void operator()()
+  {
+    mCalledFlag = true;
+  }
+  void Reset()
+  {
+    mCalledFlag = false;
+  }
+
+  bool& mCalledFlag;
+};
+
 } // unnamed namespace
 
 
@@ -595,3 +616,26 @@ int UtcDaliStageTouchedSignal(void)
   }
   END_TEST;
 }
+
+int UtcDaliStageContextLostRegainedSignals(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  bool contextLost = false;
+  bool contextRegained = false;
+  ContextStatusFunctor contextLostFunctor( contextLost );
+  ContextStatusFunctor contextRegainedFunctor( contextRegained );
+  stage.ContextLostSignal().Connect(&app, contextLostFunctor );
+  stage.ContextRegainedSignal().Connect(&app, contextRegainedFunctor );
+
+  Integration::Core& core = app.GetCore();
+  Integration::ContextNotifierInterface* notifier = core.GetContextNotifier();
+  notifier->NotifyContextLost();
+  DALI_TEST_EQUALS( contextLost, true, TEST_LOCATION );
+
+  notifier->NotifyContextRegained();
+  DALI_TEST_EQUALS( contextRegained, true, TEST_LOCATION );
+
+  END_TEST;
+}
index 617cab8..1eb95b4 100644 (file)
@@ -22,6 +22,8 @@
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/images/bitmap-packed-pixel.h>
 #include <dali/internal/event/images/bitmap-compressed.h>
 #include <dali/internal/event/images/bitmap-external.h>
@@ -242,7 +244,8 @@ void ConvertToGlFormat( Format pixelformat, unsigned& pixelDataType, unsigned& i
   }
 }
 
-Bitmap* Bitmap::New(const Profile profile = BITMAP_2D_PACKED_PIXELS, const bool managePixelBuffer = true)
+Bitmap* Bitmap::New( const Profile profile = BITMAP_2D_PACKED_PIXELS,
+                     ResourcePolicy::Discardable discardable = ResourcePolicy::DISCARD )
 {
   DALI_ASSERT_DEBUG(profile == BITMAP_2D_PACKED_PIXELS || profile == BITMAP_COMPRESSED);
 
@@ -254,20 +257,21 @@ Bitmap* Bitmap::New(const Profile profile = BITMAP_2D_PACKED_PIXELS, const bool
      * scanlines past the bottom of the image in the buffer if requested.*/
     case BITMAP_2D_PACKED_PIXELS:
     {
-      Bitmap * const bitmap = new Dali::Internal::BitmapPackedPixel(managePixelBuffer);
+      Bitmap * const bitmap = new Dali::Internal::BitmapPackedPixel( discardable );
       return bitmap;
     }
 
     /** The data for the bitmap is buffered in an opaque form.*/
     case BITMAP_COMPRESSED:
     {
-      return new Dali::Internal::BitmapCompressed(managePixelBuffer);
+      return new Dali::Internal::BitmapCompressed( discardable );
     }
   }
   return 0;
 }
 
-Bitmap::Bitmap( bool discardable, Dali::Integration::PixelBuffer* pixBuf)
+
+Bitmap::Bitmap( ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf)
 : mImageWidth(0),
   mImageHeight(0),
   mPixelFormat(Pixel::RGBA8888),
@@ -280,7 +284,7 @@ Bitmap::Bitmap( bool discardable, Dali::Integration::PixelBuffer* pixBuf)
 
 void Bitmap::DiscardBuffer()
 {
-  if ( mDiscardable )
+  if( mDiscardable == ResourcePolicy::DISCARD )
   {
     DeletePixelBuffer();
   }
@@ -299,7 +303,10 @@ PixelBuffer* Bitmap::ReleaseBuffer()
 Bitmap::~Bitmap()
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
-  DeletePixelBuffer();
+  if( mDiscardable == ResourcePolicy::DISCARD )
+  {
+    DeletePixelBuffer();
+  }
 }
 
 /**
@@ -330,4 +337,3 @@ void Bitmap::Initialize( Pixel::Format pixelFormat,
 } //namespace Integration
 
 } //namespace Dali
-
index f4b4472..977fb1e 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/images/pixel.h>
 #include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/resource-policies.h>
 
 namespace Dali
 {
@@ -53,13 +54,14 @@ typedef unsigned char                 PixelBuffer;  ///< Pixel data buffers are
 class DALI_IMPORT_API Bitmap : public Dali::RefObject
 {
 protected:
+
   /**
    * Constructor
-   * Use the static function Bitmap::Create() to create instances.
+   * Use the static function Bitmap::New() to create instances.
    * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
    * @param[in] pixBuf External buffer of pixel data or null.
    */
-  Bitmap( bool discardable = false, Dali::Integration::PixelBuffer* pixBuf = 0 );
+  Bitmap( ResourcePolicy::Discardable discardable = ResourcePolicy::RETAIN, Dali::Integration::PixelBuffer* pixBuf = 0 );
 
   /**
    * Initializes internal class members
@@ -87,17 +89,18 @@ public:
   };
 
   /**
-   * Create a new instance of a Bitmap with the profile asked for.
+   * Create a new instance of a Bitmap with the required profile.
    * @return Pointer to created Bitmap subclass. Clients should immediately
    * wrap this in a reference-counting smart pointer or store it in a similarly
    * automatic owning collection.
    * @param[in] profile Defines required features of the bitmap (\sa Profile).
-   * @param[in] managePixelBuffer If true, the bitmap object owns it's own
-   * buffer of pixel data and can delete it, else the lifetime of the pixel
-   * buffer is managed by an external component and is guaranteed to remain
+   * @param[in] discardable If this is set to DISCARD, the bitmap
+   * object owns it's own buffer of pixel data and can delete it. If
+   * it's set to RETAIN, then the lifetime of the pixel buffer is
+   * managed by an external component and is guaranteed to remain
    * dereferenceable at least as long as the Bitmap remains alive.
    **/
-  static Bitmap* New(Profile profile, bool managePixelBuffer);
+  static Bitmap* New( Profile profile, ResourcePolicy::Discardable discardable );
 
   /** \name GeneralFeatures
    * Features that are generic between profiles. */
@@ -131,13 +134,13 @@ public:
   }
 
   /**
-   * Get the pixel buffer
-   * @return The buffer. You can modify its contents.
+   * Get the pixel buffer if it's present.
+   * @return The buffer if present, or NULL if there is no pixel buffer.
+   * You can modify its contents.
    * @sa ReserveBuffer GetBufferSize
    */
   virtual PixelBuffer* GetBuffer()
   {
-    DALI_ASSERT_DEBUG(mData != NULL);
     return mData;
   }
 
@@ -304,7 +307,7 @@ public:
    */
   bool IsDiscardable() const
   {
-    return mDiscardable;
+    return mDiscardable == ResourcePolicy::DISCARD;
   }
 
  /**
@@ -334,7 +337,7 @@ protected:
 
 private:
 
-  bool mDiscardable; ///< Should delete the buffer when discard buffer is called.
+  ResourcePolicy::Discardable mDiscardable; ///< Should delete the buffer when discard buffer is called.
 
   Bitmap(const Bitmap& other);  ///< defined private to prevent use
   Bitmap& operator = (const Bitmap& other); ///< defined private to prevent use
diff --git a/dali/integration-api/context-notifier.h b/dali/integration-api/context-notifier.h
new file mode 100644 (file)
index 0000000..348f292
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__
+#define __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+namespace Dali
+{
+namespace Integration
+{
+
+/**
+ * Interface to inform dali core of context loss and regain
+ */
+class ContextNotifierInterface
+{
+public:
+  /**
+   * Notify that the GL context has been lost, e.g. during ReplaceSurface
+   * or Pause.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  virtual void NotifyContextLost() = 0;
+
+  /**
+   * Notify that the GL context has been re-created, e.g. after ReplaceSurface
+   * or Context loss.
+   *
+   * In the case of ReplaceSurface, both ContextDestroyed() and ContextCreated() will have
+   * been called on the render thread before this is called on the event thread.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  virtual void NotifyContextRegained() = 0;
+};
+
+} // namespace Integration
+} // namespace Dali
+
+
+#endif // __DALI_INTEGRATION_CONTEXT_NOTIFICATION_H__
index 186209d..44a4323 100644 (file)
@@ -51,10 +51,10 @@ const unsigned int RENDER_TASK_SYNC       = 0x40;  ///< The refresh once render
 } // namespace KeepUpdating
 
 Core* Core::New(RenderController& renderController, PlatformAbstraction& platformAbstraction,
-                GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, GestureManager& gestureManager)
+                GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, GestureManager& gestureManager, ResourcePolicy::DataRetention policy )
 {
   Core* instance = new Core;
-  instance->mImpl = new Internal::Core( renderController, platformAbstraction, glAbstraction, glSyncAbstraction, gestureManager );
+  instance->mImpl = new Internal::Core( renderController, platformAbstraction, glAbstraction, glSyncAbstraction, gestureManager, policy );
 
   return instance;
 }
@@ -64,14 +64,28 @@ Core::~Core()
   delete mImpl;
 }
 
+ContextNotifierInterface* Core::GetContextNotifier()
+{
+  return mImpl->GetContextNotifier();
+}
+
+// @todo Rename to ResetGlContext
 void Core::ContextCreated()
 {
   mImpl->ContextCreated();
 }
 
-void Core::ContextToBeDestroyed()
+// @todo Replace with StopRendering that prevents RenderManager from rendering
+// until we get ResetGLContext again, change ContextCreated to reset gpu buffer cache,
+// gl texture id's
+void Core::ContextDestroyed()
+{
+  mImpl->ContextDestroyed();
+}
+
+void Core::RecoverFromContextLoss()
 {
-  mImpl->ContextToBeDestroyed();
+  mImpl->RecoverFromContextLoss();
 }
 
 void Core::SurfaceResized(unsigned int width, unsigned int height)
index d9d5332..2a2fbb0 100644 (file)
@@ -21,6 +21,8 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/common/view-mode.h>
+#include <dali/integration-api/context-notifier.h>
+#include <dali/integration-api/resource-policies.h>
 
 namespace Dali
 {
@@ -43,6 +45,7 @@ class SystemOverlay;
 struct Event;
 struct TouchData;
 
+
 /**
  * The reasons why further updates are required.
  */
@@ -205,13 +208,17 @@ public:
    * @param[in] glAbstraction The interface providing OpenGL services.
    * @param[in] glSyncAbstraction The interface providing OpenGL sync objects.
    * @param[in] gestureManager The interface providing gesture manager services.
+   * @param[in] policy The data retention policy. This depends on application setting
+   * and platform support. Dali should honour this policy when deciding to discard
+   * intermediate resource data.
    * @return A newly allocated Core.
    */
   static Core* New(RenderController& renderController,
                    PlatformAbstraction& platformAbstraction,
                    GlAbstraction& glAbstraction,
                    GlSyncAbstraction& glSyncAbstraction,
-                   GestureManager& gestureManager);
+                   GestureManager& gestureManager,
+                   ResourcePolicy::DataRetention policy);
 
   /**
    * Non-virtual destructor. Core is not intended as a base class.
@@ -221,6 +228,11 @@ public:
   // GL Context Lifecycle
 
   /**
+   * Get the object that will notify the application/toolkit when context is lost/regained
+   */
+  ContextNotifierInterface* GetContextNotifier();
+
+  /**
    * Notify the Core that the GL context has been created.
    * The context must be created before the Core can render.
    * Multi-threading note: this method should be called from the rendering thread only
@@ -234,7 +246,18 @@ public:
    * Multi-threading note: this method should be called from the rendering thread only
    * @post The Core is unaware of any GL context.
    */
-  void ContextToBeDestroyed();
+  void ContextDestroyed();
+
+  /**
+   * Notify the Core that the GL context has been re-created, e.g. after ReplaceSurface
+   * or Context loss.
+   *
+   * In the case of ReplaceSurface, both ContextToBeDestroyed() and ContextCreated() will have
+   * been called on the render thread before this is called on the event thread.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  void RecoverFromContextLoss();
 
   /**
    * Notify the Core that the GL surface has been resized.
index c820882..3742942 100644 (file)
@@ -26,11 +26,13 @@ platform_abstraction_src_files = \
 
 platform_abstraction_header_files = \
    $(platform_abstraction_src_dir)/core.h \
+   $(platform_abstraction_src_dir)/context-notifier.h \
    $(platform_abstraction_src_dir)/glyph-set.h \
    $(platform_abstraction_src_dir)/debug.h \
    $(platform_abstraction_src_dir)/profiling.h \
    $(platform_abstraction_src_dir)/input-options.h \
    $(platform_abstraction_src_dir)/bitmap.h \
+   $(platform_abstraction_src_dir)/resource-policies.h \
    $(platform_abstraction_src_dir)/image-data.h \
    $(platform_abstraction_src_dir)/resource-types.h \
    $(platform_abstraction_src_dir)/resource-request.h \
index 925546e..a5111a7 100644 (file)
@@ -32,6 +32,7 @@ namespace Integration
 class Bitmap;
 class DynamicsFactory;
 
+
 /**
  * PlatformAbstraction is an abstract interface, used by Dali to access platform specific services.
  * A concrete implementation must be created for each platform, and provided when creating the
diff --git a/dali/integration-api/resource-policies.h b/dali/integration-api/resource-policies.h
new file mode 100644 (file)
index 0000000..524e5aa
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_POLICIES_H__
+#define __DALI_INTEGRATION_RESOURCE_POLICIES_H__
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+namespace Dali
+{
+namespace ResourcePolicy
+{
+
+/**
+ * The data retention policy describes how dali should retain resource data.
+ */
+enum DataRetention
+{
+  DALI_RETAINS_ALL_DATA,  // retains Meshes and bitmaps
+  DALI_RETAINS_MESH_DATA, // retains meshes, but discards bitmaps loaded from files
+  DALI_DISCARDS_ALL_DATA, // discards all data (expects application to regenerate UI on context loss)
+};
+
+/**
+ * The discardable policy describes whether a resource can be discarded (i.e. it is throw-away
+ * or recoverable)
+ */
+enum Discardable
+{
+  DISCARD, // @todo Change to IS_RECOVERABLE?
+  RETAIN
+};
+
+} // namespace ResourcePolicy
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_DISCARD_POLICY_H__
index ba9f874..97787c7 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/integration-api/system-overlay.h>
 #include <dali/integration-api/core.h>
+#include <dali/integration-api/debug.h>
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/integration-api/gl-sync-abstraction.h>
 #include <dali/integration-api/render-controller.h>
@@ -46,6 +47,7 @@
 #include <dali/internal/event/effects/shader-factory.h>
 #include <dali/internal/update/touch/touch-resampler.h>
 #include <dali/internal/event/common/type-registry-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
 
 #include <dali/internal/render/gl-resources/texture-cache.h>
 #include <dali/internal/render/gl-resources/context.h>
@@ -56,8 +58,15 @@ using Dali::Internal::SceneGraph::DiscardQueue;
 using Dali::Internal::SceneGraph::RenderQueue;
 using Dali::Internal::SceneGraph::TextureCache;
 
+namespace
+{
 // The Update for frame N+1 may be processed whilst frame N is being rendered.
-static const unsigned int MAXIMUM_UPDATE_COUNT = 2u;
+const unsigned int MAXIMUM_UPDATE_COUNT = 2u;
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE");
+#endif
+}
 
 namespace Dali
 {
@@ -76,7 +85,7 @@ using Integration::RenderStatus;
 
 Core::Core( RenderController& renderController, PlatformAbstraction& platform,
             GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction,
-            GestureManager& gestureManager)
+            GestureManager& gestureManager, ResourcePolicy::DataRetention dataRetentionPolicy)
 : mRenderController( renderController ),
   mPlatform(platform),
   mGestureEventProcessor(NULL),
@@ -113,6 +122,14 @@ Core::Core( RenderController& renderController, PlatformAbstraction& platform,
 
   RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
   TextureCache& textureCache = mRenderManager->GetTextureCache();
+
+  ResourcePolicy::Discardable discardPolicy = ResourcePolicy::DISCARD;
+  if( dataRetentionPolicy == ResourcePolicy::DALI_RETAINS_ALL_DATA )
+  {
+    discardPolicy = ResourcePolicy::RETAIN;
+  }
+  textureCache.SetDiscardBitmapsPolicy(discardPolicy);
+
   mDiscardQueue = new DiscardQueue( renderQueue );
 
   mResourceManager = new ResourceManager(  mPlatform,
@@ -137,7 +154,7 @@ Core::Core( RenderController& renderController, PlatformAbstraction& platform,
                                        textureCache,
                                       *mTouchResampler );
 
-  mResourceClient = new ResourceClient( *mResourceManager, *mUpdateManager );
+  mResourceClient = new ResourceClient( *mResourceManager, *mUpdateManager, dataRetentionPolicy );
 
   mStage = IntrusivePtr<Stage>( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager ) );
 
@@ -196,12 +213,26 @@ Core::~Core()
   delete mResourcePostProcessQueue;
 }
 
+Integration::ContextNotifierInterface* Core::GetContextNotifier()
+{
+  return mStage.Get();
+}
+
+void Core::RecoverFromContextLoss()
+{
+  DALI_LOG_INFO(gCoreFilter, Debug::Verbose, "Core::RecoverFromContextLoss()\n");
+
+  mImageFactory->RecoverFromContextLoss(); // Reload images from files
+  mFontFactory->RecoverFromContextLoss();  // Reload glyphs from cache into new atlas
+  mStage->GetRenderTaskList().RecoverFromContextLoss(); // Re-trigger render-tasks
+}
+
 void Core::ContextCreated()
 {
   mRenderManager->ContextCreated();
 }
 
-void Core::ContextToBeDestroyed()
+void Core::ContextDestroyed()
 {
   mRenderManager->ContextDestroyed();
 }
@@ -213,7 +244,7 @@ void Core::SurfaceResized(unsigned int width, unsigned int height)
 
 void Core::SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical)
 {
-  mPlatform.SetDpi( dpiHorizontal, dpiVertical  );
+  mPlatform.SetDpi( dpiHorizontal, dpiVertical );
   mFontFactory->SetDpi( dpiHorizontal, dpiVertical);
   mStage->SetDpi( Vector2( dpiHorizontal , dpiVertical) );
 }
index c421838..b456e82 100644 (file)
 
 // INTERNAL INCLUDES
 #include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/context-notifier.h>
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/internal/event/animation/animation-playlist-declarations.h>
 #include <dali/internal/event/common/stage-def.h>
 #include <dali/internal/update/resources/resource-manager-declarations.h>
 #include <dali/public-api/common/view-mode.h>
+#include <dali/integration-api/resource-policies.h>
 
 namespace Dali
 {
@@ -82,7 +84,8 @@ public:
         Integration::PlatformAbstraction& platform,
         Integration::GlAbstraction& glAbstraction,
         Integration::GlSyncAbstraction& glSyncAbstraction,
-        Integration::GestureManager& gestureManager );
+        Integration::GestureManager& gestureManager,
+        ResourcePolicy::DataRetention dataRetentionPolicy );
 
   /**
    * Destructor
@@ -90,14 +93,24 @@ public:
   ~Core();
 
   /**
+   * @copydoc Dali::Integration::Core::GetContextNotifier()
+   */
+  Integration::ContextNotifierInterface* GetContextNotifier();
+
+  /**
    * @copydoc Dali::Integration::Core::ContextCreated()
    */
   void ContextCreated();
 
   /**
-   * @copydoc Dali::Integration::Core::ContextToBeDestroyed()
+   * @copydoc Dali::Integration::Core::ContextDestroyed()
+   */
+  void ContextDestroyed();
+
+  /**
+   * @copydoc Dali::Integration::Core::RecoverFromContextLoss()
    */
-  void ContextToBeDestroyed();
+  void RecoverFromContextLoss();
 
   /**
    * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int)
index 7dce84e..de0c281 100644 (file)
@@ -524,6 +524,26 @@ Dali::Stage::TouchedSignalV2& Stage::TouchedSignal()
   return mTouchedSignalV2;
 }
 
+Dali::Stage::ContextStatusSignal& Stage::ContextLostSignal()
+{
+  return mContextLostSignal;
+}
+
+Dali::Stage::ContextStatusSignal& Stage::ContextRegainedSignal()
+{
+  return mContextRegainedSignal;
+}
+
+void Stage::NotifyContextLost()
+{
+  mContextLostSignal.Emit();
+}
+
+void Stage::NotifyContextRegained()
+{
+  mContextRegainedSignal.Emit();
+}
+
 Stage::Stage( AnimationPlaylist& playlist,
               PropertyNotificationManager& propertyNotificationManager,
               SceneGraph::UpdateManager& updateManager,
index a7c1645..a0e9d6a 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/common/stage.h>
 #include <dali/public-api/object/base-object.h>
+#include <dali/integration-api/context-notifier.h>
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/internal/event/actors/layer-impl.h>
 #include <dali/internal/event/common/object-registry-impl.h>
@@ -69,7 +70,7 @@ class RenderTaskList;
 /**
  * Implementation of Stage
  */
-class Stage : public BaseObject, public RenderTaskDefaults
+class Stage : public BaseObject, public RenderTaskDefaults, public Integration::ContextNotifierInterface
 {
 public:
 
@@ -331,6 +332,7 @@ public:
     return mNotificationManager;
   }
 
+
   /**
    * @copydoc Dali::Stage::KeepRendering()
    */
@@ -370,6 +372,28 @@ public:
     */
   Dali::Stage::TouchedSignalV2& TouchedSignal();
 
+  /**
+   * @copydoc Dali::Stage::ContextLostSignal()
+   */
+  Dali::Stage::ContextStatusSignal& ContextLostSignal();
+
+  /**
+   * @copydoc Dali::Stage::ContextRegainedSignal()
+   */
+  Dali::Stage::ContextStatusSignal& ContextRegainedSignal();
+
+private: // Implementation of ContextNotificationInterface:
+
+  /**
+   * @copydoc Dali::Integration::NotifyContextLost();
+   */
+  virtual void NotifyContextLost();
+
+  /**
+   * @copydoc Dali::Integration::NotifyContextRegained();
+   */
+  virtual void NotifyContextRegained();
+
 private:
 
   /**
@@ -445,6 +469,9 @@ private:
 
   // The touched signal
   Dali::Stage::TouchedSignalV2                  mTouchedSignalV2;
+
+  Dali::Stage::ContextStatusSignal mContextLostSignal;
+  Dali::Stage::ContextStatusSignal mContextRegainedSignal;
 };
 
 } // namespace Internal
index 7a336fb..7e41ca9 100644 (file)
@@ -33,8 +33,11 @@ namespace Internal
 {
 using namespace Dali::Pixel;
 
-BitmapCompressed::BitmapCompressed( const bool bitmapOwnsBuffer ) : Bitmap(bitmapOwnsBuffer), mBufferSize(0)
-{}
+BitmapCompressed::BitmapCompressed( const ResourcePolicy::Discardable discardable )
+: Bitmap( discardable ),
+  mBufferSize(0)
+{
+}
 
 BitmapCompressed::~BitmapCompressed()
 {
index a476f9d..6835ad8 100644 (file)
@@ -45,7 +45,7 @@ public:
    * Constructor
    * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
    */
-  BitmapCompressed( bool discardable = false );
+  BitmapCompressed( ResourcePolicy::Discardable discardable = ResourcePolicy::RETAIN );
 
   virtual const Bitmap::CompressedProfile* GetCompressedProfile() const { return this; }
   virtual Bitmap::CompressedProfile* GetCompressedProfile() { return this; }
index f1e36fa..58d5609 100644 (file)
@@ -34,7 +34,7 @@ BitmapExternal::BitmapExternal(Dali::Integration::PixelBuffer* pixBuf,
                Pixel::Format pixelFormat,
                unsigned int bufferWidth,
                unsigned int bufferHeight)
-: BitmapPackedPixel(false, NULL/*pixBuf is externally owned*/),
+: BitmapPackedPixel(ResourcePolicy::RETAIN, NULL/*pixBuf is externally owned*/),
   mExternalData(pixBuf)
 {
   mImageWidth   = width;
index 1ba1aa0..d97b1d4 100644 (file)
@@ -31,7 +31,7 @@ namespace Internal
 using namespace Dali::Pixel;
 
 
-BitmapPackedPixel::BitmapPackedPixel( bool discardable, Dali::Integration::PixelBuffer* pixBuf )
+BitmapPackedPixel::BitmapPackedPixel( ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf )
 : Bitmap( discardable, pixBuf ),
   mBufferWidth(0),
   mBufferHeight(0),
index 20cdb39..12c6777 100644 (file)
@@ -48,7 +48,7 @@ public:
    * Constructor
    * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
    */
-  BitmapPackedPixel( bool discardable = false, Dali::Integration::PixelBuffer* pixBuf = 0 );
+  BitmapPackedPixel( ResourcePolicy::Discardable discardable = ResourcePolicy::RETAIN, Dali::Integration::PixelBuffer* pixBuf = 0 );
 
 public:
   virtual const Bitmap::PackedPixelsProfile* GetPackedPixelsProfile() const { return this; }
index 67e0895..0dc4c10 100644 (file)
@@ -170,7 +170,7 @@ ResourceTicketPtr ImageFactory::Reload( Request* request )
 
     if( size == attrib.GetSize() )
     {
-      mResourceClient.ReloadResource( ticket->GetId() );
+      mResourceClient.ReloadResource( ticket->GetId(), false );
     }
     else
     {
@@ -182,6 +182,26 @@ ResourceTicketPtr ImageFactory::Reload( Request* request )
   return ticket;
 }
 
+void ImageFactory::RecoverFromContextLoss()
+{
+  for( RequestIdMap::iterator it = mRequestCache.begin(); it != mRequestCache.end(); ++it )
+  {
+    // go through requests, reload with resource ticket's attributes.
+    Request* request = (*it).second;
+    if( request->resourceId )
+    {
+      ResourceTicketPtr ticket = mResourceClient.RequestResourceTicket( request->resourceId );
+
+      // do not reload if still loading
+      if ( ticket->GetLoadingState() != ResourceLoading )
+      {
+        // Ensure the finished status is reset
+        mResourceClient.ReloadResource( ticket->GetId(), true );
+      }
+    }
+  }
+}
+
 const std::string& ImageFactory::GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const
 {
   if( request )
index 5232ccf..89511af 100644 (file)
@@ -78,10 +78,25 @@ public:
    * This operation uses the originally requested attributes when reloading the image.
    * @pre req must be registered with ImageFactory
    * @note if image is still loading, no new load request will be issued
-   * @param [in]  req Request pointer
-   * @return[out] the ResourceTicket mapped to the request
+   * @param[in]  requestPtr Request pointer
+   * @return the ResourceTicket mapped to the request
    */
-  ResourceTicketPtr Reload( ImageFactoryCache::Request* req );
+  ResourceTicketPtr Reload( ImageFactoryCache::Request* requestPtr );
+
+  /**
+   * Ensures all filesystem images are reloaded into textures.
+   * This operation uses the originally requested attributes when reloading the image.
+   *
+   * Recovering from context loss does not change the number of tickets if the
+   * image size has changed on the file system since the last load/reload.
+   *
+   * If two different requests mapped to the same resource before, they will still
+   * map to the same resource after context regain even if there would be a better
+   * fitting texture.
+   * @pre requests must be registered with ImageFactory
+   * @note If an image is still loading, no new load request will be issued.
+   */
+  void RecoverFromContextLoss();
 
   /**
    * Get resource path used in request.
index adc1d2f..1b5d69c 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/math/matrix.h>
 #include <dali/public-api/geometry/mesh.h>
+#include <dali/integration-api/platform-abstraction.h>
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/modeling/material-impl.h>
 #include <dali/internal/update/modeling/scene-graph-mesh.h>
@@ -47,10 +48,19 @@ MeshIPtr Mesh::New( const Dali::MeshData& meshData, bool discardable, bool scali
 Mesh::Mesh( const Dali::MeshData& publicMeshData, bool discardable, bool scalingRequired )
 : mBoneContainer( publicMeshData.GetBones() )
 {
-  ResourceClient& resourceClient = ThreadLocalStorage::Get().GetResourceClient();
+  ThreadLocalStorage tls = ThreadLocalStorage::Get();
+  ResourceClient& resourceClient = tls.GetResourceClient();
+  ResourcePolicy::DataRetention dataRetentionPolicy = resourceClient.GetResourceDataRetentionPolicy();
+
+  ResourcePolicy::Discardable discard = ResourcePolicy::DISCARD;
+  if( ! (dataRetentionPolicy == ResourcePolicy::DALI_DISCARDS_ALL_DATA) ||
+      ! discardable )
+  {
+    discard = ResourcePolicy::RETAIN;
+  }
 
   // Copy the mesh-data into an internal structure, and pass ownership to the resourceClient
-  OwnerPointer<MeshData> meshDataPtr( new MeshData( publicMeshData, discardable, scalingRequired ) );
+  OwnerPointer<MeshData> meshDataPtr( new MeshData( publicMeshData, discard, scalingRequired ) );
   const ResourceTicketPtr& ticket = resourceClient.AllocateMesh( meshDataPtr );
 
   mTicket = ticket.Get();
@@ -118,4 +128,3 @@ void Mesh::ResourceSavingFailed( const ResourceTicket& ticket )
 } // namespace Internal
 
 } // namespace Dali
-
index 00bdb56..4514cc9 100644 (file)
@@ -25,6 +25,8 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/common/light.h>
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/modeling/entity-impl.h>
 #include <dali/internal/event/modeling/material-impl.h>
 #include <dali/internal/event/modeling/mesh-impl.h>
@@ -228,6 +230,11 @@ unsigned int ModelData::NumberOfLights() const
 
 void ModelData::Unpack( ResourceClient& resourceClient )
 {
+  ResourcePolicy::DataRetention dataRetentionPolicy = resourceClient.GetResourceDataRetentionPolicy();
+  ResourcePolicy::Discardable discardable = (dataRetentionPolicy == ResourcePolicy::DALI_DISCARDS_ALL_DATA ) ? ResourcePolicy::DISCARD : ResourcePolicy::RETAIN;
+
+  bool scalable = false; /* scaling is transmitted through parent Node */
+
   // Only unpack once
   if ( !mUnpacked )
   {
@@ -235,7 +242,7 @@ void ModelData::Unpack( ResourceClient& resourceClient )
     for ( size_t meshIdx = 0; meshIdx < NumberOfMeshes(); meshIdx++ )
     {
       // Copy the mesh-data into an internal structure, and pass ownership to the resourceClient
-      OwnerPointer<MeshData> meshDataPtr( new MeshData( GetMesh( meshIdx ), true /* discardable */, false /* scaling is transmitted through parent Node */ ) );
+      OwnerPointer<MeshData> meshDataPtr( new MeshData( GetMesh( meshIdx ), discardable, scalable ));
       ResourceTicketPtr meshTicket = resourceClient.AllocateMesh( meshDataPtr );
 
       AddMeshTicket( meshTicket );
index ef10943..e0d8c66 100644 (file)
@@ -163,6 +163,20 @@ void RenderTaskList::NotifyCompleted()
   }
 }
 
+void RenderTaskList::RecoverFromContextLoss()
+{
+  for ( RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter )
+  {
+    Dali::RenderTask task = *iter;
+
+    // If the render target renders only once to an offscreen, re-render the render task
+    if( task.GetRefreshRate() == Dali::RenderTask::REFRESH_ONCE && task.GetTargetFrameBuffer() )
+    {
+      task.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 4c2f73d..25e5b79 100644 (file)
@@ -96,6 +96,12 @@ public:
    */
   static void NotifyFinished( void* object );
 
+  /**
+   * This method refreshes all render tasks that have a frame buffer
+   * and a refresh rate of RefreshOnce.
+   */
+  void RecoverFromContextLoss();
+
 protected:
 
   /**
index 53fb3e1..b8dd6cf 100644 (file)
@@ -46,9 +46,10 @@ typedef BitmapCache::iterator                        BitmapCacheIter;
 
 struct ResourceClient::Impl
 {
-  Impl()
+  Impl(ResourcePolicy::DataRetention dataRetentionPolicy)
   : mNextId(0),
-    mGlyphLoadObserver( NULL)
+    mGlyphLoadObserver(NULL),
+    mDataRetentionPolicy( dataRetentionPolicy )
   {
   }
 
@@ -56,14 +57,16 @@ struct ResourceClient::Impl
   TicketContainer  mTickets;
   BitmapCache      mBitmaps;
   GlyphLoadObserver* mGlyphLoadObserver;
+  ResourcePolicy::DataRetention mDataRetentionPolicy;
 };
 
 ResourceClient::ResourceClient( ResourceManager& resourceManager,
-                                SceneGraph::UpdateManager& updateManager )
+                                SceneGraph::UpdateManager& updateManager,
+                                ResourcePolicy::DataRetention dataRetentionPolicy)
 : mResourceManager(resourceManager),
   mUpdateManager(updateManager)
 {
-  mImpl = new ResourceClient::Impl();
+  mImpl = new ResourceClient::Impl(dataRetentionPolicy);
   mResourceManager.SetClient(*this);
 }
 
@@ -80,6 +83,11 @@ ResourceClient::~ResourceClient()
   delete mImpl;
 }
 
+ResourcePolicy::DataRetention ResourceClient::GetResourceDataRetentionPolicy()
+{
+  return mImpl->mDataRetentionPolicy;
+}
+
 ResourceTicketPtr ResourceClient::RequestResource(
   const ResourceType& type,
   const std::string& path,
@@ -202,7 +210,7 @@ ResourceTicketPtr ResourceClient::LoadShader( ShaderResourceType& type,
   return newTicket;
 }
 
-bool ResourceClient::ReloadResource( ResourceId id, LoadResourcePriority priority )
+bool ResourceClient::ReloadResource( ResourceId id, bool resetFinishedStatus, LoadResourcePriority priority )
 {
   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ReloadResource(Id: %u)\n", id);
 
@@ -218,7 +226,7 @@ bool ResourceClient::ReloadResource( ResourceId id, LoadResourcePriority priorit
     DALI_ASSERT_DEBUG(ticket && "Null ticket for tracked resource request." );
     const ResourceTypePath * const typePathPtr = &ticket->GetTypePath();
     DALI_ASSERT_DEBUG( typePathPtr );
-    RequestReloadResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, id, *typePathPtr, priority );
+    RequestReloadResourceMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, id, *typePathPtr, priority, resetFinishedStatus );
   }
   else
   {
@@ -271,7 +279,8 @@ ImageTicketPtr ResourceClient::AllocateBitmapImage( unsigned int width,
                                                     unsigned int bufferHeight,
                                                     Pixel::Format pixelformat )
 {
-  Bitmap* const bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, false/*buffer is available via public-api, therefore not discardable*/ );
+  /* buffer is available via public-api, therefore not discardable */
+  Bitmap* const bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
   Bitmap::PackedPixelsProfile* const packedBitmap = bitmap->GetPackedPixelsProfile();
   DALI_ASSERT_DEBUG(packedBitmap);
 
@@ -432,10 +441,17 @@ void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData&
 {
   DALI_ASSERT_DEBUG( ticket );
 
+  ResourcePolicy::Discardable discardable = ResourcePolicy::RETAIN;
+  if( mImpl->mDataRetentionPolicy == ResourcePolicy::DALI_DISCARDS_ALL_DATA )
+  {
+    discardable = ResourcePolicy::DISCARD;
+  }
+
   RequestUpdateMeshMessage( mUpdateManager.GetEventToUpdate(),
                             mResourceManager,
                             ticket->GetId(),
-                            meshData );
+                            meshData,
+                            discardable );
 }
 
 Bitmap* ResourceClient::GetBitmap(ResourceTicketPtr ticket)
index 1b0180e..923e73f 100644 (file)
@@ -80,14 +80,21 @@ public:
    * @param[in] resourceManager The resource manager
    * @param[in] updateManager The update manager
    */
-  ResourceClient( ResourceManager& resourceManager, SceneGraph::UpdateManager& updateManager );
+  ResourceClient( ResourceManager& resourceManager,
+                  SceneGraph::UpdateManager& updateManager,
+                  ResourcePolicy::DataRetention dataRetentionPolicy );
 
   /**
    * Virtual destructor.
    */
   virtual ~ResourceClient();
 
-public: // Used by application-side objects e.g. Dali::Image
+public:
+  /**
+   * Get the global data retention policy.
+   * @return the global data retention policy
+   */
+  ResourcePolicy::DataRetention GetResourceDataRetentionPolicy();
 
   /**
    * Request a resource from the native filesystem.
@@ -134,10 +141,11 @@ public: // Used by application-side objects e.g. Dali::Image
    * ResourceLoadingFailed()
    *
    * @param[in] id resource id
+   * @param[in] resetFinishedStatus True if the finished status of the current image should be reset.
    * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
    * @return true if successful, false if resource doesn't exist
    */
-  bool ReloadResource( ResourceId id, Integration::LoadResourcePriority priority = Integration::LoadPriorityNormal );
+  bool ReloadResource( ResourceId id, bool resetFinishedStatus = false, Integration::LoadResourcePriority priority = Integration::LoadPriorityNormal );
 
   /**
    * Save a resource to the given url.
index eabda31..24449f3 100644 (file)
@@ -143,6 +143,37 @@ GlyphLoadObserver& GlyphAtlasManager::GetLoadObserver()
   return mGlyphResourceManager;
 }
 
+void GlyphAtlasManager::ReloadAtlases()
+{
+  std::vector<GlyphAtlas*> newAtlasList;
+
+  // Copy all atlases to a new list
+  for( AtlasList::Iterator it = mAtlasList.Begin(), end = mAtlasList.End() ;
+       it != end ; ++it )
+  {
+    // Create a new atlas the same size as the previous atlas.
+    GlyphAtlas* oldAtlas = *it;
+
+    GlyphAtlas* newAtlas = GlyphAtlas::New(oldAtlas->GetSize());
+    newAtlas->CloneContents( oldAtlas );
+
+    // Add it to temporary list
+    newAtlasList.push_back(newAtlas);
+
+    mGlyphResourceManager.RemoveObserver( *oldAtlas );
+  }
+  // destroy old atlases
+  mAtlasList.Clear();
+
+  // Add new atlases to proper list
+  for( std::vector<GlyphAtlas*>::iterator it = newAtlasList.begin(); it != newAtlasList.end(); ++it )
+  {
+    AddAtlas( *it );
+  }
+
+  mAtlasesChanged = true;
+}
+
 GlyphAtlas* GlyphAtlasManager::CreateAtlas( unsigned int size )
 {
   GlyphAtlas* atlas =  GlyphAtlas::New( size  );
index 958d66b..2663f92 100644 (file)
@@ -118,6 +118,12 @@ public:
    */
   GlyphLoadObserver& GetLoadObserver();
 
+  /**
+   * Reload glyphs into atlas, should be used after GL context has been regained
+   * (i.e. the GL texture backing the atlas has been lost)
+   */
+  void ReloadAtlases();
+
 private:
 
   // Undefined copy constructor.
index c088d0f..3062a3c 100644 (file)
@@ -140,6 +140,11 @@ void FontFactory::SetDpi( float horizontalDpi, float verticalDpi )
   mVerticalDpi = verticalDpi;
 }
 
+void FontFactory::RecoverFromContextLoss()
+{
+  mAtlasManager->ReloadAtlases();
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 3974b6f..cdd530f 100644 (file)
@@ -92,6 +92,12 @@ public:
    */
   void SetDpi( float horizontalDpi, float verticalDpi );
 
+  /**
+   * Called when context has been regained after a loss. The text subsystem will
+   * reload the glyphs into a new atlas and inform their observers.
+   */
+  void RecoverFromContextLoss();
+
 public: // FontLookupInterface
 
   /**
index c510a19..f9f9c83 100644 (file)
@@ -337,7 +337,6 @@ TextVertexBuffer* Font::TextRequired( const Integration::TextArray& text, const
 
   mMetrics->LoadMetricsSynchronously( text );
 
-
   return mAtlasManager.TextRequired(text, format, *(mMetrics.Get()));
 }
 
index 641441f..a154eee 100644 (file)
@@ -208,10 +208,13 @@ void RenderManager::ContextCreated()
 
 void RenderManager::ContextDestroyed()
 {
+  // @todo Set an atomic value to prevent render manager rendering again until
+  // ContextCreated has been called.
+
   mImpl->context.GlContextDestroyed();
 
   // inform texture cache
-  mImpl->textureCache.GlContextDestroyed();
+  mImpl->textureCache.GlContextDestroyed(); // Clears gl texture ids
 
   // inform renderers
   RendererOwnerContainer::Iterator end = mImpl->rendererContainer.End();
@@ -219,7 +222,7 @@ void RenderManager::ContextDestroyed()
   for( ; iter != end; ++iter )
   {
     GlResourceOwner* renderer = *iter;
-    renderer->GlContextDestroyed();
+    renderer->GlContextDestroyed(); // Clear up vertex buffers
   }
 }
 
index 0900dc6..75c44f1 100644 (file)
@@ -36,32 +36,39 @@ namespace Dali
 namespace Internal
 {
 
-BitmapTexture::BitmapTexture(Integration::Bitmap* const bitmap, const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile, Context& context)
-: Texture(context,
-          bitmapPackedPixelsProfile->GetBufferWidth(),
-          bitmapPackedPixelsProfile->GetBufferHeight(),
-          bitmap->GetImageWidth(),
-          bitmap->GetImageHeight(),
-          bitmap->GetPixelFormat()),
+BitmapTexture::BitmapTexture(
+  Integration::Bitmap* const bitmap,
+  const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile,
+  Context& context,
+  ResourcePolicy::Discardable policy)
+: Texture( context,
+           bitmapPackedPixelsProfile->GetBufferWidth(),
+           bitmapPackedPixelsProfile->GetBufferHeight(),
+           bitmap->GetImageWidth(),
+           bitmap->GetImageHeight(),
+           bitmap->GetPixelFormat()),
   mBitmap(bitmap),
-  mClearPixels(false)
+  mClearPixels(false),
+  mDiscardPolicy(policy)
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
   DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
 }
 
 BitmapTexture::BitmapTexture(
-  unsigned int  width,
-  unsigned int  height,
+  unsigned int width,
+  unsigned int height,
   Pixel::Format pixelFormat,
-  bool          clearPixels,
-  Context&      context)
-: Texture(context,
-          width, height,
-          width, height,
-          pixelFormat),
+  bool clearPixels,
+  Context& context,
+  ResourcePolicy::Discardable policy)
+: Texture( context,
+           width, height,
+           width, height,
+           pixelFormat),
   mBitmap(NULL),
-  mClearPixels(clearPixels)
+  mClearPixels(clearPixels),
+  mDiscardPolicy(policy)
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
 }
@@ -69,12 +76,15 @@ BitmapTexture::BitmapTexture(
 BitmapTexture::~BitmapTexture()
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
   // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
   // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
 }
 
 void BitmapTexture::UploadBitmapArray( const BitmapUploadArray& bitmapArray )
 {
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
   if( mId == 0 )
   {
     CreateGlTexture();
@@ -110,20 +120,20 @@ void BitmapTexture::UploadBitmapArray( const BitmapUploadArray& bitmapArray )
                             bitmapWidth,
                             bitmapHeight);
 
-     mContext.TexSubImage2D(GL_TEXTURE_2D,
-                            0,                   /* mip map level */
-                            bitmapItem.mXpos,    /* X pos */
-                            bitmapItem.mYpos,    /* Y pos */
-                            bitmapWidth,         /* width */
-                            bitmapHeight,        /* height */
-                            pixelFormat,         /* our bitmap format (should match internal format) */
-                            pixelDataType,       /* pixel data type */
-                            pixels);             /* texture data */
-
-     if( BitmapUpload::DISCARD_PIXEL_DATA == bitmapItem.mDiscard)
-     {
-       delete [] bitmapItem.mPixelData;
-     }
+    mContext.TexSubImage2D(GL_TEXTURE_2D,
+                           0,                   /* mip map level */
+                           bitmapItem.mXpos,    /* X pos */
+                           bitmapItem.mYpos,    /* Y pos */
+                           bitmapWidth,         /* width */
+                           bitmapHeight,        /* height */
+                           pixelFormat,         /* our bitmap format (should match internal format) */
+                           pixelDataType,       /* pixel data type */
+                           pixels);             /* texture data */
+
+    if( BitmapUpload::DISCARD_PIXEL_DATA == bitmapItem.mDiscard)
+    {
+      delete [] bitmapItem.mPixelData;
+    }
   }
 }
 
@@ -248,14 +258,15 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap )
 
   const unsigned char* pixels = mBitmap->GetBuffer();
 
+  // We should never have null pixel data here - resource manager has deliberately loaded/reloaded data
+
   DALI_ASSERT_DEBUG( pixels != NULL );
 
-  if ( NULL == pixels )
+  if( NULL == pixels )
   {
-    DALI_LOG_ERROR("bitmap has no data\n");
-    GlCleanup(); // Note, We suicide here in the case of bad input.
+    DALI_LOG_ERROR("BitmapTexture::Upload() - Bitmap has no pixel data.\n");
   }
-  else
+  else if( mId != 0 )
   {
     if( mImageWidth == mBitmap->GetImageWidth() &&
         mImageHeight == mBitmap->GetImageHeight() &&
@@ -263,26 +274,19 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap )
         mHeight == bitmapPackedPixels->GetBufferHeight() &&
         mPixelFormat == mBitmap->GetPixelFormat() ) // and size hasn't changed
     {
-      if ( mId ) // If the texture is already bound
-      {
-        RectArea area(0, 0, mImageWidth, mImageHeight);  // just update whole texture
-        AreaUpdated( area, pixels );
-        mBitmap->DiscardBuffer();
-      }
+      RectArea area(0, 0, mImageWidth, mImageHeight);  // just update whole texture
+      AreaUpdated( area, pixels );
+      DiscardBitmapBuffer();
     }
-    else
-    {                                           // Otherwise, reload the pixel data
+    else // Otherwise, reload the pixel data
+    {
       mImageWidth  = mBitmap->GetImageWidth();
       mImageHeight = mBitmap->GetImageHeight();
       mWidth       = bitmapPackedPixels->GetBufferWidth();
       mHeight      = bitmapPackedPixels->GetBufferHeight();
       mPixelFormat = mBitmap->GetPixelFormat();
 
-      if ( mId ) // If the texture is already bound
-      {
-        AssignBitmap( false, pixels );
-        mBitmap->DiscardBuffer();
-      }
+      AssignBitmap( false, pixels );
     }
   }
 }
@@ -294,14 +298,12 @@ void BitmapTexture::UpdateArea( const RectArea& updateArea )
   if( mBitmap != 0 )
   {
     const unsigned char* pixels = mBitmap->GetBuffer();
-    if ( NULL == pixels )
-    {
-      DALI_LOG_ERROR("bitmap has no data\n");
-      GlCleanup(); ///!ToDo: Why do we suicide in the case of bad input?
-    }
-    else
+
+    // Pixel data could be null if we've uploaded to GL and discarded the data.
+
+    if( NULL != pixels )
     {
-      if ( mId ) // If the texture is already bound
+      if( mId ) // If the texture is already bound
       {
         if( updateArea.IsEmpty() )
         {
@@ -376,18 +378,21 @@ bool BitmapTexture::UpdateOnCreate()
 bool BitmapTexture::CreateGlTexture()
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
-  DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
+  DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "BitmapTexture::CreateGlTexture() Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
 
   if( mBitmap )
   {
     const unsigned char* pixels = mBitmap->GetBuffer();
 
-    DALI_ASSERT_DEBUG(pixels != NULL);
+    // pixel data could be NULL here if we've had a context loss and we previously discarded
+    // the pixel data on the previous upload. If it is null, then we shouldn't generate a
+    // new GL Texture; leaving mId as zero. Eventually, the bitmap will get reloaded,
+    // and pixels will become non-null.
 
     if( NULL != pixels )
     {
       AssignBitmap( true, pixels );
-      mBitmap->DiscardBuffer();
+      DiscardBitmapBuffer();
     }
   }
   else
@@ -433,6 +438,18 @@ unsigned int BitmapTexture::GetHeight() const
   return height;
 }
 
+void BitmapTexture::DiscardBitmapBuffer()
+{
+  DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::DISCARD?"DISCARD":"RETAIN");
+
+  if( ResourcePolicy::DISCARD == mDiscardPolicy )
+  {
+    DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "  Discarding bitmap\n");
+    mBitmap->DiscardBuffer();
+  }
+}
+
+
 } //namespace Internal
 
 } //namespace Dali
index 4e33d90..46073c8 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/internal/common/bitmap-upload.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/integration-api/debug.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
 
 namespace Dali
 {
@@ -54,7 +55,7 @@ public:
    * @param[in] bitmapPackedPixelsProfile The Bitmap features related to an addressable array of raw pixel data
    * @param     context The GL context
    */
-  BitmapTexture(Integration::Bitmap* const bitmap, const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile, Context& context);
+  BitmapTexture(Integration::Bitmap* const bitmap, const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile, Context& context, ResourcePolicy::Discardable discardPolicy);
 
   /**
    * Constructor
@@ -66,7 +67,7 @@ public:
    * @param[in] context Dali context
    */
   BitmapTexture( unsigned int width, unsigned int height, Pixel::Format pixelFormat,
-                 bool clearPixels, Context& context );
+                 bool clearPixels, Context& context, ResourcePolicy::Discardable discardPolicy );
 
   /**
    * Destructor.
@@ -159,9 +160,15 @@ private:
    */
   void AssignBitmap( bool generateTexture, const unsigned char* pixels );
 
+  /**
+   * If the discard policy is not RETAIN, then discards the bitmap's pixel buffer
+   */
+  void DiscardBitmapBuffer();
+
 private:
   Integration::BitmapPtr mBitmap;      ///< The Bitmap the Texture was created from (may be NULL)
   bool                   mClearPixels; ///< true if initial texture should be cleared on creation
+  ResourcePolicy::Discardable mDiscardPolicy; ///< The bitmap discard policy
 
   // Changes scope, should be at end of class
   DALI_LOG_OBJECT_STRING_DECLARATION;
index 7642833..ba5ff0d 100644 (file)
@@ -36,14 +36,15 @@ namespace Dali
 namespace Internal
 {
 
-CompressedBitmapTexture::CompressedBitmapTexture(Internal::BitmapCompressed* const bitmap, Context& context)
+CompressedBitmapTexture::CompressedBitmapTexture(Internal::BitmapCompressed* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy)
 : Texture(context,
           bitmap->GetImageWidth(),
           bitmap->GetImageHeight(),
           bitmap->GetImageWidth(),
           bitmap->GetImageHeight(),
           bitmap->GetPixelFormat()),
-  mBitmap(bitmap)
+  mBitmap(bitmap),
+  mDiscardPolicy(discardPolicy)
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
   DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
@@ -139,7 +140,11 @@ void CompressedBitmapTexture::Update( Integration::Bitmap* bitmap )
     if ( mId ) // If the texture is already bound
     {
       AssignBitmap( false, pixels, mBitmap->GetBufferSize() );
-      mBitmap->DiscardBuffer();
+
+      if( mDiscardPolicy == ResourcePolicy::DISCARD )
+      {
+        mBitmap->DiscardBuffer();
+      }
     }
   }
 }
index 45f124b..583c1ff 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/public-api/images/bitmap-image.h>
 #include <dali/internal/common/message.h>
 #include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
 #include <dali/internal/common/bitmap-upload.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/internal/event/images/bitmap-compressed.h>
@@ -55,9 +56,10 @@ public:
    * Constructor
    * Creates a new texture object from a Bitmap
    * @param[in] bitmap The Bitmap
-   * @param     context The GL context
+   * @param[in] context The GL context
+   * @param[in] discardPolicy The discard policy
    */
-  CompressedBitmapTexture( Internal::BitmapCompressed* const bitmap, Context& context );
+  CompressedBitmapTexture( Internal::BitmapCompressed* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy );
 
   /**
    * Destructor.
@@ -121,6 +123,7 @@ private:
 
 private:
   Internal::BitmapCompressedPtr mBitmap;      ///< The Bitmap the Texture was created from (may be NULL)
+  ResourcePolicy::Discardable mDiscardPolicy;
 
   // Changes scope, should be at end of class
   DALI_LOG_OBJECT_STRING_DECLARATION;
index f664268..6d5aef8 100644 (file)
@@ -72,6 +72,7 @@ const unsigned int UNINITIALIZED_TEXTURE_UNIT = std::numeric_limits<unsigned int
 
 #ifdef DEBUG_ENABLED
 Debug::Filter* Context::gGlLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT");
+Debug::Filter* gContextLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT_META");
 #endif
 
 Context::Context(Integration::GlAbstraction& glAbstraction)
@@ -118,6 +119,8 @@ Context::~Context()
 
 void Context::GlContextCreated()
 {
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
+
   DALI_ASSERT_DEBUG(!mGlContextCreated);
 
   mGlContextCreated = true;
@@ -125,15 +128,14 @@ void Context::GlContextCreated()
   // Set the initial GL state, and check it.
   ResetGlState();
 
-  const ProgramContainer::iterator endp = mProgramCache.end();
-  for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
-  {
-    (*itp).second->GlContextCreated();
-  }
+  // Programs now load on demand
 }
 
 void Context::GlContextDestroyed()
 {
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextDestroyed()\n");
+
+  // Inform programs they are no longer valid
   const ProgramContainer::iterator endp = mProgramCache.end();
   for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
   {
@@ -252,6 +254,7 @@ void Context::ResetVertexAttributeState()
 
 void Context::ResetGlState()
 {
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
   DALI_ASSERT_DEBUG(mGlContextCreated);
 
   mClearColorSet = false;
index 9b37ad6..073a2a0 100644 (file)
@@ -584,7 +584,7 @@ public:
    */
   void DeleteBuffers(GLsizei n, const GLuint* buffers)
   {
-    // TODO: this is to prevent mesh destructor from doing GL calls when DALi core is being deleted
+    // @todo: this is to prevent mesh destructor from doing GL calls when DALi core is being deleted
     // can be taken out once render manages either knows about meshes or gpubuffers and can tell them directly that context is lost
     if( this->IsGlContextCreated() )
     {
index c8249ff..2191b23 100644 (file)
@@ -36,6 +36,14 @@ using Dali::Internal::Texture;
 using Dali::Internal::FrameBufferTexture;
 using Dali::Integration::Bitmap;
 
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
+#endif
+}
+
+
 namespace Dali
 {
 namespace Internal
@@ -52,7 +60,8 @@ TextureCache::TextureCache( RenderQueue& renderQueue,
                             Context& context)
 : TextureCacheDispatcher(renderQueue),
   mPostProcessResourceDispatcher(postProcessResourceDispatcher),
-  mContext(context)
+  mContext(context),
+  mDiscardBitmapsPolicy(ResourcePolicy::DISCARD)
 {
 }
 
@@ -68,7 +77,7 @@ void TextureCache::CreateTexture( ResourceId        id,
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
 
-  Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext);
+  Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
   mTextures.insert(TexturePair(id, texture));
 }
 
@@ -76,7 +85,7 @@ void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
 
-  Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext);
+  Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
   mTextures.insert(TexturePair(id, texture));
 }
 
@@ -120,7 +129,7 @@ void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
     TexturePointer texturePtr = textureIter->second;
     if( texturePtr )
     {
-      texturePtr->Update(bitmap.Get());
+      texturePtr->Update( bitmap.Get() );
 
       ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
       mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
@@ -372,6 +381,19 @@ void TextureCache::GlContextDestroyed()
   }
 }
 
+void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
+{
+  DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
+                 policy==ResourcePolicy::RETAIN?"RETAIN":"DISCARD" );
+  mDiscardBitmapsPolicy = policy;
+}
+
+ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
+{
+  return mDiscardBitmapsPolicy;
+}
+
+
 /********************************************************************************
  **********************  Implements TextureCacheDispatcher  *********************
  ********************************************************************************/
index 581b082..dad0f54 100644 (file)
@@ -27,6 +27,8 @@
 #include <dali/public-api/images/native-image.h>
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/math/vector4.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/resource-policies.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/internal/update/common/scene-graph-buffers.h>
@@ -68,7 +70,7 @@ typedef TextureContainer::const_iterator        TextureConstIter;
 class TextureCache : public TextureCacheDispatcher
 {
 public:
 /**
+ /**
    * Constructor
    * @param[in] renderQueue Queue to use for dispatching messages to this object
    * @param[in] postProcessDispatcher Dispatcher for resource post processing requests
@@ -215,6 +217,18 @@ public:
    */
   void GlContextDestroyed();
 
+  /**
+   * Set whether textures should retain or discard their bitmaps after upload to GL
+   * @param[in] policy Whether to retain or discard bitmaps
+   */
+  void SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy );
+
+  /**
+   * Get the discard policy.
+   * @return The discard policy.
+   */
+  ResourcePolicy::Discardable GetDiscardBitmapsPolicy();
+
 protected: // Implements TextureCacheDispatcher
 
   /**
@@ -285,6 +299,7 @@ private:
   typedef TextureResourceObservers::iterator       TextureResourceObserversIter;
 
   TextureResourceObservers mObservers;
+  ResourcePolicy::Discardable mDiscardBitmapsPolicy;
 };
 
 
index 87fa20a..72ac11a 100644 (file)
@@ -38,21 +38,21 @@ namespace Internal
 namespace TextureFactory
 {
 
-Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap, Context& context )
+Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy )
 {
   DALI_ASSERT_DEBUG( bitmap );
   Texture * texture = 0;
   Integration::Bitmap::PackedPixelsProfile * const  packedPixelBitmapView = bitmap->GetPackedPixelsProfile();
   if( packedPixelBitmapView )
   {
-    texture = new BitmapTexture( bitmap, packedPixelBitmapView, context );
+    texture = new BitmapTexture( bitmap, packedPixelBitmapView, context, discardPolicy );
   }
   else
   {
     Internal::BitmapCompressed * const compressedBitmap = dynamic_cast<Dali::Internal::BitmapCompressed*>( bitmap );
     if( compressedBitmap != 0 )
     {
-      texture = new CompressedBitmapTexture( compressedBitmap, context );
+      texture = new CompressedBitmapTexture( compressedBitmap, context, discardPolicy );
     }
   }
   if( texture )
@@ -70,9 +70,10 @@ Internal::Texture* NewBitmapTexture( unsigned int      width,
                                      unsigned int      height,
                                      Pixel::Format     pixelFormat,
                                      bool              clearPixels,
-                                     Context&          context )
+                                     Context&          context,
+                                     ResourcePolicy::Discardable discardPolicy )
 {
-  Texture *texture=new BitmapTexture(width, height, pixelFormat, clearPixels, context);
+  Texture *texture=new BitmapTexture(width, height, pixelFormat, clearPixels, context, discardPolicy);
 
   return texture;
 }
@@ -120,4 +121,3 @@ Internal::Texture* NewFrameBufferTexture( NativeImagePtr nativeImage,
 } // TextureFactory
 } // Internal
 } // Dali
-
index c71dd30..59131eb 100644 (file)
@@ -21,7 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/images/native-image.h>
-
+#include <dali/internal/render/gl-resources/texture-cache.h>
 
 namespace Dali
 {
@@ -45,7 +45,9 @@ namespace TextureFactory
  * @param[in] context The GL context
  * @return A newly allocated texture
  */
-Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap, Context& context );
+Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap,
+                                     Context& context,
+                                     ResourcePolicy::Discardable discardPolicy );
 
 /**
  * Creates a new bitmap texture object of the given dimensions.
@@ -59,7 +61,8 @@ Internal::Texture* NewBitmapTexture( unsigned int      width,
                                      unsigned int      height,
                                      Pixel::Format     pixelFormat,
                                      bool              clearPixels,
-                                     Context&          context );
+                                     Context&          context,
+                                     ResourcePolicy::Discardable discardPolicy );
 
 /**
  * Creates a texture object from a native image (eg.: EGLImage).
index 6e2c98d..32b41a5 100644 (file)
@@ -98,8 +98,7 @@ Texture::Texture(Context&      context,
   mHeight(height),
   mImageWidth(imageWidth),
   mImageHeight(imageHeight),
-  mPixelFormat(pixelFormat),
-  mDiscarded(false)
+  mPixelFormat(pixelFormat)
 {
 }
 
@@ -275,7 +274,7 @@ void Texture::ApplyTextureParameter( GLint filterType, FilterMode::Type currentF
 
 void Texture::ApplySampler( unsigned int samplerBitfield )
 {
-  if( mSamplerBitfield != samplerBitfield )
+  if( mSamplerBitfield != samplerBitfield && mId != 0 )
   {
     ApplyTextureParameter( GL_TEXTURE_MIN_FILTER,
                            ImageSampler::GetMinifyFilterMode( mSamplerBitfield ),
index 1ff8a7e..805c47d 100644 (file)
@@ -85,11 +85,12 @@ public:
 
   /**
    * Binds the texture for use.
-   * Only when Bind() is first called, does a texture create an
-   * an opengl texture.
+   * If there is no GL texture yet, it tries to create one.
+   *
    * @param target (e.g. GL_TEXTURE_2D)
    * @param textureunit to bind to
-   * @return True if the opengl texture was created
+   * @return True if the opengl texture was created, false if there was already a texture
+   * or no texture could be created yet ( e.g. no bitmap data after context loss )
    */
   virtual bool Bind(GLenum target, GLenum textureunit);
 
@@ -274,7 +275,6 @@ protected:
   unsigned int  mImageHeight;  ///< height of the original image (may be smaller than texture height)
 
   Pixel::Format mPixelFormat;  ///< Pixel format of the contained image data.
-  bool          mDiscarded;    ///< True if texture was added to the DiscardQueue
 
 };
 
index 292cf66..96bd12a 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
 #include <dali/internal/common/internal-constants.h>
 #include <dali/internal/render/common/culling-algorithms.h>
 #include <dali/internal/render/common/performance-monitor.h>
@@ -36,6 +37,10 @@ using namespace std;
 
 namespace
 {
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gImageRenderFilter=Debug::Filter::New(Debug::NoLogging, false, "LOG_IMAGE_RENDERER");
+#endif
+
 /**
  * VertexToTextureCoord
  * Represents a mapping between a 1 dimensional vertex coordinate
@@ -184,6 +189,8 @@ void ImageRenderer::GlContextDestroyed()
 
 void ImageRenderer::GlCleanup()
 {
+  DALI_LOG_INFO( gImageRenderFilter, Debug::Verbose, "GlCleanup() textureId=%d  texture:%p\n", mTextureId, mTexture);
+
   mVertexBuffer.Reset();
   mIndexBuffer.Reset();
 }
@@ -245,6 +252,8 @@ bool ImageRenderer::IsOutsideClipSpace( const Matrix& modelMatrix, const Matrix&
 
 void ImageRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
 {
+  DALI_LOG_INFO( gImageRenderFilter, Debug::Verbose, "DoRender() textureId=%d  texture:%p\n", mTextureId, mTexture);
+
   DALI_ASSERT_DEBUG( 0 != mTextureId && "ImageRenderer::DoRender. mTextureId == 0." );
   DALI_ASSERT_DEBUG( NULL != mTexture && "ImageRenderer::DoRender. mTexture == NULL." );
 
@@ -256,6 +265,12 @@ void ImageRenderer::DoRender( BufferIndex bufferIndex, Program& program, const M
   DALI_ASSERT_DEBUG( mVertexBuffer );
 
   mTextureCache->BindTexture( mTexture, mTextureId,  GL_TEXTURE_2D, GL_TEXTURE0 );
+
+  if( mTexture->GetTextureId() == 0 )
+  {
+    return; // early out if we haven't got a GL texture yet (e.g. due to context loss)
+  }
+
   mTexture->ApplySampler( mSamplerBitfield );
 
   // make sure the vertex is bound, this has to be done before
index b014a48..c6b605c 100644 (file)
@@ -169,9 +169,9 @@ GLint Program::GetAttribLocation( AttribType type )
 
   if( mAttribLocations[ type ] == ATTRIB_UNKNOWN )
   {
-    LOG_GL( "GetAttribLocation(program=%d,%s) = %d\n", mProgramId, gStdAttribs[type], mAttribLocations[type] );
     GLint loc = CHECK_GL( mContext, mGlAbstraction.GetAttribLocation( mProgramId, gStdAttribs[type] ) );
     mAttribLocations[ type ] = loc;
+    LOG_GL( "GetAttribLocation(program=%d,%s) = %d\n", mProgramId, gStdAttribs[type], mAttribLocations[type] );
   }
 
   return mAttribLocations[type];
@@ -204,10 +204,10 @@ GLint Program::GetUniformLocation( unsigned int uniformIndex )
 
   if( location == UNIFORM_NOT_QUERIED )
   {
-    LOG_GL( "GetUniformLocation(program=%d,%s) = %d\n", mProgramId, mUniformLocations[ uniformIndex ].first.c_str(), mUniformLocations[ uniformIndex ].second );
     location = CHECK_GL( mContext, mGlAbstraction.GetUniformLocation( mProgramId, mUniformLocations[ uniformIndex ].first.c_str() ) );
 
     mUniformLocations[ uniformIndex ].second = location;
+    LOG_GL( "GetUniformLocation(program=%d,%s) = %d\n", mProgramId, mUniformLocations[ uniformIndex ].first.c_str(), mUniformLocations[ uniformIndex ].second );
   }
 
   return location;
@@ -412,22 +412,18 @@ void Program::SetUniformMatrix3fv( GLint location, GLsizei count, const GLfloat*
 
 void Program::GlContextCreated()
 {
-  if (!mLinked)
-  {
-    Load();
-  }
 }
 
 void Program::GlContextDestroyed()
 {
-  Unload();
+  mLinked = false;
 
   mVertexShaderId = 0;
   mFragmentShaderId = 0;
   mProgramId = 0;
   mContext.SetCurrentProgram( NULL );
 
-  ResetAttribsUniforms();
+  ResetAttribsUniformCache();
 }
 
 bool Program::ModifiesGeometry()
@@ -455,7 +451,7 @@ Program::Program(Integration::ShaderDataPtr shaderData, Context& context, bool m
     RegisterUniform( gStdUniforms[ i ] );
   }
   // reset values
-  ResetAttribsUniforms();
+  ResetAttribsUniformCache();
 }
 
 Program::~Program()
@@ -656,7 +652,7 @@ void Program::FreeShaders()
   }
 }
 
-void Program::ResetAttribsUniforms()
+void Program::ResetAttribsUniformCache()
 {
   // reset attribute locations
   for( unsigned i = 0; i < ATTRIB_TYPE_LAST; ++i )
index 5cd97a3..b9efacc 100644 (file)
@@ -348,7 +348,7 @@ private:
   /**
    * Resets caches
    */
-  void ResetAttribsUniforms();
+  void ResetAttribsUniformCache();
 
 private:  // Data
 
index be32605..2cd7859 100644 (file)
@@ -317,7 +317,8 @@ void Shader::SetUniforms( Context& context,
   if( mTexture )
   {
     // got effect texture, bind it to texture unit 1
-    mTexture->Bind( GL_TEXTURE_2D, GL_TEXTURE1 );
+    mTextureCache->BindTexture( mTexture, mRenderTextureId, GL_TEXTURE_2D, GL_TEXTURE1 );
+
     // Just apply the default sampling options for now
     mTexture->ApplySampler( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) );
 
index 69227ab..13bbf90 100644 (file)
 
 #include <dali/internal/update/modeling/internal-mesh-data.h>
 
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+
 namespace Dali
 {
 
 namespace Internal
 {
 
-MeshData::MeshData( const Dali::MeshData& meshData, bool discardable, bool scalingRequired )
+MeshData::MeshData( const Dali::MeshData& meshData, ResourcePolicy::Discardable discardable, bool scalingRequired )
 : mVertices( meshData.GetVertices() ),
   mFaces( meshData.GetFaces() ),
   mBones( meshData.GetBones() ),
@@ -32,7 +35,7 @@ MeshData::MeshData( const Dali::MeshData& meshData, bool discardable, bool scali
   mGeometryType( meshData.GetVertexGeometryType() ),
   mHasNormals( meshData.HasNormals() ),
   mHasColor( meshData.HasColor() ),
-  mDiscardable( discardable ),
+  mDiscardable( discardable==ResourcePolicy::DISCARD ),
   mDiscarded( false ),
   mScalingRequired( scalingRequired )
 {
@@ -118,7 +121,7 @@ bool MeshData::HasColor() const
 
 void MeshData::Discard()
 {
-  if (mDiscardable)
+  if( mDiscardable )
   {
     DALI_ASSERT_DEBUG( !mDiscarded );
     VertexContainer().swap(mVertices);  // this will enforce releasing the memory
index ae3e33a..73b0539 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <dali/public-api/geometry/mesh-data.h>
+#include <dali/integration-api/resource-policies.h>
 
 namespace Dali
 {
@@ -52,7 +53,7 @@ public:
    * @param[in] discardable if true, the vertex and index data will be discarded after they are uploaded to gl
    * @param[in] scalingRequired - True if this Mesh should be scaled to fit actor size
    */
-  explicit MeshData( const Dali::MeshData& meshData, bool discardable, bool scalingRequired );
+  explicit MeshData( const Dali::MeshData& meshData, ResourcePolicy::Discardable discardable, bool scalingRequired );
 
   /**
    * @copydoc Dali::MeshData::GetVertexCount
index 4bdf15e..321498d 100644 (file)
@@ -124,6 +124,18 @@ void Mesh::UploadVertexData( Context& context, BufferIndex renderBufferIndex )
     return;
   }
 
+  DoUpload(context);
+
+  // Note, dispatcher should only be used in Render Thread (as should the rest of this method!)
+  ResourcePostProcessRequest ppRequest( mResourceId, ResourcePostProcessRequest::UPLOADED );
+  mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+
+  mRenderMeshData->Discard();
+  mRefreshVertexBuffer = false;
+}
+
+void Mesh::DoUpload( Context& context )
+{
   const MeshData::VertexContainer& vertices = mRenderMeshData->GetVertices();
 
   DALI_ASSERT_DEBUG( !vertices.empty() );
@@ -149,13 +161,6 @@ void Mesh::UploadVertexData( Context& context, BufferIndex renderBufferIndex )
     mIndicesBuffer->UpdateDataBuffer( numberOfIndices * sizeof(GLushort), &(faces.at(0)) );
     mNumberOfFaces = mRenderMeshData->GetFaceCount();
   }
-
-  // Note, dispatcher should only be used in Render Thread (as should the rest of this method!)
-  ResourcePostProcessRequest ppRequest( mResourceId, ResourcePostProcessRequest::UPLOADED );
-  mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
-
-  mRenderMeshData->Discard();
-  mRefreshVertexBuffer = false;
 }
 
 void Mesh::BindBuffers(Context& context)
@@ -168,9 +173,18 @@ void Mesh::BindBuffers(Context& context)
 
   DALI_ASSERT_DEBUG( mIndicesBuffer || mRenderMeshData->GetVertexGeometryType() == Dali::MeshData::POINTS );
 
-  mVertexBuffer->Bind();
+  // Try and recover from context loss using retained data.
+  if( ! mVertexBuffer->BufferIsValid() && ! mRenderMeshData->GetVertices().empty() )
+  {
+    DoUpload( context );
+  }
+
+  if( mVertexBuffer->BufferIsValid() )
+  {
+    mVertexBuffer->Bind();
+  }
 
-  if( mIndicesBuffer)
+  if( mIndicesBuffer && mIndicesBuffer->BufferIsValid())
   {
     mIndicesBuffer->Bind();
   }
index 5c694c2..f463fe6 100644 (file)
@@ -107,7 +107,7 @@ public:
   void MeshDataUpdated( BufferIndex bufferIndex, ThreadBuffer threadBuffer, MeshData* meshData );
 
   /**
-   * Sends the vertex data to GL
+   * Sends the vertex data to GL if it has been refreshed. Notify resource manager when it has finished.
    * @pre this function should only be called from the render thread
    * @param[in] context The GL context.
    * @param[in] renderBufferIndex The index that should be accessed in double buffered values.
@@ -115,6 +115,12 @@ public:
   void UploadVertexData( Context& context, BufferIndex renderBufferIndex );
 
   /**
+   * Actually perform the vertex upload.
+   * @param[in] context The GL context.
+   */
+  void DoUpload( Context& context );
+
+  /**
    * Bind the vertex and index buffers.
    * @pre this function should only be called from the render thread
    * @param[in] context The GL context.
index 0f7e805..cf8e95f 100644 (file)
@@ -255,7 +255,9 @@ bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, Resourc
     break;
   }
 
-  ATTACHMENT_LOG_FMT(Debug::General, " finished:%s ready:%s \n", mFinishedResourceAcquisition?"T":"F", ready?"T":"F");
+  ATTACHMENT_LOG_FMT(Debug::General, " ObjName:%s finished:%s ready:%s \n",
+                     DALI_LOG_GET_OBJECT_C_STR(mParent),
+                     mFinishedResourceAcquisition?"T":"F", ready?"T":"F");
 
   return ready;
 }
@@ -264,7 +266,9 @@ void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
 {
   DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
 
-  ATTACHMENT_LOG_FMT(Debug::General, " textureId:%d\n", mTextureId);
+  ATTACHMENT_LOG_FMT(Debug::General, "ObjName:%s textureId:%d\n",
+                     DALI_LOG_GET_OBJECT_C_STR(mParent),
+                     mTextureId);
 
   // Check whether we need to refresh the vertex buffer.
   if ( mRefreshMeshData )
index c56833a..8c28a81 100644 (file)
@@ -88,6 +88,11 @@ typedef ShaderCache::iterator                 ShaderCacheIter;
 typedef ShaderCache::size_type                ShaderCacheSize;
 typedef pair<ResourceId, ShaderDataPtr>       ShaderDataPair;
 
+static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
+{
+  return container.erase(id) != 0;
+}
+
 struct ResourceManager::ResourceManagerImpl
 {
   ResourceManagerImpl( PlatformAbstraction& platformAbstraction,
@@ -445,13 +450,21 @@ void ResourceManager::HandleUpdateMeshRequest( BufferIndex updateBufferIndex, Re
   new (slot) DerivedType( mesh, &SceneGraph::Mesh::MeshDataUpdated, SceneGraph::Mesh::RENDER_THREAD, meshData );
 }
 
-void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority )
+void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
 {
   DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
   DALI_LOG_INFO( Debug::Filter::gResource, Debug::General, "ResourceManager: HandleReloadRequest(id:%u, path:%s)\n", id, typePath.path.c_str() );
 
   bool resourceIsAlreadyLoading = true;
 
+  if( resetFinishedStatus )
+  {
+    if( ! RemoveId( mImpl->newCompleteRequests, id ) )
+    {
+      RemoveId( mImpl->oldCompleteRequests, id );
+    }
+  }
+
   // ID might be in the loading set
   LiveRequestIter iter = mImpl->loadingRequests.find( id );
   if ( iter == mImpl->loadingRequests.end() )
@@ -463,7 +476,7 @@ void ResourceManager::HandleReloadResourceRequest( ResourceId id, const Resource
 
   if ( !resourceIsAlreadyLoading )
   {
-    //load resource again
+    // load resource again
     mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
     SendToClient( LoadingMessage( *mImpl->mResourceClient, id ) );
   }
@@ -539,11 +552,6 @@ void ResourceManager::HandleSaveResourceRequest( ResourceId id, const ResourceTy
   }
 }
 
-static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
-{
-  return container.erase(id) != 0;
-}
-
 void ResourceManager::HandleDiscardResourceRequest( ResourceId deadId, ResourceTypeId typeId )
 {
   bool wasComplete = false;
index 56bfd55..2a2a947 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <dali/internal/common/event-to-update.h>
 #include <dali/internal/common/message.h>
+#include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/common/bitmap-upload.h>
 #include <dali/internal/event/text/font-impl.h>
 #include <dali/internal/event/modeling/model-data-impl.h>
@@ -284,8 +285,9 @@ public: // Used by ResourceClient
    * @param[in] id The resource id
    * @param[in] typePath The type & path of the resource
    * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
+   * @param[in] resetFinishedStatus True if the finished status of the resource id should be reset
    */
-  void HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, Integration::LoadResourcePriority priority );
+  void HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, Integration::LoadResourcePriority priority, bool resetFinishedStatus );
 
   /**
    * Save a resource to the given url
@@ -631,14 +633,14 @@ inline void RequestUpdateBitmapAreaMessage( EventToUpdate& eventToUpdate,
 inline void RequestUpdateMeshMessage( EventToUpdate& eventToUpdate,
                                       ResourceManager& manager,
                                       ResourceId id,
-                                      const Dali::MeshData& meshData )
+                                      const Dali::MeshData& meshData,
+                                      ResourcePolicy::Discardable discardable )
 {
   typedef MessageDoubleBuffered2< ResourceManager, ResourceId, OwnerPointer< MeshData > > LocalType;
-
   // Reserve some memory inside the message queue
   unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
 
-  MeshData* internalMeshData = new MeshData( meshData, true, false );
+  MeshData* internalMeshData = new MeshData( meshData, discardable, false );
 
   // Construct message in the message queue memory; note that delete should not be called on the return value
   new (slot) LocalType( &manager, &ResourceManager::HandleUpdateMeshRequest, id, internalMeshData );
@@ -648,15 +650,16 @@ inline void RequestReloadResourceMessage( EventToUpdate& eventToUpdate,
                                           ResourceManager& manager,
                                           ResourceId id,
                                           const ResourceTypePath& typePath,
-                                          Integration::LoadResourcePriority priority )
+                                          Integration::LoadResourcePriority priority,
+                                          bool resetFinishedStatus )
 {
-  typedef MessageValue3< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority > LocalType;
+  typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority, bool > LocalType;
 
   // Reserve some memory inside the message queue
   unsigned int* slot = eventToUpdate.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::HandleReloadResourceRequest, id, typePath, priority );
+  new (slot) LocalType( &manager, &ResourceManager::HandleReloadResourceRequest, id, typePath, priority, resetFinishedStatus );
 }
 
 inline void RequestSaveResourceMessage( EventToUpdate& eventToUpdate,
index 0a1d842..8be0a89 100644 (file)
@@ -194,4 +194,15 @@ Stage::TouchedSignalV2& Stage::TouchedSignal()
   return GetImplementation(*this).TouchedSignal();
 }
 
+
+Stage::ContextStatusSignal& Stage::ContextLostSignal()
+{
+  return GetImplementation(*this).ContextLostSignal();
+}
+
+Stage::ContextStatusSignal& Stage::ContextRegainedSignal()
+{
+  return GetImplementation(*this).ContextRegainedSignal();
+}
+
 } // namespace Dali
index 9884e5d..de8add0 100644 (file)
@@ -54,6 +54,7 @@ public:
   typedef SignalV2< void (const KeyEvent&)> KeyEventSignalV2;  ///< Key event signal type
   typedef SignalV2< void () > EventProcessingFinishedSignalV2; ///< Event Processing finished signal type
   typedef SignalV2< void (const TouchEvent&)> TouchedSignalV2; ///< Touched signal type
+  typedef SignalV2< void () > ContextStatusSignal; // Context status signal type
 
   static const Vector4 DEFAULT_BACKGROUND_COLOR; ///< Default black background.
   static const Vector4 DEBUG_BACKGROUND_COLOR;   ///< Green background, useful when debugging.
@@ -62,6 +63,8 @@ public:
   static const char* const SIGNAL_KEY_EVENT; ///< name "key-event"
   static const char* const SIGNAL_EVENT_PROCESSING_FINISHED; ///< name "event-processing-finished"
   static const char* const SIGNAL_TOUCHED; ///< name "touched"
+  static const char* const SIGNAL_CONTEXT_LOST; ///< name "context-lost"
+  static const char* const SIGNAL_CONTEXT_REGAINED; ///< name "context-regained"
 
   /**
    * @brief Allows the creation of an empty stage handle.
@@ -289,6 +292,25 @@ public:
    */
   TouchedSignalV2& TouchedSignal();
 
+  /**
+   * @brief This signal is emitted when the GL context is lost (Platform specific behaviour).
+   *
+   * If the application is responsible for handling context loss, it should listen to
+   * this signal and tear down UI components when recieved.
+   * @return The ContextLost signal to connect to.
+   */
+  ContextStatusSignal& ContextLostSignal();
+
+  /**
+   * @brief This signal is emitted when the GL context is regained (Platform specific
+   * behaviour).
+   *
+   * If the application is responsible for handling context loss, it should listen to
+   * this signal and rebuild UI components on receipt.
+   * @return The ContextRegained signal to connect to.
+   */
+  ContextStatusSignal& ContextRegainedSignal();
+
 public: // Not intended for application developers
 
   /**