#include <dali/public-api/dali-core.h>
#include <dali-test-suite-utils.h>
+#include <cstdio>
+
using namespace Dali;
#include <mesh-builder.h>
END_TEST;
}
+
+int UtcDaliRendererSetIndicesRange(void)
+{
+ std::string
+ vertexShader(
+ "attribute vec2 aPosition;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = aPosition;\n"
+ "}"
+ ),
+ fragmentShader(
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0)\n"
+ "}\n"
+ );
+
+ TestApplication application;
+ tet_infoline("Test setting the range of indices to draw");
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ gl.EnableDrawCallTrace( true );
+
+ Actor actor = Actor::New();
+ actor.SetSize( 100, 100 );
+
+ // create geometry
+ Geometry geometry = Geometry::New();
+ geometry.SetGeometryType( Geometry::LINE_LOOP );
+
+ // --------------------------------------------------------------------------
+ // index buffer
+ unsigned indices[] = { 0, 2, 4, 6, 8, // offset = 0, count = 5
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // offset = 5, count = 10
+ 1, 3, 5, 7, 9, 1 }; // offset = 15, count = 6 // line strip
+ Property::Map format;
+ format["indices"] = Property::INTEGER;
+ PropertyBuffer indexBuffer = PropertyBuffer::New( format );
+ indexBuffer.SetData( indices, sizeof(indices)/sizeof(indices[0]));
+
+ // --------------------------------------------------------------------------
+ // vertex buffer
+ struct Vertex
+ {
+ Vector2 position;
+ };
+ Vertex shapes[] =
+ {
+ // pentagon // star
+ { Vector2( 0.0f, 1.00f) }, { Vector2( 0.0f, -1.00f) },
+ { Vector2( -0.95f, 0.31f) }, { Vector2( 0.59f, 0.81f) },
+ { Vector2( -0.59f, -0.81f) }, { Vector2( -0.95f, -0.31f) },
+ { Vector2( 0.59f, -0.81f) }, { Vector2( 0.95f, -0.31f) },
+ { Vector2( 0.95f, 0.31f) }, { Vector2( -0.59f, 0.81f) },
+ };
+ Property::Map vertexFormat;
+ vertexFormat["aPosition"] = Property::VECTOR2;
+ PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
+ vertexBuffer.SetData( shapes, sizeof(shapes)/sizeof(shapes[0]));
+
+ // --------------------------------------------------------------------------
+ geometry.SetIndexBuffer( indexBuffer );
+ geometry.AddVertexBuffer( vertexBuffer );
+
+ // create shader
+ Shader shader = Shader::New( vertexShader,fragmentShader );
+ Renderer renderer = Renderer::New( geometry, shader );
+ actor.AddRenderer( renderer );
+
+ Stage stage = Stage::GetCurrent();
+ stage.Add( actor );
+
+ char buffer[ 128 ];
+
+ // LINE_LOOP, first 0, count 5
+ {
+ renderer.SetIndicesRange( 0, 5 );
+ application.SendNotification();
+ application.Render();
+ sprintf( buffer, "%u, 5, %u, indices", GL_LINE_LOOP, GL_UNSIGNED_SHORT );
+ bool result = gl.GetDrawTrace().FindMethodAndParams( "DrawElements" , buffer );
+ DALI_TEST_CHECK( result );
+ }
+
+ // LINE_LOOP, first 5, count 10
+ {
+ renderer.SetIndicesRange( 5, 10 );
+ sprintf( buffer, "%u, 10, %u, indices", GL_LINE_LOOP, GL_UNSIGNED_SHORT );
+ application.SendNotification();
+ application.Render();
+ bool result = gl.GetDrawTrace().FindMethodAndParams( "DrawElements" , buffer );
+ DALI_TEST_CHECK( result );
+ }
+
+ // LINE_STRIP, first 15, count 6
+ {
+ renderer.SetIndicesRange( 15, 6 );
+ geometry.SetGeometryType( Geometry::LINE_STRIP );
+ sprintf( buffer, "%u, 6, %u, indices", GL_LINE_STRIP, GL_UNSIGNED_SHORT );
+ application.SendNotification();
+ application.Render();
+ bool result = gl.GetDrawTrace().FindMethodAndParams( "DrawElements" , buffer );
+ DALI_TEST_CHECK( result );
+ }
+
+ END_TEST;
+}
BLENDING_DEST_FACTOR_ALPHA, ///< name "destinationBlendFactorAlpha", type INTEGER
BLENDING_COLOR, ///< name "blendingColor", type VECTOR4
BLEND_PRE_MULTIPLIED_ALPHA, ///< name "blendPreMultipledAlpha", type BOOLEAN
+ INDEXED_DRAW_FIRST_ELEMENT, ///< name "indexedDrawFirstElement", type INTEGER
+ INDEXED_DRAW_ELEMENTS_COUNT ///< name "indexedDrawElementsCount", type INTEGER
};
};
Geometry GetGeometry() const;
/**
+ * @brief Sets effective range of indices to draw from bound index buffer
+ * @param [in] firstElement first element to draw
+ * @param [in] elementsCount number of elements to draw
+ */
+ inline void SetIndicesRange( int firstElement, int elementsCount )
+ {
+ SetProperty( Property::INDEXED_DRAW_FIRST_ELEMENT, firstElement );
+ SetProperty( Property::INDEXED_DRAW_ELEMENTS_COUNT, elementsCount );
+ }
+
+ /**
* @brief Sets the texture set to be used by this renderer
*
* @param[in] textureSet The texture set to be used by this renderer
DALI_PROPERTY( "destinationBlendFactorAlpha", INTEGER, true, false, false, Dali::Renderer::Property::BLENDING_DEST_FACTOR_ALPHA )
DALI_PROPERTY( "blendingColor", VECTOR4, true, false, false, Dali::Renderer::Property::BLENDING_COLOR )
DALI_PROPERTY( "blendPreMultipliedAlpha", BOOLEAN, true, false, false, Dali::Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA )
+DALI_PROPERTY( "indexedDrawFirstElement", INTEGER, true, false, false, Dali::Renderer::Property::INDEXED_DRAW_FIRST_ELEMENT )
+DALI_PROPERTY( "indexedDrawElementsCount", INTEGER, true, false, false, Dali::Renderer::Property::INDEXED_DRAW_ELEMENTS_COUNT )
DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> RENDERER_IMPL = { DEFAULT_PROPERTY_DETAILS };
return Color::TRANSPARENT; // GL default
}
+void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
+{
+ if( firstElement != mIndexedDrawFirstElement )
+ {
+ mIndexedDrawFirstElement = firstElement;
+ SetIndexedDrawFirstElementMessage( GetEventThreadServices(), *mSceneObject, mIndexedDrawFirstElement );
+ }
+}
+
+void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
+{
+ if( elementsCount != mIndexedDrawElementCount )
+ {
+ mIndexedDrawElementCount = elementsCount;
+ SetIndexedDrawElementsCountMessage( GetEventThreadServices(), *mSceneObject, mIndexedDrawElementCount );
+ }
+}
+
+
void Renderer::EnablePreMultipliedAlpha( bool preMultipled )
{
if( mPremultipledAlphaEnabled != preMultipled )
}
break;
}
+ case Dali::Renderer::Property::INDEXED_DRAW_FIRST_ELEMENT:
+ {
+ int firstElement;
+ if( propertyValue.Get( firstElement ) )
+ {
+ SetIndexedDrawFirstElement( firstElement );
+ }
+ break;
+ }
+ case Dali::Renderer::Property::INDEXED_DRAW_ELEMENTS_COUNT:
+ {
+ int elementsCount;
+ if( propertyValue.Get( elementsCount ) )
+ {
+ SetIndexedDrawElementsCount( elementsCount );
+ }
+ break;
+ }
}
}
value = IsPreMultipliedAlphaEnabled();
break;
}
+ case Dali::Renderer::Property::INDEXED_DRAW_FIRST_ELEMENT:
+ {
+ value = static_cast<int>( mIndexedDrawFirstElement );
+ break;
+ }
+ case Dali::Renderer::Property::INDEXED_DRAW_ELEMENTS_COUNT:
+ {
+ value = static_cast<int>( mIndexedDrawElementCount );
+ break;
+ }
}
return value;
}
}
Renderer::Renderer()
-: mSceneObject(NULL),
+: mSceneObject (NULL ),
mBlendColor( NULL ),
- mDepthIndex(0),
- mOnStageCount(0),
- mFaceCullingMode(Dali::Renderer::NONE),
+ mDepthIndex( 0 ),
+ mOnStageCount( 0 ),
+ mIndexedDrawFirstElement( 0 ),
+ mIndexedDrawElementCount( 0 ),
+ mFaceCullingMode( Dali::Renderer::NONE ),
mBlendingMode( Dali::BlendingMode::AUTO ),
mBlendingOptions(),
mPremultipledAlphaEnabled( false )
Vector4 GetBlendColor() const;
/**
+ * @copydoc Dali::Renderer::SetIndexedDrawFirstElement
+ */
+ void SetIndexedDrawFirstElement( size_t firstElement );
+
+ /**
+ * @copydoc Dali::Renderer::SetIndexedDrawElementsCount
+ */
+ void SetIndexedDrawElementsCount( size_t elementsCount );
+
+ /**
* @brief Set whether the Pre-multiplied Alpha Blending is required
*
* @param[in] preMultipled whether alpha is pre-multiplied.
int mDepthIndex;
int mOnStageCount;
+ size_t mIndexedDrawFirstElement; ///< Offset of first element to draw from bound index buffer
+ size_t mIndexedDrawElementCount; ///< Number of elements to draw
+
Dali::Renderer::FaceCullingMode mFaceCullingMode; ///< Local copy of face culling mode
BlendingMode::Type mBlendingMode; ///< Local copy of blending mode
BlendingOptions mBlendingOptions; ///< Local copy of blending options bitmask
void RenderGeometry::UploadAndDraw(
Context& context,
BufferIndex bufferIndex,
- Vector<GLint>& attributeLocation )
+ Vector<GLint>& attributeLocation,
+ size_t elementBufferOffset,
+ size_t elementBufferCount )
{
if( !mHasBeenUpdated )
{
//Bind index buffer
unsigned int numIndices(0u);
+ intptr_t firstIndexOffset(0u);
if( mIndexBuffer )
{
numIndices = mIndexBuffer->GetDataSize() / mIndexBuffer->GetElementSize();
+ if ( elementBufferCount )
+ {
+ numIndices = elementBufferCount > numIndices ? numIndices : elementBufferCount;
+ }
+ firstIndexOffset = elementBufferOffset * sizeof(GLushort);
}
//Draw call
{
if( numIndices )
{
- context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
{
if( numIndices )
{
- context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
{
if( numIndices )
{
- context.DrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
{
if( numIndices )
{
- context.DrawElements(GL_TRIANGLE_FAN, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_TRIANGLE_FAN, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
{
if( numIndices )
{
- context.DrawElements(GL_LINE_LOOP, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_LINE_LOOP, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
{
if( numIndices )
{
- context.DrawElements(GL_LINE_STRIP, numIndices, GL_UNSIGNED_SHORT, 0);
+ context.DrawElements(GL_LINE_STRIP, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset) );
}
else
{
* @param[in] context The GL context
* @param[in] bufferIndex The current buffer index
* @param[in] attributeLocation The location for the attributes in the shader
+ * @param[in] elementBufferOffset The index of first element to draw if index buffer bound
+ * @param[in] elementBufferCount Number of elements to draw if index buffer bound
*/
void UploadAndDraw(Context& context,
BufferIndex bufferIndex,
- Vector<GLint>& attributeLocation );
+ Vector<GLint>& attributeLocation,
+ size_t elementBufferOffset,
+ size_t elementBufferCount );
private:
mAttributesLocation(),
mBlendingOptions(),
mFaceCullingMode( faceCullingMode ),
+ mIndexedDrawFirstElement( 0 ),
+ mIndexedDrawElementsCount( 0 ),
mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
mUpdateAttributesLocation( true ),
mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
mBlendingOptions.SetBlendColor( *color );
}
+void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
+{
+ mIndexedDrawFirstElement = firstElement;
+}
+
+void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
+{
+ mIndexedDrawElementsCount = elementsCount;
+}
+
void Renderer::EnablePreMultipliedAlpha( bool enable )
{
mPremultipledAlphaEnabled = enable;
mUpdateAttributesLocation = false;
}
- mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation );
+ mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
}
}
void SetBlendColor( const Vector4* color );
/**
+ * Set the first element index to draw by the indexed draw
+ * @param[in] firstElement index of first element to draw
+ */
+ void SetIndexedDrawFirstElement( size_t firstElement );
+
+ /**
+ * Set the number of elements to draw by the indexed draw
+ * @param[in] elementsCount number of elements to draw
+ */
+ void SetIndexedDrawElementsCount( size_t elementsCount );
+
+ /**
* @brief Set whether the Pre-multiplied Alpha Blending is required
*
* @param[in] preMultipled whether alpha is pre-multiplied.
BlendingOptions mBlendingOptions; /// Blending options including blend color, blend func and blend equation
Dali::Renderer::FaceCullingMode mFaceCullingMode; /// Mode of face culling
+ size_t mIndexedDrawFirstElement; /// Offset of first element to draw
+ size_t mIndexedDrawElementsCount; /// Number of elements to draw
+
unsigned int mSamplerBitfield; ///< Sampler options used for texture filtering
bool mUpdateAttributesLocation:1; ///< Indicates attribute locations have changed
bool mPremultipledAlphaEnabled:1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
RESEND_FACE_CULLING_MODE = 1 << 2,
RESEND_BLEND_COLOR = 1 << 3,
RESEND_BLEND_BIT_MASK = 1 << 4,
- RESEND_PREMULTIPLIED_ALPHA = 1 << 5
+ RESEND_PREMULTIPLIED_ALPHA = 1 << 5,
+ RESEND_INDEXED_DRAW_FIRST_ELEMENT = 1 << 6,
+ RESEND_INDEXED_DRAW_ELEMENTS_COUNT = 1 << 7,
};
}
}
Renderer::Renderer()
-:mSceneController(0),
- mRenderer(NULL),
- mTextureSet(NULL),
- mGeometry(NULL),
- mShader(NULL),
- mBlendColor(NULL),
- mBlendBitmask(0u),
+:mSceneController( 0 ),
+ mRenderer( NULL ),
+ mTextureSet( NULL ),
+ mGeometry( NULL ),
+ mShader( NULL ),
+ mBlendColor( NULL ),
+ mBlendBitmask( 0u ),
mFaceCullingMode( Dali::Renderer::NONE ),
mBlendingMode( Dali::BlendingMode::AUTO ),
- mReferenceCount(0),
- mRegenerateUniformMap(0),
- mResendFlag(0),
- mResourcesReady(false),
- mFinishedResourceAcquisition(false),
- mDepthIndex(0)
-{
- mUniformMapChanged[0]=false;
- mUniformMapChanged[1]=false;
+ mReferenceCount( 0 ),
+ mRegenerateUniformMap( 0 ),
+ mResendFlag( 0 ),
+ mResourcesReady( false ),
+ mFinishedResourceAcquisition( false ),
+ mIndexedDrawFirstElement( 0 ),
+ mIndexedDrawElementsCount( 0 ),
+ mDepthIndex( 0 )
+{
+ mUniformMapChanged[0] = false;
+ mUniformMapChanged[1] = false;
// Observe our own PropertyOwner's uniform map
AddUniformMapObserver( *this );
new (slot) DerivedType( mRenderer, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled );
mResendFlag &= ~RESEND_PREMULTIPLIED_ALPHA;
}
+
+ if( mResendFlag & RESEND_INDEXED_DRAW_FIRST_ELEMENT )
+ {
+ typedef MessageValue1< Render::Renderer, size_t > DerivedType;
+ unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+ new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement );
+ mResendFlag &= ~RESEND_INDEXED_DRAW_FIRST_ELEMENT;
+ }
+
+ if( mResendFlag & RESEND_INDEXED_DRAW_ELEMENTS_COUNT )
+ {
+ typedef MessageValue1< Render::Renderer, size_t > DerivedType;
+ unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+ new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount );
+ mResendFlag &= ~RESEND_INDEXED_DRAW_FIRST_ELEMENT;
+ }
+
+
}
void Renderer::SetTextures( TextureSet* textureSet )
mResendFlag |= RESEND_BLEND_COLOR;
}
+void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
+{
+ mIndexedDrawFirstElement = firstElement;
+ mResendFlag |= RESEND_INDEXED_DRAW_FIRST_ELEMENT;
+}
+
+void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
+{
+ mIndexedDrawElementsCount = elementsCount;
+ mResendFlag |= RESEND_INDEXED_DRAW_ELEMENTS_COUNT;
+}
+
void Renderer::EnablePreMultipliedAlpha( bool preMultipled )
{
mPremultipledAlphaEnabled = preMultipled;
void SetBlendColor( const Vector4& blendColor );
/**
+ * Set the index of first element for indexed draw
+ * @param[in] firstElement index of first element to draw
+ */
+ void SetIndexedDrawFirstElement( size_t firstElement );
+
+ /**
+ * Set the number of elements to draw by indexed draw
+ * @param[in] elementsCount number of elements to draw
+ */
+ void SetIndexedDrawElementsCount( size_t elementsCount );
+
+ /**
* @brief Set whether the Pre-multiplied Alpha Blending is required
*
* @param[in] preMultipled whether alpha is pre-multiplied.
bool mFinishedResourceAcquisition; ///< Set during DoPrepareResources; true if ready & all resource acquisition has finished (successfully or otherwise)
bool mPremultipledAlphaEnabled; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
+ size_t mIndexedDrawFirstElement; ///< first element index to be drawn using indexed draw
+ size_t mIndexedDrawElementsCount; ///< number of elements to be drawn using indexed draw
+
public:
int mDepthIndex; ///< Used only in PrepareRenderInstructions
};
new (slot) LocalType( &renderer, &Renderer::SetBlendColor, blendColor );
}
+inline void SetIndexedDrawFirstElementMessage( EventThreadServices& eventThreadServices, const Renderer& renderer, size_t firstElement )
+{
+ typedef MessageValue1< Renderer, size_t > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+ new (slot) LocalType( &renderer, &Renderer::SetIndexedDrawFirstElement, firstElement );
+}
+
+inline void SetIndexedDrawElementsCountMessage( EventThreadServices& eventThreadServices, const Renderer& renderer, size_t elementsCount )
+{
+ typedef MessageValue1< Renderer, size_t > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+ new (slot) LocalType( &renderer, &Renderer::SetIndexedDrawElementsCount, elementsCount );
+}
+
inline void SetEnablePreMultipliedAlphaMessage( EventThreadServices& eventThreadServices, const Renderer& renderer, bool preMultiplied )
{
typedef MessageValue1< Renderer, bool > LocalType;