Ensured shader blending hints override actor color 92/38792/4
authorDavid Steele <david.steele@partner.samsung.com>
Tue, 28 Apr 2015 17:25:17 +0000 (18:25 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Thu, 30 Apr 2015 09:26:40 +0000 (10:26 +0100)
Changed scene-graph-material to have a blending policy set by
PrepareRender() that is used to determine how the actor should behave
w.r.t opacity.

Fixed the default blending options in the scene-graph-material.

Change-Id: Ic9f5a5410a3927cc0846af566d633e84d22c00c2
Signed-off-by: David Steele <david.steele@partner.samsung.com>
automated-tests/src/dali/utc-Dali-Material.cpp
dali/internal/update/effects/scene-graph-material.cpp
dali/internal/update/effects/scene-graph-material.h
dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp

index 7b853c3..d5dd995 100644 (file)
@@ -305,7 +305,7 @@ int UtcDaliMaterialSetBlendMode03(void)
 {
   TestApplication application;
 
-  tet_infoline("Test setting the blend mode to auto with a transparent color renders with blending enabled");
+  tet_infoline("Test setting the blend mode to auto with a transparent material color renders with blending enabled");
 
   Geometry geometry = CreateQuadGeometry();
   Material material = CreateMaterial(0.5f);
@@ -363,6 +363,70 @@ int UtcDaliMaterialSetBlendMode04(void)
   END_TEST;
 }
 
+int UtcDaliMaterialSetBlendMode04b(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque material color and a transparent actor color renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  actor.SetColor( Vector4(1.0f, 0.0f, 1.0f, 0.5f) );
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode04c(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque material color and an opaque actor color renders with blending disabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  actor.SetColor( Color::MAGENTA );
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
 int UtcDaliMaterialSetBlendMode05(void)
 {
   TestApplication application;
@@ -394,3 +458,103 @@ int UtcDaliMaterialSetBlendMode05(void)
 
   END_TEST;
 }
+
+int UtcDaliMaterialSetBlendMode06(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with an opaque color and an image without an alpha channel and a shader with the hint OUTPUT_IS_TRANSPARENT renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_TRANSPARENT );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode07(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with a transparent color and an image without an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled");
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::TRANSPARENT);
+
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode08(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with an opaque color and an image with an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+  BufferImage image = BufferImage::New( 50, 50, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
index 914f9b8..fd22706 100644 (file)
@@ -33,14 +33,19 @@ namespace Internal
 namespace SceneGraph
 {
 
+namespace
+{
+const unsigned int DEFAULT_BLENDING_OPTIONS( BlendingOptions().GetBitmask() );
+}
+
 Material::Material()
 : mColor( Color::WHITE ),
   mBlendColor( Color::WHITE ),
   mFaceCullingMode(Dali::Material::NONE),
   mBlendingMode(Dali::BlendingMode::AUTO),
-  mBlendingOptions(DEFAULT_BLENDING_EQUATION_ALPHA),
+  mBlendingOptions( DEFAULT_BLENDING_OPTIONS ),
   mShader(NULL),
-  mBlendingEnabled(false)
+  mBlendPolicy(OPAQUE)
 {
   // Observe own property-owner's uniform map
   AddUniformMapObserver( *this );
@@ -94,25 +99,31 @@ void Material::RemoveSampler( Sampler* sampler )
 
 void Material::PrepareRender( BufferIndex bufferIndex )
 {
-  mBlendingEnabled[bufferIndex] = false; // The best default
+  mBlendPolicy = OPAQUE;
+
+  // @todo MESH_REWORK Add dirty flags to reduce processing.
 
   switch(mBlendingMode[bufferIndex])
   {
     case BlendingMode::OFF:
     {
-      mBlendingEnabled[bufferIndex] = false;
+      mBlendPolicy = OPAQUE;
       break;
     }
     case BlendingMode::ON:
     {
-      mBlendingEnabled[bufferIndex] = true;
+      mBlendPolicy = TRANSPARENT;
       break;
     }
     case BlendingMode::AUTO:
     {
       bool opaque = true;
 
-      //  @todo: MESH_REWORK - Change hints for new SceneGraphShader
+      //  @todo: MESH_REWORK - Change hints for new SceneGraphShader:
+      // If shader hint OUTPUT_IS_OPAQUE is enabled, set policy to ALWAYS_OPAQUE
+      // If shader hint OUTPUT_IS_TRANSPARENT is enabled, set policy to ALWAYS_TRANSPARENT
+      // else test remainder, and set policy to either ALWAYS_TRANSPARENT or USE_ACTOR_COLOR
+
       if( mShader->GeometryHintEnabled( Dali::ShaderEffect::HINT_BLENDING ) )
       {
         opaque = false;
@@ -149,7 +160,7 @@ void Material::PrepareRender( BufferIndex bufferIndex )
         opaque = (opaqueCount == affectingCount);
       }
 
-      mBlendingEnabled[bufferIndex] = ! opaque;
+      mBlendPolicy = opaque ? Material::USE_ACTOR_COLOR : Material::TRANSPARENT;
     }
   }
 }
@@ -159,9 +170,9 @@ Vector<Sampler*>& Material::GetSamplers()
   return mSamplers;
 }
 
-bool Material::GetBlendingEnabled( BufferIndex bufferIndex ) const
+Material::BlendPolicy Material::GetBlendPolicy() const
 {
-  return mBlendingEnabled[bufferIndex];
+  return mBlendPolicy;
 }
 
 void Material::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
index 148433d..e4af877 100644 (file)
@@ -43,6 +43,17 @@ class Material : public PropertyOwner, public MaterialDataProvider, public Unifo
 {
 public:
   /**
+   * This enum defines the outputs of the PrepareRender step, and is used
+   * by the Renderer to determine final opacity.
+   */
+  enum BlendPolicy
+  {
+    OPAQUE,          ///< If the renderer should always be opaque
+    TRANSPARENT,     ///< If the renderer should always be transparent
+    USE_ACTOR_COLOR  ///< If the renderer should determine opacity using the actor color
+  };
+
+  /**
    * Constructor
    */
   Material();
@@ -79,13 +90,14 @@ public:
   void PrepareRender( BufferIndex bufferIndex );
 
   /**
-   * Return true if the material requires blending
-   * @return true if the material requires blending
+   * Return the blend policy ( a combination of all the different shader hints, color, samper and image properties ).
+   * This should only be called from the update thread
+   * @return The material's blend policy
    */
-  bool GetBlendingEnabled( BufferIndex bufferIndex ) const;
+  BlendPolicy GetBlendPolicy() const;
 
   /**
-   * Set the blending options. This should only be called from the update-thread.
+   * Set the blending options. This should only be called from the update thread.
    * @param[in] updateBufferIndex The current update buffer index.
    * @param[in] options A bitmask of blending options.
    */
@@ -203,7 +215,7 @@ private:
   Shader* mShader;
   Vector<Sampler*> mSamplers; // Not owned
   ConnectionChangePropagator mConnectionObservers;
-  DoubleBuffered<int> mBlendingEnabled; // The output of the current blending mode and sampler properties
+  BlendPolicy mBlendPolicy; ///< The blend policy as determined by PrepareRender
 };
 
 inline void SetShaderMessage( EventThreadServices& eventThreadServices, const Material& material, const Shader& shader )
index a005dd1..ea33d06 100644 (file)
@@ -185,15 +185,30 @@ bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
 {
   bool opaque = false;
 
-  if( mParent )
+  if( mMaterial != NULL )
   {
-    opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
-  }
-
-  if( opaque && mMaterial != NULL )
-  {
-    // Calculated by material in PrepareRender step
-    opaque = ! mMaterial->GetBlendingEnabled( updateBufferIndex );
+    Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
+    switch( blendPolicy )
+    {
+      case Material::OPAQUE:
+      {
+        opaque = true;
+        break;
+      }
+      case Material::TRANSPARENT:
+      {
+        opaque = false;
+        break;
+      }
+      case Material::USE_ACTOR_COLOR:
+      {
+        if( mParent )
+        {
+          opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
+        }
+        break;
+      }
+    }
   }
 
   return opaque;