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
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) );
{
// 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 )
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);
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
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);
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);
--- /dev/null
+/*
+ * 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;
+}
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);
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);
// 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
// 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() );
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
// 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
// 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 );
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 );
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 );
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 );
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 );
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 );
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 );
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", "");
return image;
}
-
/** Call this every test */
void TestPlatformAbstraction::Initialize()
{
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
void SetReadMetricsResult( bool success, std::vector<Integration::GlyphMetrics>& glyphMetricsContainer );
-
private:
mutable TraceCallStack mTrace;
size_t mSeconds;
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 );
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();
}
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 )
{
mPlatformAbstraction,
mGlAbstraction,
mGlSyncAbstraction,
- mGestureManager );
+ mGestureManager,
+ mDataRetentionPolicy);
mCore->ContextCreated();
mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
void TestApplication::ResetContext()
{
- mCore->ContextToBeDestroyed();
+ mCore->ContextDestroyed();
mCore->ContextCreated();
}
#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
{
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();
Vector2 mDpi;
unsigned int mLastVSyncTime;
+ ResourcePolicy::DataRetention mDataRetentionPolicy;
};
} // Dali
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)
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 );
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 );
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", "");
mReadMetrics = glyphMetricsContainer; // copy
}
+
} // namespace Dali
void SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics );
void SetReadMetricsResult( bool success, std::vector<Integration::GlyphMetrics>& glyphMetricsContainer );
-
-
private:
mutable TraceCallStack mTrace;
size_t mSeconds;
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);
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);
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);
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);
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);
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);
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);
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);
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);
// 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);
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);
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)
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)
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)
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)
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;
+}
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
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 );
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 );
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) );
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)
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);
#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>
return true;
}
+
+struct ContextStatusFunctor
+{
+ ContextStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag )
+ {
+ mCalledFlag = false;
+ }
+
+ void operator()()
+ {
+ mCalledFlag = true;
+ }
+ void Reset()
+ {
+ mCalledFlag = false;
+ }
+
+ bool& mCalledFlag;
+};
+
} // unnamed namespace
}
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;
+}
// 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>
}
}
-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);
* 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),
void Bitmap::DiscardBuffer()
{
- if ( mDiscardable )
+ if( mDiscardable == ResourcePolicy::DISCARD )
{
DeletePixelBuffer();
}
Bitmap::~Bitmap()
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
- DeletePixelBuffer();
+ if( mDiscardable == ResourcePolicy::DISCARD )
+ {
+ DeletePixelBuffer();
+ }
}
/**
} //namespace Integration
} //namespace Dali
-
#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
{
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
};
/**
- * 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. */
}
/**
- * 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;
}
*/
bool IsDiscardable() const
{
- return mDiscardable;
+ return mDiscardable == ResourcePolicy::DISCARD;
}
/**
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
--- /dev/null
+#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__
} // 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;
}
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)
// 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
{
struct Event;
struct TouchData;
+
/**
* The reasons why further updates are required.
*/
* @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.
// 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
* 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.
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 \
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
--- /dev/null
+#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__
// 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>
#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>
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
{
Core::Core( RenderController& renderController, PlatformAbstraction& platform,
GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction,
- GestureManager& gestureManager)
+ GestureManager& gestureManager, ResourcePolicy::DataRetention dataRetentionPolicy)
: mRenderController( renderController ),
mPlatform(platform),
mGestureEventProcessor(NULL),
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,
textureCache,
*mTouchResampler );
- mResourceClient = new ResourceClient( *mResourceManager, *mUpdateManager );
+ mResourceClient = new ResourceClient( *mResourceManager, *mUpdateManager, dataRetentionPolicy );
mStage = IntrusivePtr<Stage>( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager ) );
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();
}
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) );
}
// 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
{
Integration::PlatformAbstraction& platform,
Integration::GlAbstraction& glAbstraction,
Integration::GlSyncAbstraction& glSyncAbstraction,
- Integration::GestureManager& gestureManager );
+ Integration::GestureManager& gestureManager,
+ ResourcePolicy::DataRetention dataRetentionPolicy );
/**
* Destructor
~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)
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,
#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>
/**
* Implementation of Stage
*/
-class Stage : public BaseObject, public RenderTaskDefaults
+class Stage : public BaseObject, public RenderTaskDefaults, public Integration::ContextNotifierInterface
{
public:
return mNotificationManager;
}
+
/**
* @copydoc Dali::Stage::KeepRendering()
*/
*/
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:
/**
// The touched signal
Dali::Stage::TouchedSignalV2 mTouchedSignalV2;
+
+ Dali::Stage::ContextStatusSignal mContextLostSignal;
+ Dali::Stage::ContextStatusSignal mContextRegainedSignal;
};
} // 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()
{
* 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; }
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;
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),
* 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; }
if( size == attrib.GetSize() )
{
- mResourceClient.ReloadResource( ticket->GetId() );
+ mResourceClient.ReloadResource( ticket->GetId(), false );
}
else
{
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 )
* 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.
// 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>
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();
} // namespace Internal
} // namespace Dali
-
// 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>
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 )
{
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 );
}
}
+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
*/
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:
/**
struct ResourceClient::Impl
{
- Impl()
+ Impl(ResourcePolicy::DataRetention dataRetentionPolicy)
: mNextId(0),
- mGlyphLoadObserver( NULL)
+ mGlyphLoadObserver(NULL),
+ mDataRetentionPolicy( dataRetentionPolicy )
{
}
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);
}
delete mImpl;
}
+ResourcePolicy::DataRetention ResourceClient::GetResourceDataRetentionPolicy()
+{
+ return mImpl->mDataRetentionPolicy;
+}
+
ResourceTicketPtr ResourceClient::RequestResource(
const ResourceType& type,
const std::string& path,
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);
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
{
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);
{
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)
* @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.
* 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.
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 );
*/
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.
mVerticalDpi = verticalDpi;
}
+void FontFactory::RecoverFromContextLoss()
+{
+ mAtlasManager->ReloadAtlases();
+}
+
} // namespace Internal
} // namespace Dali
*/
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
/**
mMetrics->LoadMetricsSynchronously( text );
-
return mAtlasManager.TextRequired(text, format, *(mMetrics.Get()));
}
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();
for( ; iter != end; ++iter )
{
GlResourceOwner* renderer = *iter;
- renderer->GlContextDestroyed();
+ renderer->GlContextDestroyed(); // Clear up vertex buffers
}
}
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);
}
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();
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;
+ }
}
}
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() &&
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 );
}
}
}
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() )
{
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
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
#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
{
* @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
* @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.
*/
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;
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));
if ( mId ) // If the texture is already bound
{
AssignBitmap( false, pixels, mBitmap->GetBufferSize() );
- mBitmap->DiscardBuffer();
+
+ if( mDiscardPolicy == ResourcePolicy::DISCARD )
+ {
+ mBitmap->DiscardBuffer();
+ }
}
}
}
#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>
* 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.
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;
#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)
void Context::GlContextCreated()
{
+ DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
+
DALI_ASSERT_DEBUG(!mGlContextCreated);
mGlContextCreated = true;
// 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 )
{
void Context::ResetGlState()
{
+ DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
DALI_ASSERT_DEBUG(mGlContextCreated);
mClearColorSet = false;
*/
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() )
{
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
Context& context)
: TextureCacheDispatcher(renderQueue),
mPostProcessResourceDispatcher(postProcessResourceDispatcher),
- mContext(context)
+ mContext(context),
+ mDiscardBitmapsPolicy(ResourcePolicy::DISCARD)
{
}
{
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));
}
{
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));
}
TexturePointer texturePtr = textureIter->second;
if( texturePtr )
{
- texturePtr->Update(bitmap.Get());
+ texturePtr->Update( bitmap.Get() );
ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
}
}
+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 *********************
********************************************************************************/
#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>
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
*/
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
/**
typedef TextureResourceObservers::iterator TextureResourceObserversIter;
TextureResourceObservers mObservers;
+ ResourcePolicy::Discardable mDiscardBitmapsPolicy;
};
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 )
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;
}
} // TextureFactory
} // Internal
} // Dali
-
// 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
{
* @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.
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).
mHeight(height),
mImageWidth(imageWidth),
mImageHeight(imageHeight),
- mPixelFormat(pixelFormat),
- mDiscarded(false)
+ mPixelFormat(pixelFormat)
{
}
void Texture::ApplySampler( unsigned int samplerBitfield )
{
- if( mSamplerBitfield != samplerBitfield )
+ if( mSamplerBitfield != samplerBitfield && mId != 0 )
{
ApplyTextureParameter( GL_TEXTURE_MIN_FILTER,
ImageSampler::GetMinifyFilterMode( mSamplerBitfield ),
/**
* 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);
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
};
// 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>
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
void ImageRenderer::GlCleanup()
{
+ DALI_LOG_INFO( gImageRenderFilter, Debug::Verbose, "GlCleanup() textureId=%d texture:%p\n", mTextureId, mTexture);
+
mVertexBuffer.Reset();
mIndexBuffer.Reset();
}
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." );
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
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];
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;
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()
RegisterUniform( gStdUniforms[ i ] );
}
// reset values
- ResetAttribsUniforms();
+ ResetAttribsUniformCache();
}
Program::~Program()
}
}
-void Program::ResetAttribsUniforms()
+void Program::ResetAttribsUniformCache()
{
// reset attribute locations
for( unsigned i = 0; i < ATTRIB_TYPE_LAST; ++i )
/**
* Resets caches
*/
- void ResetAttribsUniforms();
+ void ResetAttribsUniformCache();
private: // Data
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 ) );
#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() ),
mGeometryType( meshData.GetVertexGeometryType() ),
mHasNormals( meshData.HasNormals() ),
mHasColor( meshData.HasColor() ),
- mDiscardable( discardable ),
+ mDiscardable( discardable==ResourcePolicy::DISCARD ),
mDiscarded( false ),
mScalingRequired( scalingRequired )
{
void MeshData::Discard()
{
- if (mDiscardable)
+ if( mDiscardable )
{
DALI_ASSERT_DEBUG( !mDiscarded );
VertexContainer().swap(mVertices); // this will enforce releasing the memory
*/
#include <dali/public-api/geometry/mesh-data.h>
+#include <dali/integration-api/resource-policies.h>
namespace Dali
{
* @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
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() );
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)
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();
}
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.
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.
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;
}
{
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 )
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,
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() )
if ( !resourceIsAlreadyLoading )
{
- //load resource again
+ // load resource again
mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
SendToClient( LoadingMessage( *mImpl->mResourceClient, id ) );
}
}
}
-static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
-{
- return container.erase(id) != 0;
-}
-
void ResourceManager::HandleDiscardResourceRequest( ResourceId deadId, ResourceTypeId typeId )
{
bool wasComplete = false;
#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>
* @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
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 );
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,
return GetImplementation(*this).TouchedSignal();
}
+
+Stage::ContextStatusSignal& Stage::ContextLostSignal()
+{
+ return GetImplementation(*this).ContextLostSignal();
+}
+
+Stage::ContextStatusSignal& Stage::ContextRegainedSignal()
+{
+ return GetImplementation(*this).ContextRegainedSignal();
+}
+
} // namespace Dali
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.
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.
*/
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
/**