Buffer::Buffer(const Graphics::BufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
: BufferResource(createInfo, controller)
{
+ // Check if buffer is CPU allocated
+ if(((0 | BufferUsage::UNIFORM_BUFFER) & mCreateInfo.usage) &&
+ (0 | BufferPropertiesFlagBit::CPU_ALLOCATED) & mCreateInfo.propertiesFlags)
+ {
+ // cpu allocated buffer
+ mCpuAllocated = true;
+ }
+
+ // Check if buffer is transient
+ if((0 | BufferPropertiesFlagBit::TRANSIENT_MEMORY) & mCreateInfo.propertiesFlags)
+ {
+ // memory is transient, may be lazily allocated when
+ // mapped, together with cpu allocated it may create emulated uniform
+ // buffer in this implementation
+ mTransient = true;
+ }
+
controller.AddBuffer(*this);
}
bool Buffer::InitializeResource()
{
- auto gl = mController.GetGL();
- gl->GenBuffers(1, &mBufferId);
- gl->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
- gl->BufferData(GL_ARRAY_BUFFER, mCreateInfo.size, nullptr, GL_STATIC_DRAW);
+ // CPU allocated uniform buffer is a special "compatibility" mode
+ // for older GLES
+ if(mCpuAllocated && !mTransient)
+ {
+ InitializeCPUBuffer();
+ }
+ else if(!mCpuAllocated)
+ {
+ InitializeGPUBuffer();
+ }
+
return true;
}
+void Buffer::InitializeCPUBuffer()
+{
+ // Just allocate memory
+ // @TODO put better CPU memory management in place
+ const auto allocators = GetCreateInfo().allocationCallbacks;
+ if(allocators)
+ {
+ mBufferPtr = allocators->allocCallback(mCreateInfo.size, 0, allocators->userData);
+ }
+ else
+ {
+ mBufferPtr = malloc(mCreateInfo.size);
+ }
+}
+
+void Buffer::InitializeGPUBuffer()
+{
+ auto context = mController.GetCurrentContext();
+ auto gl = mController.GetGL();
+ if(!gl || !context)
+ {
+ return;
+ }
+
+ gl->GenBuffers(1, &mBufferId);
+ context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
+ gl->BufferData(GL_ARRAY_BUFFER, GLsizeiptr(mCreateInfo.size), nullptr, GL_STATIC_DRAW);
+}
+
void Buffer::DestroyResource()
{
- auto gl = mController.GetGL();
- gl->DeleteBuffers(1, &mBufferId);
+ // Destroy CPU allocated buffer
+ if(mCpuAllocated && mBufferPtr)
+ {
+ const auto allocators = GetCreateInfo().allocationCallbacks;
+ if(allocators)
+ {
+ allocators->freeCallback(mBufferPtr, allocators->userData);
+ }
+ else
+ {
+ free(mBufferPtr);
+ }
+ mBufferPtr = nullptr;
+ }
+ // Deestroy GPU allocation
+ else
+ {
+ auto gl = mController.GetGL();
+ if(gl)
+ {
+ gl->DeleteBuffers(1, &mBufferId);
+ }
+ }
}
void Buffer::DiscardResource()
void Buffer::Bind(Graphics::BufferUsage bindingTarget) const
{
- auto gl = mController.GetGL();
- switch(bindingTarget)
+ auto context = mController.GetCurrentContext();
+ auto gl = mController.GetGL();
+ if(!gl || !context)
{
- case Graphics::BufferUsage::VERTEX_BUFFER:
- {
- gl->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
- break;
- }
- case Graphics::BufferUsage::INDEX_BUFFER:
+ return;
+ }
+
+ // CPU allocated buffer may be bound only as Uniform Buffer
+ // on special binding point
+ if(mCpuAllocated && mBufferPtr)
+ {
+ if(bindingTarget == Graphics::BufferUsage::UNIFORM_BUFFER)
{
- gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);
- break;
+ // TODO: probably nothing to do, the GLES Context
+ // we may use CPU backed buffer for future data
+ // transfers (copy operations)
}
- default:
+ }
+ else
+ {
+ switch(bindingTarget)
{
- //
+ case Graphics::BufferUsage::VERTEX_BUFFER:
+ {
+ context->BindBuffer(GL_ARRAY_BUFFER, mBufferId);
+ break;
+ }
+ case Graphics::BufferUsage::INDEX_BUFFER:
+ {
+ context->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);
+ break;
+ }
+ default:
+ {
+ // Nothing to do
+ }
}
}
}
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES